001: /*
002: * $RCSfile: MlibSubsampleBinaryToGrayOpImage.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:06 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.mlib;
013:
014: import java.awt.image.RenderedImage;
015: import javax.media.jai.ImageLayout;
016: import javax.media.jai.Interpolation;
017: import java.util.Map;
018: import java.awt.Rectangle;
019: import java.awt.geom.Point2D;
020: import java.awt.image.Raster;
021: import java.awt.image.WritableRaster;
022: import java.awt.image.DataBuffer;
023: import java.awt.image.ColorModel;
024: import java.awt.image.IndexColorModel;
025: import java.awt.image.SampleModel;
026: import java.awt.image.MultiPixelPackedSampleModel;
027: import java.awt.image.PixelInterleavedSampleModel;
028: import java.awt.image.SinglePixelPackedSampleModel;
029: import java.awt.image.BandedSampleModel;
030: import java.awt.image.PixelInterleavedSampleModel;
031: import javax.media.jai.ImageLayout;
032: import java.util.Map;
033: import javax.media.jai.GeometricOpImage;
034: import com.sun.medialib.mlib.*;
035: import com.sun.media.jai.util.ImageUtil;
036: import com.sun.media.jai.util.JDKWorkarounds;
037: import javax.media.jai.PlanarImage;
038: import com.sun.media.jai.opimage.SubsampleBinaryToGrayOpImage;
039:
040: /**
041: * A mediaLib class extending <code>GeometricOpImage</code> to
042: * subsample binary images to gray scale images. Image scaling operations
043: * require rectilinear backwards mapping and padding by the resampling
044: * filter dimensions.
045: *
046: * <p> When applying scale factors of scaleX, scaleY to a source image
047: * with width of src_width and height of src_height, the resulting image
048: * is defined to have the following bounds:
049: *
050: * <code></pre>
051: * dst minX = floor(src minX * scaleX)
052: * dst minY = floor(src minY * scaleY)
053: * dst width = floor(src width * scaleX)
054: * dst height = floor(src height * scaleY)
055: * </pre></code>
056: *
057: * @see ScaleOpImage
058: * @see com.sun.media.jai.opimage.SubsampleBinaryToGrayOpImage
059: *
060: */
061: class MlibSubsampleBinaryToGrayOpImage extends
062: SubsampleBinaryToGrayOpImage {
063:
064: /**
065: * Constructs a <code>MlibSubsampleBinaryToGrayOpImage</code>
066: * from a <code>RenderedImage</code> source, x and y scale
067: * object. The image dimensions are determined by forward-mapping
068: * the source bounds, and are passed to the superclass constructor
069: * by means of the <code>layout</code> parameter. Other fields of
070: * the layout are passed through unchanged. If
071: * <code>layout</code> is <code>null</code>, a new
072: * <code>ImageLayout</code> will be constructor to hold the bounds
073: * information.
074: *
075: * The float rounding errors, such as 1.2 being
076: * internally represented as 1.200001, are dealt with
077: * the floatTol, which is set up so that only 1/10 of pixel
078: * error will occur at the end of a line, which yields correct
079: * results with Math.round() operation.
080: * The repeatability is guaranteed with a one-time computed
081: * tables for x-values and y-values.
082: *
083: * @param source a <code>RenderedImage</code>.
084: * @param layout an <code>ImageLayout</code> optionally containing
085: * the tile grid layout, <code>SampleModel</code>, and
086: * <code>ColorModel</code>, or <code>null</code>.
087:
088: * from this <code>OpImage</code>, or <code>null</code>. If
089: * <code>null</code>, no caching will be performed.
090: * @param scaleX scale factor along x axis.
091: * @param scaleY scale factor along y axis.
092: *
093: * @throws IllegalArgumentException if combining the
094: * source bounds with the layout parameter results in negative
095: * output width or height.
096: */
097: public MlibSubsampleBinaryToGrayOpImage(RenderedImage source,
098: ImageLayout layout, Map config, float scaleX, float scaleY) {
099:
100: super (source, layout, config, scaleX, scaleY);
101: }
102:
103: /**
104: * Returns the minimum bounding box of the region of the specified
105: * source to which a particular <code>Rectangle</code> of the
106: * destination will be mapped.
107: *
108: * @param destRect the <code>Rectangle</code> in destination coordinates.
109: * @param sourceIndex the index of the source image.
110: *
111: * @return a <code>Rectangle</code> indicating the source bounding box,
112: * or <code>null</code> if the bounding box is unknown.
113: *
114: * @throws IllegalArgumentException if <code>sourceIndex</code> is
115: * negative or greater than the index of the last source.
116: * @throws IllegalArgumentException if <code>destRect</code> is
117: * <code>null</code>.
118: */
119: protected Rectangle backwardMapRect(Rectangle destRect,
120: int sourceIndex) {
121: Rectangle sourceRect = super .backwardMapRect(destRect,
122: sourceIndex);
123:
124: // Increment dimensions (fix for 4643583).
125: sourceRect.width += (int) invScaleX;
126: sourceRect.height += (int) invScaleY;
127:
128: // Clamp rectangle to source bounds (fix for 4696977).
129: return sourceRect.intersection(getSourceImage(0).getBounds());
130: }
131:
132: /**
133: * Subsample (and condense) the given rectangle by the specified scale.
134: * The sources are cobbled.
135: *
136: * @param sources an array of sources, guarantee to provide all
137: * necessary source data for computing the rectangle.
138: * @param dest a tile that contains the rectangle to be computed.
139: * @param destRect the rectangle within this OpImage to be processed.
140: */
141: protected void computeRect(Raster[] sources, WritableRaster dest,
142: Rectangle destRect) {
143:
144: Raster source = sources[0];
145: Rectangle srcRect = source.getBounds();
146:
147: // Hard-code the source format tag as we know that the image
148: // has a binary layout.
149: int sourceFormatTag = dest.getSampleModel().getDataType()
150: | MediaLibAccessor.BINARY | MediaLibAccessor.UNCOPIED;
151:
152: // Derive format tag for the destination only by providing a
153: // null-valued srcs[] parameter.
154: int destFormatTag = MediaLibAccessor.findCompatibleTag(null,
155: dest);
156:
157: MediaLibAccessor srcAccessor = new MediaLibAccessor(source,
158: srcRect, sourceFormatTag, true);
159: MediaLibAccessor dstAccessor = new MediaLibAccessor(dest,
160: destRect, destFormatTag);
161: mediaLibImage srcML[], dstML[];
162:
163: switch (dstAccessor.getDataType()) {
164: case DataBuffer.TYPE_BYTE:
165: case DataBuffer.TYPE_USHORT:
166: case DataBuffer.TYPE_SHORT:
167: case DataBuffer.TYPE_INT:
168: srcML = srcAccessor.getMediaLibImages();
169: dstML = dstAccessor.getMediaLibImages();
170: for (int i = 0; i < dstML.length; i++) {
171: Image.SubsampleBinaryToGray(dstML[i], srcML[i],
172: (double) scaleX, (double) scaleY, lutGray);
173: }
174: break;
175: default:
176: String className = this .getClass().getName();
177: throw new RuntimeException(JaiI18N.getString("Generic2"));
178: }
179:
180: if (dstAccessor.isDataCopy()) {
181: dstAccessor.clampDataArrays();
182: dstAccessor.copyDataToRaster();
183: }
184: }
185:
186: }
|