001: /*
002: * $RCSfile: DivideIntoConstOpImage.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:24 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import javax.media.jai.ColormapOpImage;
015: import com.sun.media.jai.util.ImageUtil;
016: import java.awt.Rectangle;
017: import java.awt.image.DataBuffer;
018: import java.awt.image.Raster;
019: import java.awt.image.RenderedImage;
020: import java.awt.image.WritableRaster;
021: import javax.media.jai.ImageLayout;
022: import javax.media.jai.RasterAccessor;
023: import javax.media.jai.RasterFormatTag;
024: import java.util.Map;
025:
026: /**
027: * An <code>OpImage</code> implementing the "DivideIntoConst" operation.
028: *
029: * <p>This <code>OpImage</code> divides the pixels of a rendered
030: * image into a set of constants, one for each band of the source image.
031: * The destination pixel values are calculated as:
032: * <pre>
033: * for (int h = 0; h < dstHeight; h++) {
034: * for (int w = 0; w < dstWidth; w++) {
035: * for (int b = 0; b < dstNumBands; b++) {
036: * if (constants.length < dstNumBands) {
037: * dst[h][w][b] = constants[0] / srcs[h][w][b];
038: * } else {
039: * dst[h][w][b] = constants[b] / srcs[h][w][b];
040: * }
041: * }
042: * }
043: * }
044: * </pre>
045: *
046: * @see javax.media.jai.operator.DivideIntoConstDescriptor
047: * @see DivideIntoConstCRIF
048: *
049: *
050: * @since EA2
051: */
052: final class DivideIntoConstOpImage extends ColormapOpImage {
053:
054: /** The constants to be subtracted from, one for each band. */
055: protected double[] constants;
056:
057: /**
058: * Constructor.
059: *
060: * @param source The source image.
061: * @param layout The destination image layout.
062: * @param constants The constants to be divided into.
063: */
064: public DivideIntoConstOpImage(RenderedImage source, Map config,
065: ImageLayout layout, double[] constants) {
066: super (source, layout, config, true);
067:
068: int numBands = getSampleModel().getNumBands();
069:
070: if (constants.length < numBands) {
071: this .constants = new double[numBands];
072: for (int i = 0; i < numBands; i++) {
073: this .constants[i] = constants[0];
074: }
075: } else {
076: this .constants = (double[]) constants.clone();
077: }
078:
079: // Set flag to permit in-place operation.
080: permitInPlaceOperation();
081:
082: // Initialize the colormap if necessary.
083: initializeColormapOperation();
084: }
085:
086: /**
087: * Transform the colormap according to the rescaling parameters.
088: */
089: protected void transformColormap(byte[][] colormap) {
090: for (int b = 0; b < 3; b++) {
091: byte[] map = colormap[b];
092: int mapSize = map.length;
093:
094: double c = b < constants.length ? constants[b]
095: : constants[0];
096:
097: for (int i = 0; i < mapSize; i++) {
098: map[i] = ImageUtil.clampRoundByte(c / (map[i] & 0xFF));
099: }
100: }
101: }
102:
103: /**
104: * Divides the pixel values within a specified rectangle into a constant.
105: *
106: * @param sources Cobbled sources, guaranteed to provide all the
107: * source data necessary for computing the rectangle.
108: * @param dest The tile containing the rectangle to be computed.
109: * @param destRect The rectangle within the tile to be computed.
110: */
111: protected void computeRect(Raster[] sources, WritableRaster dest,
112: Rectangle destRect) {
113: // Retrieve format tags.
114: RasterFormatTag[] formatTags = getFormatTags();
115:
116: Rectangle srcRect = mapDestRect(destRect, 0);
117:
118: RasterAccessor dst = new RasterAccessor(dest, destRect,
119: formatTags[1], getColorModel());
120: RasterAccessor src = new RasterAccessor(sources[0], srcRect,
121: formatTags[0], getSourceImage(0).getColorModel());
122:
123: switch (dst.getDataType()) {
124: case DataBuffer.TYPE_BYTE:
125: computeRectByte(src, dst);
126: break;
127: case DataBuffer.TYPE_USHORT:
128: computeRectUShort(src, dst);
129: break;
130: case DataBuffer.TYPE_SHORT:
131: computeRectShort(src, dst);
132: break;
133: case DataBuffer.TYPE_INT:
134: computeRectInt(src, dst);
135: break;
136: case DataBuffer.TYPE_FLOAT:
137: computeRectFloat(src, dst);
138: break;
139: case DataBuffer.TYPE_DOUBLE:
140: computeRectDouble(src, dst);
141: break;
142: }
143:
144: if (dst.needsClamping()) {
145: /* Further clamp down to underlying raster data type. */
146: dst.clampDataArrays();
147: }
148: dst.copyDataToRaster();
149: }
150:
151: private void computeRectByte(RasterAccessor src, RasterAccessor dst) {
152: int dstWidth = dst.getWidth();
153: int dstHeight = dst.getHeight();
154: int dstBands = dst.getNumBands();
155:
156: int dstLineStride = dst.getScanlineStride();
157: int dstPixelStride = dst.getPixelStride();
158: int[] dstBandOffsets = dst.getBandOffsets();
159: byte[][] dstData = dst.getByteDataArrays();
160:
161: int srcLineStride = src.getScanlineStride();
162: int srcPixelStride = src.getPixelStride();
163: int[] srcBandOffsets = src.getBandOffsets();
164: byte[][] srcData = src.getByteDataArrays();
165:
166: for (int b = 0; b < dstBands; b++) {
167: double c = constants[b];
168: byte[] d = dstData[b];
169: byte[] s = srcData[b];
170:
171: int dstLineOffset = dstBandOffsets[b];
172: int srcLineOffset = srcBandOffsets[b];
173:
174: for (int h = 0; h < dstHeight; h++) {
175: int dstPixelOffset = dstLineOffset;
176: int srcPixelOffset = srcLineOffset;
177:
178: dstLineOffset += dstLineStride;
179: srcLineOffset += srcLineStride;
180:
181: for (int w = 0; w < dstWidth; w++) {
182: double t = s[srcPixelOffset] & 0xFF;
183: d[dstPixelOffset] = ImageUtil.clampRoundByte(c / t);
184:
185: dstPixelOffset += dstPixelStride;
186: srcPixelOffset += srcPixelStride;
187: }
188: }
189: }
190: }
191:
192: private void computeRectUShort(RasterAccessor src,
193: RasterAccessor dst) {
194: int dstWidth = dst.getWidth();
195: int dstHeight = dst.getHeight();
196: int dstBands = dst.getNumBands();
197:
198: int dstLineStride = dst.getScanlineStride();
199: int dstPixelStride = dst.getPixelStride();
200: int[] dstBandOffsets = dst.getBandOffsets();
201: short[][] dstData = dst.getShortDataArrays();
202:
203: int srcLineStride = src.getScanlineStride();
204: int srcPixelStride = src.getPixelStride();
205: int[] srcBandOffsets = src.getBandOffsets();
206: short[][] srcData = src.getShortDataArrays();
207:
208: for (int b = 0; b < dstBands; b++) {
209: double c = constants[b];
210: short[] d = dstData[b];
211: short[] s = srcData[b];
212:
213: int dstLineOffset = dstBandOffsets[b];
214: int srcLineOffset = srcBandOffsets[b];
215:
216: for (int h = 0; h < dstHeight; h++) {
217: int dstPixelOffset = dstLineOffset;
218: int srcPixelOffset = srcLineOffset;
219:
220: dstLineOffset += dstLineStride;
221: srcLineOffset += srcLineStride;
222:
223: for (int w = 0; w < dstWidth; w++) {
224: double t = s[srcPixelOffset] & 0xFFFF;
225: d[dstPixelOffset] = ImageUtil.clampRoundUShort(c
226: / t);
227:
228: dstPixelOffset += dstPixelStride;
229: srcPixelOffset += srcPixelStride;
230: }
231: }
232: }
233: }
234:
235: private void computeRectShort(RasterAccessor src, RasterAccessor dst) {
236: int dstWidth = dst.getWidth();
237: int dstHeight = dst.getHeight();
238: int dstBands = dst.getNumBands();
239:
240: int dstLineStride = dst.getScanlineStride();
241: int dstPixelStride = dst.getPixelStride();
242: int[] dstBandOffsets = dst.getBandOffsets();
243: short[][] dstData = dst.getShortDataArrays();
244:
245: int srcLineStride = src.getScanlineStride();
246: int srcPixelStride = src.getPixelStride();
247: int[] srcBandOffsets = src.getBandOffsets();
248: short[][] srcData = src.getShortDataArrays();
249:
250: for (int b = 0; b < dstBands; b++) {
251: double c = constants[b];
252: short[] d = dstData[b];
253: short[] s = srcData[b];
254:
255: int dstLineOffset = dstBandOffsets[b];
256: int srcLineOffset = srcBandOffsets[b];
257:
258: for (int h = 0; h < dstHeight; h++) {
259: int dstPixelOffset = dstLineOffset;
260: int srcPixelOffset = srcLineOffset;
261:
262: dstLineOffset += dstLineStride;
263: srcLineOffset += srcLineStride;
264:
265: for (int w = 0; w < dstWidth; w++) {
266: d[dstPixelOffset] = ImageUtil.clampRoundShort(c
267: / s[srcPixelOffset]);
268:
269: dstPixelOffset += dstPixelStride;
270: srcPixelOffset += srcPixelStride;
271: }
272: }
273: }
274: }
275:
276: private void computeRectInt(RasterAccessor src, RasterAccessor dst) {
277: int dstWidth = dst.getWidth();
278: int dstHeight = dst.getHeight();
279: int dstBands = dst.getNumBands();
280:
281: int dstLineStride = dst.getScanlineStride();
282: int dstPixelStride = dst.getPixelStride();
283: int[] dstBandOffsets = dst.getBandOffsets();
284: int[][] dstData = dst.getIntDataArrays();
285:
286: int srcLineStride = src.getScanlineStride();
287: int srcPixelStride = src.getPixelStride();
288: int[] srcBandOffsets = src.getBandOffsets();
289: int[][] srcData = src.getIntDataArrays();
290:
291: for (int b = 0; b < dstBands; b++) {
292: double c = constants[b];
293: int[] d = dstData[b];
294: int[] s = srcData[b];
295:
296: int dstLineOffset = dstBandOffsets[b];
297: int srcLineOffset = srcBandOffsets[b];
298:
299: for (int h = 0; h < dstHeight; h++) {
300: int dstPixelOffset = dstLineOffset;
301: int srcPixelOffset = srcLineOffset;
302:
303: dstLineOffset += dstLineStride;
304: srcLineOffset += srcLineStride;
305:
306: for (int w = 0; w < dstWidth; w++) {
307: d[dstPixelOffset] = ImageUtil.clampRoundInt(c
308: / s[srcPixelOffset]);
309:
310: dstPixelOffset += dstPixelStride;
311: srcPixelOffset += srcPixelStride;
312: }
313: }
314: }
315: }
316:
317: private void computeRectFloat(RasterAccessor src, RasterAccessor dst) {
318: int dstWidth = dst.getWidth();
319: int dstHeight = dst.getHeight();
320: int dstBands = dst.getNumBands();
321:
322: int dstLineStride = dst.getScanlineStride();
323: int dstPixelStride = dst.getPixelStride();
324: int[] dstBandOffsets = dst.getBandOffsets();
325: float[][] dstData = dst.getFloatDataArrays();
326:
327: int srcLineStride = src.getScanlineStride();
328: int srcPixelStride = src.getPixelStride();
329: int[] srcBandOffsets = src.getBandOffsets();
330: float[][] srcData = src.getFloatDataArrays();
331:
332: for (int b = 0; b < dstBands; b++) {
333: double c = constants[b];
334: float[] d = dstData[b];
335: float[] s = srcData[b];
336:
337: int dstLineOffset = dstBandOffsets[b];
338: int srcLineOffset = srcBandOffsets[b];
339:
340: for (int h = 0; h < dstHeight; h++) {
341: int dstPixelOffset = dstLineOffset;
342: int srcPixelOffset = srcLineOffset;
343:
344: dstLineOffset += dstLineStride;
345: srcLineOffset += srcLineStride;
346:
347: for (int w = 0; w < dstWidth; w++) {
348: d[dstPixelOffset] = ImageUtil.clampFloat(c
349: / s[srcPixelOffset]);
350:
351: dstPixelOffset += dstPixelStride;
352: srcPixelOffset += srcPixelStride;
353: }
354: }
355: }
356: }
357:
358: private void computeRectDouble(RasterAccessor src,
359: RasterAccessor dst) {
360: int dstWidth = dst.getWidth();
361: int dstHeight = dst.getHeight();
362: int dstBands = dst.getNumBands();
363:
364: int dstLineStride = dst.getScanlineStride();
365: int dstPixelStride = dst.getPixelStride();
366: int[] dstBandOffsets = dst.getBandOffsets();
367: double[][] dstData = dst.getDoubleDataArrays();
368:
369: int srcLineStride = src.getScanlineStride();
370: int srcPixelStride = src.getPixelStride();
371: int[] srcBandOffsets = src.getBandOffsets();
372: double[][] srcData = src.getDoubleDataArrays();
373:
374: for (int b = 0; b < dstBands; b++) {
375: double c = constants[b];
376: double[] d = dstData[b];
377: double[] s = srcData[b];
378:
379: int dstLineOffset = dstBandOffsets[b];
380: int srcLineOffset = srcBandOffsets[b];
381:
382: for (int h = 0; h < dstHeight; h++) {
383: int dstPixelOffset = dstLineOffset;
384: int srcPixelOffset = srcLineOffset;
385:
386: dstLineOffset += dstLineStride;
387: srcLineOffset += srcLineStride;
388:
389: for (int w = 0; w < dstWidth; w++) {
390: d[dstPixelOffset] = c / s[srcPixelOffset];
391:
392: dstPixelOffset += dstPixelStride;
393: srcPixelOffset += srcPixelStride;
394: }
395: }
396: }
397: }
398: }
|