001: /*
002: * $RCSfile: AndOpImage.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:56:14 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import java.awt.Rectangle;
015: import java.awt.image.DataBuffer;
016: import java.awt.image.Raster;
017: import java.awt.image.RenderedImage;
018: import java.awt.image.SampleModel;
019: import java.awt.image.WritableRaster;
020: import javax.media.jai.ImageLayout;
021: import javax.media.jai.OpImage;
022: import javax.media.jai.PointOpImage;
023: import javax.media.jai.RasterAccessor;
024: import javax.media.jai.RasterFormatTag;
025: import java.util.Map;
026:
027: // import com.sun.media.jai.test.OpImageTester;
028:
029: /**
030: * An <code>OpImage</code> implementing the "And" operation as
031: * described in <code>javax.media.jai.operator.AndDescriptor</code>.
032: *
033: * <p>This <code>OpImage</code> logically "ands" the pixel values of two source
034: * images on a per-band basis. In case the two source images have different
035: * number of bands, the number of bands for the destination image is the
036: * smaller band number of the two source images. That is
037: * <code>dstNumBands = Math.min(src1NumBands, src2NumBands)</code>.
038: * In case the two source images have different data types, the data type
039: * for the destination image is the bigger data type of the two source
040: * images.
041: *
042: * <p>The value of the pixel (x, y) in the destination image is defined as:
043: * <pre>
044: * for (b = 0; b < numBands; b++) {
045: * dst[y][x][b] = src1[y][x][b] & src2[y][x][b];
046: * }
047: * </pre>
048: *
049: * The data type <code>byte</code> is treated as unsigned, with maximum
050: * value as 255 and minimum value as 0.
051: *
052: * @since EA2
053: * @see javax.media.jai.operator.AndDescriptor
054: * @see AndCRIF
055: *
056: */
057: final class AndOpImage extends PointOpImage {
058:
059: /**
060: * Constructs an <code>AndOpImage</code>.
061: *
062: * <p>The <code>layout</code> parameter may optionally contains the
063: * tile grid layout, sample model, and/or color model. The image
064: * dimension is determined by the intersection of the bounding boxes
065: * of the two source images.
066: *
067: * <p>The image layout of the first source image, <code>source1</code>,
068: * is used as the fall-back for the image layout of the destination
069: * image. Any layout parameters not specified in the <code>layout</code>
070: * argument are set to the same value as that of <code>source1</code>.
071: *
072: * @param source1 The first source image.
073: * @param source2 The second source image.
074: * @param layout The destination image layout.
075: */
076: public AndOpImage(RenderedImage source1, RenderedImage source2,
077: Map config, ImageLayout layout) {
078: super (source1, source2, layout, config, true);
079:
080: // Set flag to permit in-place operation.
081: permitInPlaceOperation();
082: }
083:
084: /**
085: * Multiplies the pixel values of two source images within a specified
086: * rectangle.
087: *
088: * @param sources Cobbled sources, guaranteed to provide all the
089: * source data necessary for computing the rectangle.
090: * @param dest The tile containing the rectangle to be computed.
091: * @param destRect The rectangle within the tile to be computed.
092: */
093: protected void computeRect(Raster[] sources, WritableRaster dest,
094: Rectangle destRect) {
095: // Retrieve format tags.
096: RasterFormatTag[] formatTags = getFormatTags();
097:
098: /* For PointOpImage, srcRect = destRect. */
099: RasterAccessor s1 = new RasterAccessor(sources[0], destRect,
100: formatTags[0], getSourceImage(0).getColorModel());
101: RasterAccessor s2 = new RasterAccessor(sources[1], destRect,
102: formatTags[1], getSourceImage(1).getColorModel());
103: RasterAccessor d = new RasterAccessor(dest, destRect,
104: formatTags[2], getColorModel());
105:
106: if (d.isBinary()) {
107: byte[] src1Bits = s1.getBinaryDataArray();
108: byte[] src2Bits = s2.getBinaryDataArray();
109: byte[] dstBits = d.getBinaryDataArray();
110:
111: int length = dstBits.length;
112: for (int i = 0; i < length; i++) {
113: dstBits[i] = (byte) (src1Bits[i] & src2Bits[i]);
114: }
115:
116: d.copyBinaryDataToRaster();
117:
118: return;
119: }
120:
121: int src1LineStride = s1.getScanlineStride();
122: int src1PixelStride = s1.getPixelStride();
123: int[] src1BandOffsets = s1.getBandOffsets();
124:
125: int src2LineStride = s2.getScanlineStride();
126: int src2PixelStride = s2.getPixelStride();
127: int[] src2BandOffsets = s2.getBandOffsets();
128:
129: int dstNumBands = d.getNumBands();
130: int dstWidth = d.getWidth();
131: int dstHeight = d.getHeight();
132: int dstLineStride = d.getScanlineStride();
133: int dstPixelStride = d.getPixelStride();
134: int[] dstBandOffsets = d.getBandOffsets();
135:
136: switch (d.getDataType()) {
137:
138: case DataBuffer.TYPE_BYTE:
139: byteLoop(dstNumBands, dstWidth, dstHeight, src1LineStride,
140: src1PixelStride, src1BandOffsets, s1
141: .getByteDataArrays(), src2LineStride,
142: src2PixelStride, src2BandOffsets, s2
143: .getByteDataArrays(), dstLineStride,
144: dstPixelStride, dstBandOffsets, d
145: .getByteDataArrays());
146: break;
147:
148: case DataBuffer.TYPE_USHORT:
149: case DataBuffer.TYPE_SHORT:
150: shortLoop(dstNumBands, dstWidth, dstHeight, src1LineStride,
151: src1PixelStride, src1BandOffsets, s1
152: .getShortDataArrays(), src2LineStride,
153: src2PixelStride, src2BandOffsets, s2
154: .getShortDataArrays(), dstLineStride,
155: dstPixelStride, dstBandOffsets, d
156: .getShortDataArrays());
157: break;
158:
159: case DataBuffer.TYPE_INT:
160: intLoop(dstNumBands, dstWidth, dstHeight, src1LineStride,
161: src1PixelStride, src1BandOffsets, s1
162: .getIntDataArrays(), src2LineStride,
163: src2PixelStride, src2BandOffsets, s2
164: .getIntDataArrays(), dstLineStride,
165: dstPixelStride, dstBandOffsets, d
166: .getIntDataArrays());
167: break;
168: }
169:
170: d.copyDataToRaster();
171: }
172:
173: private void byteLoop(int dstNumBands, int dstWidth, int dstHeight,
174: int src1LineStride, int src1PixelStride,
175: int[] src1BandOffsets, byte[][] src1Data,
176: int src2LineStride, int src2PixelStride,
177: int[] src2BandOffsets, byte[][] src2Data,
178: int dstLineStride, int dstPixelStride,
179: int[] dstBandOffsets, byte[][] dstData) {
180:
181: for (int b = 0; b < dstNumBands; b++) {
182: byte[] s1 = src1Data[b];
183: byte[] s2 = src2Data[b];
184: byte[] d = dstData[b];
185: int src1LineOffset = src1BandOffsets[b];
186: int src2LineOffset = src2BandOffsets[b];
187: int dstLineOffset = dstBandOffsets[b];
188:
189: for (int h = 0; h < dstHeight; h++) {
190: int src1PixelOffset = src1LineOffset;
191: int src2PixelOffset = src2LineOffset;
192: int dstPixelOffset = dstLineOffset;
193: src1LineOffset += src1LineStride;
194: src2LineOffset += src2LineStride;
195: dstLineOffset += dstLineStride;
196:
197: for (int w = 0; w < dstWidth; w++) {
198: d[dstPixelOffset] = (byte) (s1[src1PixelOffset] & s2[src2PixelOffset]);
199: src1PixelOffset += src1PixelStride;
200: src2PixelOffset += src2PixelStride;
201: dstPixelOffset += dstPixelStride;
202: }
203: }
204: }
205: }
206:
207: private void shortLoop(int dstNumBands, int dstWidth,
208: int dstHeight, int src1LineStride, int src1PixelStride,
209: int[] src1BandOffsets, short[][] src1Data,
210: int src2LineStride, int src2PixelStride,
211: int[] src2BandOffsets, short[][] src2Data,
212: int dstLineStride, int dstPixelStride,
213: int[] dstBandOffsets, short[][] dstData) {
214:
215: for (int b = 0; b < dstNumBands; b++) {
216: short[] s1 = src1Data[b];
217: short[] s2 = src2Data[b];
218: short[] d = dstData[b];
219: int src1LineOffset = src1BandOffsets[b];
220: int src2LineOffset = src2BandOffsets[b];
221: int dstLineOffset = dstBandOffsets[b];
222:
223: for (int h = 0; h < dstHeight; h++) {
224: int src1PixelOffset = src1LineOffset;
225: int src2PixelOffset = src2LineOffset;
226: int dstPixelOffset = dstLineOffset;
227: src1LineOffset += src1LineStride;
228: src2LineOffset += src2LineStride;
229: dstLineOffset += dstLineStride;
230:
231: for (int w = 0; w < dstWidth; w++) {
232: d[dstPixelOffset] = (short) (s1[src1PixelOffset] & s2[src2PixelOffset]);
233:
234: src1PixelOffset += src1PixelStride;
235: src2PixelOffset += src2PixelStride;
236: dstPixelOffset += dstPixelStride;
237: }
238: }
239: }
240: }
241:
242: private void intLoop(int dstNumBands, int dstWidth, int dstHeight,
243: int src1LineStride, int src1PixelStride,
244: int[] src1BandOffsets, int[][] src1Data,
245: int src2LineStride, int src2PixelStride,
246: int[] src2BandOffsets, int[][] src2Data, int dstLineStride,
247: int dstPixelStride, int[] dstBandOffsets, int[][] dstData) {
248:
249: for (int b = 0; b < dstNumBands; b++) {
250: int[] s1 = src1Data[b];
251: int[] s2 = src2Data[b];
252: int[] d = dstData[b];
253: int src1LineOffset = src1BandOffsets[b];
254: int src2LineOffset = src2BandOffsets[b];
255: int dstLineOffset = dstBandOffsets[b];
256:
257: for (int h = 0; h < dstHeight; h++) {
258: int src1PixelOffset = src1LineOffset;
259: int src2PixelOffset = src2LineOffset;
260: int dstPixelOffset = dstLineOffset;
261: src1LineOffset += src1LineStride;
262: src2LineOffset += src2LineStride;
263: dstLineOffset += dstLineStride;
264:
265: for (int w = 0; w < dstWidth; w++) {
266: d[dstPixelOffset] = s1[src1PixelOffset]
267: & s2[src2PixelOffset];
268:
269: src1PixelOffset += src1PixelStride;
270: src2PixelOffset += src2PixelStride;
271: dstPixelOffset += dstPixelStride;
272: }
273: }
274: }
275: }
276:
277: // public static void main(String args[]) {
278: // System.out.println("AndOpImage Test");
279: // ImageLayout layout;
280: // OpImage src1, src2, dst;
281: // Rectangle rect = new Rectangle(0, 0, 5, 5);
282:
283: // System.out.println("1. PixelInterleaved byte 3-band");
284: // layout = OpImageTester.createImageLayout(
285: // 0, 0, 800, 800, 0, 0, 200, 200, DataBuffer.TYPE_BYTE, 3, false);
286: // src1 = OpImageTester.createRandomOpImage(layout);
287: // src2 = OpImageTester.createRandomOpImage(layout);
288: // dst = new AndOpImage(src1, src2, null, null);
289: // OpImageTester.testOpImage(dst, rect);
290: // OpImageTester.timeOpImage(dst, 10);
291:
292: // System.out.println("2. Banded byte 3-band");
293: // layout = OpImageTester.createImageLayout(
294: // 0, 0, 800, 800, 0, 0, 200, 200, DataBuffer.TYPE_BYTE, 3, true);
295: // src1 = OpImageTester.createRandomOpImage(layout);
296: // src2 = OpImageTester.createRandomOpImage(layout);
297: // dst = new AndOpImage(src1, src2, null, null);
298: // OpImageTester.testOpImage(dst, rect);
299: // OpImageTester.timeOpImage(dst, 10);
300:
301: // System.out.println("3. PixelInterleaved int 3-band");
302: // layout = OpImageTester.createImageLayout(
303: // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_INT, 3, false);
304: // src1 = OpImageTester.createRandomOpImage(layout);
305: // src2 = OpImageTester.createRandomOpImage(layout);
306: // dst = new AndOpImage(src1, src2, null, null);
307: // OpImageTester.testOpImage(dst, rect);
308: // OpImageTester.timeOpImage(dst, 10);
309:
310: // System.out.println("4. Banded int 3-band");
311: // layout = OpImageTester.createImageLayout(
312: // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_INT, 3, true);
313: // src1 = OpImageTester.createRandomOpImage(layout);
314: // src2 = OpImageTester.createRandomOpImage(layout);
315: // dst = new AndOpImage(src1, src2, null, null);
316: // OpImageTester.testOpImage(dst, rect);
317: // OpImageTester.timeOpImage(dst, 10);
318: // }
319: }
|