001: /*
002: * $RCSfile: MagnitudePhaseOpImage.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:31 $
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.PlanarImage;
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: /// XXX Testing
031: /// import java.awt.Point;
032: /// import javax.media.jai.TiledImage;
033:
034: /**
035: * An <code>OpImage</code> implementing magnitude, magnitude squared,
036: * and phase operations as described in
037: * <code>javax.media.jai.operator.MagnitudeDescriptor</code>,
038: * <code>javax.media.jai.operator.MagnitudeSquaredDescriptor</code>, and
039: * <code>javax.media.jai.operator.PhaseDescriptor</code>
040: *
041: * <p> This implementation assumes that the number of bands in the source image
042: * is at least two. The number of bands in the destination image is clamped to
043: * half (in the integer division sense) of the number of bands in the source
044: * image.
045: *
046: * @since EA3
047: *
048: * @see javax.media.jai.UntiledOpImage
049: * @see javax.media.jai.operator.MagnitudeDescriptor
050: * @see javax.media.jai.operator.MagnitudeSquaredDescriptor
051: * @see javax.media.jai.operator.PhaseDescriptor
052: *
053: */
054: final class MagnitudePhaseOpImage extends PointOpImage {
055: /** A flag indicating a magnitude or modulus operation. */
056: public static final int MAGNITUDE = 1;
057:
058: /** A flag indicating a magnitude squared or "power spectrum" operation. */
059: public static final int MAGNITUDE_SQUARED = 2;
060:
061: /** A flag indicating a phase operation. */
062: public static final int PHASE = 3;
063:
064: /** The type of operation as specified by one of the static final types. */
065: protected int operationType;
066:
067: /** The gain to be applied to the phase. */
068: private double phaseGain = 1.0;
069:
070: /** The bias to be applied to the phase. */
071: private double phaseBias = 0.0;
072:
073: /**
074: * Constructs a <code>MagnitudePhaseOpImage</code> object.
075: *
076: * <p>The tile grid layout, SampleModel, and ColorModel may optionally
077: * be specified by an ImageLayout object.
078: *
079: * @param source A RenderedImage.
080: * @param layout An ImageLayout optionally containing the tile grid layout,
081: * SampleModel, and ColorModel, or null.
082: * @param operationType One of the static final flag values defined in
083: * this class which indicates the type of operation to perform.
084: */
085: public MagnitudePhaseOpImage(RenderedImage source, Map config,
086: ImageLayout layout, int operationType) {
087: super (source, layout, config, true);
088:
089: // Cache the parameter.
090: this .operationType = operationType;
091:
092: // Initialize the SampleModel flag.
093: boolean needNewSampleModel = false;
094:
095: // Reset the data type to that specified by the layout if it
096: // has been modified within the superclass constructor chain.
097: int dataType = sampleModel.getTransferType();
098: if (layout != null
099: && dataType != layout.getSampleModel(source)
100: .getTransferType()) {
101: dataType = layout.getSampleModel(source).getTransferType();
102: needNewSampleModel = true;
103: }
104:
105: // Force the band count to be at most half that of the source image.
106: int numBands = sampleModel.getNumBands();
107: if (numBands > source.getSampleModel().getNumBands() / 2) {
108: numBands = source.getSampleModel().getNumBands() / 2;
109: needNewSampleModel = true;
110: }
111:
112: // Create a new SampleModel for the destination.
113: if (needNewSampleModel) {
114: sampleModel = RasterFactory.createComponentSampleModel(
115: sampleModel, dataType, sampleModel.getWidth(),
116: sampleModel.getHeight(), numBands);
117:
118: if (colorModel != null
119: && !JDKWorkarounds.areCompatibleDataModels(
120: sampleModel, colorModel)) {
121: colorModel = ImageUtil.getCompatibleColorModel(
122: sampleModel, config);
123: }
124: }
125:
126: if (operationType == PHASE) {
127: // Set phase gain and bias as a function of destination data type.
128: switch (dataType) {
129: case DataBuffer.TYPE_BYTE:
130: phaseGain = 255.0 / (2.0 * Math.PI);
131: phaseBias = Math.PI;
132: break;
133: case DataBuffer.TYPE_SHORT:
134: phaseGain = Short.MAX_VALUE / (2.0 * Math.PI);
135: phaseBias = Math.PI;
136: break;
137: case DataBuffer.TYPE_USHORT:
138: phaseGain = (Short.MAX_VALUE - Short.MIN_VALUE)
139: / (2.0 * Math.PI);
140: phaseBias = Math.PI;
141: break;
142: case DataBuffer.TYPE_INT:
143: phaseGain = Integer.MAX_VALUE / (2.0 * Math.PI);
144: phaseBias = Math.PI;
145: break;
146: default:
147: // A floating point type: do nothing.
148: }
149: }
150: }
151:
152: /*
153: * Calculate the magnitude [squared] or phase of the source image.
154: *
155: * @param sources Cobbled sources, guaranteed to provide all the
156: * source data necessary for computing the rectangle.
157: * @param dest The tile containing the rectangle to be computed.
158: * @param destRect The rectangle within the tile to be computed.
159: */
160: protected void computeRect(Raster[] sources, WritableRaster dest,
161: Rectangle destRect) {
162: // Retrieve format tags.
163: RasterFormatTag[] formatTags = getFormatTags();
164:
165: // Construct RasterAccessors.
166: RasterAccessor srcAccessor = new RasterAccessor(sources[0],
167: destRect, formatTags[0], getSourceImage(0)
168: .getColorModel());
169: RasterAccessor dstAccessor = new RasterAccessor(dest, destRect,
170: formatTags[1], getColorModel());
171:
172: // Branch to the method appropriate to the accessor data type.
173: switch (dstAccessor.getDataType()) {
174: case DataBuffer.TYPE_BYTE:
175: computeRectByte(srcAccessor, dstAccessor, destRect.height,
176: destRect.width);
177: break;
178: case DataBuffer.TYPE_SHORT:
179: computeRectShort(srcAccessor, dstAccessor, destRect.height,
180: destRect.width);
181: break;
182: case DataBuffer.TYPE_USHORT:
183: computeRectUShort(srcAccessor, dstAccessor,
184: destRect.height, destRect.width);
185: break;
186: case DataBuffer.TYPE_INT:
187: computeRectInt(srcAccessor, dstAccessor, destRect.height,
188: destRect.width);
189: break;
190: case DataBuffer.TYPE_FLOAT:
191: computeRectFloat(srcAccessor, dstAccessor, destRect.height,
192: destRect.width);
193: break;
194: case DataBuffer.TYPE_DOUBLE:
195: computeRectDouble(srcAccessor, dstAccessor,
196: destRect.height, destRect.width);
197: break;
198: default:
199: // NB: This statement should be unreachable.
200: throw new RuntimeException(JaiI18N
201: .getString("MagnitudePhaseOpImage0"));
202: }
203:
204: if (dstAccessor.needsClamping()) {
205: dstAccessor.clampDataArrays();
206: }
207:
208: // Make sure that the output data is copied to the destination.
209: dstAccessor.copyDataToRaster();
210: }
211:
212: private void computeRectDouble(RasterAccessor srcAccessor,
213: RasterAccessor dstAccessor, int numRows, int numCols) {
214: // Set pixel and line strides.
215: int srcPixelStride = srcAccessor.getPixelStride();
216: int srcScanlineStride = srcAccessor.getScanlineStride();
217: int dstPixelStride = dstAccessor.getPixelStride();
218: int dstScanlineStride = dstAccessor.getScanlineStride();
219:
220: // Loop over the destination bands.
221: int numDstBands = sampleModel.getNumBands();
222: for (int dstBand = 0; dstBand < numDstBands; dstBand++) {
223: // Set source band indices.
224: int srcBandReal = 2 * dstBand;
225: int srcBandImag = srcBandReal + 1;
226:
227: // Get the source and destination arrays for this band.
228: double[] srcReal = srcAccessor
229: .getDoubleDataArray(srcBandReal);
230: double[] srcImag = srcAccessor
231: .getDoubleDataArray(srcBandImag);
232: double[] dstData = dstAccessor.getDoubleDataArray(dstBand);
233:
234: // Initialize the data offsets for this band.
235: int srcOffsetReal = srcAccessor.getBandOffset(srcBandReal);
236: int srcOffsetImag = srcAccessor.getBandOffset(srcBandImag);
237: int dstOffset = dstAccessor.getBandOffset(dstBand);
238:
239: // Initialize the line offsets for looping.
240: int srcLineReal = srcOffsetReal;
241: int srcLineImag = srcOffsetImag;
242: int dstLine = dstOffset;
243:
244: for (int row = 0; row < numRows; row++) {
245: // Initialize pixel offsets for this row.
246: int srcPixelReal = srcLineReal;
247: int srcPixelImag = srcLineImag;
248: int dstPixel = dstLine;
249:
250: // Switch per line based on operation type.
251: switch (operationType) {
252: case MAGNITUDE:
253: for (int col = 0; col < numCols; col++) {
254: double real = srcReal[srcPixelReal];
255: double imag = srcImag[srcPixelImag];
256:
257: dstData[dstPixel] = Math.sqrt(real * real
258: + imag * imag);
259:
260: srcPixelReal += srcPixelStride;
261: srcPixelImag += srcPixelStride;
262: dstPixel += dstPixelStride;
263: }
264: break;
265: case MAGNITUDE_SQUARED:
266: for (int col = 0; col < numCols; col++) {
267: double real = srcReal[srcPixelReal];
268: double imag = srcImag[srcPixelImag];
269:
270: dstData[dstPixel] = real * real + imag * imag;
271:
272: srcPixelReal += srcPixelStride;
273: srcPixelImag += srcPixelStride;
274: dstPixel += dstPixelStride;
275: }
276: break;
277: case PHASE:
278: for (int col = 0; col < numCols; col++) {
279: double real = srcReal[srcPixelReal];
280: double imag = srcImag[srcPixelImag];
281:
282: dstData[dstPixel] = Math.atan2(imag, real);
283:
284: srcPixelReal += srcPixelStride;
285: srcPixelImag += srcPixelStride;
286: dstPixel += dstPixelStride;
287: }
288: break;
289: }
290:
291: // Increment the line offsets.
292: srcLineReal += srcScanlineStride;
293: srcLineImag += srcScanlineStride;
294: dstLine += dstScanlineStride;
295: }
296: }
297: }
298:
299: private void computeRectFloat(RasterAccessor srcAccessor,
300: RasterAccessor dstAccessor, int numRows, int numCols) {
301: // Set pixel and line strides.
302: int srcPixelStride = srcAccessor.getPixelStride();
303: int srcScanlineStride = srcAccessor.getScanlineStride();
304: int dstPixelStride = dstAccessor.getPixelStride();
305: int dstScanlineStride = dstAccessor.getScanlineStride();
306:
307: // Loop over the destination bands.
308: int numDstBands = sampleModel.getNumBands();
309: for (int dstBand = 0; dstBand < numDstBands; dstBand++) {
310: // Set source band indices.
311: int srcBandReal = 2 * dstBand;
312: int srcBandImag = srcBandReal + 1;
313:
314: // Get the source and destination arrays for this band.
315: float[] srcReal = srcAccessor
316: .getFloatDataArray(srcBandReal);
317: float[] srcImag = srcAccessor
318: .getFloatDataArray(srcBandImag);
319: float[] dstData = dstAccessor.getFloatDataArray(dstBand);
320:
321: // Initialize the data offsets for this band.
322: int srcOffsetReal = srcAccessor.getBandOffset(srcBandReal);
323: int srcOffsetImag = srcAccessor.getBandOffset(srcBandImag);
324: int dstOffset = dstAccessor.getBandOffset(dstBand);
325:
326: // Initialize the line offsets for looping.
327: int srcLineReal = srcOffsetReal;
328: int srcLineImag = srcOffsetImag;
329: int dstLine = dstOffset;
330:
331: for (int row = 0; row < numRows; row++) {
332: // Initialize pixel offsets for this row.
333: int srcPixelReal = srcLineReal;
334: int srcPixelImag = srcLineImag;
335: int dstPixel = dstLine;
336:
337: // Switch per line based on operation type.
338: switch (operationType) {
339: case MAGNITUDE:
340: for (int col = 0; col < numCols; col++) {
341: float real = srcReal[srcPixelReal];
342: float imag = srcImag[srcPixelImag];
343:
344: dstData[dstPixel] = ImageUtil.clampFloat(Math
345: .sqrt(real * real + imag * imag));
346:
347: srcPixelReal += srcPixelStride;
348: srcPixelImag += srcPixelStride;
349: dstPixel += dstPixelStride;
350: }
351: break;
352: case MAGNITUDE_SQUARED:
353: for (int col = 0; col < numCols; col++) {
354: float real = srcReal[srcPixelReal];
355: float imag = srcImag[srcPixelImag];
356:
357: dstData[dstPixel] = real * real + imag * imag;
358:
359: srcPixelReal += srcPixelStride;
360: srcPixelImag += srcPixelStride;
361: dstPixel += dstPixelStride;
362: }
363: break;
364: case PHASE:
365: for (int col = 0; col < numCols; col++) {
366: float real = srcReal[srcPixelReal];
367: float imag = srcImag[srcPixelImag];
368:
369: dstData[dstPixel] = ImageUtil.clampFloat(Math
370: .atan2(imag, real));
371:
372: srcPixelReal += srcPixelStride;
373: srcPixelImag += srcPixelStride;
374: dstPixel += dstPixelStride;
375: }
376: break;
377: }
378:
379: // Increment the line offsets.
380: srcLineReal += srcScanlineStride;
381: srcLineImag += srcScanlineStride;
382: dstLine += dstScanlineStride;
383: }
384: }
385: }
386:
387: private void computeRectInt(RasterAccessor srcAccessor,
388: RasterAccessor dstAccessor, int numRows, int numCols) {
389: // Set pixel and line strides.
390: int srcPixelStride = srcAccessor.getPixelStride();
391: int srcScanlineStride = srcAccessor.getScanlineStride();
392: int dstPixelStride = dstAccessor.getPixelStride();
393: int dstScanlineStride = dstAccessor.getScanlineStride();
394:
395: // Loop over the destination bands.
396: int numDstBands = sampleModel.getNumBands();
397: for (int dstBand = 0; dstBand < numDstBands; dstBand++) {
398: // Set source band indices.
399: int srcBandReal = 2 * dstBand;
400: int srcBandImag = srcBandReal + 1;
401:
402: // Get the source and destination arrays for this band.
403: int[] srcReal = srcAccessor.getIntDataArray(srcBandReal);
404: int[] srcImag = srcAccessor.getIntDataArray(srcBandImag);
405: int[] dstData = dstAccessor.getIntDataArray(dstBand);
406:
407: // Initialize the data offsets for this band.
408: int srcOffsetReal = srcAccessor.getBandOffset(srcBandReal);
409: int srcOffsetImag = srcAccessor.getBandOffset(srcBandImag);
410: int dstOffset = dstAccessor.getBandOffset(dstBand);
411:
412: // Initialize the line offsets for looping.
413: int srcLineReal = srcOffsetReal;
414: int srcLineImag = srcOffsetImag;
415: int dstLine = dstOffset;
416:
417: for (int row = 0; row < numRows; row++) {
418: // Initialize pixel offsets for this row.
419: int srcPixelReal = srcLineReal;
420: int srcPixelImag = srcLineImag;
421: int dstPixel = dstLine;
422:
423: // Switch per line based on operation type.
424: switch (operationType) {
425: case MAGNITUDE:
426: for (int col = 0; col < numCols; col++) {
427: int real = srcReal[srcPixelReal];
428: int imag = srcImag[srcPixelImag];
429:
430: dstData[dstPixel] = ImageUtil
431: .clampRoundInt(Math.sqrt(real * real
432: + imag * imag));
433:
434: srcPixelReal += srcPixelStride;
435: srcPixelImag += srcPixelStride;
436: dstPixel += dstPixelStride;
437: }
438: break;
439: case MAGNITUDE_SQUARED:
440: for (int col = 0; col < numCols; col++) {
441: int real = srcReal[srcPixelReal];
442: int imag = srcImag[srcPixelImag];
443:
444: dstData[dstPixel] = real * real + imag * imag;
445:
446: srcPixelReal += srcPixelStride;
447: srcPixelImag += srcPixelStride;
448: dstPixel += dstPixelStride;
449: }
450: break;
451: case PHASE:
452: for (int col = 0; col < numCols; col++) {
453: int real = srcReal[srcPixelReal];
454: int imag = srcImag[srcPixelImag];
455:
456: dstData[dstPixel] = ImageUtil
457: .clampRoundInt((Math.atan2(imag, real) + phaseBias)
458: * phaseGain);
459:
460: srcPixelReal += srcPixelStride;
461: srcPixelImag += srcPixelStride;
462: dstPixel += dstPixelStride;
463: }
464: break;
465: }
466:
467: // Increment the line offsets.
468: srcLineReal += srcScanlineStride;
469: srcLineImag += srcScanlineStride;
470: dstLine += dstScanlineStride;
471: }
472: }
473: }
474:
475: private void computeRectUShort(RasterAccessor srcAccessor,
476: RasterAccessor dstAccessor, int numRows, int numCols) {
477: // Set pixel and line strides.
478: int srcPixelStride = srcAccessor.getPixelStride();
479: int srcScanlineStride = srcAccessor.getScanlineStride();
480: int dstPixelStride = dstAccessor.getPixelStride();
481: int dstScanlineStride = dstAccessor.getScanlineStride();
482:
483: // Loop over the destination bands.
484: int numDstBands = sampleModel.getNumBands();
485: for (int dstBand = 0; dstBand < numDstBands; dstBand++) {
486: // Set source band indices.
487: int srcBandReal = 2 * dstBand;
488: int srcBandImag = srcBandReal + 1;
489:
490: // Get the source and destination arrays for this band.
491: short[] srcReal = srcAccessor
492: .getShortDataArray(srcBandReal);
493: short[] srcImag = srcAccessor
494: .getShortDataArray(srcBandImag);
495: short[] dstData = dstAccessor.getShortDataArray(dstBand);
496:
497: // Initialize the data offsets for this band.
498: int srcOffsetReal = srcAccessor.getBandOffset(srcBandReal);
499: int srcOffsetImag = srcAccessor.getBandOffset(srcBandImag);
500: int dstOffset = dstAccessor.getBandOffset(dstBand);
501:
502: // Initialize the line offsets for looping.
503: int srcLineReal = srcOffsetReal;
504: int srcLineImag = srcOffsetImag;
505: int dstLine = dstOffset;
506:
507: for (int row = 0; row < numRows; row++) {
508: // Initialize pixel offsets for this row.
509: int srcPixelReal = srcLineReal;
510: int srcPixelImag = srcLineImag;
511: int dstPixel = dstLine;
512:
513: // Switch per line based on operation type.
514: switch (operationType) {
515: case MAGNITUDE:
516: for (int col = 0; col < numCols; col++) {
517: int real = srcReal[srcPixelReal] & 0xffff;
518: int imag = srcImag[srcPixelImag] & 0xffff;
519:
520: dstData[dstPixel] = ImageUtil
521: .clampRoundUShort(Math.sqrt(real * real
522: + imag * imag));
523:
524: srcPixelReal += srcPixelStride;
525: srcPixelImag += srcPixelStride;
526: dstPixel += dstPixelStride;
527: }
528: break;
529: case MAGNITUDE_SQUARED:
530: for (int col = 0; col < numCols; col++) {
531: int real = srcReal[srcPixelReal] & 0xffff;
532: int imag = srcImag[srcPixelImag] & 0xffff;
533:
534: dstData[dstPixel] = ImageUtil.clampUShort(real
535: * real + imag * imag);
536:
537: srcPixelReal += srcPixelStride;
538: srcPixelImag += srcPixelStride;
539: dstPixel += dstPixelStride;
540: }
541: break;
542: case PHASE:
543: for (int col = 0; col < numCols; col++) {
544: int real = srcReal[srcPixelReal] & 0xffff;
545: int imag = srcImag[srcPixelImag] & 0xffff;
546:
547: dstData[dstPixel] = ImageUtil
548: .clampRoundUShort((Math.atan2(imag,
549: real) + phaseBias)
550: * phaseGain);
551:
552: srcPixelReal += srcPixelStride;
553: srcPixelImag += srcPixelStride;
554: dstPixel += dstPixelStride;
555: }
556: break;
557: }
558:
559: // Increment the line offsets.
560: srcLineReal += srcScanlineStride;
561: srcLineImag += srcScanlineStride;
562: dstLine += dstScanlineStride;
563: }
564: }
565: }
566:
567: private void computeRectShort(RasterAccessor srcAccessor,
568: RasterAccessor dstAccessor, int numRows, int numCols) {
569: // Set pixel and line strides.
570: int srcPixelStride = srcAccessor.getPixelStride();
571: int srcScanlineStride = srcAccessor.getScanlineStride();
572: int dstPixelStride = dstAccessor.getPixelStride();
573: int dstScanlineStride = dstAccessor.getScanlineStride();
574:
575: // Loop over the destination bands.
576: int numDstBands = sampleModel.getNumBands();
577: for (int dstBand = 0; dstBand < numDstBands; dstBand++) {
578: // Set source band indices.
579: int srcBandReal = 2 * dstBand;
580: int srcBandImag = srcBandReal + 1;
581:
582: // Get the source and destination arrays for this band.
583: short[] srcReal = srcAccessor
584: .getShortDataArray(srcBandReal);
585: short[] srcImag = srcAccessor
586: .getShortDataArray(srcBandImag);
587: short[] dstData = dstAccessor.getShortDataArray(dstBand);
588:
589: // Initialize the data offsets for this band.
590: int srcOffsetReal = srcAccessor.getBandOffset(srcBandReal);
591: int srcOffsetImag = srcAccessor.getBandOffset(srcBandImag);
592: int dstOffset = dstAccessor.getBandOffset(dstBand);
593:
594: // Initialize the line offsets for looping.
595: int srcLineReal = srcOffsetReal;
596: int srcLineImag = srcOffsetImag;
597: int dstLine = dstOffset;
598:
599: for (int row = 0; row < numRows; row++) {
600: // Initialize pixel offsets for this row.
601: int srcPixelReal = srcLineReal;
602: int srcPixelImag = srcLineImag;
603: int dstPixel = dstLine;
604:
605: // Switch per line based on operation type.
606: switch (operationType) {
607: case MAGNITUDE:
608: for (int col = 0; col < numCols; col++) {
609: short real = srcReal[srcPixelReal];
610: short imag = srcImag[srcPixelImag];
611:
612: dstData[dstPixel] = ImageUtil
613: .clampRoundShort(Math.sqrt(real * real
614: + imag * imag));
615:
616: srcPixelReal += srcPixelStride;
617: srcPixelImag += srcPixelStride;
618: dstPixel += dstPixelStride;
619: }
620: break;
621: case MAGNITUDE_SQUARED:
622: for (int col = 0; col < numCols; col++) {
623: short real = srcReal[srcPixelReal];
624: short imag = srcImag[srcPixelImag];
625:
626: dstData[dstPixel] = ImageUtil.clampShort(real
627: * real + imag * imag);
628:
629: srcPixelReal += srcPixelStride;
630: srcPixelImag += srcPixelStride;
631: dstPixel += dstPixelStride;
632: }
633: break;
634: case PHASE:
635: for (int col = 0; col < numCols; col++) {
636: short real = srcReal[srcPixelReal];
637: short imag = srcImag[srcPixelImag];
638:
639: dstData[dstPixel] = ImageUtil
640: .clampRoundShort((Math
641: .atan2(imag, real) + phaseBias)
642: * phaseGain);
643:
644: srcPixelReal += srcPixelStride;
645: srcPixelImag += srcPixelStride;
646: dstPixel += dstPixelStride;
647: }
648: break;
649: }
650:
651: // Increment the line offsets.
652: srcLineReal += srcScanlineStride;
653: srcLineImag += srcScanlineStride;
654: dstLine += dstScanlineStride;
655: }
656: }
657: }
658:
659: private void computeRectByte(RasterAccessor srcAccessor,
660: RasterAccessor dstAccessor, int numRows, int numCols) {
661: // Set pixel and line strides.
662: int srcPixelStride = srcAccessor.getPixelStride();
663: int srcScanlineStride = srcAccessor.getScanlineStride();
664: int dstPixelStride = dstAccessor.getPixelStride();
665: int dstScanlineStride = dstAccessor.getScanlineStride();
666:
667: // Loop over the destination bands.
668: int numDstBands = sampleModel.getNumBands();
669: for (int dstBand = 0; dstBand < numDstBands; dstBand++) {
670: // Set source band indices.
671: int srcBandReal = 2 * dstBand;
672: int srcBandImag = srcBandReal + 1;
673:
674: // Get the source and destination arrays for this band.
675: byte[] srcReal = srcAccessor.getByteDataArray(srcBandReal);
676: byte[] srcImag = srcAccessor.getByteDataArray(srcBandImag);
677: byte[] dstData = dstAccessor.getByteDataArray(dstBand);
678:
679: // Initialize the data offsets for this band.
680: int srcOffsetReal = srcAccessor.getBandOffset(srcBandReal);
681: int srcOffsetImag = srcAccessor.getBandOffset(srcBandImag);
682: int dstOffset = dstAccessor.getBandOffset(dstBand);
683:
684: // Initialize the line offsets for looping.
685: int srcLineReal = srcOffsetReal;
686: int srcLineImag = srcOffsetImag;
687: int dstLine = dstOffset;
688:
689: for (int row = 0; row < numRows; row++) {
690: // Initialize pixel offsets for this row.
691: int srcPixelReal = srcLineReal;
692: int srcPixelImag = srcLineImag;
693: int dstPixel = dstLine;
694:
695: // Switch per line based on operation type.
696: switch (operationType) {
697: case MAGNITUDE:
698: for (int col = 0; col < numCols; col++) {
699: int real = srcReal[srcPixelReal] & 0xff;
700: int imag = srcImag[srcPixelImag] & 0xff;
701:
702: dstData[dstPixel] = ImageUtil
703: .clampRoundByte(Math.sqrt(real * real
704: + imag * imag));
705:
706: srcPixelReal += srcPixelStride;
707: srcPixelImag += srcPixelStride;
708: dstPixel += dstPixelStride;
709: }
710: break;
711: case MAGNITUDE_SQUARED:
712: for (int col = 0; col < numCols; col++) {
713: int real = srcReal[srcPixelReal] & 0xff;
714: int imag = srcImag[srcPixelImag] & 0xff;
715:
716: dstData[dstPixel] = ImageUtil.clampByte(real
717: * real + imag * imag);
718:
719: srcPixelReal += srcPixelStride;
720: srcPixelImag += srcPixelStride;
721: dstPixel += dstPixelStride;
722: }
723: break;
724: case PHASE:
725: for (int col = 0; col < numCols; col++) {
726: int real = srcReal[srcPixelReal] & 0xff;
727: int imag = srcImag[srcPixelImag] & 0xff;
728:
729: dstData[dstPixel] = ImageUtil
730: .clampRoundByte((Math.atan2(imag, real) + phaseBias)
731: * phaseGain);
732:
733: srcPixelReal += srcPixelStride;
734: srcPixelImag += srcPixelStride;
735: dstPixel += dstPixelStride;
736: }
737: break;
738: }
739:
740: // Increment the line offsets.
741: srcLineReal += srcScanlineStride;
742: srcLineImag += srcScanlineStride;
743: dstLine += dstScanlineStride;
744: }
745: }
746: }
747:
748: // public static void main(String args[]) {
749: // int opType = args.length > 0 ?
750: // Integer.valueOf(args[0]).intValue() : 1;
751: // int dataType = args.length > 1 ?
752: // Integer.valueOf(args[1]).intValue() : DataBuffer.TYPE_DOUBLE;
753: // double[] pixels = new double[] { 1, 2, 3, 4,
754: // 5, 6, 7, 8,
755: // 9, 10, 11, 12,
756: // 13, 14, 15, 16 };
757: // WritableRaster pattern =
758: // RasterFactory.createBandedRaster(dataType, 2, 2, 4,
759: // new Point(0, 0));
760: // pattern.setPixels(0, 0, 2, 2, pixels);
761: // TiledImage src =
762: // TiledImage.createInterleaved(0, 0,
763: // pattern.getWidth(), pattern.getHeight(),
764: // pattern.getSampleModel().getNumBands(),
765: // pattern.getSampleModel().getTransferType(),
766: // pattern.getWidth(), pattern.getHeight(),
767: // new int[] {0, 1, 2, 3});
768: // src.setData(pattern);
769:
770: // MagnitudePhaseOpImage dst =
771: // new MagnitudePhaseOpImage(src, null, opType);
772: // pixels = dst.getData().getPixels(0, 0, 2, 2, (double[])null);
773: // System.out.println("");
774: // for(int i = 0; i < pixels.length; i += 2) {
775: // System.out.println(pixels[i] + " " + pixels[i+1]);
776: // }
777: // }
778: }
|