001: /*
002: * $RCSfile: ComplexArithmeticOpImage.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:18 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import java.awt.Rectangle;
015: import java.awt.image.ColorModel;
016: import java.awt.image.DataBuffer;
017: import java.awt.image.Raster;
018: import java.awt.image.RenderedImage;
019: import java.awt.image.SampleModel;
020: import java.awt.image.WritableRaster;
021: import javax.media.jai.ImageLayout;
022: import javax.media.jai.PointOpImage;
023: import javax.media.jai.RasterAccessor;
024: import javax.media.jai.RasterFormatTag;
025: import javax.media.jai.RasterFactory;
026: import java.util.Map;
027: import com.sun.media.jai.util.ImageUtil;
028: import com.sun.media.jai.util.JDKWorkarounds;
029:
030: /**
031: * An <code>OpImage</code> implementing complex multiplication and division
032: * as described in
033: * <code>javax.media.jai.operator.MultiplyComplexDescriptor</code> and
034: * <code>javax.media.jai.operator.DivideComplexDescriptor</code>.
035: *
036: * @since EA4
037: *
038: * @see javax.media.jai.PointOpImage
039: * @see javax.media.jai.operator.MultiplyComplexDescriptor
040: * @see javax.media.jai.operator.DivideComplexDescriptor
041: *
042: */
043: final class ComplexArithmeticOpImage extends PointOpImage {
044: /** Flag indicating division (true) or multiplication (false). */
045: protected boolean isDivision = false;
046:
047: /* Array of indices into real bands of first source. */
048: private int[] s1r;
049:
050: /* Array of indices into imaginary bands of first source. */
051: private int[] s1i;
052:
053: /* Array of indices into real bands of second source. */
054: private int[] s2r;
055:
056: /* Array of indices into imaginary bands of second source. */
057: private int[] s2i;
058:
059: /**
060: * Force the destination band count to be even.
061: */
062:
063: private static ImageLayout layoutHelper(ImageLayout layout,
064: RenderedImage source) {
065: // Create an ImageLayout or clone the one passed in.
066: ImageLayout il;
067: if (layout == null) {
068: il = new ImageLayout();
069: } else {
070: il = (ImageLayout) layout.clone();
071: }
072:
073: if (il.isValid(ImageLayout.SAMPLE_MODEL_MASK)) {
074: SampleModel sm = il.getSampleModel(null);
075: int nBands = sm.getNumBands();
076: if (nBands % 2 != 0) {
077: nBands++;
078: sm = RasterFactory.createComponentSampleModel(sm, sm
079: .getTransferType(), sm.getWidth(), sm
080: .getHeight(), nBands);
081: il.setSampleModel(sm); // newly added
082:
083: // Clear the ColorModel mask if needed.
084: ColorModel cm = layout.getColorModel(null);
085: if (cm != null
086: && !JDKWorkarounds.areCompatibleDataModels(sm,
087: cm)) {
088: // Clear the mask bit if incompatible.
089: il.unsetValid(ImageLayout.COLOR_MODEL_MASK);
090: }
091: }
092: }
093:
094: return il;
095: }
096:
097: /**
098: * Constructs a <code>ComplexArithmeticOpImage</code> object.
099: *
100: * <p>The <code>layout</code> parameter may optionally contains the
101: * tile grid layout, sample model, and/or color model. The image
102: * dimension is determined by the intersection of the bounding boxes
103: * of the two source images.
104: *
105: * <p>The image layout of the first source image, <code>source1</code>,
106: * is used as the fall-back for the image layout of the destination
107: * image. Any layout parameters not specified in the <code>layout</code>
108: * argument are set to the same value as that of <code>source1</code>.
109: *
110: * @param source1 The first source image.
111: * @param source2 The second source image.
112: * @param layout The destination image layout.
113: * @param isDivision Whether the operation is division; if not, it's
114: * multiplication.
115: */
116: public ComplexArithmeticOpImage(RenderedImage source1,
117: RenderedImage source2, Map config, ImageLayout layout,
118: boolean isDivision) {
119: super (source1, source2, layoutHelper(layout, source1), config,
120: true);
121:
122: // Cache the division parameter.
123: this .isDivision = isDivision;
124:
125: // Get the source band counts.
126: int numBands1 = source1.getSampleModel().getNumBands();
127: int numBands2 = source2.getSampleModel().getNumBands();
128:
129: // Handle the special case (cf. descriptor).
130: int numBandsDst = Math.min(numBands1, numBands2);
131:
132: int numBandsFromHint = 0;
133: if (layout != null)
134: numBandsFromHint = layout.getSampleModel(null)
135: .getNumBands();
136:
137: if (layout != null
138: && layout.isValid(ImageLayout.SAMPLE_MODEL_MASK)
139: && ((numBands1 == 2 && numBands2 > 2)
140: || (numBands2 == 2 && numBands1 > 2) || (numBands1 >= numBandsFromHint
141: && numBands2 >= numBandsFromHint && numBandsFromHint > 0))) {
142: if (numBandsFromHint % 2 == 0) {
143: numBandsDst = numBandsFromHint;
144: // Clamp the destination band count to the maximum
145: // number of bands in the sources.
146: numBandsDst = Math.min(Math.max(numBands1, numBands2),
147: numBandsDst);
148: }
149: }
150:
151: if (numBandsDst != sampleModel.getNumBands()) {
152: sampleModel = RasterFactory.createComponentSampleModel(
153: sampleModel, sampleModel.getTransferType(),
154: sampleModel.getWidth(), sampleModel.getHeight(),
155: numBandsDst);
156:
157: if (colorModel != null
158: && !JDKWorkarounds.areCompatibleDataModels(
159: sampleModel, colorModel)) {
160: colorModel = ImageUtil.getCompatibleColorModel(
161: sampleModel, config);
162: }
163: }
164:
165: // Initialize index arrays.
166: int numElements = sampleModel.getNumBands() / 2;
167: s1r = new int[numElements];
168: s1i = new int[numElements];
169: s2r = new int[numElements];
170: s2i = new int[numElements];
171: int s1Inc = numBands1 > 2 ? 2 : 0;
172: int s2Inc = numBands2 > 2 ? 2 : 0;
173: int i1 = 0;
174: int i2 = 0;
175: for (int b = 0; b < numElements; b++) {
176: s1r[b] = i1;
177: s1i[b] = i1 + 1;
178: s2r[b] = i2;
179: s2i[b] = i2 + 1;
180: i1 += s1Inc;
181: i2 += s2Inc;
182: }
183:
184: // Set flag to permit in-place operation.
185: permitInPlaceOperation();
186: }
187:
188: /**
189: * Calculate the product or quotient of the source images.
190: *
191: * @param sources Cobbled sources, guaranteed to provide all the
192: * source data necessary for computing the rectangle.
193: * @param dest The tile containing the rectangle to be computed.
194: * @param destRect The rectangle within the tile to be computed.
195: */
196: protected void computeRect(Raster[] sources, WritableRaster dest,
197: Rectangle destRect) {
198: // Retrieve format tags.
199: RasterFormatTag[] formatTags = getFormatTags();
200:
201: RasterAccessor src1Accessor = new RasterAccessor(sources[0],
202: destRect, formatTags[0], getSourceImage(0)
203: .getColorModel());
204: RasterAccessor src2Accessor = new RasterAccessor(sources[1],
205: destRect, formatTags[1], getSourceImage(1)
206: .getColorModel());
207: RasterAccessor dstAccessor = new RasterAccessor(dest, destRect,
208: formatTags[2], getColorModel());
209:
210: // Branch to the method appropriate to the accessor data type.
211: switch (dstAccessor.getDataType()) {
212: case DataBuffer.TYPE_BYTE:
213: computeRectByte(src1Accessor, src2Accessor, dstAccessor);
214: break;
215: case DataBuffer.TYPE_SHORT:
216: computeRectShort(src1Accessor, src2Accessor, dstAccessor);
217: break;
218: case DataBuffer.TYPE_USHORT:
219: computeRectUShort(src1Accessor, src2Accessor, dstAccessor);
220: break;
221: case DataBuffer.TYPE_INT:
222: computeRectInt(src1Accessor, src2Accessor, dstAccessor);
223: break;
224: case DataBuffer.TYPE_FLOAT:
225: computeRectFloat(src1Accessor, src2Accessor, dstAccessor);
226: break;
227: case DataBuffer.TYPE_DOUBLE:
228: computeRectDouble(src1Accessor, src2Accessor, dstAccessor);
229: break;
230: default:
231: // NB: This statement should be unreachable.
232: throw new RuntimeException(JaiI18N
233: .getString("ComplexArithmeticOpImage0"));
234: }
235:
236: if (dstAccessor.needsClamping()) {
237: dstAccessor.clampDataArrays();
238: }
239: // Make sure that the output data is copied to the destination.
240: dstAccessor.copyDataToRaster();
241: }
242:
243: private void computeRectDouble(RasterAccessor src1Accessor,
244: RasterAccessor src2Accessor, RasterAccessor dstAccessor) {
245: // Set the size of the rectangle.
246: int numRows = dstAccessor.getHeight();
247: int numCols = dstAccessor.getWidth();
248:
249: // Set pixel and line strides.
250: int src1PixelStride = src1Accessor.getPixelStride();
251: int src1ScanlineStride = src1Accessor.getScanlineStride();
252: int src2PixelStride = src2Accessor.getPixelStride();
253: int src2ScanlineStride = src2Accessor.getScanlineStride();
254: int dstPixelStride = dstAccessor.getPixelStride();
255: int dstScanlineStride = dstAccessor.getScanlineStride();
256:
257: // Loop over the destination bands.
258: int numElements = sampleModel.getNumBands() / 2;
259: for (int element = 0; element < numElements; element++) {
260: // Set band indices.
261: int realBand = 2 * element;
262: int imagBand = realBand + 1;
263:
264: // Get the source and destination arrays for this element.
265: double[] src1Real = src1Accessor
266: .getDoubleDataArray(s1r[element]);
267: double[] src1Imag = src1Accessor
268: .getDoubleDataArray(s1i[element]);
269: double[] src2Real = src2Accessor
270: .getDoubleDataArray(s2r[element]);
271: double[] src2Imag = src2Accessor
272: .getDoubleDataArray(s2i[element]);
273: double[] dstReal = dstAccessor.getDoubleDataArray(realBand);
274: double[] dstImag = dstAccessor.getDoubleDataArray(imagBand);
275:
276: // Initialize the data offsets for this element.
277: int src1OffsetReal = src1Accessor
278: .getBandOffset(s1r[element]);
279: int src1OffsetImag = src1Accessor
280: .getBandOffset(s1i[element]);
281: int src2OffsetReal = src2Accessor
282: .getBandOffset(s2r[element]);
283: int src2OffsetImag = src2Accessor
284: .getBandOffset(s2i[element]);
285: int dstOffsetReal = dstAccessor.getBandOffset(realBand);
286: int dstOffsetImag = dstAccessor.getBandOffset(imagBand);
287:
288: // Initialize the line offsets for looping.
289: int src1LineReal = src1OffsetReal;
290: int src1LineImag = src1OffsetImag;
291: int src2LineReal = src2OffsetReal;
292: int src2LineImag = src2OffsetImag;
293: int dstLineReal = dstOffsetReal;
294: int dstLineImag = dstOffsetImag;
295:
296: for (int row = 0; row < numRows; row++) {
297: // Initialize pixel offsets for this row.
298: int src1PixelReal = src1LineReal;
299: int src1PixelImag = src1LineImag;
300: int src2PixelReal = src2LineReal;
301: int src2PixelImag = src2LineImag;
302: int dstPixelReal = dstLineReal;
303: int dstPixelImag = dstLineImag;
304:
305: // Switch per line depending on operation type.
306: if (isDivision) { // Division
307: for (int col = 0; col < numCols; col++) {
308: double a = src1Real[src1PixelReal];
309: double b = src1Imag[src1PixelImag];
310: double c = src2Real[src2PixelReal];
311: double d = src2Imag[src2PixelImag];
312:
313: double denom = c * c + d * d;
314: dstReal[dstPixelReal] = (a * c + b * d) / denom;
315: dstImag[dstPixelImag] = (b * c - a * d) / denom;
316:
317: src1PixelReal += src1PixelStride;
318: src1PixelImag += src1PixelStride;
319: src2PixelReal += src2PixelStride;
320: src2PixelImag += src2PixelStride;
321: dstPixelReal += dstPixelStride;
322: dstPixelImag += dstPixelStride;
323: }
324: } else { // Multiplication
325: for (int col = 0; col < numCols; col++) {
326: double a = src1Real[src1PixelReal];
327: double b = src1Imag[src1PixelImag];
328: double c = src2Real[src2PixelReal];
329: double d = src2Imag[src2PixelImag];
330:
331: dstReal[dstPixelReal] = a * c - b * d;
332: dstImag[dstPixelImag] = a * d + b * c;
333:
334: src1PixelReal += src1PixelStride;
335: src1PixelImag += src1PixelStride;
336: src2PixelReal += src2PixelStride;
337: src2PixelImag += src2PixelStride;
338: dstPixelReal += dstPixelStride;
339: dstPixelImag += dstPixelStride;
340: }
341: }
342:
343: // Increment the line offsets.
344: src1LineReal += src1ScanlineStride;
345: src1LineImag += src1ScanlineStride;
346: src2LineReal += src2ScanlineStride;
347: src2LineImag += src2ScanlineStride;
348: dstLineReal += dstScanlineStride;
349: dstLineImag += dstScanlineStride;
350: }
351: }
352: }
353:
354: private void computeRectFloat(RasterAccessor src1Accessor,
355: RasterAccessor src2Accessor, RasterAccessor dstAccessor) {
356: // Set the size of the rectangle.
357: int numRows = dstAccessor.getHeight();
358: int numCols = dstAccessor.getWidth();
359:
360: // Set pixel and line strides.
361: int src1PixelStride = src1Accessor.getPixelStride();
362: int src1ScanlineStride = src1Accessor.getScanlineStride();
363: int src2PixelStride = src2Accessor.getPixelStride();
364: int src2ScanlineStride = src2Accessor.getScanlineStride();
365: int dstPixelStride = dstAccessor.getPixelStride();
366: int dstScanlineStride = dstAccessor.getScanlineStride();
367:
368: // Loop over the destination bands.
369: int numElements = sampleModel.getNumBands() / 2;
370: for (int element = 0; element < numElements; element++) {
371: // Set band indices.
372: int realBand = 2 * element;
373: int imagBand = realBand + 1;
374:
375: // Get the source and destination arrays for this element.
376: float[] src1Real = src1Accessor
377: .getFloatDataArray(s1r[element]);
378: float[] src1Imag = src1Accessor
379: .getFloatDataArray(s1i[element]);
380: float[] src2Real = src2Accessor
381: .getFloatDataArray(s2r[element]);
382: float[] src2Imag = src2Accessor
383: .getFloatDataArray(s2i[element]);
384: float[] dstReal = dstAccessor.getFloatDataArray(realBand);
385: float[] dstImag = dstAccessor.getFloatDataArray(imagBand);
386:
387: // Initialize the data offsets for this element.
388: int src1OffsetReal = src1Accessor
389: .getBandOffset(s1r[element]);
390: int src1OffsetImag = src1Accessor
391: .getBandOffset(s1i[element]);
392: int src2OffsetReal = src2Accessor
393: .getBandOffset(s2r[element]);
394: int src2OffsetImag = src2Accessor
395: .getBandOffset(s2i[element]);
396: int dstOffsetReal = dstAccessor.getBandOffset(realBand);
397: int dstOffsetImag = dstAccessor.getBandOffset(imagBand);
398:
399: // Initialize the line offsets for looping.
400: int src1LineReal = src1OffsetReal;
401: int src1LineImag = src1OffsetImag;
402: int src2LineReal = src2OffsetReal;
403: int src2LineImag = src2OffsetImag;
404: int dstLineReal = dstOffsetReal;
405: int dstLineImag = dstOffsetImag;
406:
407: for (int row = 0; row < numRows; row++) {
408: // Initialize pixel offsets for this row.
409: int src1PixelReal = src1LineReal;
410: int src1PixelImag = src1LineImag;
411: int src2PixelReal = src2LineReal;
412: int src2PixelImag = src2LineImag;
413: int dstPixelReal = dstLineReal;
414: int dstPixelImag = dstLineImag;
415:
416: // Switch per line depending on operation type.
417: if (isDivision) { // Division
418: for (int col = 0; col < numCols; col++) {
419: float a = src1Real[src1PixelReal];
420: float b = src1Imag[src1PixelImag];
421: float c = src2Real[src2PixelReal];
422: float d = src2Imag[src2PixelImag];
423:
424: float denom = c * c + d * d;
425: dstReal[dstPixelReal] = (a * c + b * d) / denom;
426: dstImag[dstPixelImag] = (b * c - a * d) / denom;
427:
428: src1PixelReal += src1PixelStride;
429: src1PixelImag += src1PixelStride;
430: src2PixelReal += src2PixelStride;
431: src2PixelImag += src2PixelStride;
432: dstPixelReal += dstPixelStride;
433: dstPixelImag += dstPixelStride;
434: }
435: } else { // Multiplication
436: for (int col = 0; col < numCols; col++) {
437: float a = src1Real[src1PixelReal];
438: float b = src1Imag[src1PixelImag];
439: float c = src2Real[src2PixelReal];
440: float d = src2Imag[src2PixelImag];
441:
442: dstReal[dstPixelReal] = a * c - b * d;
443: dstImag[dstPixelImag] = a * d + b * c;
444:
445: src1PixelReal += src1PixelStride;
446: src1PixelImag += src1PixelStride;
447: src2PixelReal += src2PixelStride;
448: src2PixelImag += src2PixelStride;
449: dstPixelReal += dstPixelStride;
450: dstPixelImag += dstPixelStride;
451: }
452: }
453:
454: // Increment the line offsets.
455: src1LineReal += src1ScanlineStride;
456: src1LineImag += src1ScanlineStride;
457: src2LineReal += src2ScanlineStride;
458: src2LineImag += src2ScanlineStride;
459: dstLineReal += dstScanlineStride;
460: dstLineImag += dstScanlineStride;
461: }
462: }
463: }
464:
465: private void computeRectInt(RasterAccessor src1Accessor,
466: RasterAccessor src2Accessor, RasterAccessor dstAccessor) {
467: // Set the size of the rectangle.
468: int numRows = dstAccessor.getHeight();
469: int numCols = dstAccessor.getWidth();
470:
471: // Set pixel and line strides.
472: int src1PixelStride = src1Accessor.getPixelStride();
473: int src1ScanlineStride = src1Accessor.getScanlineStride();
474: int src2PixelStride = src2Accessor.getPixelStride();
475: int src2ScanlineStride = src2Accessor.getScanlineStride();
476: int dstPixelStride = dstAccessor.getPixelStride();
477: int dstScanlineStride = dstAccessor.getScanlineStride();
478:
479: // Loop over the destination bands.
480: int numElements = sampleModel.getNumBands() / 2;
481: for (int element = 0; element < numElements; element++) {
482: // Set band indices.
483: int realBand = 2 * element;
484: int imagBand = realBand + 1;
485:
486: // Get the source and destination arrays for this element.
487: int[] src1Real = src1Accessor.getIntDataArray(s1r[element]);
488: int[] src1Imag = src1Accessor.getIntDataArray(s1i[element]);
489: int[] src2Real = src2Accessor.getIntDataArray(s2r[element]);
490: int[] src2Imag = src2Accessor.getIntDataArray(s2i[element]);
491: int[] dstReal = dstAccessor.getIntDataArray(realBand);
492: int[] dstImag = dstAccessor.getIntDataArray(imagBand);
493:
494: // Initialize the data offsets for this element.
495: int src1OffsetReal = src1Accessor
496: .getBandOffset(s1r[element]);
497: int src1OffsetImag = src1Accessor
498: .getBandOffset(s1i[element]);
499: int src2OffsetReal = src2Accessor
500: .getBandOffset(s2r[element]);
501: int src2OffsetImag = src2Accessor
502: .getBandOffset(s2i[element]);
503: int dstOffsetReal = dstAccessor.getBandOffset(realBand);
504: int dstOffsetImag = dstAccessor.getBandOffset(imagBand);
505:
506: // Initialize the line offsets for looping.
507: int src1LineReal = src1OffsetReal;
508: int src1LineImag = src1OffsetImag;
509: int src2LineReal = src2OffsetReal;
510: int src2LineImag = src2OffsetImag;
511: int dstLineReal = dstOffsetReal;
512: int dstLineImag = dstOffsetImag;
513:
514: for (int row = 0; row < numRows; row++) {
515: // Initialize pixel offsets for this row.
516: int src1PixelReal = src1LineReal;
517: int src1PixelImag = src1LineImag;
518: int src2PixelReal = src2LineReal;
519: int src2PixelImag = src2LineImag;
520: int dstPixelReal = dstLineReal;
521: int dstPixelImag = dstLineImag;
522:
523: // Switch per line depending on operation type.
524: if (isDivision) { // Division
525: for (int col = 0; col < numCols; col++) {
526: int a = src1Real[src1PixelReal];
527: int b = src1Imag[src1PixelImag];
528: int c = src2Real[src2PixelReal];
529: int d = src2Imag[src2PixelImag];
530:
531: float denom = c * c + d * d;
532: dstReal[dstPixelReal] = ImageUtil
533: .clampRoundInt((a * c + b * d) / denom);
534: dstImag[dstPixelImag] = ImageUtil
535: .clampRoundInt((b * c - a * d) / denom);
536:
537: src1PixelReal += src1PixelStride;
538: src1PixelImag += src1PixelStride;
539: src2PixelReal += src2PixelStride;
540: src2PixelImag += src2PixelStride;
541: dstPixelReal += dstPixelStride;
542: dstPixelImag += dstPixelStride;
543: }
544: } else { // Multiplication
545: for (int col = 0; col < numCols; col++) {
546: long a = src1Real[src1PixelReal];
547: long b = src1Imag[src1PixelImag];
548: long c = src2Real[src2PixelReal];
549: long d = src2Imag[src2PixelImag];
550:
551: dstReal[dstPixelReal] = ImageUtil.clampInt(a
552: * c - b * d);
553: dstImag[dstPixelImag] = ImageUtil.clampInt(a
554: * d + b * c);
555:
556: src1PixelReal += src1PixelStride;
557: src1PixelImag += src1PixelStride;
558: src2PixelReal += src2PixelStride;
559: src2PixelImag += src2PixelStride;
560: dstPixelReal += dstPixelStride;
561: dstPixelImag += dstPixelStride;
562: }
563: }
564:
565: // Increment the line offsets.
566: src1LineReal += src1ScanlineStride;
567: src1LineImag += src1ScanlineStride;
568: src2LineReal += src2ScanlineStride;
569: src2LineImag += src2ScanlineStride;
570: dstLineReal += dstScanlineStride;
571: dstLineImag += dstScanlineStride;
572: }
573: }
574: }
575:
576: private void computeRectUShort(RasterAccessor src1Accessor,
577: RasterAccessor src2Accessor, RasterAccessor dstAccessor) {
578: // Set the size of the rectangle.
579: int numRows = dstAccessor.getHeight();
580: int numCols = dstAccessor.getWidth();
581:
582: // Set pixel and line strides.
583: int src1PixelStride = src1Accessor.getPixelStride();
584: int src1ScanlineStride = src1Accessor.getScanlineStride();
585: int src2PixelStride = src2Accessor.getPixelStride();
586: int src2ScanlineStride = src2Accessor.getScanlineStride();
587: int dstPixelStride = dstAccessor.getPixelStride();
588: int dstScanlineStride = dstAccessor.getScanlineStride();
589:
590: // Loop over the destination bands.
591: int numElements = sampleModel.getNumBands() / 2;
592: for (int element = 0; element < numElements; element++) {
593: // Set band indices.
594: int realBand = 2 * element;
595: int imagBand = realBand + 1;
596:
597: // Get the source and destination arrays for this element.
598: short[] src1Real = src1Accessor
599: .getShortDataArray(s1r[element]);
600: short[] src1Imag = src1Accessor
601: .getShortDataArray(s1i[element]);
602: short[] src2Real = src2Accessor
603: .getShortDataArray(s2r[element]);
604: short[] src2Imag = src2Accessor
605: .getShortDataArray(s2i[element]);
606: short[] dstReal = dstAccessor.getShortDataArray(realBand);
607: short[] dstImag = dstAccessor.getShortDataArray(imagBand);
608:
609: // Initialize the data offsets for this element.
610: int src1OffsetReal = src1Accessor
611: .getBandOffset(s1r[element]);
612: int src1OffsetImag = src1Accessor
613: .getBandOffset(s1i[element]);
614: int src2OffsetReal = src2Accessor
615: .getBandOffset(s2r[element]);
616: int src2OffsetImag = src2Accessor
617: .getBandOffset(s2i[element]);
618: int dstOffsetReal = dstAccessor.getBandOffset(realBand);
619: int dstOffsetImag = dstAccessor.getBandOffset(imagBand);
620:
621: // Initialize the line offsets for looping.
622: int src1LineReal = src1OffsetReal;
623: int src1LineImag = src1OffsetImag;
624: int src2LineReal = src2OffsetReal;
625: int src2LineImag = src2OffsetImag;
626: int dstLineReal = dstOffsetReal;
627: int dstLineImag = dstOffsetImag;
628:
629: for (int row = 0; row < numRows; row++) {
630: // Initialize pixel offsets for this row.
631: int src1PixelReal = src1LineReal;
632: int src1PixelImag = src1LineImag;
633: int src2PixelReal = src2LineReal;
634: int src2PixelImag = src2LineImag;
635: int dstPixelReal = dstLineReal;
636: int dstPixelImag = dstLineImag;
637:
638: // Switch per line depending on operation type.
639: if (isDivision) { // Division
640: for (int col = 0; col < numCols; col++) {
641: int a = src1Real[src1PixelReal] & 0xffff;
642: int b = src1Imag[src1PixelImag] & 0xffff;
643: int c = src2Real[src2PixelReal] & 0xffff;
644: int d = src2Imag[src2PixelImag] & 0xffff;
645:
646: int denom = c * c + d * d;
647: dstReal[dstPixelReal] = ImageUtil
648: .clampUShort((a * c + b * d) / denom);
649: dstImag[dstPixelImag] = ImageUtil
650: .clampUShort((b * c - a * d) / denom);
651:
652: src1PixelReal += src1PixelStride;
653: src1PixelImag += src1PixelStride;
654: src2PixelReal += src2PixelStride;
655: src2PixelImag += src2PixelStride;
656: dstPixelReal += dstPixelStride;
657: dstPixelImag += dstPixelStride;
658: }
659: } else { // Multiplication
660: for (int col = 0; col < numCols; col++) {
661: int a = src1Real[src1PixelReal] & 0xffff;
662: int b = src1Imag[src1PixelImag] & 0xffff;
663: int c = src2Real[src2PixelReal] & 0xffff;
664: int d = src2Imag[src2PixelImag] & 0xffff;
665:
666: dstReal[dstPixelReal] = ImageUtil.clampUShort(a
667: * c - b * d);
668: dstImag[dstPixelImag] = ImageUtil.clampUShort(a
669: * d + b * c);
670:
671: src1PixelReal += src1PixelStride;
672: src1PixelImag += src1PixelStride;
673: src2PixelReal += src2PixelStride;
674: src2PixelImag += src2PixelStride;
675: dstPixelReal += dstPixelStride;
676: dstPixelImag += dstPixelStride;
677: }
678: }
679:
680: // Increment the line offsets.
681: src1LineReal += src1ScanlineStride;
682: src1LineImag += src1ScanlineStride;
683: src2LineReal += src2ScanlineStride;
684: src2LineImag += src2ScanlineStride;
685: dstLineReal += dstScanlineStride;
686: dstLineImag += dstScanlineStride;
687: }
688: }
689: }
690:
691: private void computeRectShort(RasterAccessor src1Accessor,
692: RasterAccessor src2Accessor, RasterAccessor dstAccessor) {
693: // Set the size of the rectangle.
694: int numRows = dstAccessor.getHeight();
695: int numCols = dstAccessor.getWidth();
696:
697: // Set pixel and line strides.
698: int src1PixelStride = src1Accessor.getPixelStride();
699: int src1ScanlineStride = src1Accessor.getScanlineStride();
700: int src2PixelStride = src2Accessor.getPixelStride();
701: int src2ScanlineStride = src2Accessor.getScanlineStride();
702: int dstPixelStride = dstAccessor.getPixelStride();
703: int dstScanlineStride = dstAccessor.getScanlineStride();
704:
705: // Loop over the destination bands.
706: int numElements = sampleModel.getNumBands() / 2;
707: for (int element = 0; element < numElements; element++) {
708: // Set band indices.
709: int realBand = 2 * element;
710: int imagBand = realBand + 1;
711:
712: // Get the source and destination arrays for this element.
713: short[] src1Real = src1Accessor
714: .getShortDataArray(s1r[element]);
715: short[] src1Imag = src1Accessor
716: .getShortDataArray(s1i[element]);
717: short[] src2Real = src2Accessor
718: .getShortDataArray(s2r[element]);
719: short[] src2Imag = src2Accessor
720: .getShortDataArray(s2i[element]);
721: short[] dstReal = dstAccessor.getShortDataArray(realBand);
722: short[] dstImag = dstAccessor.getShortDataArray(imagBand);
723:
724: // Initialize the data offsets for this element.
725: int src1OffsetReal = src1Accessor
726: .getBandOffset(s1r[element]);
727: int src1OffsetImag = src1Accessor
728: .getBandOffset(s1i[element]);
729: int src2OffsetReal = src2Accessor
730: .getBandOffset(s2r[element]);
731: int src2OffsetImag = src2Accessor
732: .getBandOffset(s2i[element]);
733: int dstOffsetReal = dstAccessor.getBandOffset(realBand);
734: int dstOffsetImag = dstAccessor.getBandOffset(imagBand);
735:
736: // Initialize the line offsets for looping.
737: int src1LineReal = src1OffsetReal;
738: int src1LineImag = src1OffsetImag;
739: int src2LineReal = src2OffsetReal;
740: int src2LineImag = src2OffsetImag;
741: int dstLineReal = dstOffsetReal;
742: int dstLineImag = dstOffsetImag;
743:
744: for (int row = 0; row < numRows; row++) {
745: // Initialize pixel offsets for this row.
746: int src1PixelReal = src1LineReal;
747: int src1PixelImag = src1LineImag;
748: int src2PixelReal = src2LineReal;
749: int src2PixelImag = src2LineImag;
750: int dstPixelReal = dstLineReal;
751: int dstPixelImag = dstLineImag;
752:
753: // Switch per line depending on operation type.
754: if (isDivision) { // Division
755: for (int col = 0; col < numCols; col++) {
756: int a = src1Real[src1PixelReal];
757: int b = src1Imag[src1PixelImag];
758: int c = src2Real[src2PixelReal];
759: int d = src2Imag[src2PixelImag];
760:
761: int denom = c * c + d * d;
762: dstReal[dstPixelReal] = ImageUtil.clampShort((a
763: * c + b * d)
764: / denom);
765: dstImag[dstPixelImag] = ImageUtil.clampShort((b
766: * c - a * d)
767: / denom);
768:
769: src1PixelReal += src1PixelStride;
770: src1PixelImag += src1PixelStride;
771: src2PixelReal += src2PixelStride;
772: src2PixelImag += src2PixelStride;
773: dstPixelReal += dstPixelStride;
774: dstPixelImag += dstPixelStride;
775: }
776: } else { // Multiplication
777: for (int col = 0; col < numCols; col++) {
778: int a = src1Real[src1PixelReal];
779: int b = src1Imag[src1PixelImag];
780: int c = src2Real[src2PixelReal];
781: int d = src2Imag[src2PixelImag];
782:
783: dstReal[dstPixelReal] = ImageUtil.clampShort(a
784: * c - b * d);
785: dstImag[dstPixelImag] = ImageUtil.clampShort(a
786: * d + b * c);
787:
788: src1PixelReal += src1PixelStride;
789: src1PixelImag += src1PixelStride;
790: src2PixelReal += src2PixelStride;
791: src2PixelImag += src2PixelStride;
792: dstPixelReal += dstPixelStride;
793: dstPixelImag += dstPixelStride;
794: }
795: }
796:
797: // Increment the line offsets.
798: src1LineReal += src1ScanlineStride;
799: src1LineImag += src1ScanlineStride;
800: src2LineReal += src2ScanlineStride;
801: src2LineImag += src2ScanlineStride;
802: dstLineReal += dstScanlineStride;
803: dstLineImag += dstScanlineStride;
804: }
805: }
806: }
807:
808: private void computeRectByte(RasterAccessor src1Accessor,
809: RasterAccessor src2Accessor, RasterAccessor dstAccessor) {
810: // Set the size of the rectangle.
811: int numRows = dstAccessor.getHeight();
812: int numCols = dstAccessor.getWidth();
813:
814: // Set pixel and line strides.
815: int src1PixelStride = src1Accessor.getPixelStride();
816: int src1ScanlineStride = src1Accessor.getScanlineStride();
817: int src2PixelStride = src2Accessor.getPixelStride();
818: int src2ScanlineStride = src2Accessor.getScanlineStride();
819: int dstPixelStride = dstAccessor.getPixelStride();
820: int dstScanlineStride = dstAccessor.getScanlineStride();
821:
822: // Loop over the destination bands.
823: int numElements = sampleModel.getNumBands() / 2;
824: for (int element = 0; element < numElements; element++) {
825: // Set band indices.
826: int realBand = 2 * element;
827: int imagBand = realBand + 1;
828:
829: // Get the source and destination arrays for this element.
830: byte[] src1Real = src1Accessor
831: .getByteDataArray(s1r[element]);
832: byte[] src1Imag = src1Accessor
833: .getByteDataArray(s1i[element]);
834: byte[] src2Real = src2Accessor
835: .getByteDataArray(s2r[element]);
836: byte[] src2Imag = src2Accessor
837: .getByteDataArray(s2i[element]);
838: byte[] dstReal = dstAccessor.getByteDataArray(realBand);
839: byte[] dstImag = dstAccessor.getByteDataArray(imagBand);
840:
841: // Initialize the data offsets for this element.
842: int src1OffsetReal = src1Accessor
843: .getBandOffset(s1r[element]);
844: int src1OffsetImag = src1Accessor
845: .getBandOffset(s1i[element]);
846: int src2OffsetReal = src2Accessor
847: .getBandOffset(s2r[element]);
848: int src2OffsetImag = src2Accessor
849: .getBandOffset(s2i[element]);
850: int dstOffsetReal = dstAccessor.getBandOffset(realBand);
851: int dstOffsetImag = dstAccessor.getBandOffset(imagBand);
852:
853: // Initialize the line offsets for looping.
854: int src1LineReal = src1OffsetReal;
855: int src1LineImag = src1OffsetImag;
856: int src2LineReal = src2OffsetReal;
857: int src2LineImag = src2OffsetImag;
858: int dstLineReal = dstOffsetReal;
859: int dstLineImag = dstOffsetImag;
860:
861: for (int row = 0; row < numRows; row++) {
862: // Initialize pixel offsets for this row.
863: int src1PixelReal = src1LineReal;
864: int src1PixelImag = src1LineImag;
865: int src2PixelReal = src2LineReal;
866: int src2PixelImag = src2LineImag;
867: int dstPixelReal = dstLineReal;
868: int dstPixelImag = dstLineImag;
869:
870: // Switch per line depending on operation type.
871: if (isDivision) { // Division
872: for (int col = 0; col < numCols; col++) {
873: int a = src1Real[src1PixelReal] & 0xff;
874: int b = src1Imag[src1PixelImag] & 0xff;
875: int c = src2Real[src2PixelReal] & 0xff;
876: int d = src2Imag[src2PixelImag] & 0xff;
877:
878: int denom = c * c + d * d;
879: dstReal[dstPixelReal] = ImageUtil.clampByte((a
880: * c + b * d)
881: / denom);
882: dstImag[dstPixelImag] = ImageUtil.clampByte((b
883: * c - a * d)
884: / denom);
885:
886: src1PixelReal += src1PixelStride;
887: src1PixelImag += src1PixelStride;
888: src2PixelReal += src2PixelStride;
889: src2PixelImag += src2PixelStride;
890: dstPixelReal += dstPixelStride;
891: dstPixelImag += dstPixelStride;
892: }
893: } else { // Multiplication
894: for (int col = 0; col < numCols; col++) {
895: int a = src1Real[src1PixelReal] & 0xff;
896: int b = src1Imag[src1PixelImag] & 0xff;
897: int c = src2Real[src2PixelReal] & 0xff;
898: int d = src2Imag[src2PixelImag] & 0xff;
899:
900: dstReal[dstPixelReal] = ImageUtil.clampByte(a
901: * c - b * d);
902: dstImag[dstPixelImag] = ImageUtil.clampByte(a
903: * d + b * c);
904:
905: src1PixelReal += src1PixelStride;
906: src1PixelImag += src1PixelStride;
907: src2PixelReal += src2PixelStride;
908: src2PixelImag += src2PixelStride;
909: dstPixelReal += dstPixelStride;
910: dstPixelImag += dstPixelStride;
911: }
912: }
913:
914: // Increment the line offsets.
915: src1LineReal += src1ScanlineStride;
916: src1LineImag += src1ScanlineStride;
917: src2LineReal += src2ScanlineStride;
918: src2LineImag += src2ScanlineStride;
919: dstLineReal += dstScanlineStride;
920: dstLineImag += dstScanlineStride;
921: }
922: }
923: }
924: }
|