001: /*
002: * $RCSfile: MinFilterOpImage.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:35 $
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 javax.media.jai.RasterFormatTag;
028: import java.util.Map;
029: import javax.media.jai.operator.MinFilterShape;
030:
031: // import com.sun.media.jai.test.OpImageTester;
032:
033: /**
034: * An abstract OpImage class that subclasses will use to perform
035: * MinFiltering with specific masks.
036: *
037: */
038: abstract class MinFilterOpImage extends AreaOpImage {
039:
040: protected MinFilterShape maskType;
041: protected int maskSize;
042:
043: /**
044: * Creates a MinFilterOpImage given an image source, an
045: * optional BorderExtender, a maskType and maskSize. The image
046: * dimensions are derived the source image. The tile grid layout,
047: * SampleModel, and ColorModel may optionally be specified by an
048: * ImageLayout object.
049: *
050: * @param source a RenderedImage.
051: * @param extender a BorderExtender, or null.
052: * @param layout an ImageLayout optionally containing the tile grid layout,
053: * SampleModel, and ColorModel, or null.
054: * @param maskType the filter mask type.
055: * @param maskSize the filter mask size.
056: */
057: public MinFilterOpImage(RenderedImage source,
058: BorderExtender extender, Map config, ImageLayout layout,
059: MinFilterShape maskType, int maskSize) {
060: super (source, layout, config, true, extender,
061: (maskSize - 1) / 2, (maskSize - 1) / 2, (maskSize / 2),
062: (maskSize / 2));
063:
064: this .maskType = maskType;
065: this .maskSize = maskSize;
066: }
067:
068: /**
069: * Performs min filtering on a specified rectangle. The sources are
070: * cobbled.
071: *
072: * @param sources an array of source Rasters, guaranteed to provide all
073: * necessary source data for computing the output.
074: * @param dest a WritableRaster tile containing the area to be computed.
075: * @param destRect the rectangle within dest to be processed.
076: */
077: protected void computeRect(Raster[] sources, WritableRaster dest,
078: Rectangle destRect) {
079: // Retrieve format tags.
080: RasterFormatTag[] formatTags = getFormatTags();
081:
082: Raster source = sources[0];
083: Rectangle srcRect = mapDestRect(destRect, 0);
084:
085: RasterAccessor srcAccessor = new RasterAccessor(source,
086: srcRect, formatTags[0], getSource(0).getColorModel());
087: RasterAccessor dstAccessor = new RasterAccessor(dest, destRect,
088: formatTags[1], getColorModel());
089:
090: switch (dstAccessor.getDataType()) {
091: case DataBuffer.TYPE_BYTE:
092: byteLoop(srcAccessor, dstAccessor, maskSize);
093: break;
094: case DataBuffer.TYPE_SHORT:
095: shortLoop(srcAccessor, dstAccessor, maskSize);
096: break;
097: case DataBuffer.TYPE_USHORT:
098: ushortLoop(srcAccessor, dstAccessor, maskSize);
099: break;
100: case DataBuffer.TYPE_INT:
101: intLoop(srcAccessor, dstAccessor, maskSize);
102: break;
103: case DataBuffer.TYPE_FLOAT:
104: floatLoop(srcAccessor, dstAccessor, maskSize);
105: break;
106: case DataBuffer.TYPE_DOUBLE:
107: doubleLoop(srcAccessor, dstAccessor, maskSize);
108: break;
109: }
110:
111: // If the RasterAccessor object set up a temporary buffer for the
112: // op to write to, tell the RasterAccessor to write that data
113: // to the raster no that we're done with it.
114: if (dstAccessor.isDataCopy()) {
115: dstAccessor.clampDataArrays();
116: dstAccessor.copyDataToRaster();
117: }
118: }
119:
120: /** Performs min filtering using the subclass's mask on byte data */
121: protected abstract void byteLoop(RasterAccessor src,
122: RasterAccessor dst, int filterSize);
123:
124: /** Performs min filtering using the subclass's mask on short data */
125: protected abstract void shortLoop(RasterAccessor src,
126: RasterAccessor dst, int filterSize);
127:
128: /** Performs min filtering using the subclass's mask on ushort data */
129: protected abstract void ushortLoop(RasterAccessor src,
130: RasterAccessor dst, int filterSize);
131:
132: /** Performs min filtering using the subclass's mask on int data */
133: protected abstract void intLoop(RasterAccessor src,
134: RasterAccessor dst, int filterSize);
135:
136: /** Performs min filtering using the subclass's mask on float data */
137: protected abstract void floatLoop(RasterAccessor src,
138: RasterAccessor dst, int filterSize);
139:
140: /** Performs min filtering using the subclass's mask on double data */
141: protected abstract void doubleLoop(RasterAccessor src,
142: RasterAccessor dst, int filterSize);
143:
144: /** Returns the min of the input integer array */
145: static int minFilter(int data[]) {
146: if (data.length == 3) {
147: int a = data[0];
148: int b = data[1];
149: int c = data[2];
150: if (a < b) {
151: return (a < c ? a : c);
152: } else {
153: return (b < c ? b : c);
154: }
155: }
156:
157: int min = data[0];
158: for (int i = 1; i < data.length; i++) {
159: if (data[i] < min)
160: min = data[i];
161: }
162: return min;
163: }
164:
165: /** Returns the min of the input float array */
166: static float minFilterFloat(float data[]) {
167: if (data.length == 3) {
168: float a = data[0];
169: float b = data[1];
170: float c = data[2];
171: if (a < b) {
172: return (a < c ? a : c);
173: } else {
174: return (b < c ? b : c);
175: }
176: }
177:
178: float min = data[0];
179: for (int i = 1; i < data.length; i++) {
180: if (data[i] < min)
181: min = data[i];
182: }
183: return min;
184:
185: }
186:
187: /** Returns the min of the input double array */
188: static double minFilterDouble(double data[]) {
189: if (data.length == 3) {
190: double a = data[0];
191: double b = data[1];
192: double c = data[2];
193: if (a < b) {
194: return (a < c ? a : c);
195: } else {
196: return (b < c ? b : c);
197: }
198: }
199:
200: double min = data[0];
201: for (int i = 1; i < data.length; i++) {
202: if (data[i] < min)
203: min = data[i];
204: }
205: return min;
206:
207: }
208:
209: // // Calls a method on OpImage that uses introspection, to make this
210: // // class, discover it's createTestImage() call, call it and then
211: // // benchmark the performance of the created OpImage chain.
212: // public static void main(String args[]) {
213: // String classname =
214: // "com.sun.media.jai.opimage.MinFilterSquareOpImage";
215: // OpImageTester.performDiagnostics(classname,args);
216: // classname =
217: // "com.sun.media.jai.opimage.MinFilterXOpImage";
218: // OpImageTester.performDiagnostics(classname,args);
219: // classname =
220: // "com.sun.media.jai.opimage.MinFilterPlusOpImage";
221: // OpImageTester.performDiagnostics(classname,args);
222: // classname =
223: // "com.sun.media.jai.opimage.MinFilterSeparableOpImage";
224: // OpImageTester.performDiagnostics(classname,args);
225: // }
226: }
|