001: /*
002: * $RCSfile: OrOpImage.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:38 $
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 "Or" operation as
031: * described in <code>javax.media.jai.operator.OrDescriptor</code>.
032: *
033: * <p>This <code>OpImage</code> logically "ors" 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.OrDescriptor
054: * @see OrCRIF
055: *
056: */
057: final class OrOpImage extends PointOpImage {
058:
059: /**
060: * Constructs an <code>OrOpImage</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 OrOpImage(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: * Ors 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], getSource(0).getColorModel());
101: RasterAccessor s2 = new RasterAccessor(sources[1], destRect,
102: formatTags[1], getSource(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: int src1LineStride = s1.getScanlineStride();
121: int src1PixelStride = s1.getPixelStride();
122: int[] src1BandOffsets = s1.getBandOffsets();
123:
124: int src2LineStride = s2.getScanlineStride();
125: int src2PixelStride = s2.getPixelStride();
126: int[] src2BandOffsets = s2.getBandOffsets();
127:
128: int dstNumBands = d.getNumBands();
129: int dstWidth = d.getWidth();
130: int dstHeight = d.getHeight();
131: int dstLineStride = d.getScanlineStride();
132: int dstPixelStride = d.getPixelStride();
133: int[] dstBandOffsets = d.getBandOffsets();
134:
135: switch (d.getDataType()) {
136:
137: case DataBuffer.TYPE_BYTE:
138: byteLoop(dstNumBands, dstWidth, dstHeight, src1LineStride,
139: src1PixelStride, src1BandOffsets, s1
140: .getByteDataArrays(), src2LineStride,
141: src2PixelStride, src2BandOffsets, s2
142: .getByteDataArrays(), dstLineStride,
143: dstPixelStride, dstBandOffsets, d
144: .getByteDataArrays());
145: break;
146:
147: case DataBuffer.TYPE_USHORT:
148: case DataBuffer.TYPE_SHORT:
149: shortLoop(dstNumBands, dstWidth, dstHeight, src1LineStride,
150: src1PixelStride, src1BandOffsets, s1
151: .getShortDataArrays(), src2LineStride,
152: src2PixelStride, src2BandOffsets, s2
153: .getShortDataArrays(), dstLineStride,
154: dstPixelStride, dstBandOffsets, d
155: .getShortDataArrays());
156: break;
157:
158: case DataBuffer.TYPE_INT:
159: intLoop(dstNumBands, dstWidth, dstHeight, src1LineStride,
160: src1PixelStride, src1BandOffsets, s1
161: .getIntDataArrays(), src2LineStride,
162: src2PixelStride, src2BandOffsets, s2
163: .getIntDataArrays(), dstLineStride,
164: dstPixelStride, dstBandOffsets, d
165: .getIntDataArrays());
166: break;
167: }
168:
169: d.copyDataToRaster();
170: }
171:
172: private void byteLoop(int dstNumBands, int dstWidth, int dstHeight,
173: int src1LineStride, int src1PixelStride,
174: int[] src1BandOffsets, byte[][] src1Data,
175: int src2LineStride, int src2PixelStride,
176: int[] src2BandOffsets, byte[][] src2Data,
177: int dstLineStride, int dstPixelStride,
178: int[] dstBandOffsets, byte[][] dstData) {
179:
180: for (int b = 0; b < dstNumBands; b++) {
181: byte[] s1 = src1Data[b];
182: byte[] s2 = src2Data[b];
183: byte[] d = dstData[b];
184: int src1LineOffset = src1BandOffsets[b];
185: int src2LineOffset = src2BandOffsets[b];
186: int dstLineOffset = dstBandOffsets[b];
187:
188: for (int h = 0; h < dstHeight; h++) {
189: int src1PixelOffset = src1LineOffset;
190: int src2PixelOffset = src2LineOffset;
191: int dstPixelOffset = dstLineOffset;
192: src1LineOffset += src1LineStride;
193: src2LineOffset += src2LineStride;
194: dstLineOffset += dstLineStride;
195:
196: for (int w = 0; w < dstWidth; w++) {
197: d[dstPixelOffset] = (byte) (s1[src1PixelOffset] | s2[src2PixelOffset]);
198: src1PixelOffset += src1PixelStride;
199: src2PixelOffset += src2PixelStride;
200: dstPixelOffset += dstPixelStride;
201: }
202: }
203: }
204: }
205:
206: private void shortLoop(int dstNumBands, int dstWidth,
207: int dstHeight, int src1LineStride, int src1PixelStride,
208: int[] src1BandOffsets, short[][] src1Data,
209: int src2LineStride, int src2PixelStride,
210: int[] src2BandOffsets, short[][] src2Data,
211: int dstLineStride, int dstPixelStride,
212: int[] dstBandOffsets, short[][] dstData) {
213:
214: for (int b = 0; b < dstNumBands; b++) {
215: short[] s1 = src1Data[b];
216: short[] s2 = src2Data[b];
217: short[] d = dstData[b];
218: int src1LineOffset = src1BandOffsets[b];
219: int src2LineOffset = src2BandOffsets[b];
220: int dstLineOffset = dstBandOffsets[b];
221:
222: for (int h = 0; h < dstHeight; h++) {
223: int src1PixelOffset = src1LineOffset;
224: int src2PixelOffset = src2LineOffset;
225: int dstPixelOffset = dstLineOffset;
226: src1LineOffset += src1LineStride;
227: src2LineOffset += src2LineStride;
228: dstLineOffset += dstLineStride;
229:
230: for (int w = 0; w < dstWidth; w++) {
231: d[dstPixelOffset] = (short) (s1[src1PixelOffset] | s2[src2PixelOffset]);
232:
233: src1PixelOffset += src1PixelStride;
234: src2PixelOffset += src2PixelStride;
235: dstPixelOffset += dstPixelStride;
236: }
237: }
238: }
239: }
240:
241: private void intLoop(int dstNumBands, int dstWidth, int dstHeight,
242: int src1LineStride, int src1PixelStride,
243: int[] src1BandOffsets, int[][] src1Data,
244: int src2LineStride, int src2PixelStride,
245: int[] src2BandOffsets, int[][] src2Data, int dstLineStride,
246: int dstPixelStride, int[] dstBandOffsets, int[][] dstData) {
247:
248: for (int b = 0; b < dstNumBands; b++) {
249: int[] s1 = src1Data[b];
250: int[] s2 = src2Data[b];
251: int[] d = dstData[b];
252: int src1LineOffset = src1BandOffsets[b];
253: int src2LineOffset = src2BandOffsets[b];
254: int dstLineOffset = dstBandOffsets[b];
255:
256: for (int h = 0; h < dstHeight; h++) {
257: int src1PixelOffset = src1LineOffset;
258: int src2PixelOffset = src2LineOffset;
259: int dstPixelOffset = dstLineOffset;
260: src1LineOffset += src1LineStride;
261: src2LineOffset += src2LineStride;
262: dstLineOffset += dstLineStride;
263:
264: for (int w = 0; w < dstWidth; w++) {
265: d[dstPixelOffset] = s1[src1PixelOffset]
266: | s2[src2PixelOffset];
267:
268: src1PixelOffset += src1PixelStride;
269: src2PixelOffset += src2PixelStride;
270: dstPixelOffset += dstPixelStride;
271: }
272: }
273: }
274: }
275:
276: // public static void main(String args[]) {
277: // System.out.println("OrOpImage Test");
278: // ImageLayout layout;
279: // OpImage src1, src2, dst;
280: // Rectangle rect = new Rectangle(0, 0, 5, 5);
281:
282: // System.out.println("1. PixelInterleaved byte 3-band");
283: // layout = OpImageTester.createImageLayout(
284: // 0, 0, 800, 800, 0, 0, 200, 200, DataBuffer.TYPE_BYTE, 3, false);
285: // src1 = OpImageTester.createRandomOpImage(layout);
286: // src2 = OpImageTester.createRandomOpImage(layout);
287: // dst = new OrOpImage(src1, src2, null, null);
288: // OpImageTester.testOpImage(dst, rect);
289: // OpImageTester.timeOpImage(dst, 10);
290:
291: // System.out.println("2. Banded byte 3-band");
292: // layout = OpImageTester.createImageLayout(
293: // 0, 0, 800, 800, 0, 0, 200, 200, DataBuffer.TYPE_BYTE, 3, true);
294: // src1 = OpImageTester.createRandomOpImage(layout);
295: // src2 = OpImageTester.createRandomOpImage(layout);
296: // dst = new OrOpImage(src1, src2, null, null);
297: // OpImageTester.testOpImage(dst, rect);
298: // OpImageTester.timeOpImage(dst, 10);
299:
300: // System.out.println("3. PixelInterleaved int 3-band");
301: // layout = OpImageTester.createImageLayout(
302: // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_INT, 3, false);
303: // src1 = OpImageTester.createRandomOpImage(layout);
304: // src2 = OpImageTester.createRandomOpImage(layout);
305: // dst = new OrOpImage(src1, src2, null, null);
306: // OpImageTester.testOpImage(dst, rect);
307: // OpImageTester.timeOpImage(dst, 10);
308:
309: // System.out.println("4. Banded int 3-band");
310: // layout = OpImageTester.createImageLayout(
311: // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_INT, 3, true);
312: // src1 = OpImageTester.createRandomOpImage(layout);
313: // src2 = OpImageTester.createRandomOpImage(layout);
314: // dst = new OrOpImage(src1, src2, null, null);
315: // OpImageTester.testOpImage(dst, rect);
316: // OpImageTester.timeOpImage(dst, 10);
317: // }
318: }
|