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