001: /*
002: * $RCSfile: MlibMedianFilterOpImage.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:55:59 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.mlib;
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 javax.media.jai.operator.MedianFilterShape;
030: import com.sun.medialib.mlib.*;
031:
032: /**
033: * An OpImage class that subclasses will use to perform
034: * MedianFiltering with specific masks.
035: *
036: *
037: */
038: final class MlibMedianFilterOpImage extends AreaOpImage {
039:
040: protected int maskType;
041: protected int maskSize;
042:
043: /**
044: * Creates a MlibMedianFilterOpImage 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 MlibMedianFilterOpImage(RenderedImage source,
058: BorderExtender extender, Map config, ImageLayout layout,
059: MedianFilterShape maskType, int maskSize) {
060: super (source, layout, config, true, extender,
061: (maskSize - 1) / 2, (maskSize - 1) / 2, (maskSize / 2),
062: (maskSize / 2));
063: this .maskType = mapToMlibMaskType(maskType);
064: this .maskSize = maskSize;
065: }
066:
067: private static int mapToMlibMaskType(MedianFilterShape maskType) {
068: if (maskType.equals(MedianFilterDescriptor.MEDIAN_MASK_SQUARE)) {
069: return Constants.MLIB_MEDIAN_MASK_RECT;
070: } else if (maskType
071: .equals(MedianFilterDescriptor.MEDIAN_MASK_PLUS)) {
072: return Constants.MLIB_MEDIAN_MASK_PLUS;
073: } else if (maskType
074: .equals(MedianFilterDescriptor.MEDIAN_MASK_X)) {
075: return Constants.MLIB_MEDIAN_MASK_X;
076: } else if (maskType
077: .equals(MedianFilterDescriptor.MEDIAN_MASK_SQUARE_SEPARABLE)) {
078: return Constants.MLIB_MEDIAN_MASK_RECT_SEPARABLE;
079: }
080: throw new RuntimeException(JaiI18N
081: .getString("MedianFilterOpImage0"));
082: }
083:
084: /**
085: * Performs median filtering on a specified rectangle. The sources are
086: * cobbled.
087: *
088: * @param sources an array of source Rasters, guaranteed to provide all
089: * necessary source data for computing the output.
090: * @param dest a WritableRaster tile containing the area to be computed.
091: * @param destRect the rectangle within dest to be processed.
092: */
093: protected void computeRect(Raster[] sources, WritableRaster dest,
094: Rectangle destRect) {
095: Raster source = sources[0];
096: Rectangle srcRect = mapDestRect(destRect, 0);
097:
098: int formatTag = MediaLibAccessor.findCompatibleTag(sources,
099: dest);
100:
101: MediaLibAccessor srcAccessor = new MediaLibAccessor(source,
102: srcRect, formatTag);
103: MediaLibAccessor dstAccessor = new MediaLibAccessor(dest,
104: destRect, formatTag);
105: int numBands = getSampleModel().getNumBands();
106:
107: int cmask = (1 << numBands) - 1;
108: mediaLibImage[] srcML = srcAccessor.getMediaLibImages();
109: mediaLibImage[] dstML = dstAccessor.getMediaLibImages();
110: for (int i = 0; i < dstML.length; i++) {
111: switch (dstAccessor.getDataType()) {
112: case DataBuffer.TYPE_BYTE:
113: case DataBuffer.TYPE_USHORT:
114: case DataBuffer.TYPE_SHORT:
115: case DataBuffer.TYPE_INT:
116: if (maskSize == 3) {
117: // Call appropriate Medialib accelerated function
118: Image.MedianFilter3x3(dstML[i], srcML[i], maskType,
119: cmask, Constants.MLIB_EDGE_DST_NO_WRITE);
120: } else if (maskSize == 5) {
121: // Call appropriate Medialib accelerated function
122: Image.MedianFilter5x5(dstML[i], srcML[i], maskType,
123: cmask, Constants.MLIB_EDGE_DST_NO_WRITE);
124: } else if (maskSize == 7) {
125: // Call appropriate Medialib accelerated function
126: Image.MedianFilter7x7(dstML[i], srcML[i], maskType,
127: cmask, Constants.MLIB_EDGE_DST_NO_WRITE);
128: } else {
129: // Call the generic version
130: Image.MedianFilterMxN(dstML[i], srcML[i], maskSize,
131: maskSize, maskType, cmask,
132: Constants.MLIB_EDGE_DST_NO_WRITE);
133: }
134: break;
135: case DataBuffer.TYPE_FLOAT:
136: case DataBuffer.TYPE_DOUBLE:
137: if (maskSize == 3) {
138: // Call appropriate Medialib accelerated function
139: Image.MedianFilter3x3_Fp(dstML[i], srcML[i],
140: maskType, cmask,
141: Constants.MLIB_EDGE_DST_NO_WRITE);
142: } else if (maskSize == 5) {
143: // Call appropriate Medialib accelerated function
144: Image.MedianFilter5x5_Fp(dstML[i], srcML[i],
145: maskType, cmask,
146: Constants.MLIB_EDGE_DST_NO_WRITE);
147: } else if (maskSize == 7) {
148: // Call appropriate Medialib accelerated function
149: Image.MedianFilter7x7_Fp(dstML[i], srcML[i],
150: maskType, cmask,
151: Constants.MLIB_EDGE_DST_NO_WRITE);
152: } else {
153: // Call the generic version
154: Image.MedianFilterMxN_Fp(dstML[i], srcML[i],
155: maskSize, maskSize, maskType, cmask,
156: Constants.MLIB_EDGE_DST_NO_WRITE);
157: }
158: break;
159: default:
160: String className = this .getClass().getName();
161: throw new RuntimeException(JaiI18N
162: .getString("Generic2"));
163: }
164: }
165:
166: if (dstAccessor.isDataCopy()) {
167: dstAccessor.copyDataToRaster();
168: }
169: }
170: }
|