001: /*
002: * $RCSfile: ConjugateOpImage.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:19 $
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 java.awt.image.renderable.ParameterBlock;
022: import javax.media.jai.ImageLayout;
023: import javax.media.jai.PointOpImage;
024: import javax.media.jai.OpImage;
025: import javax.media.jai.RasterAccessor;
026: import javax.media.jai.RasterFormatTag;
027: import javax.media.jai.RasterFactory;
028: import java.util.Map;
029: import com.sun.media.jai.util.ImageUtil;
030: import com.sun.media.jai.util.JDKWorkarounds;
031:
032: /// Testing
033: /// import javax.media.jai.JAI;
034: /// import javax.media.jai.TiledImage;
035:
036: /**
037: * An <code>OpImage</code> implementing the "conjugate" operation as
038: * described in <code>javax.media.jai.operator.ConjugateDescriptor</code>.
039: *
040: * <p> Note that this operation requires a signed destination image so that
041: * the SampleModel is overriden to force byte and unsigned short types to
042: * short and integer, respectively.
043: *
044: * @since EA4
045: */
046: final class ConjugateOpImage extends PointOpImage {
047:
048: /**
049: * Force the destination image to have a signed data type.
050: */
051: private static ImageLayout layoutHelper(ImageLayout layout,
052: RenderedImage source) {
053: // Create or clone the layout.
054: ImageLayout il = layout == null ? new ImageLayout()
055: : (ImageLayout) layout.clone();
056:
057: // Get the reference SampleModel.
058: SampleModel sm = il.getSampleModel(source);
059:
060: // Get the data type.
061: int dataType = sm.getTransferType();
062:
063: // Determine whether the destination requires a different data type
064: // and set it if so.
065: boolean createNewSampleModel = false;
066: if (dataType == DataBuffer.TYPE_BYTE) {
067: dataType = DataBuffer.TYPE_SHORT;
068: createNewSampleModel = true;
069: } else if (dataType == DataBuffer.TYPE_USHORT) {
070: dataType = DataBuffer.TYPE_INT;
071: createNewSampleModel = true;
072: }
073:
074: // Create a new SampleModel for the destination if necessary.
075: if (createNewSampleModel) {
076: sm = RasterFactory.createComponentSampleModel(sm, dataType,
077: sm.getWidth(), sm.getHeight(), sm.getNumBands());
078:
079: il.setSampleModel(sm);
080:
081: // Check ColorModel.
082: ColorModel cm = il.getColorModel(null);
083: if (cm != null
084: && !JDKWorkarounds.areCompatibleDataModels(sm, cm)) {
085: // Clear the mask bit if incompatible.
086: il.unsetValid(ImageLayout.COLOR_MODEL_MASK);
087: }
088: }
089:
090: return il;
091: }
092:
093: /**
094: * Constructs a ConjugateOpImage. The image dimensions are copied
095: * from the source image. The tile grid layout, SampleModel, and
096: * ColorModel may optionally be specified by an ImageLayout object.
097: * The destination data type must be the smallest appropriate signed
098: * data type.
099: *
100: * @param source a RenderedImage.
101: * @param layout an ImageLayout optionally containing the tile
102: * grid layout, SampleModel, and ColorModel, or null.
103: */
104: public ConjugateOpImage(RenderedImage source, Map config,
105: ImageLayout layout) {
106: super (source, layoutHelper(layout, source), config, true);
107:
108: // Set flag to permit in-place operation.
109: permitInPlaceOperation();
110: }
111:
112: /**
113: * Calculates the complex conjugate of the source image.
114: * The sources are cobbled.
115: *
116: * @param sources an array of sources, guarantee to provide all
117: * necessary source data for computing the rectangle.
118: * @param dest a tile that contains the rectangle to be computed.
119: * @param destRect the rectangle within this OpImage to be processed.
120: */
121: protected void computeRect(Raster[] sources, WritableRaster dest,
122: Rectangle destRect) {
123: // Retrieve format tags.
124: RasterFormatTag[] formatTags = getFormatTags();
125:
126: Raster source = sources[0];
127: Rectangle srcRect = mapDestRect(destRect, 0);
128:
129: RasterAccessor srcAccessor = new RasterAccessor(source,
130: srcRect, formatTags[0], getSourceImage(0)
131: .getColorModel());
132:
133: RasterAccessor dstAccessor = new RasterAccessor(dest, destRect,
134: formatTags[1], getColorModel());
135:
136: switch (dstAccessor.getDataType()) {
137: case DataBuffer.TYPE_SHORT:
138: shortLoop(srcAccessor, dstAccessor);
139: break;
140: case DataBuffer.TYPE_INT:
141: intLoop(srcAccessor, dstAccessor);
142: break;
143: case DataBuffer.TYPE_FLOAT:
144: floatLoop(srcAccessor, dstAccessor);
145: break;
146: case DataBuffer.TYPE_DOUBLE:
147: doubleLoop(srcAccessor, dstAccessor);
148: break;
149: case DataBuffer.TYPE_BYTE:
150: case DataBuffer.TYPE_USHORT:
151: default:
152: throw new RuntimeException(JaiI18N
153: .getString("ConjugateOpImage0"));
154: }
155:
156: // If the RasterAccessor object set up a temporary buffer for the
157: // op to write to, tell the RasterAccessor to write that data
158: // to the raster no that we're done with it.
159: if (dstAccessor.isDataCopy()) {
160: dstAccessor.clampDataArrays();
161: dstAccessor.copyDataToRaster();
162: }
163: }
164:
165: private void shortLoop(RasterAccessor src, RasterAccessor dst) {
166: int dwidth = dst.getWidth();
167: int dheight = dst.getHeight();
168: int dnumBands = dst.getNumBands();
169:
170: short dstDataArrays[][] = dst.getShortDataArrays();
171: int dstBandOffsets[] = dst.getBandOffsets();
172: int dstPixelStride = dst.getPixelStride();
173: int dstScanlineStride = dst.getScanlineStride();
174:
175: short srcDataArrays[][] = src.getShortDataArrays();
176: int srcBandOffsets[] = src.getBandOffsets();
177: int srcPixelStride = src.getPixelStride();
178: int srcScanlineStride = src.getScanlineStride();
179:
180: for (int k = 0; k < dnumBands; k++) {
181: boolean isRealPart = k % 2 == 0;
182: short dstData[] = dstDataArrays[k];
183: short srcData[] = srcDataArrays[k];
184: int srcScanlineOffset = srcBandOffsets[k];
185: int dstScanlineOffset = dstBandOffsets[k];
186: if (isRealPart) { // real part: copy value
187: for (int j = 0; j < dheight; j++) {
188: int srcPixelOffset = srcScanlineOffset;
189: int dstPixelOffset = dstScanlineOffset;
190: for (int i = 0; i < dwidth; i++) {
191: dstData[dstPixelOffset] = srcData[srcPixelOffset];
192: srcPixelOffset += srcPixelStride;
193: dstPixelOffset += dstPixelStride;
194: }
195: srcScanlineOffset += srcScanlineStride;
196: dstScanlineOffset += dstScanlineStride;
197: }
198: } else { // imaginary part: negate value
199: for (int j = 0; j < dheight; j++) {
200: int srcPixelOffset = srcScanlineOffset;
201: int dstPixelOffset = dstScanlineOffset;
202: for (int i = 0; i < dwidth; i++) {
203: dstData[dstPixelOffset] = ImageUtil
204: .clampShort(-srcData[srcPixelOffset]);
205: srcPixelOffset += srcPixelStride;
206: dstPixelOffset += dstPixelStride;
207: }
208: srcScanlineOffset += srcScanlineStride;
209: dstScanlineOffset += dstScanlineStride;
210: }
211: }
212: }
213: }
214:
215: // identical to byteLoops, except datatypes have changed. clumsy,
216: // but there's no other way in Java
217: private void intLoop(RasterAccessor src, RasterAccessor dst) {
218: int dwidth = dst.getWidth();
219: int dheight = dst.getHeight();
220: int dnumBands = dst.getNumBands();
221:
222: int dstDataArrays[][] = dst.getIntDataArrays();
223: int dstBandOffsets[] = dst.getBandOffsets();
224: int dstPixelStride = dst.getPixelStride();
225: int dstScanlineStride = dst.getScanlineStride();
226:
227: int srcDataArrays[][] = src.getIntDataArrays();
228: int srcBandOffsets[] = src.getBandOffsets();
229: int srcPixelStride = src.getPixelStride();
230: int srcScanlineStride = src.getScanlineStride();
231:
232: for (int k = 0; k < dnumBands; k++) {
233: boolean isRealPart = k % 2 == 0;
234: int dstData[] = dstDataArrays[k];
235: int srcData[] = srcDataArrays[k];
236: int srcScanlineOffset = srcBandOffsets[k];
237: int dstScanlineOffset = dstBandOffsets[k];
238: if (isRealPart) { // real part: copy value
239: for (int j = 0; j < dheight; j++) {
240: int srcPixelOffset = srcScanlineOffset;
241: int dstPixelOffset = dstScanlineOffset;
242: for (int i = 0; i < dwidth; i++) {
243: dstData[dstPixelOffset] = srcData[srcPixelOffset];
244: srcPixelOffset += srcPixelStride;
245: dstPixelOffset += dstPixelStride;
246: }
247: srcScanlineOffset += srcScanlineStride;
248: dstScanlineOffset += dstScanlineStride;
249: }
250: } else { // imaginary part: negate value
251: for (int j = 0; j < dheight; j++) {
252: int srcPixelOffset = srcScanlineOffset;
253: int dstPixelOffset = dstScanlineOffset;
254: for (int i = 0; i < dwidth; i++) {
255: dstData[dstPixelOffset] = -srcData[srcPixelOffset];
256: srcPixelOffset += srcPixelStride;
257: dstPixelOffset += dstPixelStride;
258: }
259: srcScanlineOffset += srcScanlineStride;
260: dstScanlineOffset += dstScanlineStride;
261: }
262: }
263: }
264: }
265:
266: private void floatLoop(RasterAccessor src, RasterAccessor dst) {
267: int dwidth = dst.getWidth();
268: int dheight = dst.getHeight();
269: int dnumBands = dst.getNumBands();
270:
271: float dstDataArrays[][] = dst.getFloatDataArrays();
272: int dstBandOffsets[] = dst.getBandOffsets();
273: int dstPixelStride = dst.getPixelStride();
274: int dstScanlineStride = dst.getScanlineStride();
275:
276: float srcDataArrays[][] = src.getFloatDataArrays();
277: int srcBandOffsets[] = src.getBandOffsets();
278: int srcPixelStride = src.getPixelStride();
279: int srcScanlineStride = src.getScanlineStride();
280:
281: for (int k = 0; k < dnumBands; k++) {
282: boolean isRealPart = k % 2 == 0;
283: float dstData[] = dstDataArrays[k];
284: float srcData[] = srcDataArrays[k];
285: int srcScanlineOffset = srcBandOffsets[k];
286: int dstScanlineOffset = dstBandOffsets[k];
287: if (isRealPart) { // real part: copy value
288: for (int j = 0; j < dheight; j++) {
289: int srcPixelOffset = srcScanlineOffset;
290: int dstPixelOffset = dstScanlineOffset;
291: for (int i = 0; i < dwidth; i++) {
292: dstData[dstPixelOffset] = srcData[srcPixelOffset];
293: srcPixelOffset += srcPixelStride;
294: dstPixelOffset += dstPixelStride;
295: }
296: srcScanlineOffset += srcScanlineStride;
297: dstScanlineOffset += dstScanlineStride;
298: }
299: } else { // imaginary part: negate value
300: for (int j = 0; j < dheight; j++) {
301: int srcPixelOffset = srcScanlineOffset;
302: int dstPixelOffset = dstScanlineOffset;
303: for (int i = 0; i < dwidth; i++) {
304: dstData[dstPixelOffset] = -srcData[srcPixelOffset];
305: srcPixelOffset += srcPixelStride;
306: dstPixelOffset += dstPixelStride;
307: }
308: srcScanlineOffset += srcScanlineStride;
309: dstScanlineOffset += dstScanlineStride;
310: }
311: }
312: }
313: }
314:
315: private void doubleLoop(RasterAccessor src, RasterAccessor dst) {
316: int dwidth = dst.getWidth();
317: int dheight = dst.getHeight();
318: int dnumBands = dst.getNumBands();
319:
320: double dstDataArrays[][] = dst.getDoubleDataArrays();
321: int dstBandOffsets[] = dst.getBandOffsets();
322: int dstPixelStride = dst.getPixelStride();
323: int dstScanlineStride = dst.getScanlineStride();
324:
325: double srcDataArrays[][] = src.getDoubleDataArrays();
326: int srcBandOffsets[] = src.getBandOffsets();
327: int srcPixelStride = src.getPixelStride();
328: int srcScanlineStride = src.getScanlineStride();
329:
330: for (int k = 0; k < dnumBands; k++) {
331: boolean isRealPart = k % 2 == 0;
332: double dstData[] = dstDataArrays[k];
333: double srcData[] = srcDataArrays[k];
334: int srcScanlineOffset = srcBandOffsets[k];
335: int dstScanlineOffset = dstBandOffsets[k];
336: if (isRealPart) { // real part: copy value
337: for (int j = 0; j < dheight; j++) {
338: int srcPixelOffset = srcScanlineOffset;
339: int dstPixelOffset = dstScanlineOffset;
340: for (int i = 0; i < dwidth; i++) {
341: dstData[dstPixelOffset] = srcData[srcPixelOffset];
342: srcPixelOffset += srcPixelStride;
343: dstPixelOffset += dstPixelStride;
344: }
345: srcScanlineOffset += srcScanlineStride;
346: dstScanlineOffset += dstScanlineStride;
347: }
348: } else { // imaginary part: negate value
349: for (int j = 0; j < dheight; j++) {
350: int srcPixelOffset = srcScanlineOffset;
351: int dstPixelOffset = dstScanlineOffset;
352: for (int i = 0; i < dwidth; i++) {
353: dstData[dstPixelOffset] = -srcData[srcPixelOffset];
354: srcPixelOffset += srcPixelStride;
355: dstPixelOffset += dstPixelStride;
356: }
357: srcScanlineOffset += srcScanlineStride;
358: dstScanlineOffset += dstScanlineStride;
359: }
360: }
361: }
362: }
363:
364: // public static void main(String[] args) {
365: // int[] dataTypes =
366: // new int[] {DataBuffer.TYPE_BYTE, DataBuffer.TYPE_SHORT,
367: // DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT,
368: // DataBuffer.TYPE_FLOAT, DataBuffer.TYPE_DOUBLE};
369:
370: // for(int dt = 0; dt < dataTypes.length; dt++) {
371: // WritableRaster wr =
372: // RasterFactory.createBandedRaster(dataTypes[dt],
373: // 5, 5, 4, null);
374: // int k = 0;
375: // for(int y = 0; y < 5; y++) {
376: // for(int x = 0; x < 5; x++) {
377: // for(int z = 0; z < 4; z++) {
378: // wr.setSample(x, y, z, k++);
379: // }
380: // }
381: // }
382: // SampleModel sm =
383: // RasterFactory.createBandedSampleModel(dataTypes[dt],
384: // 2, 2, 4, null, null);
385: // TiledImage ti = new TiledImage(0, 0, 5, 5, 0, 0, sm, null);
386: // ti.setData(wr);
387: // RenderedImage ri = JAI.create("conjugate", ti);
388: // Raster r = ri.getData();
389: // for(int y = 0; y < 5; y++) {
390: // for(int x = 0; x < 5; x++) {
391: // for(int z = 0; z < 4; z++) {
392: // System.out.print(r.getSampleDouble(x, y, z)+" ");
393: // }
394: // System.out.print(" : ");
395: // }
396: // System.out.println("");
397: // }
398: // System.out.println("");
399: // }
400: // }
401: }
|