001: /*
002: * $RCSfile: AbsoluteOpImage.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:11 $
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 "Absolute" operation as
031: * described in <code>javax.media.jai.operator.AbsoluteDescriptor</code>.
032: *
033: * <p>This <code>OpImage</code> takes the absolute value of the pixel
034: * values of an image. The operation is done on a per-band basis.
035: * For an integral number, its absolute value is taken as x = (~x) +1,
036: * where ~x is the 1's complement of that number.
037: * If the number is the maximum negative of its type, then it will remain
038: * the same value.
039: *
040: * @since EA2
041: * @see javax.media.jai.operator.AbsoluteDescriptor
042: * @see AbsoluteCRIF
043: *
044: */
045: final class AbsoluteOpImage extends PointOpImage {
046:
047: /**
048: * Constructs an <code>AbsoluteOpImage</code>.
049: *
050: * <p>The <code>layout</code> parameter may optionally contains the
051: * tile grid layout, sample model, and/or color model. The image
052: * dimension is set to the same values as that of the source image.
053: *
054: * <p>The image layout of the source image is used as the fall-back
055: * for the image layout of the destination image. Any layout parameters
056: * not specified in the <code>layout</code> argument are set to the
057: * same value as that of the source.
058: *
059: * @param source The source image.
060: * @param layout The destination image layout.
061: */
062: public AbsoluteOpImage(RenderedImage source, Map config,
063: ImageLayout layout) {
064: super (source, layout, config, true);
065:
066: // Set flag to permit in-place operation.
067: permitInPlaceOperation();
068: }
069:
070: /**
071: * Map the pixels inside a specified rectangle whose value is within a
072: * rang to a constant on a per-band basis.
073: *
074: * @param sources Cobbled sources, guaranteed to provide all the
075: * source data necessary for computing the rectangle.
076: * @param dest The tile containing the rectangle to be computed.
077: * @param destRect The rectangle within the tile to be computed.
078: */
079: protected void computeRect(Raster[] sources, WritableRaster dest,
080: Rectangle destRect) {
081: // Retrieve format tags.
082: RasterFormatTag[] formatTags = getFormatTags();
083:
084: RasterAccessor src = new RasterAccessor(sources[0], destRect,
085: formatTags[0], getSourceImage(0).getColorModel());
086: RasterAccessor dst = new RasterAccessor(dest, destRect,
087: formatTags[1], getColorModel());
088:
089: if (dst.isBinary()) {
090: byte[] dstBits = dst.getBinaryDataArray();
091: System.arraycopy(src.getBinaryDataArray(), 0, dstBits, 0,
092: dstBits.length);
093:
094: dst.copyBinaryDataToRaster();
095:
096: return;
097: }
098:
099: /* Find out what kind of data type is used to store the image */
100: switch (dst.getDataType()) {
101: case DataBuffer.TYPE_BYTE:
102: byteAbsolute(dst.getNumBands(), dst.getWidth(), dst
103: .getHeight(), src.getScanlineStride(), src
104: .getPixelStride(), src.getBandOffsets(), src
105: .getByteDataArrays(), dst.getScanlineStride(), dst
106: .getPixelStride(), dst.getBandOffsets(), dst
107: .getByteDataArrays());
108: break;
109:
110: case DataBuffer.TYPE_SHORT:
111: shortAbsolute(dst.getNumBands(), dst.getWidth(), dst
112: .getHeight(), src.getScanlineStride(), src
113: .getPixelStride(), src.getBandOffsets(), src
114: .getShortDataArrays(), dst.getScanlineStride(), dst
115: .getPixelStride(), dst.getBandOffsets(), dst
116: .getShortDataArrays());
117: break;
118:
119: case DataBuffer.TYPE_USHORT:
120: ushortAbsolute(dst.getNumBands(), dst.getWidth(), dst
121: .getHeight(), src.getScanlineStride(), src
122: .getPixelStride(), src.getBandOffsets(), src
123: .getShortDataArrays(), dst.getScanlineStride(), dst
124: .getPixelStride(), dst.getBandOffsets(), dst
125: .getShortDataArrays());
126: break;
127:
128: case DataBuffer.TYPE_INT:
129: intAbsolute(dst.getNumBands(), dst.getWidth(), dst
130: .getHeight(), src.getScanlineStride(), src
131: .getPixelStride(), src.getBandOffsets(), src
132: .getIntDataArrays(), dst.getScanlineStride(), dst
133: .getPixelStride(), dst.getBandOffsets(), dst
134: .getIntDataArrays());
135: break;
136:
137: case DataBuffer.TYPE_FLOAT:
138: floatAbsolute(dst.getNumBands(), dst.getWidth(), dst
139: .getHeight(), src.getScanlineStride(), src
140: .getPixelStride(), src.getBandOffsets(), src
141: .getFloatDataArrays(), dst.getScanlineStride(), dst
142: .getPixelStride(), dst.getBandOffsets(), dst
143: .getFloatDataArrays());
144: break;
145:
146: case DataBuffer.TYPE_DOUBLE:
147: doubleAbsolute(dst.getNumBands(), dst.getWidth(), dst
148: .getHeight(), src.getScanlineStride(), src
149: .getPixelStride(), src.getBandOffsets(), src
150: .getDoubleDataArrays(), dst.getScanlineStride(),
151: dst.getPixelStride(), dst.getBandOffsets(), dst
152: .getDoubleDataArrays());
153: break;
154: }
155: if (dst.needsClamping()) {
156: dst.clampDataArrays();
157: }
158: dst.copyDataToRaster();
159: }
160:
161: private void byteAbsolute(int numBands, int dstWidth,
162: int dstHeight, int srcScanlineStride, int srcPixelStride,
163: int[] srcBandOffsets, byte[][] srcData,
164: int dstScanlineStride, int dstPixelStride,
165: int[] dstBandOffsets, byte[][] dstData) {
166: for (int band = 0; band < numBands; band++) {
167: byte[] src = srcData[band];
168: byte[] dst = dstData[band];
169: int pixelValue;
170: int srcLineOffset = srcBandOffsets[band];
171: int dstLineOffset = dstBandOffsets[band];
172:
173: for (int h = 0; h < dstHeight; h++) {
174: int srcPixelOffset = srcLineOffset;
175: int dstPixelOffset = dstLineOffset;
176:
177: for (int w = 0; w < dstWidth; w++) {
178: // For byte data, this is a straight copy.
179: dst[dstPixelOffset] = src[srcPixelOffset];
180: srcPixelOffset += srcPixelStride;
181: dstPixelOffset += dstPixelStride;
182: }
183:
184: srcLineOffset += srcScanlineStride;
185: dstLineOffset += dstScanlineStride;
186: }
187: }
188: }
189:
190: private void shortAbsolute(int numBands, int dstWidth,
191: int dstHeight, int srcScanlineStride, int srcPixelStride,
192: int[] srcBandOffsets, short[][] srcData,
193: int dstScanlineStride, int dstPixelStride,
194: int[] dstBandOffsets, short[][] dstData) {
195: for (int band = 0; band < numBands; band++) {
196: short[] src = srcData[band];
197: short[] dst = dstData[band];
198: short pixelValue;
199: int srcLineOffset = srcBandOffsets[band];
200: int dstLineOffset = dstBandOffsets[band];
201:
202: for (int h = 0; h < dstHeight; h++) {
203: int srcPixelOffset = srcLineOffset;
204: int dstPixelOffset = dstLineOffset;
205:
206: for (int w = 0; w < dstWidth; w++) {
207: pixelValue = src[srcPixelOffset];
208:
209: if ((pixelValue != Short.MIN_VALUE)
210: && (pixelValue & Short.MIN_VALUE) != 0) {
211: // It is not 0x8000 and its sign bit is set.
212: dst[dstPixelOffset] = (short) -src[srcPixelOffset];
213: } else {
214: // It is either the minimum of short, i.e. 0x8000,
215: // or a positive number;
216: dst[dstPixelOffset] = src[srcPixelOffset];
217: }
218:
219: srcPixelOffset += srcPixelStride;
220: dstPixelOffset += dstPixelStride;
221: }
222:
223: srcLineOffset += srcScanlineStride;
224: dstLineOffset += dstScanlineStride;
225: }
226: }
227: }
228:
229: private void ushortAbsolute(int numBands, int dstWidth,
230: int dstHeight, int srcScanlineStride, int srcPixelStride,
231: int[] srcBandOffsets, short[][] srcData,
232: int dstScanlineStride, int dstPixelStride,
233: int[] dstBandOffsets, short[][] dstData) {
234: for (int band = 0; band < numBands; band++) {
235: short[] src = srcData[band];
236: short[] dst = dstData[band];
237: int srcLineOffset = srcBandOffsets[band];
238: int dstLineOffset = dstBandOffsets[band];
239:
240: for (int h = 0; h < dstHeight; h++) {
241: int srcPixelOffset = srcLineOffset;
242: int dstPixelOffset = dstLineOffset;
243:
244: for (int w = 0; w < dstWidth; w++) {
245: // For unsigned short data, this is a straight copy.
246: dst[dstPixelOffset] = src[srcPixelOffset];
247: srcPixelOffset += srcPixelStride;
248: dstPixelOffset += dstPixelStride;
249: }
250:
251: srcLineOffset += srcScanlineStride;
252: dstLineOffset += dstScanlineStride;
253: }
254: }
255: }
256:
257: private void intAbsolute(int numBands, int dstWidth, int dstHeight,
258: int srcScanlineStride, int srcPixelStride,
259: int[] srcBandOffsets, int[][] srcData,
260: int dstScanlineStride, int dstPixelStride,
261: int[] dstBandOffsets, int[][] dstData) {
262: for (int band = 0; band < numBands; band++) {
263: int[] src = srcData[band];
264: int[] dst = dstData[band];
265: int pixelValue;
266: int srcLineOffset = srcBandOffsets[band];
267: int dstLineOffset = dstBandOffsets[band];
268:
269: for (int h = 0; h < dstHeight; h++) {
270: int srcPixelOffset = srcLineOffset;
271: int dstPixelOffset = dstLineOffset;
272:
273: for (int w = 0; w < dstWidth; w++) {
274: pixelValue = src[srcPixelOffset];
275:
276: if ((pixelValue != Integer.MIN_VALUE)
277: && (pixelValue & Integer.MIN_VALUE) != 0) {
278: // It is not 0x80000000 and its sign bit is set.
279: dst[dstPixelOffset] = -src[srcPixelOffset];
280: } else {
281: // It is either the minimum of int, i.e. 0x80000000,
282: // or a positive number;
283: dst[dstPixelOffset] = src[srcPixelOffset];
284: }
285:
286: srcPixelOffset += srcPixelStride;
287: dstPixelOffset += dstPixelStride;
288: }
289:
290: srcLineOffset += srcScanlineStride;
291: dstLineOffset += dstScanlineStride;
292: }
293: }
294: }
295:
296: private void floatAbsolute(int numBands, int dstWidth,
297: int dstHeight, int srcScanlineStride, int srcPixelStride,
298: int[] srcBandOffsets, float[][] srcData,
299: int dstScanlineStride, int dstPixelStride,
300: int[] dstBandOffsets, float[][] dstData) {
301: for (int band = 0; band < numBands; band++) {
302: float[] src = srcData[band];
303: float[] dst = dstData[band];
304: int srcLineOffset = srcBandOffsets[band];
305: int dstLineOffset = dstBandOffsets[band];
306:
307: for (int h = 0; h < dstHeight; h++) {
308: int srcPixelOffset = srcLineOffset;
309: int dstPixelOffset = dstLineOffset;
310:
311: // as per Math.abs()
312: for (int w = 0; w < dstWidth; w++) {
313: if (src[srcPixelOffset] <= 0.0F) {
314: dst[dstPixelOffset] = 0.0F - src[srcPixelOffset];
315: } else {
316: dst[dstPixelOffset] = src[srcPixelOffset];
317: }
318:
319: srcPixelOffset += srcPixelStride;
320: dstPixelOffset += dstPixelStride;
321: }
322:
323: srcLineOffset += srcScanlineStride;
324: dstLineOffset += dstScanlineStride;
325: }
326: }
327: }
328:
329: private void doubleAbsolute(int numBands, int dstWidth,
330: int dstHeight, int srcScanlineStride, int srcPixelStride,
331: int[] srcBandOffsets, double[][] srcData,
332: int dstScanlineStride, int dstPixelStride,
333: int[] dstBandOffsets, double[][] dstData) {
334: for (int band = 0; band < numBands; band++) {
335: double[] src = srcData[band];
336: double[] dst = dstData[band];
337: int srcLineOffset = srcBandOffsets[band];
338: int dstLineOffset = dstBandOffsets[band];
339:
340: for (int h = 0; h < dstHeight; h++) {
341: int srcPixelOffset = srcLineOffset;
342: int dstPixelOffset = dstLineOffset;
343:
344: // as per Math.abs()
345: for (int w = 0; w < dstWidth; w++) {
346: if (src[srcPixelOffset] <= 0.0D) {
347: dst[dstPixelOffset] = 0.0D - src[srcPixelOffset];
348: } else {
349: dst[dstPixelOffset] = src[srcPixelOffset];
350: }
351:
352: srcPixelOffset += srcPixelStride;
353: dstPixelOffset += dstPixelStride;
354: }
355:
356: srcLineOffset += srcScanlineStride;
357: dstLineOffset += dstScanlineStride;
358: }
359: }
360: }
361:
362: // public static void main(String args[]) {
363: // System.out.println( "AbsoluteOpImage Test");
364: // ImageLayout layout;
365: // OpImage src, dst;
366: // Rectangle rect = new Rectangle(0, 0, 5, 5);
367:
368: // System.out.println("1. PixelInterleaved byte 3-band");
369: // layout = OpImageTester.createImageLayout(0, 0, 800, 800, 0, 0, 200, 200,
370: // DataBuffer.TYPE_BYTE, 3, false);
371: // src = OpImageTester.createRandomOpImage(layout);
372: // dst = new AbsoluteOpImage(src, null, null);
373: // OpImageTester.testOpImage(dst, rect);
374: // OpImageTester.timeOpImage(dst, 10);
375:
376: // System.out.println("2. Banded byte 3-band");
377: // layout = OpImageTester.createImageLayout(0, 0, 800, 800, 0, 0, 200, 200,
378: // DataBuffer.TYPE_BYTE, 3, true);
379: // src = OpImageTester.createRandomOpImage(layout);
380: // dst = new AbsoluteOpImage(src, null, null);
381: // OpImageTester.testOpImage(dst, rect);
382: // OpImageTester.timeOpImage(dst, 10);
383:
384: // System.out.println("3. PixelInterleaved int 3-band");
385: // layout = OpImageTester.createImageLayout(0, 0, 512, 512, 0, 0, 200, 200,
386: // DataBuffer.TYPE_INT, 3, false);
387: // src = OpImageTester.createRandomOpImage(layout);
388: // dst = new AbsoluteOpImage(src, null, null);
389: // OpImageTester.testOpImage(dst, rect);
390: // OpImageTester.timeOpImage(dst, 10);
391:
392: // System.out.println("4. Banded int 3-band");
393: // layout = OpImageTester.createImageLayout(0, 0, 512, 512, 0, 0, 200, 200,
394: // DataBuffer.TYPE_INT, 3, true);
395: // src = OpImageTester.createRandomOpImage(layout);
396: // dst = new AbsoluteOpImage(src, null, null);
397: // OpImageTester.testOpImage(dst, rect);
398: // OpImageTester.timeOpImage(dst, 10);
399:
400: // System.out.println("5. PixelInterleaved float 3-band");
401: // layout = OpImageTester.createImageLayout(0, 0, 512, 512, 0, 0, 200, 200,
402: // DataBuffer.TYPE_FLOAT, 3, false);
403: // src = OpImageTester.createRandomOpImage(layout);
404: // dst = new AbsoluteOpImage(src, null, null);
405: // OpImageTester.testOpImage(dst, rect);
406: // OpImageTester.timeOpImage(dst, 10);
407:
408: // System.out.println("6. Banded float 3-band");
409: // layout = OpImageTester.createImageLayout(0, 0, 512, 512, 0, 0, 200, 200,
410: // DataBuffer.TYPE_FLOAT, 3, true);
411: // src = OpImageTester.createRandomOpImage(layout);
412: // dst = new AbsoluteOpImage(src, null, null);
413: // OpImageTester.testOpImage(dst, rect);
414: // OpImageTester.timeOpImage(dst, 10);
415:
416: // System.out.println("7. PixelInterleaved double 3-band");
417: // layout = OpImageTester.createImageLayout(0, 0, 512, 512, 0, 0, 200, 200,
418: // DataBuffer.TYPE_DOUBLE, 3, false);
419: // src = OpImageTester.createRandomOpImage(layout);
420: // dst = new AbsoluteOpImage(src, null, null);
421: // OpImageTester.testOpImage(dst, rect);
422: // OpImageTester.timeOpImage(dst, 10);
423:
424: // System.out.println("8. Banded double 3-band");
425: // layout = OpImageTester.createImageLayout(0, 0, 512, 512, 0, 0, 200, 200,
426: // DataBuffer.TYPE_DOUBLE, 3, true);
427: // src = OpImageTester.createRandomOpImage(layout);
428: // dst = new AbsoluteOpImage(src, null, null);
429: // OpImageTester.testOpImage(dst, rect);
430: // OpImageTester.timeOpImage(dst, 10);
431: // }
432: }
|