001: /*
002: * $RCSfile: ScaleCRIF.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:42 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import java.awt.RenderingHints;
015: import java.awt.geom.AffineTransform;
016: import java.awt.geom.Rectangle2D;
017: import java.awt.image.DataBuffer;
018: import java.awt.image.MultiPixelPackedSampleModel;
019: import java.awt.image.RenderedImage;
020: import java.awt.image.SampleModel;
021: import java.awt.image.renderable.RenderedImageFactory;
022: import java.awt.image.renderable.RenderContext;
023: import java.awt.image.renderable.ParameterBlock;
024: import java.awt.image.renderable.RenderableImage;
025: import javax.media.jai.BorderExtender;
026: import javax.media.jai.ImageLayout;
027: import javax.media.jai.Interpolation;
028: import javax.media.jai.InterpolationNearest;
029: import javax.media.jai.InterpolationBilinear;
030: import javax.media.jai.InterpolationBicubic;
031: import javax.media.jai.InterpolationBicubic2;
032: import javax.media.jai.InterpolationTable;
033: import javax.media.jai.TileCache;
034: import javax.media.jai.CRIFImpl;
035: import java.util.Map;
036:
037: /**
038: * @see ScaleOpImage
039: */
040: public class ScaleCRIF extends CRIFImpl {
041:
042: private static final float TOLERANCE = 0.01F;
043:
044: /** Constructor. */
045: public ScaleCRIF() {
046: super ("scale");
047: }
048:
049: /**
050: * Creates a new instance of ScaleOpImage in the rendered layer.
051: * This method satisfies the implementation of RIF.
052: *
053: * @param paramBlock The source image, the X and Y scale factor,
054: * and the interpolation method for resampling.
055: */
056: public RenderedImage create(ParameterBlock paramBlock,
057: RenderingHints renderHints) {
058:
059: // Get ImageLayout from renderHints if any.
060: ImageLayout layout = RIFUtil.getImageLayoutHint(renderHints);
061:
062: // Get TileCache from renderHints if any.
063: TileCache cache = RIFUtil.getTileCacheHint(renderHints);
064:
065: // Get BorderExtender from renderHints if any.
066: BorderExtender extender = RIFUtil
067: .getBorderExtenderHint(renderHints);
068:
069: RenderedImage source = paramBlock.getRenderedSource(0);
070: float xScale = paramBlock.getFloatParameter(0);
071: float yScale = paramBlock.getFloatParameter(1);
072: float xTrans = paramBlock.getFloatParameter(2);
073: float yTrans = paramBlock.getFloatParameter(3);
074: Interpolation interp = (Interpolation) paramBlock
075: .getObjectParameter(4);
076:
077: // Check and see if we are scaling by 1.0 in both x and y and no
078: // translations. If so call the copy operation.
079:
080: if (xScale == 1.0F && yScale == 1.0F && xTrans == 0.0F
081: && yTrans == 0.0F) {
082: return new CopyOpImage(source, renderHints, layout);
083: }
084:
085: // Check to see whether the operation specified is a pure
086: // integer translation. If so call translate
087: // If the hints contain an ImageLayout hint, then we can't use
088: // TranslateIntOpImage since that can't deal with the ImageLayout hint
089: if (xScale == 1.0F && yScale == 1.0F
090: && (Math.abs(xTrans - (int) xTrans) < TOLERANCE)
091: && (Math.abs(yTrans - (int) yTrans) < TOLERANCE)
092: && layout == null) {
093: // It's an integer translate.
094: return new TranslateIntOpImage(source, renderHints,
095: (int) xTrans, (int) yTrans);
096: }
097:
098: if (interp instanceof InterpolationNearest) {
099: //
100: // Special case -- if the image is represented using
101: // a MultiPixelPackedSampleModel and a byte, ushort,
102: // or int DataBuffer we can access the pixel data directly.
103: // Note that there is a potential loophole that has not been
104: // resolved by Java2D as to whether the underlying DataBuffer
105: // must be of one of the standard types. Here we make the
106: // assumption that it will be -- we can't check without
107: // forcing an actual tile to be computed.
108: //
109: SampleModel sm = source.getSampleModel();
110: if ((sm instanceof MultiPixelPackedSampleModel)
111: && (sm.getSampleSize(0) == 1)
112: && (sm.getDataType() == DataBuffer.TYPE_BYTE
113: || sm.getDataType() == DataBuffer.TYPE_USHORT || sm
114: .getDataType() == DataBuffer.TYPE_INT)) {
115: return new ScaleNearestBinaryOpImage(source, extender,
116: renderHints, layout, xScale, yScale, xTrans,
117: yTrans, interp);
118: } else {
119: return new ScaleNearestOpImage(source, extender,
120: renderHints, layout, xScale, yScale, xTrans,
121: yTrans, interp);
122: }
123: } else if (interp instanceof InterpolationBilinear) {
124: SampleModel sm = source.getSampleModel();
125: if ((sm instanceof MultiPixelPackedSampleModel)
126: && (sm.getSampleSize(0) == 1)
127: && (sm.getDataType() == DataBuffer.TYPE_BYTE
128: || sm.getDataType() == DataBuffer.TYPE_USHORT || sm
129: .getDataType() == DataBuffer.TYPE_INT)) {
130: return new ScaleBilinearBinaryOpImage(source, extender,
131: renderHints, layout, xScale, yScale, xTrans,
132: yTrans, interp);
133: } else {
134: return new ScaleBilinearOpImage(source, extender,
135: renderHints, layout, xScale, yScale, xTrans,
136: yTrans, interp);
137: }
138: } else if ((interp instanceof InterpolationBicubic)
139: || (interp instanceof InterpolationBicubic2)) {
140: return new ScaleBicubicOpImage(source, extender,
141: renderHints, layout, xScale, yScale, xTrans,
142: yTrans, interp);
143: } else {
144: return new ScaleGeneralOpImage(source, extender,
145: renderHints, layout, xScale, yScale, xTrans,
146: yTrans, interp);
147: }
148: }
149:
150: /**
151: * Creates a new instance of <code>AffineOpImage</code>
152: * in the renderable layer. This method satisfies the
153: * implementation of CRIF.
154: */
155: public RenderedImage create(RenderContext renderContext,
156: ParameterBlock paramBlock) {
157: return paramBlock.getRenderedSource(0);
158: }
159:
160: /**
161: * Maps the output RenderContext into the RenderContext for the ith
162: * source.
163: * This method satisfies the implementation of CRIF.
164: *
165: * @param i The index of the source image.
166: * @param renderContext The renderContext being applied to the operation.
167: * @param paramBlock The ParameterBlock containing the sources
168: * and the translation factors.
169: * @param image The RenderableImageOp from which this method
170: * was called.
171: */
172: public RenderContext mapRenderContext(int i,
173: RenderContext renderContext, ParameterBlock paramBlock,
174: RenderableImage image) {
175:
176: float scale_x = paramBlock.getFloatParameter(0);
177: float scale_y = paramBlock.getFloatParameter(1);
178: float trans_x = paramBlock.getFloatParameter(2);
179: float trans_y = paramBlock.getFloatParameter(3);
180:
181: AffineTransform scale = new AffineTransform(scale_x, 0.0, 0.0,
182: scale_y, trans_x, trans_y);
183:
184: RenderContext RC = (RenderContext) renderContext.clone();
185: AffineTransform usr2dev = RC.getTransform();
186: usr2dev.concatenate(scale);
187: RC.setTransform(usr2dev);
188: return RC;
189: }
190:
191: /**
192: * Gets the bounding box for the output of <code>ScaleOpImage</code>.
193: * This method satisfies the implementation of CRIF.
194: */
195: public Rectangle2D getBounds2D(ParameterBlock paramBlock) {
196:
197: RenderableImage source = paramBlock.getRenderableSource(0);
198:
199: float scale_x = paramBlock.getFloatParameter(0);
200: float scale_y = paramBlock.getFloatParameter(1);
201: float trans_x = paramBlock.getFloatParameter(2);
202: float trans_y = paramBlock.getFloatParameter(3);
203: Interpolation interp = (Interpolation) paramBlock
204: .getObjectParameter(4);
205:
206: // Get the source dimensions
207: float x0 = (float) source.getMinX();
208: float y0 = (float) source.getMinY();
209: float w = (float) source.getWidth();
210: float h = (float) source.getHeight();
211:
212: // Forward map the source using x0, y0, w and h
213: float d_x0 = x0 * scale_x + trans_x;
214: float d_y0 = y0 * scale_y + trans_y;
215: float d_w = w * scale_x;
216: float d_h = h * scale_y;
217:
218: return new Rectangle2D.Float(d_x0, d_y0, d_w, d_h);
219: }
220:
221: }
|