001: /*
002: * $RCSfile: MaxFilterSeparableOpImage.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:32 $
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.SampleModel;
017: import java.awt.image.Raster;
018: import java.awt.image.RenderedImage;
019: import java.awt.image.WritableRaster;
020: import java.awt.image.renderable.ParameterBlock;
021: import java.awt.image.renderable.RenderedImageFactory;
022: import javax.media.jai.AreaOpImage;
023: import javax.media.jai.BorderExtender;
024: import javax.media.jai.ImageLayout;
025: import javax.media.jai.OpImage;
026: import javax.media.jai.RasterAccessor;
027: import java.util.Map;
028: import javax.media.jai.operator.MaxFilterDescriptor;
029: import com.sun.media.jai.opimage.MaxFilterOpImage;
030:
031: // import com.sun.media.jai.test.OpImageTester;
032:
033: /**
034: * An OpImage class to perform max filtering on a source image.
035: *
036: */
037: final class MaxFilterSeparableOpImage extends MaxFilterOpImage {
038:
039: /**
040: * Creates a MaxFilterSeperableOpImage with the given source and
041: * maskSize. The image dimensions are derived from the source
042: * image. The tile grid layout, SampleModel, and ColorModel may
043: * optionally be specified by an ImageLayout object.
044: *
045: * @param source a RenderedImage.
046: * @param extender a BorderExtender, or null.
047: * @param layout an ImageLayout optionally containing the tile grid layout,
048: * SampleModel, and ColorModel, or null.
049: * @param maskSize the mask size.
050: */
051: public MaxFilterSeparableOpImage(RenderedImage source,
052: BorderExtender extender, Map config, ImageLayout layout,
053: int maskSize) {
054: super (source, extender, config, layout,
055: MaxFilterDescriptor.MAX_MASK_SQUARE, maskSize);
056: }
057:
058: protected void byteLoop(RasterAccessor src, RasterAccessor dst,
059: int filterSize) {
060: int dwidth = dst.getWidth();
061: int dheight = dst.getHeight();
062: int dnumBands = dst.getNumBands();
063:
064: byte dstDataArrays[][] = dst.getByteDataArrays();
065: int dstBandOffsets[] = dst.getBandOffsets();
066: int dstPixelStride = dst.getPixelStride();
067: int dstScanlineStride = dst.getScanlineStride();
068:
069: byte srcDataArrays[][] = src.getByteDataArrays();
070: int srcBandOffsets[] = src.getBandOffsets();
071: int srcPixelStride = src.getPixelStride();
072: int srcScanlineStride = src.getScanlineStride();
073:
074: int maxValues[] = new int[filterSize];
075: int val, maxval;
076: int wp = filterSize;
077: int tmpBuffer[] = new int[filterSize * dwidth];
078: int tmpBufferSize = filterSize * dwidth;
079:
080: for (int k = 0; k < dnumBands; k++) {
081: byte dstData[] = dstDataArrays[k];
082: byte srcData[] = srcDataArrays[k];
083: int srcScanlineOffset = srcBandOffsets[k];
084: int dstScanlineOffset = dstBandOffsets[k];
085:
086: int revolver = 0;
087: for (int j = 0; j < filterSize - 1; j++) {
088: int srcPixelOffset = srcScanlineOffset;
089:
090: for (int i = 0; i < dwidth; i++) {
091: int imageOffset = srcPixelOffset;
092: maxval = Integer.MIN_VALUE;
093: for (int v = 0; v < wp; v++) {
094: val = srcData[imageOffset] & 0xff;
095: imageOffset += srcPixelStride;
096: maxval = (val > maxval) ? val : maxval;
097: }
098: tmpBuffer[revolver + i] = maxval;
099: srcPixelOffset += srcPixelStride;
100: }
101: revolver += dwidth;
102: srcScanlineOffset += srcScanlineStride;
103: }
104:
105: // srcScanlineStride already bumped by
106: // filterSize-1*scanlineStride
107:
108: for (int j = 0; j < dheight; j++) {
109: int srcPixelOffset = srcScanlineOffset;
110: int dstPixelOffset = dstScanlineOffset;
111:
112: for (int i = 0; i < dwidth; i++) {
113: int imageOffset = srcPixelOffset;
114: maxval = Integer.MIN_VALUE;
115: for (int v = 0; v < wp; v++) {
116: val = srcData[imageOffset] & 0xff;
117: imageOffset += srcPixelStride;
118: maxval = (val > maxval) ? val : maxval;
119: }
120: tmpBuffer[revolver + i] = maxval;
121:
122: maxval = Integer.MIN_VALUE;
123: for (int b = i; b < tmpBufferSize; b += dwidth) {
124: val = tmpBuffer[b];
125: maxval = (val > maxval) ? val : maxval;
126: }
127:
128: dstData[dstPixelOffset] = (byte) maxval;
129: srcPixelOffset += srcPixelStride;
130: dstPixelOffset += dstPixelStride;
131: }
132:
133: revolver += dwidth;
134: if (revolver == tmpBufferSize) {
135: revolver = 0;
136: }
137:
138: srcScanlineOffset += srcScanlineStride;
139: dstScanlineOffset += dstScanlineStride;
140: }
141: }
142: }
143:
144: protected void shortLoop(RasterAccessor src, RasterAccessor dst,
145: int filterSize) {
146: int dwidth = dst.getWidth();
147: int dheight = dst.getHeight();
148: int dnumBands = dst.getNumBands();
149:
150: short dstDataArrays[][] = dst.getShortDataArrays();
151: int dstBandOffsets[] = dst.getBandOffsets();
152: int dstPixelStride = dst.getPixelStride();
153: int dstScanlineStride = dst.getScanlineStride();
154:
155: short srcDataArrays[][] = src.getShortDataArrays();
156: int srcBandOffsets[] = src.getBandOffsets();
157: int srcPixelStride = src.getPixelStride();
158: int srcScanlineStride = src.getScanlineStride();
159:
160: int maxValues[] = new int[filterSize];
161: int val, maxval;
162: int wp = filterSize;
163: int tmpBuffer[] = new int[filterSize * dwidth];
164: int tmpBufferSize = filterSize * dwidth;
165:
166: for (int k = 0; k < dnumBands; k++) {
167: short dstData[] = dstDataArrays[k];
168: short srcData[] = srcDataArrays[k];
169: int srcScanlineOffset = srcBandOffsets[k];
170: int dstScanlineOffset = dstBandOffsets[k];
171:
172: int revolver = 0;
173: for (int j = 0; j < filterSize - 1; j++) {
174: int srcPixelOffset = srcScanlineOffset;
175:
176: for (int i = 0; i < dwidth; i++) {
177: int imageOffset = srcPixelOffset;
178: maxval = Integer.MIN_VALUE;
179: for (int v = 0; v < wp; v++) {
180: val = srcData[imageOffset];
181: imageOffset += srcPixelStride;
182: maxval = (val > maxval) ? val : maxval;
183: }
184: tmpBuffer[revolver + i] = maxval;
185: srcPixelOffset += srcPixelStride;
186: }
187: revolver += dwidth;
188: srcScanlineOffset += srcScanlineStride;
189: }
190:
191: // srcScanlineStride already bumped by
192: // filterSize-1*scanlineStride
193:
194: for (int j = 0; j < dheight; j++) {
195: int srcPixelOffset = srcScanlineOffset;
196: int dstPixelOffset = dstScanlineOffset;
197:
198: for (int i = 0; i < dwidth; i++) {
199: int imageOffset = srcPixelOffset;
200: maxval = Integer.MIN_VALUE;
201: for (int v = 0; v < wp; v++) {
202: val = srcData[imageOffset];
203: imageOffset += srcPixelStride;
204: maxval = (val > maxval) ? val : maxval;
205: }
206: tmpBuffer[revolver + i] = maxval;
207:
208: maxval = Integer.MIN_VALUE;
209: for (int b = i; b < tmpBufferSize; b += dwidth) {
210: val = tmpBuffer[b];
211: maxval = (val > maxval) ? val : maxval;
212: }
213:
214: dstData[dstPixelOffset] = (short) maxval;
215: srcPixelOffset += srcPixelStride;
216: dstPixelOffset += dstPixelStride;
217: }
218: revolver += dwidth;
219: if (revolver == tmpBufferSize) {
220: revolver = 0;
221: }
222: srcScanlineOffset += srcScanlineStride;
223: dstScanlineOffset += dstScanlineStride;
224: }
225: }
226:
227: }
228:
229: protected void ushortLoop(RasterAccessor src, RasterAccessor dst,
230: int filterSize) {
231: int dwidth = dst.getWidth();
232: int dheight = dst.getHeight();
233: int dnumBands = dst.getNumBands();
234:
235: short dstDataArrays[][] = dst.getShortDataArrays();
236: int dstBandOffsets[] = dst.getBandOffsets();
237: int dstPixelStride = dst.getPixelStride();
238: int dstScanlineStride = dst.getScanlineStride();
239:
240: short srcDataArrays[][] = src.getShortDataArrays();
241: int srcBandOffsets[] = src.getBandOffsets();
242: int srcPixelStride = src.getPixelStride();
243: int srcScanlineStride = src.getScanlineStride();
244:
245: int maxValues[] = new int[filterSize];
246: int val, maxval;
247: int wp = filterSize;
248: int tmpBuffer[] = new int[filterSize * dwidth];
249: int tmpBufferSize = filterSize * dwidth;
250:
251: for (int k = 0; k < dnumBands; k++) {
252: short dstData[] = dstDataArrays[k];
253: short srcData[] = srcDataArrays[k];
254: int srcScanlineOffset = srcBandOffsets[k];
255: int dstScanlineOffset = dstBandOffsets[k];
256:
257: int revolver = 0;
258: for (int j = 0; j < filterSize - 1; j++) {
259: int srcPixelOffset = srcScanlineOffset;
260:
261: for (int i = 0; i < dwidth; i++) {
262: int imageOffset = srcPixelOffset;
263: maxval = Integer.MIN_VALUE;
264: for (int v = 0; v < wp; v++) {
265: val = srcData[imageOffset] & 0xfff;
266: imageOffset += srcPixelStride;
267: maxval = (val > maxval) ? val : maxval;
268: }
269: tmpBuffer[revolver + i] = maxval;
270: srcPixelOffset += srcPixelStride;
271: }
272: revolver += dwidth;
273: srcScanlineOffset += srcScanlineStride;
274: }
275:
276: // srcScanlineStride already bumped by
277: // filterSize-1*scanlineStride
278:
279: for (int j = 0; j < dheight; j++) {
280: int srcPixelOffset = srcScanlineOffset;
281: int dstPixelOffset = dstScanlineOffset;
282:
283: for (int i = 0; i < dwidth; i++) {
284: int imageOffset = srcPixelOffset;
285: maxval = Integer.MIN_VALUE;
286: for (int v = 0; v < wp; v++) {
287: val = srcData[imageOffset] & 0xffff;
288: imageOffset += srcPixelStride;
289: maxval = (val > maxval) ? val : maxval;
290: }
291: tmpBuffer[revolver + i] = maxval;
292:
293: maxval = Integer.MIN_VALUE;
294: for (int b = i; b < tmpBufferSize; b += dwidth) {
295: val = tmpBuffer[b];
296: maxval = (val > maxval) ? val : maxval;
297: }
298:
299: dstData[dstPixelOffset] = (short) maxval;
300: srcPixelOffset += srcPixelStride;
301: dstPixelOffset += dstPixelStride;
302: }
303: revolver += dwidth;
304: if (revolver == tmpBufferSize) {
305: revolver = 0;
306: }
307: srcScanlineOffset += srcScanlineStride;
308: dstScanlineOffset += dstScanlineStride;
309: }
310: }
311: }
312:
313: protected void intLoop(RasterAccessor src, RasterAccessor dst,
314: int filterSize) {
315: int dwidth = dst.getWidth();
316: int dheight = dst.getHeight();
317: int dnumBands = dst.getNumBands();
318:
319: int dstDataArrays[][] = dst.getIntDataArrays();
320: int dstBandOffsets[] = dst.getBandOffsets();
321: int dstPixelStride = dst.getPixelStride();
322: int dstScanlineStride = dst.getScanlineStride();
323:
324: int srcDataArrays[][] = src.getIntDataArrays();
325: int srcBandOffsets[] = src.getBandOffsets();
326: int srcPixelStride = src.getPixelStride();
327: int srcScanlineStride = src.getScanlineStride();
328:
329: int maxValues[] = new int[filterSize];
330: int val, maxval;
331: int wp = filterSize;
332: int tmpBuffer[] = new int[filterSize * dwidth];
333: int tmpBufferSize = filterSize * dwidth;
334:
335: for (int k = 0; k < dnumBands; k++) {
336: int dstData[] = dstDataArrays[k];
337: int srcData[] = srcDataArrays[k];
338: int srcScanlineOffset = srcBandOffsets[k];
339: int dstScanlineOffset = dstBandOffsets[k];
340:
341: int revolver = 0;
342: for (int j = 0; j < filterSize - 1; j++) {
343: int srcPixelOffset = srcScanlineOffset;
344:
345: for (int i = 0; i < dwidth; i++) {
346: int imageOffset = srcPixelOffset;
347: maxval = Integer.MIN_VALUE;
348: for (int v = 0; v < wp; v++) {
349: val = srcData[imageOffset];
350: imageOffset += srcPixelStride;
351: maxval = (val > maxval) ? val : maxval;
352: }
353: tmpBuffer[revolver + i] = maxval;
354: srcPixelOffset += srcPixelStride;
355: }
356: revolver += dwidth;
357: srcScanlineOffset += srcScanlineStride;
358: }
359:
360: // srcScanlineStride already bumped by
361: // filterSize-1*scanlineStride
362:
363: for (int j = 0; j < dheight; j++) {
364: int srcPixelOffset = srcScanlineOffset;
365: int dstPixelOffset = dstScanlineOffset;
366:
367: for (int i = 0; i < dwidth; i++) {
368: int imageOffset = srcPixelOffset;
369: maxval = Integer.MIN_VALUE;
370: for (int v = 0; v < wp; v++) {
371: val = srcData[imageOffset];
372: imageOffset += srcPixelStride;
373: maxval = (val > maxval) ? val : maxval;
374: }
375: tmpBuffer[revolver + i] = maxval;
376:
377: maxval = Integer.MIN_VALUE;
378: for (int b = i; b < tmpBufferSize; b += dwidth) {
379: val = tmpBuffer[b];
380: maxval = (val > maxval) ? val : maxval;
381: }
382:
383: dstData[dstPixelOffset] = maxval;
384: srcPixelOffset += srcPixelStride;
385: dstPixelOffset += dstPixelStride;
386: }
387: revolver += dwidth;
388: if (revolver == tmpBufferSize) {
389: revolver = 0;
390: }
391: srcScanlineOffset += srcScanlineStride;
392: dstScanlineOffset += dstScanlineStride;
393: }
394: }
395:
396: }
397:
398: protected void floatLoop(RasterAccessor src, RasterAccessor dst,
399: int filterSize) {
400: int dwidth = dst.getWidth();
401: int dheight = dst.getHeight();
402: int dnumBands = dst.getNumBands();
403:
404: float dstDataArrays[][] = dst.getFloatDataArrays();
405: int dstBandOffsets[] = dst.getBandOffsets();
406: int dstPixelStride = dst.getPixelStride();
407: int dstScanlineStride = dst.getScanlineStride();
408:
409: float srcDataArrays[][] = src.getFloatDataArrays();
410: int srcBandOffsets[] = src.getBandOffsets();
411: int srcPixelStride = src.getPixelStride();
412: int srcScanlineStride = src.getScanlineStride();
413:
414: float maxValues[] = new float[filterSize];
415: float val, maxval;
416: int wp = filterSize;
417: float tmpBuffer[] = new float[filterSize * dwidth];
418: int tmpBufferSize = filterSize * dwidth;
419:
420: for (int k = 0; k < dnumBands; k++) {
421: float dstData[] = dstDataArrays[k];
422: float srcData[] = srcDataArrays[k];
423: int srcScanlineOffset = srcBandOffsets[k];
424: int dstScanlineOffset = dstBandOffsets[k];
425:
426: int revolver = 0;
427: for (int j = 0; j < filterSize - 1; j++) {
428: int srcPixelOffset = srcScanlineOffset;
429:
430: for (int i = 0; i < dwidth; i++) {
431: int imageOffset = srcPixelOffset;
432: maxval = -Float.MAX_VALUE;
433: for (int v = 0; v < wp; v++) {
434: val = srcData[imageOffset];
435: imageOffset += srcPixelStride;
436: maxval = (val > maxval) ? val : maxval;
437: }
438: tmpBuffer[revolver + i] = maxval;
439: srcPixelOffset += srcPixelStride;
440: }
441: revolver += dwidth;
442: srcScanlineOffset += srcScanlineStride;
443: }
444:
445: // srcScanlineStride already bumped by
446: // filterSize-1*scanlineStride
447:
448: for (int j = 0; j < dheight; j++) {
449: int srcPixelOffset = srcScanlineOffset;
450: int dstPixelOffset = dstScanlineOffset;
451:
452: for (int i = 0; i < dwidth; i++) {
453: int imageOffset = srcPixelOffset;
454: maxval = -Float.MAX_VALUE;
455: for (int v = 0; v < wp; v++) {
456: val = srcData[imageOffset];
457: imageOffset += srcPixelStride;
458: maxval = (val > maxval) ? val : maxval;
459: }
460: tmpBuffer[revolver + i] = maxval;
461:
462: maxval = -Float.MAX_VALUE;
463: for (int b = i; b < tmpBufferSize; b += dwidth) {
464: val = tmpBuffer[b];
465: maxval = (val > maxval) ? val : maxval;
466: }
467:
468: dstData[dstPixelOffset] = maxval;
469: srcPixelOffset += srcPixelStride;
470: dstPixelOffset += dstPixelStride;
471: }
472: revolver += dwidth;
473: if (revolver == tmpBufferSize) {
474: revolver = 0;
475: }
476: srcScanlineOffset += srcScanlineStride;
477: dstScanlineOffset += dstScanlineStride;
478: }
479: }
480: }
481:
482: protected void doubleLoop(RasterAccessor src, RasterAccessor dst,
483: int filterSize) {
484: int dwidth = dst.getWidth();
485: int dheight = dst.getHeight();
486: int dnumBands = dst.getNumBands();
487:
488: double dstDataArrays[][] = dst.getDoubleDataArrays();
489: int dstBandOffsets[] = dst.getBandOffsets();
490: int dstPixelStride = dst.getPixelStride();
491: int dstScanlineStride = dst.getScanlineStride();
492:
493: double srcDataArrays[][] = src.getDoubleDataArrays();
494: int srcBandOffsets[] = src.getBandOffsets();
495: int srcPixelStride = src.getPixelStride();
496: int srcScanlineStride = src.getScanlineStride();
497:
498: double maxValues[] = new double[filterSize];
499: double val, maxval;
500: int wp = filterSize;
501: double tmpBuffer[] = new double[filterSize * dwidth];
502: int tmpBufferSize = filterSize * dwidth;
503:
504: for (int k = 0; k < dnumBands; k++) {
505: double dstData[] = dstDataArrays[k];
506: double srcData[] = srcDataArrays[k];
507: int srcScanlineOffset = srcBandOffsets[k];
508: int dstScanlineOffset = dstBandOffsets[k];
509:
510: int revolver = 0;
511: for (int j = 0; j < filterSize - 1; j++) {
512: int srcPixelOffset = srcScanlineOffset;
513:
514: for (int i = 0; i < dwidth; i++) {
515: int imageOffset = srcPixelOffset;
516: maxval = -Double.MAX_VALUE;
517: for (int v = 0; v < wp; v++) {
518: val = srcData[imageOffset];
519: imageOffset += srcPixelStride;
520: maxval = (val > maxval) ? val : maxval;
521: }
522: tmpBuffer[revolver + i] = maxval;
523: srcPixelOffset += srcPixelStride;
524: }
525: revolver += dwidth;
526: srcScanlineOffset += srcScanlineStride;
527: }
528:
529: // srcScanlineStride already bumped by
530: // filterSize-1*scanlineStride
531:
532: for (int j = 0; j < dheight; j++) {
533: int srcPixelOffset = srcScanlineOffset;
534: int dstPixelOffset = dstScanlineOffset;
535:
536: for (int i = 0; i < dwidth; i++) {
537: int imageOffset = srcPixelOffset;
538: maxval = -Double.MAX_VALUE;
539: for (int v = 0; v < wp; v++) {
540: val = srcData[imageOffset];
541: imageOffset += srcPixelStride;
542: maxval = (val > maxval) ? val : maxval;
543: }
544: tmpBuffer[revolver + i] = maxval;
545:
546: maxval = -Double.MAX_VALUE;
547: for (int b = i; b < tmpBufferSize; b += dwidth) {
548: val = tmpBuffer[b];
549: maxval = (val > maxval) ? val : maxval;
550: }
551:
552: dstData[dstPixelOffset] = maxval;
553: srcPixelOffset += srcPixelStride;
554: dstPixelOffset += dstPixelStride;
555: }
556: revolver += dwidth;
557: if (revolver == tmpBufferSize) {
558: revolver = 0;
559: }
560: srcScanlineOffset += srcScanlineStride;
561: dstScanlineOffset += dstScanlineStride;
562: }
563: }
564: }
565:
566: // public static OpImage createTestImage(OpImageTester oit) {
567: // return
568: // new MaxFilterSeparableOpImage(oit.getSource(), null, null,
569: // new ImageLayout(oit.getSource()),
570: // 3);
571: // }
572:
573: // public static void main(String args[]) {
574: // String classname =
575: // "com.sun.media.jai.opimage.MaxFilterSeparableOpImage";
576: // OpImageTester.performDiagnostics(classname,args);
577: // }
578: }
|