1 /* 2 * $RCSfile: AndOpImage.java,v $ 3 * 4 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 5 * 6 * Use is subject to license terms. 7 * 8 * $Revision: 1.1 $ 9 * $Date: 2005/02/11 04:56:14 $ 10 * $State: Exp $ 11 */ 12 package com.lightcrafts.media.jai.opimage; 13 import java.awt.Rectangle; 14 import java.awt.image.DataBuffer; 15 import java.awt.image.Raster; 16 import java.awt.image.RenderedImage; 17 import java.awt.image.WritableRaster; 18 import com.lightcrafts.mediax.jai.ImageLayout; 19 import com.lightcrafts.mediax.jai.PointOpImage; 20 import com.lightcrafts.mediax.jai.RasterAccessor; 21 import com.lightcrafts.mediax.jai.RasterFormatTag; 22 import java.util.Map; 23 // import com.lightcrafts.media.jai.test.OpImageTester; 24 25 /** 26 * An <code>OpImage</code> implementing the "And" operation as 27 * described in <code>com.lightcrafts.mediax.jai.operator.AndDescriptor</code>. 28 * 29 * <p>This <code>OpImage</code> logically "ands" the pixel values of two source 30 * images on a per-band basis. In case the two source images have different 31 * number of bands, the number of bands for the destination image is the 32 * smaller band number of the two source images. That is 33 * <code>dstNumBands = Math.min(src1NumBands, src2NumBands)</code>. 34 * In case the two source images have different data types, the data type 35 * for the destination image is the bigger data type of the two source 36 * images. 37 * 38 * <p>The value of the pixel (x, y) in the destination image is defined as: 39 * <pre> 40 * for (b = 0; b < numBands; b++) { 41 * dst[y][x][b] = src1[y][x][b] & src2[y][x][b]; 42 * } 43 * </pre> 44 * 45 * The data type <code>byte</code> is treated as unsigned, with maximum 46 * value as 255 and minimum value as 0. 47 * 48 * @since EA2 49 * @see com.lightcrafts.mediax.jai.operator.AndDescriptor 50 * @see AndCRIF 51 * 52 */ 53 final class AndOpImage extends PointOpImage { 54 55 /** 56 * Constructs an <code>AndOpImage</code>. 57 * 58 * <p>The <code>layout</code> parameter may optionally contains the 59 * tile grid layout, sample model, and/or color model. The image 60 * dimension is determined by the intersection of the bounding boxes 61 * of the two source images. 62 * 63 * <p>The image layout of the first source image, <code>source1</code>, 64 * is used as the fall-back for the image layout of the destination 65 * image. Any layout parameters not specified in the <code>layout</code> 66 * argument are set to the same value as that of <code>source1</code>. 67 * 68 * @param source1 The first source image. 69 * @param source2 The second source image. 70 * @param layout The destination image layout. 71 */ AndOpImage(RenderedImage source1, RenderedImage source2, Map config, ImageLayout layout)72 public AndOpImage(RenderedImage source1, 73 RenderedImage source2, 74 Map config, 75 ImageLayout layout) { 76 super(source1, source2, layout, config, true); 77 78 // Set flag to permit in-place operation. 79 permitInPlaceOperation(); 80 } 81 82 /** 83 * Multiplies the pixel values of two source images within a specified 84 * rectangle. 85 * 86 * @param sources Cobbled sources, guaranteed to provide all the 87 * source data necessary for computing the rectangle. 88 * @param dest The tile containing the rectangle to be computed. 89 * @param destRect The rectangle within the tile to be computed. 90 */ computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect)91 protected void computeRect(Raster[] sources, 92 WritableRaster dest, 93 Rectangle destRect) { 94 // Retrieve format tags. 95 RasterFormatTag[] formatTags = getFormatTags(); 96 97 /* For PointOpImage, srcRect = destRect. */ 98 RasterAccessor s1 = new RasterAccessor(sources[0], destRect, 99 formatTags[0], 100 getSourceImage(0).getColorModel()); 101 RasterAccessor s2 = new RasterAccessor(sources[1], destRect, 102 formatTags[1], 103 getSourceImage(1).getColorModel()); 104 RasterAccessor d = new RasterAccessor(dest, destRect, 105 formatTags[2], getColorModel()); 106 107 if(d.isBinary()) { 108 byte[] src1Bits = s1.getBinaryDataArray(); 109 byte[] src2Bits = s2.getBinaryDataArray(); 110 byte[] dstBits = d.getBinaryDataArray(); 111 112 int length = dstBits.length; 113 for(int i = 0; i < length; i++) { 114 dstBits[i] = (byte)(src1Bits[i] & src2Bits[i]); 115 } 116 117 d.copyBinaryDataToRaster(); 118 119 return; 120 } 121 122 int src1LineStride = s1.getScanlineStride(); 123 int src1PixelStride = s1.getPixelStride(); 124 int[] src1BandOffsets = s1.getBandOffsets(); 125 126 int src2LineStride = s2.getScanlineStride(); 127 int src2PixelStride = s2.getPixelStride(); 128 int[] src2BandOffsets = s2.getBandOffsets(); 129 130 int dstNumBands = d.getNumBands(); 131 int dstWidth = d.getWidth(); 132 int dstHeight = d.getHeight(); 133 int dstLineStride = d.getScanlineStride(); 134 int dstPixelStride = d.getPixelStride(); 135 int[] dstBandOffsets = d.getBandOffsets(); 136 137 switch (d.getDataType()) { 138 139 case DataBuffer.TYPE_BYTE: 140 byteLoop(dstNumBands, dstWidth, dstHeight, 141 src1LineStride, src1PixelStride, 142 src1BandOffsets, s1.getByteDataArrays(), 143 src2LineStride, src2PixelStride, 144 src2BandOffsets, s2.getByteDataArrays(), 145 dstLineStride, dstPixelStride, 146 dstBandOffsets, d.getByteDataArrays()); 147 break; 148 149 case DataBuffer.TYPE_USHORT: 150 case DataBuffer.TYPE_SHORT: 151 shortLoop(dstNumBands, dstWidth, dstHeight, 152 src1LineStride, src1PixelStride, 153 src1BandOffsets, s1.getShortDataArrays(), 154 src2LineStride, src2PixelStride, 155 src2BandOffsets, s2.getShortDataArrays(), 156 dstLineStride, dstPixelStride, 157 dstBandOffsets, d.getShortDataArrays()); 158 break; 159 160 case DataBuffer.TYPE_INT: 161 intLoop(dstNumBands, dstWidth, dstHeight, 162 src1LineStride, src1PixelStride, 163 src1BandOffsets, s1.getIntDataArrays(), 164 src2LineStride, src2PixelStride, 165 src2BandOffsets, s2.getIntDataArrays(), 166 dstLineStride, dstPixelStride, 167 dstBandOffsets, d.getIntDataArrays()); 168 break; 169 } 170 171 d.copyDataToRaster(); 172 } 173 byteLoop(int dstNumBands, int dstWidth, int dstHeight, int src1LineStride, int src1PixelStride, int[] src1BandOffsets, byte[][] src1Data, int src2LineStride, int src2PixelStride, int[] src2BandOffsets, byte[][] src2Data, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, byte[][] dstData)174 private void byteLoop(int dstNumBands, int dstWidth, int dstHeight, 175 int src1LineStride, int src1PixelStride, 176 int[] src1BandOffsets, byte[][] src1Data, 177 int src2LineStride, int src2PixelStride, 178 int[] src2BandOffsets, byte[][] src2Data, 179 int dstLineStride, int dstPixelStride, 180 int[] dstBandOffsets, byte[][] dstData) { 181 182 for (int b = 0; b < dstNumBands; b++) { 183 byte[] s1 = src1Data[b]; 184 byte[] s2 = src2Data[b]; 185 byte[] d = dstData[b]; 186 int src1LineOffset = src1BandOffsets[b]; 187 int src2LineOffset = src2BandOffsets[b]; 188 int dstLineOffset = dstBandOffsets[b]; 189 190 for (int h = 0; h < dstHeight; h++) { 191 int src1PixelOffset = src1LineOffset; 192 int src2PixelOffset = src2LineOffset; 193 int dstPixelOffset = dstLineOffset; 194 src1LineOffset += src1LineStride; 195 src2LineOffset += src2LineStride; 196 dstLineOffset += dstLineStride; 197 198 for (int w = 0; w < dstWidth; w++) { 199 d[dstPixelOffset] = (byte)(s1[src1PixelOffset] & 200 s2[src2PixelOffset]); 201 src1PixelOffset += src1PixelStride; 202 src2PixelOffset += src2PixelStride; 203 dstPixelOffset += dstPixelStride; 204 } 205 } 206 } 207 } 208 shortLoop(int dstNumBands, int dstWidth, int dstHeight, int src1LineStride, int src1PixelStride, int[] src1BandOffsets, short[][] src1Data, int src2LineStride, int src2PixelStride, int[] src2BandOffsets, short[][] src2Data, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, short[][] dstData)209 private void shortLoop(int dstNumBands, int dstWidth, int dstHeight, 210 int src1LineStride, int src1PixelStride, 211 int[] src1BandOffsets, short[][] src1Data, 212 int src2LineStride, int src2PixelStride, 213 int[] src2BandOffsets, short[][] src2Data, 214 int dstLineStride, int dstPixelStride, 215 int[] dstBandOffsets, short[][] dstData) { 216 217 for (int b = 0; b < dstNumBands; b++) { 218 short[] s1 = src1Data[b]; 219 short[] s2 = src2Data[b]; 220 short[] d = dstData[b]; 221 int src1LineOffset = src1BandOffsets[b]; 222 int src2LineOffset = src2BandOffsets[b]; 223 int dstLineOffset = dstBandOffsets[b]; 224 225 for (int h = 0; h < dstHeight; h++) { 226 int src1PixelOffset = src1LineOffset; 227 int src2PixelOffset = src2LineOffset; 228 int dstPixelOffset = dstLineOffset; 229 src1LineOffset += src1LineStride; 230 src2LineOffset += src2LineStride; 231 dstLineOffset += dstLineStride; 232 233 for (int w = 0; w < dstWidth; w++) { 234 d[dstPixelOffset] = (short)(s1[src1PixelOffset] & 235 s2[src2PixelOffset]); 236 237 src1PixelOffset += src1PixelStride; 238 src2PixelOffset += src2PixelStride; 239 dstPixelOffset += dstPixelStride; 240 } 241 } 242 } 243 } 244 intLoop(int dstNumBands, int dstWidth, int dstHeight, int src1LineStride, int src1PixelStride, int[] src1BandOffsets, int[][] src1Data, int src2LineStride, int src2PixelStride, int[] src2BandOffsets, int[][] src2Data, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, int[][] dstData)245 private void intLoop(int dstNumBands, int dstWidth, int dstHeight, 246 int src1LineStride, int src1PixelStride, 247 int[] src1BandOffsets, int[][] src1Data, 248 int src2LineStride, int src2PixelStride, 249 int[] src2BandOffsets, int[][] src2Data, 250 int dstLineStride, int dstPixelStride, 251 int[] dstBandOffsets, int[][] dstData) { 252 253 for (int b = 0; b < dstNumBands; b++) { 254 int[] s1 = src1Data[b]; 255 int[] s2 = src2Data[b]; 256 int[] d = dstData[b]; 257 int src1LineOffset = src1BandOffsets[b]; 258 int src2LineOffset = src2BandOffsets[b]; 259 int dstLineOffset = dstBandOffsets[b]; 260 261 for (int h = 0; h < dstHeight; h++) { 262 int src1PixelOffset = src1LineOffset; 263 int src2PixelOffset = src2LineOffset; 264 int dstPixelOffset = dstLineOffset; 265 src1LineOffset += src1LineStride; 266 src2LineOffset += src2LineStride; 267 dstLineOffset += dstLineStride; 268 269 for (int w = 0; w < dstWidth; w++) { 270 d[dstPixelOffset] = s1[src1PixelOffset] & s2[src2PixelOffset]; 271 272 src1PixelOffset += src1PixelStride; 273 src2PixelOffset += src2PixelStride; 274 dstPixelOffset += dstPixelStride; 275 } 276 } 277 } 278 } 279 280 // public static void main(String args[]) { 281 // System.out.println("AndOpImage Test"); 282 // ImageLayout layout; 283 // OpImage src1, src2, dst; 284 // Rectangle rect = new Rectangle(0, 0, 5, 5); 285 286 // System.out.println("1. PixelInterleaved byte 3-band"); 287 // layout = OpImageTester.createImageLayout( 288 // 0, 0, 800, 800, 0, 0, 200, 200, DataBuffer.TYPE_BYTE, 3, false); 289 // src1 = OpImageTester.createRandomOpImage(layout); 290 // src2 = OpImageTester.createRandomOpImage(layout); 291 // dst = new AndOpImage(src1, src2, null, null); 292 // OpImageTester.testOpImage(dst, rect); 293 // OpImageTester.timeOpImage(dst, 10); 294 295 // System.out.println("2. Banded byte 3-band"); 296 // layout = OpImageTester.createImageLayout( 297 // 0, 0, 800, 800, 0, 0, 200, 200, DataBuffer.TYPE_BYTE, 3, true); 298 // src1 = OpImageTester.createRandomOpImage(layout); 299 // src2 = OpImageTester.createRandomOpImage(layout); 300 // dst = new AndOpImage(src1, src2, null, null); 301 // OpImageTester.testOpImage(dst, rect); 302 // OpImageTester.timeOpImage(dst, 10); 303 304 // System.out.println("3. PixelInterleaved int 3-band"); 305 // layout = OpImageTester.createImageLayout( 306 // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_INT, 3, false); 307 // src1 = OpImageTester.createRandomOpImage(layout); 308 // src2 = OpImageTester.createRandomOpImage(layout); 309 // dst = new AndOpImage(src1, src2, null, null); 310 // OpImageTester.testOpImage(dst, rect); 311 // OpImageTester.timeOpImage(dst, 10); 312 313 // System.out.println("4. Banded int 3-band"); 314 // layout = OpImageTester.createImageLayout( 315 // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_INT, 3, true); 316 // src1 = OpImageTester.createRandomOpImage(layout); 317 // src2 = OpImageTester.createRandomOpImage(layout); 318 // dst = new AndOpImage(src1, src2, null, null); 319 // OpImageTester.testOpImage(dst, rect); 320 // OpImageTester.timeOpImage(dst, 10); 321 // } 322 } 323