001: /*
002: * $RCSfile: MedianFilterXOpImage.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:34 $
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.MedianFilterDescriptor;
029:
030: // import com.sun.media.jai.test.OpImageTester;
031:
032: /**
033: * An OpImage class to perform median filtering on a source image.
034: *
035: *
036: */
037: final class MedianFilterXOpImage extends MedianFilterOpImage {
038:
039: /**
040: * Creates a MedianFilterXOpImage 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: */
050: public MedianFilterXOpImage(RenderedImage source,
051: BorderExtender extender, Map config, ImageLayout layout,
052: int maskSize) {
053: super (source, extender, config, layout,
054: MedianFilterDescriptor.MEDIAN_MASK_PLUS, maskSize);
055: }
056:
057: protected void byteLoop(RasterAccessor src, RasterAccessor dst,
058: int filterSize) {
059: int dwidth = dst.getWidth();
060: int dheight = dst.getHeight();
061: int dnumBands = dst.getNumBands();
062:
063: byte dstDataArrays[][] = dst.getByteDataArrays();
064: int dstBandOffsets[] = dst.getBandOffsets();
065: int dstPixelStride = dst.getPixelStride();
066: int dstScanlineStride = dst.getScanlineStride();
067:
068: byte srcDataArrays[][] = src.getByteDataArrays();
069: int srcBandOffsets[] = src.getBandOffsets();
070: int srcPixelStride = src.getPixelStride();
071: int srcScanlineStride = src.getScanlineStride();
072:
073: int values[] = new int[filterSize * 2 - 1];
074: int wp = filterSize;
075: int offset = filterSize / 2;
076:
077: for (int k = 0; k < dnumBands; k++) {
078: byte dstData[] = dstDataArrays[k];
079: byte srcData[] = srcDataArrays[k];
080: int srcScanlineOffset = srcBandOffsets[k];
081: int dstScanlineOffset = dstBandOffsets[k];
082: for (int j = 0; j < dheight; j++) {
083: int srcPixelOffset = srcScanlineOffset;
084: int dstPixelOffset = dstScanlineOffset;
085:
086: for (int i = 0; i < dwidth; i++) {
087: int valueCount = 0;
088:
089: // figure out where the top left of the X starts
090: int imageOffset = srcPixelOffset;
091: for (int u = 0; u < wp; u++) {
092: values[valueCount++] = (int) (srcData[imageOffset] & 0xff);
093: imageOffset += srcScanlineStride
094: + srcPixelStride;
095: }
096:
097: // remove the center element so it doesn't get counted
098: // twice when we do the second line
099: valueCount--;
100: values[offset] = values[valueCount];
101:
102: // figure out where the top right of the X starts
103: imageOffset = srcPixelOffset + srcPixelStride
104: * (filterSize - 1);
105:
106: for (int v = 0; v < wp; v++) {
107: values[valueCount++] = (int) (srcData[imageOffset] & 0xff);
108: imageOffset += srcScanlineStride
109: - srcPixelStride;
110: }
111:
112: int val = medianFilter(values);
113:
114: dstData[dstPixelOffset] = (byte) val;
115: srcPixelOffset += srcPixelStride;
116: dstPixelOffset += dstPixelStride;
117: }
118: srcScanlineOffset += srcScanlineStride;
119: dstScanlineOffset += dstScanlineStride;
120: }
121: }
122: }
123:
124: protected void shortLoop(RasterAccessor src, RasterAccessor dst,
125: int filterSize) {
126: int dwidth = dst.getWidth();
127: int dheight = dst.getHeight();
128: int dnumBands = dst.getNumBands();
129:
130: short dstDataArrays[][] = dst.getShortDataArrays();
131: int dstBandOffsets[] = dst.getBandOffsets();
132: int dstPixelStride = dst.getPixelStride();
133: int dstScanlineStride = dst.getScanlineStride();
134:
135: short srcDataArrays[][] = src.getShortDataArrays();
136: int srcBandOffsets[] = src.getBandOffsets();
137: int srcPixelStride = src.getPixelStride();
138: int srcScanlineStride = src.getScanlineStride();
139:
140: int values[] = new int[filterSize * 2 - 1];
141: int wp = filterSize;
142: int offset = filterSize / 2;
143:
144: for (int k = 0; k < dnumBands; k++) {
145: short dstData[] = dstDataArrays[k];
146: short srcData[] = srcDataArrays[k];
147: int srcScanlineOffset = srcBandOffsets[k];
148: int dstScanlineOffset = dstBandOffsets[k];
149: for (int j = 0; j < dheight; j++) {
150: int srcPixelOffset = srcScanlineOffset;
151: int dstPixelOffset = dstScanlineOffset;
152:
153: for (int i = 0; i < dwidth; i++) {
154: int valueCount = 0;
155:
156: // figure out where the top left of the X starts
157: int imageOffset = srcPixelOffset;
158: for (int u = 0; u < wp; u++) {
159: values[valueCount++] = (int) (srcData[imageOffset]);
160: imageOffset += srcScanlineStride
161: + srcPixelStride;
162: }
163:
164: // remove the center element so it doesn't get counted
165: // twice when we do the second line
166: valueCount--;
167: values[offset] = values[valueCount];
168:
169: // figure out where the top right of the X starts
170: imageOffset = srcPixelOffset + srcPixelStride
171: * (filterSize - 1);
172:
173: for (int v = 0; v < wp; v++) {
174: values[valueCount++] = (int) (srcData[imageOffset]);
175: imageOffset += srcScanlineStride
176: - srcPixelStride;
177: }
178:
179: int val = medianFilter(values);
180:
181: dstData[dstPixelOffset] = (short) val;
182: srcPixelOffset += srcPixelStride;
183: dstPixelOffset += dstPixelStride;
184: }
185: srcScanlineOffset += srcScanlineStride;
186: dstScanlineOffset += dstScanlineStride;
187: }
188: }
189: }
190:
191: protected void ushortLoop(RasterAccessor src, RasterAccessor dst,
192: int filterSize) {
193: int dwidth = dst.getWidth();
194: int dheight = dst.getHeight();
195: int dnumBands = dst.getNumBands();
196:
197: short dstDataArrays[][] = dst.getShortDataArrays();
198: int dstBandOffsets[] = dst.getBandOffsets();
199: int dstPixelStride = dst.getPixelStride();
200: int dstScanlineStride = dst.getScanlineStride();
201:
202: short srcDataArrays[][] = src.getShortDataArrays();
203: int srcBandOffsets[] = src.getBandOffsets();
204: int srcPixelStride = src.getPixelStride();
205: int srcScanlineStride = src.getScanlineStride();
206:
207: int values[] = new int[filterSize * 2 - 1];
208: int wp = filterSize;
209: int offset = filterSize / 2;
210:
211: for (int k = 0; k < dnumBands; k++) {
212: short dstData[] = dstDataArrays[k];
213: short srcData[] = srcDataArrays[k];
214: int srcScanlineOffset = srcBandOffsets[k];
215: int dstScanlineOffset = dstBandOffsets[k];
216: for (int j = 0; j < dheight; j++) {
217: int srcPixelOffset = srcScanlineOffset;
218: int dstPixelOffset = dstScanlineOffset;
219:
220: for (int i = 0; i < dwidth; i++) {
221: int valueCount = 0;
222:
223: // figure out where the top left of the X starts
224: int imageOffset = srcPixelOffset;
225: for (int u = 0; u < wp; u++) {
226: values[valueCount++] = (int) (srcData[imageOffset] & 0xffff);
227: imageOffset += srcScanlineStride
228: + srcPixelStride;
229: }
230:
231: // remove the center element so it doesn't get counted
232: // twice when we do the second line
233: valueCount--;
234: values[offset] = values[valueCount];
235:
236: // figure out where the top right of the X starts
237: imageOffset = srcPixelOffset + srcPixelStride
238: * (filterSize - 1);
239:
240: for (int v = 0; v < wp; v++) {
241: values[valueCount++] = (int) (srcData[imageOffset] & 0xffff);
242: imageOffset += srcScanlineStride
243: - srcPixelStride;
244: }
245:
246: int val = medianFilter(values);
247:
248: dstData[dstPixelOffset] = (short) val;
249: srcPixelOffset += srcPixelStride;
250: dstPixelOffset += dstPixelStride;
251: }
252: srcScanlineOffset += srcScanlineStride;
253: dstScanlineOffset += dstScanlineStride;
254: }
255: }
256: }
257:
258: protected void intLoop(RasterAccessor src, RasterAccessor dst,
259: int filterSize) {
260: int dwidth = dst.getWidth();
261: int dheight = dst.getHeight();
262: int dnumBands = dst.getNumBands();
263:
264: int dstDataArrays[][] = dst.getIntDataArrays();
265: int dstBandOffsets[] = dst.getBandOffsets();
266: int dstPixelStride = dst.getPixelStride();
267: int dstScanlineStride = dst.getScanlineStride();
268:
269: int srcDataArrays[][] = src.getIntDataArrays();
270: int srcBandOffsets[] = src.getBandOffsets();
271: int srcPixelStride = src.getPixelStride();
272: int srcScanlineStride = src.getScanlineStride();
273:
274: int values[] = new int[filterSize * 2 - 1];
275: int wp = filterSize;
276: int offset = filterSize / 2;
277:
278: for (int k = 0; k < dnumBands; k++) {
279: int dstData[] = dstDataArrays[k];
280: int srcData[] = srcDataArrays[k];
281: int srcScanlineOffset = srcBandOffsets[k];
282: int dstScanlineOffset = dstBandOffsets[k];
283: for (int j = 0; j < dheight; j++) {
284: int srcPixelOffset = srcScanlineOffset;
285: int dstPixelOffset = dstScanlineOffset;
286:
287: for (int i = 0; i < dwidth; i++) {
288: int valueCount = 0;
289:
290: // figure out where the top left of the X starts
291: int imageOffset = srcPixelOffset;
292: for (int u = 0; u < wp; u++) {
293: values[valueCount++] = srcData[imageOffset];
294: imageOffset += srcScanlineStride
295: + srcPixelStride;
296: }
297:
298: // remove the center element so it doesn't get counted
299: // twice when we do the second line
300: valueCount--;
301: values[offset] = values[valueCount];
302:
303: // figure out where the top right of the X starts
304: imageOffset = srcPixelOffset + srcPixelStride
305: * (filterSize - 1);
306:
307: for (int v = 0; v < wp; v++) {
308: values[valueCount++] = srcData[imageOffset];
309: imageOffset += srcScanlineStride
310: - srcPixelStride;
311: }
312:
313: int val = medianFilter(values);
314:
315: dstData[dstPixelOffset] = val;
316: srcPixelOffset += srcPixelStride;
317: dstPixelOffset += dstPixelStride;
318: }
319: srcScanlineOffset += srcScanlineStride;
320: dstScanlineOffset += dstScanlineStride;
321: }
322: }
323: }
324:
325: protected void floatLoop(RasterAccessor src, RasterAccessor dst,
326: int filterSize) {
327: int dwidth = dst.getWidth();
328: int dheight = dst.getHeight();
329: int dnumBands = dst.getNumBands();
330:
331: float dstDataArrays[][] = dst.getFloatDataArrays();
332: int dstBandOffsets[] = dst.getBandOffsets();
333: int dstPixelStride = dst.getPixelStride();
334: int dstScanlineStride = dst.getScanlineStride();
335:
336: float srcDataArrays[][] = src.getFloatDataArrays();
337: int srcBandOffsets[] = src.getBandOffsets();
338: int srcPixelStride = src.getPixelStride();
339: int srcScanlineStride = src.getScanlineStride();
340:
341: float values[] = new float[filterSize * 2 - 1];
342: int wp = filterSize;
343: int offset = filterSize / 2;
344:
345: for (int k = 0; k < dnumBands; k++) {
346: float dstData[] = dstDataArrays[k];
347: float srcData[] = srcDataArrays[k];
348: int srcScanlineOffset = srcBandOffsets[k];
349: int dstScanlineOffset = dstBandOffsets[k];
350: for (int j = 0; j < dheight; j++) {
351: int srcPixelOffset = srcScanlineOffset;
352: int dstPixelOffset = dstScanlineOffset;
353:
354: for (int i = 0; i < dwidth; i++) {
355: int valueCount = 0;
356:
357: // figure out where the top left of the X starts
358: int imageOffset = srcPixelOffset;
359: for (int u = 0; u < wp; u++) {
360: values[valueCount++] = srcData[imageOffset];
361: imageOffset += srcScanlineStride
362: + srcPixelStride;
363: }
364:
365: // remove the center element so it doesn't get counted
366: // twice when we do the second line
367: valueCount--;
368: values[offset] = values[valueCount];
369:
370: // figure out where the top right of the X starts
371: imageOffset = srcPixelOffset + srcPixelStride
372: * (filterSize - 1);
373:
374: for (int v = 0; v < wp; v++) {
375: values[valueCount++] = srcData[imageOffset];
376: imageOffset += srcScanlineStride
377: - srcPixelStride;
378: }
379:
380: float val = medianFilterFloat(values);
381:
382: dstData[dstPixelOffset] = val;
383: srcPixelOffset += srcPixelStride;
384: dstPixelOffset += dstPixelStride;
385: }
386: srcScanlineOffset += srcScanlineStride;
387: dstScanlineOffset += dstScanlineStride;
388: }
389: }
390: }
391:
392: protected void doubleLoop(RasterAccessor src, RasterAccessor dst,
393: int filterSize) {
394: int dwidth = dst.getWidth();
395: int dheight = dst.getHeight();
396: int dnumBands = dst.getNumBands();
397:
398: double dstDataArrays[][] = dst.getDoubleDataArrays();
399: int dstBandOffsets[] = dst.getBandOffsets();
400: int dstPixelStride = dst.getPixelStride();
401: int dstScanlineStride = dst.getScanlineStride();
402:
403: double srcDataArrays[][] = src.getDoubleDataArrays();
404: int srcBandOffsets[] = src.getBandOffsets();
405: int srcPixelStride = src.getPixelStride();
406: int srcScanlineStride = src.getScanlineStride();
407:
408: double values[] = new double[filterSize * 2 - 1];
409: int wp = filterSize;
410: int offset = filterSize / 2;
411:
412: for (int k = 0; k < dnumBands; k++) {
413: double dstData[] = dstDataArrays[k];
414: double srcData[] = srcDataArrays[k];
415: int srcScanlineOffset = srcBandOffsets[k];
416: int dstScanlineOffset = dstBandOffsets[k];
417: for (int j = 0; j < dheight; j++) {
418: int srcPixelOffset = srcScanlineOffset;
419: int dstPixelOffset = dstScanlineOffset;
420:
421: for (int i = 0; i < dwidth; i++) {
422: int valueCount = 0;
423:
424: // figure out where the top left of the X starts
425: int imageOffset = srcPixelOffset;
426: for (int u = 0; u < wp; u++) {
427: values[valueCount++] = srcData[imageOffset];
428: imageOffset += srcScanlineStride
429: + srcPixelStride;
430: }
431:
432: // remove the center element so it doesn't get counted
433: // twice when we do the second line
434: valueCount--;
435: values[offset] = values[valueCount];
436:
437: // figure out where the top right of the X starts
438: imageOffset = srcPixelOffset + srcPixelStride
439: * (filterSize - 1);
440:
441: for (int v = 0; v < wp; v++) {
442: values[valueCount++] = srcData[imageOffset];
443: imageOffset += srcScanlineStride
444: - srcPixelStride;
445: }
446:
447: double val = medianFilterDouble(values);
448:
449: dstData[dstPixelOffset] = val;
450: srcPixelOffset += srcPixelStride;
451: dstPixelOffset += dstPixelStride;
452: }
453: srcScanlineOffset += srcScanlineStride;
454: dstScanlineOffset += dstScanlineStride;
455: }
456: }
457: }
458:
459: // public static OpImage createTestImage(OpImageTester oit) {
460: // return new MedianFilterXOpImage(oit.getSource(), null, null,
461: // new ImageLayout(oit.getSource()),
462: // 3);
463: // }
464: }
|