001: /*
002: * $RCSfile: DivideOpImage.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:24 $
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.OpImage;
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: /// import com.sun.media.jai.test.OpImageTester;
031:
032: /**
033: * An <code>OpImage</code> implementing the "Divide" operation as
034: * described in <code>javax.media.jai.operator.DivideDescriptor</code>.
035: *
036: * <p>This <code>OpImage</code> divides the pixel values of the first source
037: * image by the second source image pixels on a per-band basis. In case
038: * the two source images have different number of bands, the number of
039: * bands for the destination image is the smaller of the number of bands
040: * of the two source images. That is
041: * <code>dstNumBands = Math.min(src1NumBands, src2NumBands)</code>.
042: * In case the two source images have different data types, the data type
043: * for the destination image is the bigger data type of the two source
044: * images.
045: *
046: * <p>The value of the pixel (x, y) in the destination image is defined as:
047: * <pre>
048: * for (b = 0; b < numBands; b++) {
049: * dst[y][x][b] = src1[y][x][b] / src2[y][x][b];
050: * }
051: * </pre>
052: *
053: * <p>If the result of the division overflows/underflows the
054: * maximum/minimum value supported by the destination image, then it
055: * will be clamped to the maximum/minimum value respectively. The
056: * data type <code>byte</code> is treated as unsigned, with maximum
057: * value as 255 and minimum value as 0.
058: *
059: * @since EA2
060: * @see javax.media.jai.operator.DivideDescriptor
061: * @see DivideCRIF
062: *
063: */
064: final class DivideOpImage extends PointOpImage {
065:
066: private byte[][] divideTableByte;
067:
068: /* Source 1 band increment */
069: private int s1bd = 1;
070:
071: /* Source 2 band increment */
072: private int s2bd = 1;
073:
074: /**
075: * Constructs an <code>DivideOpImage</code>.
076: *
077: * <p>The <code>layout</code> parameter may optionally contains the
078: * tile grid layout, sample model, and/or color model. The image
079: * dimension is determined by the intersection of the bounding boxes
080: * of the two source images.
081: *
082: * <p>The image layout of the first source image, <code>source1</code>,
083: * is used as the fall-back for the image layout of the destination
084: * image. Any layout parameters not specified in the <code>layout</code>
085: * argument are set to the same value as that of <code>source1</code>.
086: *
087: * @param source1 The first source image.
088: * @param source2 The second source image.
089: * @param layout The destination image layout.
090: */
091: public DivideOpImage(RenderedImage source1, RenderedImage source2,
092: Map config, ImageLayout layout) {
093: super (source1, source2, layout, config, true);
094:
095: // Get the source band counts.
096: int numBands1 = source1.getSampleModel().getNumBands();
097: int numBands2 = source2.getSampleModel().getNumBands();
098:
099: // Handle the special case of dividing each band of an N-band
100: // image by a 1-band image.
101: int numBandsDst;
102: if (layout != null
103: && layout.isValid(ImageLayout.SAMPLE_MODEL_MASK)) {
104: SampleModel sm = layout.getSampleModel(null);
105: numBandsDst = sm.getNumBands();
106:
107: // The second source must be single-banded and the first must
108: // be multi-banded.
109: if (numBandsDst > 1
110: && ((numBands1 > 1 && numBands2 == 1) || (numBands1 == 1 && numBands2 > 1))) {
111: // Clamp the destination band count to the number of
112: // bands in the multi-band source.
113: numBandsDst = Math.min(Math.max(numBands1, numBands2),
114: numBandsDst);
115:
116: // Create a new SampleModel if necessary.
117: if (numBandsDst != sampleModel.getNumBands()) {
118: sampleModel = RasterFactory
119: .createComponentSampleModel(sm, sampleModel
120: .getTransferType(), sampleModel
121: .getWidth(), sampleModel
122: .getHeight(), numBandsDst);
123:
124: if (colorModel != null
125: && !JDKWorkarounds.areCompatibleDataModels(
126: sampleModel, colorModel)) {
127: colorModel = ImageUtil.getCompatibleColorModel(
128: sampleModel, config);
129: }
130: }
131:
132: // Set the source band increments.
133: s1bd = numBands1 == 1 ? 0 : 1;
134: s2bd = numBands2 == 1 ? 0 : 1;
135: }
136: }
137:
138: if (sampleModel.getTransferType() == DataBuffer.TYPE_BYTE) {
139: /* Initialize divideTableByte. */
140: divideTableByte = new byte[256][256];
141: for (int j = 0; j < 256; j++) {
142: byte[] array = divideTableByte[j];
143:
144: if (j > 0) {
145: array[0] = (byte) 255;
146: } else {
147: array[0] = 0;
148: }
149:
150: for (int i = 1; i < 256; i++) {
151: array[i] = ImageUtil.clampRoundByte((float) j
152: / (float) i);
153: }
154: }
155: }
156:
157: // Set flag to permit in-place operation.
158: permitInPlaceOperation();
159: }
160:
161: /**
162: * Divides the pixel values of two source images within a specified
163: * rectangle.
164: *
165: * @param sources Cobbled sources, guaranteed to provide all the
166: * source data necessary for computing the rectangle.
167: * @param dest The tile containing the rectangle to be computed.
168: * @param destRect The rectangle within the tile to be computed.
169: */
170: protected void computeRect(Raster[] sources, WritableRaster dest,
171: Rectangle destRect) {
172: // Retrieve format tags.
173: RasterFormatTag[] formatTags = getFormatTags();
174:
175: /* For PointOpImage, srcRect = destRect. */
176: RasterAccessor s1 = new RasterAccessor(sources[0], destRect,
177: formatTags[0], getSourceImage(0).getColorModel());
178: RasterAccessor s2 = new RasterAccessor(sources[1], destRect,
179: formatTags[1], getSourceImage(1).getColorModel());
180: RasterAccessor d = new RasterAccessor(dest, destRect,
181: formatTags[2], getColorModel());
182:
183: if (d.isBinary()) {
184: byte[] dstBits = d.getBinaryDataArray();
185:
186: // Subtraction in this case boils down to copying image 1.
187: System.arraycopy(s1.getBinaryDataArray(), 0, dstBits, 0,
188: dstBits.length);
189:
190: d.copyBinaryDataToRaster();
191:
192: return;
193: }
194:
195: int src1LineStride = s1.getScanlineStride();
196: int src1PixelStride = s1.getPixelStride();
197: int[] src1BandOffsets = s1.getBandOffsets();
198:
199: int src2LineStride = s2.getScanlineStride();
200: int src2PixelStride = s2.getPixelStride();
201: int[] src2BandOffsets = s2.getBandOffsets();
202:
203: int dstNumBands = d.getNumBands();
204: int dstWidth = d.getWidth();
205: int dstHeight = d.getHeight();
206: int dstLineStride = d.getScanlineStride();
207: int dstPixelStride = d.getPixelStride();
208: int[] dstBandOffsets = d.getBandOffsets();
209:
210: switch (d.getDataType()) {
211:
212: case DataBuffer.TYPE_BYTE:
213: byteLoop(dstNumBands, dstWidth, dstHeight, src1LineStride,
214: src1PixelStride, src1BandOffsets, s1
215: .getByteDataArrays(), src2LineStride,
216: src2PixelStride, src2BandOffsets, s2
217: .getByteDataArrays(), dstLineStride,
218: dstPixelStride, dstBandOffsets, d
219: .getByteDataArrays());
220: break;
221:
222: case DataBuffer.TYPE_USHORT:
223: ushortLoop(dstNumBands, dstWidth, dstHeight,
224: src1LineStride, src1PixelStride, src1BandOffsets,
225: s1.getShortDataArrays(), src2LineStride,
226: src2PixelStride, src2BandOffsets, s2
227: .getShortDataArrays(), dstLineStride,
228: dstPixelStride, dstBandOffsets, d
229: .getShortDataArrays());
230: break;
231:
232: case DataBuffer.TYPE_SHORT:
233: shortLoop(dstNumBands, dstWidth, dstHeight, src1LineStride,
234: src1PixelStride, src1BandOffsets, s1
235: .getShortDataArrays(), src2LineStride,
236: src2PixelStride, src2BandOffsets, s2
237: .getShortDataArrays(), dstLineStride,
238: dstPixelStride, dstBandOffsets, d
239: .getShortDataArrays());
240: break;
241:
242: case DataBuffer.TYPE_INT:
243: intLoop(dstNumBands, dstWidth, dstHeight, src1LineStride,
244: src1PixelStride, src1BandOffsets, s1
245: .getIntDataArrays(), src2LineStride,
246: src2PixelStride, src2BandOffsets, s2
247: .getIntDataArrays(), dstLineStride,
248: dstPixelStride, dstBandOffsets, d
249: .getIntDataArrays());
250: break;
251:
252: case DataBuffer.TYPE_FLOAT:
253: floatLoop(dstNumBands, dstWidth, dstHeight, src1LineStride,
254: src1PixelStride, src1BandOffsets, s1
255: .getFloatDataArrays(), src2LineStride,
256: src2PixelStride, src2BandOffsets, s2
257: .getFloatDataArrays(), dstLineStride,
258: dstPixelStride, dstBandOffsets, d
259: .getFloatDataArrays());
260: break;
261:
262: case DataBuffer.TYPE_DOUBLE:
263: doubleLoop(dstNumBands, dstWidth, dstHeight,
264: src1LineStride, src1PixelStride, src1BandOffsets,
265: s1.getDoubleDataArrays(), src2LineStride,
266: src2PixelStride, src2BandOffsets, s2
267: .getDoubleDataArrays(), dstLineStride,
268: dstPixelStride, dstBandOffsets, d
269: .getDoubleDataArrays());
270: break;
271: }
272:
273: if (d.needsClamping()) {
274: d.clampDataArrays();
275: }
276:
277: d.copyDataToRaster();
278: }
279:
280: private void byteLoop(int dstNumBands, int dstWidth, int dstHeight,
281: int src1LineStride, int src1PixelStride,
282: int[] src1BandOffsets, byte[][] src1Data,
283: int src2LineStride, int src2PixelStride,
284: int[] src2BandOffsets, byte[][] src2Data,
285: int dstLineStride, int dstPixelStride,
286: int[] dstBandOffsets, byte[][] dstData) {
287:
288: for (int b = 0, s1b = 0, s2b = 0; b < dstNumBands; b++, s1b += s1bd, s2b += s2bd) {
289: byte[] s1 = src1Data[s1b];
290: byte[] s2 = src2Data[s2b];
291: byte[] d = dstData[b];
292: int src1LineOffset = src1BandOffsets[s1b];
293: int src2LineOffset = src2BandOffsets[s2b];
294: int dstLineOffset = dstBandOffsets[b];
295:
296: for (int h = 0; h < dstHeight; h++) {
297: int src1PixelOffset = src1LineOffset;
298: int src2PixelOffset = src2LineOffset;
299: int dstPixelOffset = dstLineOffset;
300: src1LineOffset += src1LineStride;
301: src2LineOffset += src2LineStride;
302: dstLineOffset += dstLineStride;
303:
304: for (int w = 0; w < dstWidth; w++) {
305: d[dstPixelOffset] = divideTableByte[s1[src1PixelOffset] & 0xFF][s2[src2PixelOffset] & 0xFF];
306: src1PixelOffset += src1PixelStride;
307: src2PixelOffset += src2PixelStride;
308: dstPixelOffset += dstPixelStride;
309: }
310: }
311: }
312: }
313:
314: private void ushortLoop(int dstNumBands, int dstWidth,
315: int dstHeight, int src1LineStride, int src1PixelStride,
316: int[] src1BandOffsets, short[][] src1Data,
317: int src2LineStride, int src2PixelStride,
318: int[] src2BandOffsets, short[][] src2Data,
319: int dstLineStride, int dstPixelStride,
320: int[] dstBandOffsets, short[][] dstData) {
321:
322: for (int b = 0, s1b = 0, s2b = 0; b < dstNumBands; b++, s1b += s1bd, s2b += s2bd) {
323: short[] s1 = src1Data[s1b];
324: short[] s2 = src2Data[s2b];
325: short[] d = dstData[b];
326: float f1, f2;
327: int src1LineOffset = src1BandOffsets[s1b];
328: int src2LineOffset = src2BandOffsets[s2b];
329: int dstLineOffset = dstBandOffsets[b];
330:
331: for (int h = 0; h < dstHeight; h++) {
332: int src1PixelOffset = src1LineOffset;
333: int src2PixelOffset = src2LineOffset;
334: int dstPixelOffset = dstLineOffset;
335: src1LineOffset += src1LineStride;
336: src2LineOffset += src2LineStride;
337: dstLineOffset += dstLineStride;
338:
339: for (int w = 0; w < dstWidth; w++) {
340: f1 = (float) (s1[src1PixelOffset] & 0xffff);
341: f2 = (float) (s2[src2PixelOffset] & 0xffff);
342:
343: if (f1 == 0) {
344: // 0 divided by any value is defined to return 0
345: d[dstPixelOffset] = 0;
346: } else if (f2 == 0) {
347: // Anything other than 0 divided by zero, returns
348: // the max value
349: d[dstPixelOffset] = (short) 0xffff;
350: } else {
351: d[dstPixelOffset] = ImageUtil
352: .clampRoundUShort(f1 / f2);
353: }
354:
355: src1PixelOffset += src1PixelStride;
356: src2PixelOffset += src2PixelStride;
357: dstPixelOffset += dstPixelStride;
358: }
359: }
360: }
361: }
362:
363: private void shortLoop(int dstNumBands, int dstWidth,
364: int dstHeight, int src1LineStride, int src1PixelStride,
365: int[] src1BandOffsets, short[][] src1Data,
366: int src2LineStride, int src2PixelStride,
367: int[] src2BandOffsets, short[][] src2Data,
368: int dstLineStride, int dstPixelStride,
369: int[] dstBandOffsets, short[][] dstData) {
370:
371: for (int b = 0, s1b = 0, s2b = 0; b < dstNumBands; b++, s1b += s1bd, s2b += s2bd) {
372: short[] s1 = src1Data[s1b];
373: short[] s2 = src2Data[s2b];
374: short[] d = dstData[b];
375: float f1, f2;
376: int src1LineOffset = src1BandOffsets[s1b];
377: int src2LineOffset = src2BandOffsets[s2b];
378: int dstLineOffset = dstBandOffsets[b];
379:
380: for (int h = 0; h < dstHeight; h++) {
381: int src1PixelOffset = src1LineOffset;
382: int src2PixelOffset = src2LineOffset;
383: int dstPixelOffset = dstLineOffset;
384: src1LineOffset += src1LineStride;
385: src2LineOffset += src2LineStride;
386: dstLineOffset += dstLineStride;
387:
388: for (int w = 0; w < dstWidth; w++) {
389: f1 = (float) s1[src1PixelOffset];
390: f2 = (float) s2[src2PixelOffset];
391:
392: if (f1 == 0) {
393: // 0 divided by any value is defined to return 0
394: d[dstPixelOffset] = 0;
395: } else if (f2 == 0) {
396: if (f1 < 0) {
397: d[dstPixelOffset] = Short.MIN_VALUE;
398: } else {
399: d[dstPixelOffset] = Short.MAX_VALUE;
400: }
401: } else {
402: d[dstPixelOffset] = ImageUtil
403: .clampRoundShort(f1 / f2);
404: }
405:
406: src1PixelOffset += src1PixelStride;
407: src2PixelOffset += src2PixelStride;
408: dstPixelOffset += dstPixelStride;
409: }
410: }
411: }
412: }
413:
414: private void intLoop(int dstNumBands, int dstWidth, int dstHeight,
415: int src1LineStride, int src1PixelStride,
416: int[] src1BandOffsets, int[][] src1Data,
417: int src2LineStride, int src2PixelStride,
418: int[] src2BandOffsets, int[][] src2Data, int dstLineStride,
419: int dstPixelStride, int[] dstBandOffsets, int[][] dstData) {
420: /*
421: * The destination data type may be any of the integral data types.
422: * The "clamp" function must clamp to the appropriate range for
423: * that data type.
424: */
425: switch (sampleModel.getTransferType()) {
426:
427: case DataBuffer.TYPE_BYTE:
428: for (int b = 0, s1b = 0, s2b = 0; b < dstNumBands; b++, s1b += s1bd, s2b += s2bd) {
429: int[] s1 = src1Data[s1b];
430: int[] s2 = src2Data[s2b];
431: int[] d = dstData[b];
432: float f1, f2;
433: int src1LineOffset = src1BandOffsets[s1b];
434: int src2LineOffset = src2BandOffsets[s2b];
435: int dstLineOffset = dstBandOffsets[b];
436:
437: for (int h = 0; h < dstHeight; h++) {
438: int src1PixelOffset = src1LineOffset;
439: int src2PixelOffset = src2LineOffset;
440: int dstPixelOffset = dstLineOffset;
441: src1LineOffset += src1LineStride;
442: src2LineOffset += src2LineStride;
443: dstLineOffset += dstLineStride;
444:
445: for (int w = 0; w < dstWidth; w++) {
446: f1 = (float) (s1[src1PixelOffset] & 0xFF);
447: f2 = (float) (s2[src2PixelOffset] & 0xFF);
448:
449: if (f1 == 0) {
450: // since bytes are unsigned, lowest value is 0
451: d[dstPixelOffset] = 0;
452: } else if (f2 == 0) {
453: // +ve no divided by 0 = datatype's max value
454: d[dstPixelOffset] = 255;
455: } else {
456: d[dstPixelOffset] = ImageUtil
457: .clampRoundByte(f1 / f2);
458: }
459:
460: src1PixelOffset += src1PixelStride;
461: src2PixelOffset += src2PixelStride;
462: dstPixelOffset += dstPixelStride;
463: }
464: }
465: }
466: break;
467:
468: case DataBuffer.TYPE_USHORT:
469: for (int b = 0, s1b = 0, s2b = 0; b < dstNumBands; b++, s1b += s1bd, s2b += s2bd) {
470: int[] s1 = src1Data[s1b];
471: int[] s2 = src2Data[s2b];
472: int[] d = dstData[b];
473: float f1, f2;
474: int src1LineOffset = src1BandOffsets[s1b];
475: int src2LineOffset = src2BandOffsets[s2b];
476: int dstLineOffset = dstBandOffsets[b];
477:
478: for (int h = 0; h < dstHeight; h++) {
479: int src1PixelOffset = src1LineOffset;
480: int src2PixelOffset = src2LineOffset;
481: int dstPixelOffset = dstLineOffset;
482: src1LineOffset += src1LineStride;
483: src2LineOffset += src2LineStride;
484: dstLineOffset += dstLineStride;
485:
486: for (int w = 0; w < dstWidth; w++) {
487: f1 = (float) (s1[src1PixelOffset] & 0xFFFF);
488: f2 = (float) (s2[src2PixelOffset] & 0xFFFF);
489:
490: if (f1 == 0) {
491: // The minimum value for ushort is 0
492: d[dstPixelOffset] = 0;
493: } else if (f2 == 0) {
494: // +ve no divided by 0 = datatype's max value
495: d[dstPixelOffset] = (short) 0xffff;
496: } else {
497: d[dstPixelOffset] = ImageUtil
498: .clampRoundUShort(f1 / f2);
499: }
500:
501: src1PixelOffset += src1PixelStride;
502: src2PixelOffset += src2PixelStride;
503: dstPixelOffset += dstPixelStride;
504: }
505: }
506: }
507: break;
508:
509: case DataBuffer.TYPE_SHORT:
510: for (int b = 0, s1b = 0, s2b = 0; b < dstNumBands; b++, s1b += s1bd, s2b += s2bd) {
511: int[] s1 = src1Data[s1b];
512: int[] s2 = src2Data[s2b];
513: int[] d = dstData[b];
514: float f1, f2;
515: int src1LineOffset = src1BandOffsets[s1b];
516: int src2LineOffset = src2BandOffsets[s2b];
517: int dstLineOffset = dstBandOffsets[b];
518:
519: for (int h = 0; h < dstHeight; h++) {
520: int src1PixelOffset = src1LineOffset;
521: int src2PixelOffset = src2LineOffset;
522: int dstPixelOffset = dstLineOffset;
523: src1LineOffset += src1LineStride;
524: src2LineOffset += src2LineStride;
525: dstLineOffset += dstLineStride;
526:
527: for (int w = 0; w < dstWidth; w++) {
528: f1 = (float) s1[src1PixelOffset];
529: f2 = (float) s2[src2PixelOffset];
530:
531: if (f1 == 0) {
532: d[dstPixelOffset] = 0;
533: } else if (f2 == 0) {
534: if (f1 < 0) {
535: // 0 divided by 0 is defined to return 0
536: // -ve no divided by 0 = datatype's min value
537: d[dstPixelOffset] = Short.MIN_VALUE;
538: } else {
539: d[dstPixelOffset] = Short.MAX_VALUE;
540: }
541: } else {
542: d[dstPixelOffset] = ImageUtil
543: .clampRoundShort(f1 / f2);
544: }
545:
546: src1PixelOffset += src1PixelStride;
547: src2PixelOffset += src2PixelStride;
548: dstPixelOffset += dstPixelStride;
549: }
550: }
551: }
552: break;
553:
554: case DataBuffer.TYPE_INT:
555: for (int b = 0, s1b = 0, s2b = 0; b < dstNumBands; b++, s1b += s1bd, s2b += s2bd) {
556: int[] s1 = src1Data[s1b];
557: int[] s2 = src2Data[s2b];
558: int[] d = dstData[b];
559: float f1, f2;
560: int src1LineOffset = src1BandOffsets[s1b];
561: int src2LineOffset = src2BandOffsets[s2b];
562: int dstLineOffset = dstBandOffsets[b];
563:
564: for (int h = 0; h < dstHeight; h++) {
565: int src1PixelOffset = src1LineOffset;
566: int src2PixelOffset = src2LineOffset;
567: int dstPixelOffset = dstLineOffset;
568: src1LineOffset += src1LineStride;
569: src2LineOffset += src2LineStride;
570: dstLineOffset += dstLineStride;
571:
572: for (int w = 0; w < dstWidth; w++) {
573: f1 = (float) s1[src1PixelOffset];
574: f2 = (float) s2[src2PixelOffset];
575:
576: if (f1 == 0) {
577: // 0 divided by 0 or any number is defined to return 0
578: d[dstPixelOffset] = 0;
579: } else if (f2 == 0) {
580: if (f1 < 0) {
581: d[dstPixelOffset] = Integer.MIN_VALUE;
582: } else {
583: d[dstPixelOffset] = Integer.MAX_VALUE;
584: }
585: } else {
586: d[dstPixelOffset] = ImageUtil
587: .clampRoundInt(f1 / f2);
588: }
589:
590: src1PixelOffset += src1PixelStride;
591: src2PixelOffset += src2PixelStride;
592: dstPixelOffset += dstPixelStride;
593: }
594: }
595: }
596: break;
597: }
598: }
599:
600: private void floatLoop(int dstNumBands, int dstWidth,
601: int dstHeight, int src1LineStride, int src1PixelStride,
602: int[] src1BandOffsets, float[][] src1Data,
603: int src2LineStride, int src2PixelStride,
604: int[] src2BandOffsets, float[][] src2Data,
605: int dstLineStride, int dstPixelStride,
606: int[] dstBandOffsets, float[][] dstData) {
607:
608: for (int b = 0, s1b = 0, s2b = 0; b < dstNumBands; b++, s1b += s1bd, s2b += s2bd) {
609: float[] s1 = src1Data[s1b];
610: float[] s2 = src2Data[s2b];
611: float[] d = dstData[b];
612: int src1LineOffset = src1BandOffsets[s1b];
613: int src2LineOffset = src2BandOffsets[s2b];
614: int dstLineOffset = dstBandOffsets[b];
615:
616: for (int h = 0; h < dstHeight; h++) {
617: int src1PixelOffset = src1LineOffset;
618: int src2PixelOffset = src2LineOffset;
619: int dstPixelOffset = dstLineOffset;
620: src1LineOffset += src1LineStride;
621: src2LineOffset += src2LineStride;
622: dstLineOffset += dstLineStride;
623:
624: for (int w = 0; w < dstWidth; w++) {
625: // follows IEEE-754 standard
626: d[dstPixelOffset] = s1[src1PixelOffset]
627: / s2[src2PixelOffset];
628:
629: src1PixelOffset += src1PixelStride;
630: src2PixelOffset += src2PixelStride;
631: dstPixelOffset += dstPixelStride;
632: }
633: }
634: }
635: }
636:
637: private void doubleLoop(int dstNumBands, int dstWidth,
638: int dstHeight, int src1LineStride, int src1PixelStride,
639: int[] src1BandOffsets, double[][] src1Data,
640: int src2LineStride, int src2PixelStride,
641: int[] src2BandOffsets, double[][] src2Data,
642: int dstLineStride, int dstPixelStride,
643: int[] dstBandOffsets, double[][] dstData) {
644:
645: for (int b = 0, s1b = 0, s2b = 0; b < dstNumBands; b++, s1b += s1bd, s2b += s2bd) {
646: double[] s1 = src1Data[s1b];
647: double[] s2 = src2Data[s2b];
648: double[] d = dstData[b];
649: int src1LineOffset = src1BandOffsets[s1b];
650: int src2LineOffset = src2BandOffsets[s2b];
651: int dstLineOffset = dstBandOffsets[b];
652:
653: for (int h = 0; h < dstHeight; h++) {
654: int src1PixelOffset = src1LineOffset;
655: int src2PixelOffset = src2LineOffset;
656: int dstPixelOffset = dstLineOffset;
657: src1LineOffset += src1LineStride;
658: src2LineOffset += src2LineStride;
659: dstLineOffset += dstLineStride;
660:
661: for (int w = 0; w < dstWidth; w++) {
662: // follows IEEE-754 standard
663: d[dstPixelOffset] = s1[src1PixelOffset]
664: / s2[src2PixelOffset];
665:
666: src1PixelOffset += src1PixelStride;
667: src2PixelOffset += src2PixelStride;
668: dstPixelOffset += dstPixelStride;
669: }
670: }
671: }
672: }
673:
674: // public static void main(String args[]) {
675: // System.out.println("DivideOpImage Test");
676: // ImageLayout layout;
677: // OpImage src1, src2, dst;
678: // Rectangle rect = new Rectangle(0, 0, 5, 5);
679:
680: // System.out.println("1. PixelInterleaved byte 3-band");
681: // layout = OpImageTester.createImageLayout(
682: // 0, 0, 800, 800, 0, 0, 200, 200, DataBuffer.TYPE_BYTE, 3, false);
683: // src1 = OpImageTester.createRandomOpImage(layout);
684: // src2 = OpImageTester.createRandomOpImage(layout);
685: // dst = new DivideOpImage(src1, src2, null, null);
686: // OpImageTester.testOpImage(dst, rect);
687: // OpImageTester.timeOpImage(dst, 10);
688:
689: // System.out.println("2. Banded byte 3-band");
690: // layout = OpImageTester.createImageLayout(
691: // 0, 0, 800, 800, 0, 0, 200, 200, DataBuffer.TYPE_BYTE, 3, true);
692: // src1 = OpImageTester.createRandomOpImage(layout);
693: // src2 = OpImageTester.createRandomOpImage(layout);
694: // dst = new DivideOpImage(src1, src2, null, null);
695: // OpImageTester.testOpImage(dst, rect);
696: // OpImageTester.timeOpImage(dst, 10);
697:
698: // System.out.println("3. PixelInterleaved int 3-band");
699: // layout = OpImageTester.createImageLayout(
700: // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_INT, 3, false);
701: // src1 = OpImageTester.createRandomOpImage(layout);
702: // src2 = OpImageTester.createRandomOpImage(layout);
703: // dst = new DivideOpImage(src1, src2, null, null);
704: // OpImageTester.testOpImage(dst, rect);
705: // OpImageTester.timeOpImage(dst, 10);
706:
707: // System.out.println("4. Banded int 3-band");
708: // layout = OpImageTester.createImageLayout(
709: // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_INT, 3, true);
710: // src1 = OpImageTester.createRandomOpImage(layout);
711: // src2 = OpImageTester.createRandomOpImage(layout);
712: // dst = new DivideOpImage(src1, src2, null, null);
713: // OpImageTester.testOpImage(dst, rect);
714: // OpImageTester.timeOpImage(dst, 10);
715:
716: // System.out.println("5. PixelInterleaved float 3-band");
717: // layout = OpImageTester.createImageLayout(
718: // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_FLOAT, 3, false);
719: // src1 = OpImageTester.createRandomOpImage(layout);
720: // src2 = OpImageTester.createRandomOpImage(layout);
721: // dst = new DivideOpImage(src1, src2, null, null);
722: // OpImageTester.testOpImage(dst, rect);
723: // OpImageTester.timeOpImage(dst, 10);
724:
725: // System.out.println("6. Banded float 3-band");
726: // layout = OpImageTester.createImageLayout(
727: // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_FLOAT, 3, true);
728: // src1 = OpImageTester.createRandomOpImage(layout);
729: // src2 = OpImageTester.createRandomOpImage(layout);
730: // dst = new DivideOpImage(src1, src2, null, null);
731: // OpImageTester.testOpImage(dst, rect);
732: // OpImageTester.timeOpImage(dst, 10);
733:
734: // System.out.println("7. PixelInterleaved double 3-band");
735: // layout = OpImageTester.createImageLayout(
736: // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_DOUBLE, 3, false);
737: // src1 = OpImageTester.createRandomOpImage(layout);
738: // src2 = OpImageTester.createRandomOpImage(layout);
739: // dst = new DivideOpImage(src1, src2, null, null);
740: // OpImageTester.testOpImage(dst, rect);
741: // OpImageTester.timeOpImage(dst, 10);
742:
743: // System.out.println("8. Banded double 3-band");
744: // layout = OpImageTester.createImageLayout(
745: // 0, 0, 512, 512, 0, 0, 200, 200, DataBuffer.TYPE_DOUBLE, 3, true);
746: // src1 = OpImageTester.createRandomOpImage(layout);
747: // src2 = OpImageTester.createRandomOpImage(layout);
748: // dst = new DivideOpImage(src1, src2, null, null);
749: // OpImageTester.testOpImage(dst, rect);
750: // OpImageTester.timeOpImage(dst, 10);
751: // }
752: }
|