001: /*
002: * $RCSfile: BandCombineOpImage.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:15 $
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.ComponentSampleModel;
019: import java.awt.image.WritableRaster;
020: import java.util.Map;
021: import javax.media.jai.ImageLayout;
022: import javax.media.jai.PlanarImage;
023: import javax.media.jai.PointOpImage;
024: import javax.media.jai.RasterAccessor;
025: import javax.media.jai.RasterFormatTag;
026: import javax.media.jai.RasterFactory;
027: import com.sun.media.jai.util.ImageUtil;
028: import com.sun.media.jai.util.JDKWorkarounds;
029:
030: /**
031: * An <code>OpImage</code> implementing the "BandCombine" operation.
032: *
033: * <p>This <code>OpImage</code> performs the arbitrary interband
034: * linear combination of an image using the specified matrix. The
035: * width of the matrix must be one larger that the number of bands
036: * in the source image. The height of the matrix must be equal to
037: * the number of bands in the destination image. Because the matrix
038: * can be of arbitrary size, this function can be used to produce
039: * a destination image with a different number of bands from the
040: * source image.
041: * <p>The destination image is formed by performing a matrix-
042: * multiply operation between the bands of the source image and
043: * the specified matrix. The extra column of values is a constant
044: * that is added after the matrix-multiply operation takes place.
045: *
046: * @see javax.media.jai.operator.BandCombineDescriptor
047: * @see BandCombineCRIF
048: *
049: *
050: * @since EA3
051: */
052: final class BandCombineOpImage extends PointOpImage {
053:
054: private double[][] matrix;
055:
056: /**
057: * Constructor.
058: *
059: * @param source The source image.
060: * @param layout The destination image layout.
061: * @param matrix The matrix of values used to perform the
062: * linear combination.
063: */
064: public BandCombineOpImage(RenderedImage source, Map config,
065: ImageLayout layout, double[][] matrix) {
066: super (source, layout, config, true);
067:
068: this .matrix = matrix;
069:
070: int numBands = matrix.length; // matrix height is dst numBands
071: if (getSampleModel().getNumBands() != numBands) {
072: sampleModel = RasterFactory.createComponentSampleModel(
073: sampleModel, sampleModel.getDataType(), tileWidth,
074: tileHeight, numBands);
075:
076: if (colorModel != null
077: && !JDKWorkarounds.areCompatibleDataModels(
078: sampleModel, colorModel)) {
079: colorModel = ImageUtil.getCompatibleColorModel(
080: sampleModel, config);
081: }
082: }
083: }
084:
085: /**
086: * Performs linear combination of source image with matrix
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: RasterAccessor s = new RasterAccessor(sources[0], destRect,
099: formatTags[0], getSourceImage(0).getColorModel());
100: RasterAccessor d = new RasterAccessor(dest, destRect,
101: formatTags[1], getColorModel());
102:
103: switch (d.getDataType()) {
104: case DataBuffer.TYPE_BYTE:
105: computeRectByte(s, d);
106: break;
107: case DataBuffer.TYPE_USHORT:
108: computeRectUShort(s, d);
109: break;
110: case DataBuffer.TYPE_SHORT:
111: computeRectShort(s, d);
112: break;
113: case DataBuffer.TYPE_INT:
114: computeRectInt(s, d);
115: break;
116: case DataBuffer.TYPE_FLOAT:
117: computeRectFloat(s, d);
118: break;
119: case DataBuffer.TYPE_DOUBLE:
120: computeRectDouble(s, d);
121: break;
122: }
123:
124: if (d.isDataCopy()) {
125: d.clampDataArrays();
126: d.copyDataToRaster();
127: }
128: }
129:
130: private void computeRectByte(RasterAccessor src, RasterAccessor dst) {
131: int sLineStride = src.getScanlineStride();
132: int sPixelStride = src.getPixelStride();
133: int sbands = src.getNumBands();
134: int[] sBandOffsets = src.getBandOffsets();
135: byte[][] sData = src.getByteDataArrays();
136:
137: int dwidth = dst.getWidth();
138: int dheight = dst.getHeight();
139: int dbands = dst.getNumBands();
140: int dLineStride = dst.getScanlineStride();
141: int dPixelStride = dst.getPixelStride();
142: int[] dBandOffsets = dst.getBandOffsets();
143: byte[][] dData = dst.getByteDataArrays();
144:
145: int sso = 0, dso = 0;
146:
147: for (int h = 0; h < dheight; h++) {
148: int spo = sso;
149: int dpo = dso;
150:
151: for (int w = 0; w < dwidth; w++) {
152: for (int b = 0; b < dbands; b++) {
153: float sum = 0.0F;
154: double[] mat = matrix[b];
155:
156: for (int k = 0; k < sbands; k++) {
157: sum += (float) mat[k]
158: * (float) (sData[k][spo
159: + sBandOffsets[k]] & 0xFF);
160: }
161:
162: dData[b][dpo + dBandOffsets[b]] = ImageUtil
163: .clampRoundByte(sum + (float) mat[sbands]);
164: }
165:
166: spo += sPixelStride;
167: dpo += dPixelStride;
168: }
169:
170: sso += sLineStride;
171: dso += dLineStride;
172: }
173: }
174:
175: private void computeRectUShort(RasterAccessor src,
176: RasterAccessor dst) {
177: int sLineStride = src.getScanlineStride();
178: int sPixelStride = src.getPixelStride();
179: int sbands = src.getNumBands();
180: int[] sBandOffsets = src.getBandOffsets();
181: short[][] sData = src.getShortDataArrays();
182:
183: int dwidth = dst.getWidth();
184: int dheight = dst.getHeight();
185: int dbands = dst.getNumBands();
186: int dLineStride = dst.getScanlineStride();
187: int dPixelStride = dst.getPixelStride();
188: int[] dBandOffsets = dst.getBandOffsets();
189: short[][] dData = dst.getShortDataArrays();
190:
191: int sso = 0, dso = 0;
192:
193: for (int h = 0; h < dheight; h++) {
194: int spo = sso;
195: int dpo = dso;
196:
197: for (int w = 0; w < dwidth; w++) {
198: for (int b = 0; b < dbands; b++) {
199: float sum = 0.0F;
200: double[] mat = matrix[b];
201:
202: for (int k = 0; k < sbands; k++) {
203: sum += (float) mat[k]
204: * (float) (sData[k][spo
205: + sBandOffsets[k]] & 0xFFFF);
206: }
207:
208: dData[b][dpo + dBandOffsets[b]] = ImageUtil
209: .clampRoundUShort(sum
210: + (float) matrix[b][sbands]);
211: }
212:
213: spo += sPixelStride;
214: dpo += dPixelStride;
215: }
216:
217: sso += sLineStride;
218: dso += dLineStride;
219: }
220: }
221:
222: private void computeRectShort(RasterAccessor src, RasterAccessor dst) {
223: int sLineStride = src.getScanlineStride();
224: int sPixelStride = src.getPixelStride();
225: int sbands = src.getNumBands();
226: int[] sBandOffsets = src.getBandOffsets();
227: short[][] sData = src.getShortDataArrays();
228:
229: int dwidth = dst.getWidth();
230: int dheight = dst.getHeight();
231: int dbands = dst.getNumBands();
232: int dLineStride = dst.getScanlineStride();
233: int dPixelStride = dst.getPixelStride();
234: int[] dBandOffsets = dst.getBandOffsets();
235: short[][] dData = dst.getShortDataArrays();
236:
237: int sso = 0, dso = 0;
238:
239: for (int h = 0; h < dheight; h++) {
240: int spo = sso;
241: int dpo = dso;
242:
243: for (int w = 0; w < dwidth; w++) {
244: for (int b = 0; b < dbands; b++) {
245: float sum = 0.0F;
246: double[] mat = matrix[b];
247:
248: for (int k = 0; k < sbands; k++) {
249: sum += (float) mat[k]
250: * (float) (sData[k][spo
251: + sBandOffsets[k]]);
252: }
253:
254: dData[b][dpo + dBandOffsets[b]] = ImageUtil
255: .clampRoundUShort(sum
256: + (float) matrix[b][sbands]);
257: }
258:
259: spo += sPixelStride;
260: dpo += dPixelStride;
261: }
262:
263: sso += sLineStride;
264: dso += dLineStride;
265: }
266:
267: }
268:
269: private void computeRectInt(RasterAccessor src, RasterAccessor dst) {
270: int sLineStride = src.getScanlineStride();
271: int sPixelStride = src.getPixelStride();
272: int sbands = src.getNumBands();
273: int[] sBandOffsets = src.getBandOffsets();
274: int[][] sData = src.getIntDataArrays();
275:
276: int dwidth = dst.getWidth();
277: int dheight = dst.getHeight();
278: int dbands = dst.getNumBands();
279: int dLineStride = dst.getScanlineStride();
280: int dPixelStride = dst.getPixelStride();
281: int[] dBandOffsets = dst.getBandOffsets();
282: int[][] dData = dst.getIntDataArrays();
283:
284: int sso = 0, dso = 0;
285:
286: for (int h = 0; h < dheight; h++) {
287: int spo = sso;
288: int dpo = dso;
289:
290: for (int w = 0; w < dwidth; w++) {
291: for (int b = 0; b < dbands; b++) {
292: float sum = 0.0F;
293: double[] mat = matrix[b];
294:
295: for (int k = 0; k < sbands; k++) {
296: sum += (float) mat[k]
297: * (float) (sData[k][spo
298: + sBandOffsets[k]]);
299: }
300:
301: dData[b][dpo + dBandOffsets[b]] = ImageUtil
302: .clampRoundInt(sum
303: + (float) matrix[b][sbands]);
304: }
305:
306: spo += sPixelStride;
307: dpo += dPixelStride;
308: }
309:
310: sso += sLineStride;
311: dso += dLineStride;
312: }
313: }
314:
315: private void computeRectFloat(RasterAccessor src, RasterAccessor dst) {
316: int sLineStride = src.getScanlineStride();
317: int sPixelStride = src.getPixelStride();
318: int sbands = src.getNumBands();
319: int[] sBandOffsets = src.getBandOffsets();
320: float[][] sData = src.getFloatDataArrays();
321:
322: int dwidth = dst.getWidth();
323: int dheight = dst.getHeight();
324: int dbands = dst.getNumBands();
325: int dLineStride = dst.getScanlineStride();
326: int dPixelStride = dst.getPixelStride();
327: int[] dBandOffsets = dst.getBandOffsets();
328: float[][] dData = dst.getFloatDataArrays();
329:
330: int sso = 0, dso = 0;
331:
332: for (int h = 0; h < dheight; h++) {
333: int spo = sso;
334: int dpo = dso;
335:
336: for (int w = 0; w < dwidth; w++) {
337: for (int b = 0; b < dbands; b++) {
338: float sum = 0.0F;
339: double[] mat = matrix[b];
340:
341: for (int k = 0; k < sbands; k++) {
342: sum += (float) mat[k]
343: * sData[k][spo + sBandOffsets[k]];
344: }
345:
346: dData[b][dpo + dBandOffsets[b]] = sum
347: + (float) matrix[b][sbands];
348: }
349:
350: spo += sPixelStride;
351: dpo += dPixelStride;
352: }
353:
354: sso += sLineStride;
355: dso += dLineStride;
356: }
357: }
358:
359: private void computeRectDouble(RasterAccessor src,
360: RasterAccessor dst) {
361: int sLineStride = src.getScanlineStride();
362: int sPixelStride = src.getPixelStride();
363: int sbands = src.getNumBands();
364: int[] sBandOffsets = src.getBandOffsets();
365: double[][] sData = src.getDoubleDataArrays();
366:
367: int dwidth = dst.getWidth();
368: int dheight = dst.getHeight();
369: int dbands = dst.getNumBands();
370: int dLineStride = dst.getScanlineStride();
371: int dPixelStride = dst.getPixelStride();
372: int[] dBandOffsets = dst.getBandOffsets();
373: double[][] dData = dst.getDoubleDataArrays();
374:
375: int sso = 0, dso = 0;
376:
377: for (int h = 0; h < dheight; h++) {
378: int spo = sso;
379: int dpo = dso;
380:
381: for (int w = 0; w < dwidth; w++) {
382: for (int b = 0; b < dbands; b++) {
383: double sum = 0.0D;
384: double[] mat = matrix[b];
385:
386: for (int k = 0; k < sbands; k++) {
387: sum += mat[k] * sData[k][spo + sBandOffsets[k]];
388: }
389:
390: dData[b][dpo + dBandOffsets[b]] = sum
391: + matrix[b][sbands];
392: }
393:
394: spo += sPixelStride;
395: dpo += dPixelStride;
396: }
397:
398: sso += sLineStride;
399: dso += dLineStride;
400: }
401: }
402: }
|