001: /*
002: * $RCSfile: MultiplyConstOpImage.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:37 $
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 "MultiplyConst" operation.
028: *
029: * <p>This <code>OpImage</code> multiplies a set of constants, one for
030: * each band of the source image, to the pixels of a rendered 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] = srcs[h][w][b] * constants[0];
038: * } else {
039: * dst[h][w][b] = srcs[h][w][b] * constants[b];
040: * }
041: * }
042: * }
043: * }
044: * </pre>
045: *
046: * @see javax.media.jai.operator.MultiplyConstDescriptor
047: * @see MultiplyConstCRIF
048: *
049: *
050: * @since EA2
051: */
052: final class MultiplyConstOpImage extends ColormapOpImage {
053:
054: /** The constants to be multiplied, 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 multiplied, stored as reference.
063: */
064: public MultiplyConstOpImage(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((map[i] & 0xFF) * c);
099: }
100: }
101: }
102:
103: /**
104: * Multiplies a constant to the pixel values within a specified rectangle.
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], getSource(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: float c = (float) 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: d[dstPixelOffset] = ImageUtil
183: .clampRoundByte((s[srcPixelOffset] & 0xFF)
184: * c);
185:
186: dstPixelOffset += dstPixelStride;
187: srcPixelOffset += srcPixelStride;
188: }
189: }
190: }
191: }
192:
193: private void computeRectUShort(RasterAccessor src,
194: RasterAccessor dst) {
195: int dstWidth = dst.getWidth();
196: int dstHeight = dst.getHeight();
197: int dstBands = dst.getNumBands();
198:
199: int dstLineStride = dst.getScanlineStride();
200: int dstPixelStride = dst.getPixelStride();
201: int[] dstBandOffsets = dst.getBandOffsets();
202: short[][] dstData = dst.getShortDataArrays();
203:
204: int srcLineStride = src.getScanlineStride();
205: int srcPixelStride = src.getPixelStride();
206: int[] srcBandOffsets = src.getBandOffsets();
207: short[][] srcData = src.getShortDataArrays();
208:
209: for (int b = 0; b < dstBands; b++) {
210: float c = (float) constants[b];
211: short[] d = dstData[b];
212: short[] s = srcData[b];
213:
214: int dstLineOffset = dstBandOffsets[b];
215: int srcLineOffset = srcBandOffsets[b];
216:
217: for (int h = 0; h < dstHeight; h++) {
218: int dstPixelOffset = dstLineOffset;
219: int srcPixelOffset = srcLineOffset;
220:
221: dstLineOffset += dstLineStride;
222: srcLineOffset += srcLineStride;
223:
224: for (int w = 0; w < dstWidth; w++) {
225: d[dstPixelOffset] = ImageUtil
226: .clampRoundUShort((s[srcPixelOffset] & 0xFFFF)
227: * c);
228:
229: dstPixelOffset += dstPixelStride;
230: srcPixelOffset += srcPixelStride;
231: }
232: }
233: }
234: }
235:
236: private void computeRectShort(RasterAccessor src, RasterAccessor dst) {
237: int dstWidth = dst.getWidth();
238: int dstHeight = dst.getHeight();
239: int dstBands = dst.getNumBands();
240:
241: int dstLineStride = dst.getScanlineStride();
242: int dstPixelStride = dst.getPixelStride();
243: int[] dstBandOffsets = dst.getBandOffsets();
244: short[][] dstData = dst.getShortDataArrays();
245:
246: int srcLineStride = src.getScanlineStride();
247: int srcPixelStride = src.getPixelStride();
248: int[] srcBandOffsets = src.getBandOffsets();
249: short[][] srcData = src.getShortDataArrays();
250:
251: for (int b = 0; b < dstBands; b++) {
252: float c = (float) constants[b];
253: short[] d = dstData[b];
254: short[] s = srcData[b];
255:
256: int dstLineOffset = dstBandOffsets[b];
257: int srcLineOffset = srcBandOffsets[b];
258:
259: for (int h = 0; h < dstHeight; h++) {
260: int dstPixelOffset = dstLineOffset;
261: int srcPixelOffset = srcLineOffset;
262:
263: dstLineOffset += dstLineStride;
264: srcLineOffset += srcLineStride;
265:
266: for (int w = 0; w < dstWidth; w++) {
267: d[dstPixelOffset] = ImageUtil
268: .clampRoundShort(s[srcPixelOffset] * c);
269:
270: dstPixelOffset += dstPixelStride;
271: srcPixelOffset += srcPixelStride;
272: }
273: }
274: }
275: }
276:
277: private void computeRectInt(RasterAccessor src, RasterAccessor dst) {
278: int dstWidth = dst.getWidth();
279: int dstHeight = dst.getHeight();
280: int dstBands = dst.getNumBands();
281:
282: int dstLineStride = dst.getScanlineStride();
283: int dstPixelStride = dst.getPixelStride();
284: int[] dstBandOffsets = dst.getBandOffsets();
285: int[][] dstData = dst.getIntDataArrays();
286:
287: int srcLineStride = src.getScanlineStride();
288: int srcPixelStride = src.getPixelStride();
289: int[] srcBandOffsets = src.getBandOffsets();
290: int[][] srcData = src.getIntDataArrays();
291:
292: for (int b = 0; b < dstBands; b++) {
293: double c = constants[b];
294: int[] d = dstData[b];
295: int[] s = srcData[b];
296:
297: int dstLineOffset = dstBandOffsets[b];
298: int srcLineOffset = srcBandOffsets[b];
299:
300: for (int h = 0; h < dstHeight; h++) {
301: int dstPixelOffset = dstLineOffset;
302: int srcPixelOffset = srcLineOffset;
303:
304: dstLineOffset += dstLineStride;
305: srcLineOffset += srcLineStride;
306:
307: for (int w = 0; w < dstWidth; w++) {
308: d[dstPixelOffset] = ImageUtil
309: .clampRoundInt(s[srcPixelOffset] * c);
310:
311: dstPixelOffset += dstPixelStride;
312: srcPixelOffset += srcPixelStride;
313: }
314: }
315: }
316: }
317:
318: private void computeRectFloat(RasterAccessor src, RasterAccessor dst) {
319: int dstWidth = dst.getWidth();
320: int dstHeight = dst.getHeight();
321: int dstBands = dst.getNumBands();
322:
323: int dstLineStride = dst.getScanlineStride();
324: int dstPixelStride = dst.getPixelStride();
325: int[] dstBandOffsets = dst.getBandOffsets();
326: float[][] dstData = dst.getFloatDataArrays();
327:
328: int srcLineStride = src.getScanlineStride();
329: int srcPixelStride = src.getPixelStride();
330: int[] srcBandOffsets = src.getBandOffsets();
331: float[][] srcData = src.getFloatDataArrays();
332:
333: for (int b = 0; b < dstBands; b++) {
334: double c = constants[b];
335: float[] d = dstData[b];
336: float[] s = srcData[b];
337:
338: int dstLineOffset = dstBandOffsets[b];
339: int srcLineOffset = srcBandOffsets[b];
340:
341: for (int h = 0; h < dstHeight; h++) {
342: int dstPixelOffset = dstLineOffset;
343: int srcPixelOffset = srcLineOffset;
344:
345: dstLineOffset += dstLineStride;
346: srcLineOffset += srcLineStride;
347:
348: for (int w = 0; w < dstWidth; w++) {
349: d[dstPixelOffset] = ImageUtil
350: .clampFloat(s[srcPixelOffset] * c);
351:
352: dstPixelOffset += dstPixelStride;
353: srcPixelOffset += srcPixelStride;
354: }
355: }
356: }
357: }
358:
359: private void computeRectDouble(RasterAccessor src,
360: RasterAccessor dst) {
361: int dstWidth = dst.getWidth();
362: int dstHeight = dst.getHeight();
363: int dstBands = dst.getNumBands();
364:
365: int dstLineStride = dst.getScanlineStride();
366: int dstPixelStride = dst.getPixelStride();
367: int[] dstBandOffsets = dst.getBandOffsets();
368: double[][] dstData = dst.getDoubleDataArrays();
369:
370: int srcLineStride = src.getScanlineStride();
371: int srcPixelStride = src.getPixelStride();
372: int[] srcBandOffsets = src.getBandOffsets();
373: double[][] srcData = src.getDoubleDataArrays();
374:
375: for (int b = 0; b < dstBands; b++) {
376: double c = constants[b];
377: double[] d = dstData[b];
378: double[] s = srcData[b];
379:
380: int dstLineOffset = dstBandOffsets[b];
381: int srcLineOffset = srcBandOffsets[b];
382:
383: for (int h = 0; h < dstHeight; h++) {
384: int dstPixelOffset = dstLineOffset;
385: int srcPixelOffset = srcLineOffset;
386:
387: dstLineOffset += dstLineStride;
388: srcLineOffset += srcLineStride;
389:
390: for (int w = 0; w < dstWidth; w++) {
391: d[dstPixelOffset] = s[srcPixelOffset] * c;
392:
393: dstPixelOffset += dstPixelStride;
394: srcPixelOffset += srcPixelStride;
395: }
396: }
397: }
398: }
399: }
|