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