001: /*
002: * $RCSfile: TranslateCRIF.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:45 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import java.awt.RenderingHints;
015: import java.awt.geom.Rectangle2D;
016: import java.awt.geom.Point2D;
017: import java.awt.geom.AffineTransform;
018: import java.awt.image.DataBuffer;
019: import java.awt.image.MultiPixelPackedSampleModel;
020: import java.awt.image.SampleModel;
021: import java.awt.image.RenderedImage;
022: import java.awt.image.renderable.ParameterBlock;
023: import java.awt.image.renderable.RenderableImage;
024: import java.awt.image.renderable.RenderableImageOp;
025: import java.awt.image.renderable.RenderContext;
026: import java.awt.image.renderable.RenderedImageFactory;
027: import javax.media.jai.BorderExtender;
028: import javax.media.jai.ImageLayout;
029: import javax.media.jai.Interpolation;
030: import javax.media.jai.InterpolationNearest;
031: import javax.media.jai.InterpolationBilinear;
032: import javax.media.jai.InterpolationBicubic;
033: import javax.media.jai.InterpolationBicubic2;
034: import javax.media.jai.TileCache;
035: import javax.media.jai.CRIFImpl;
036: import java.util.Map;
037:
038: /**
039: * This image factory supports image operator <code>TranslateOpImage</code>
040: * in the rendered and renderable image layers.
041: *
042: * @see TranslateOpImage
043: */
044: public class TranslateCRIF extends CRIFImpl {
045:
046: private static final float TOLERANCE = 0.01F;
047:
048: /** Constructor. */
049: public TranslateCRIF() {
050: super ("translate");
051: }
052:
053: /**
054: * Creates a new instance of <code>TranslateOpImage</code>
055: * in the rendered layer. This method satisfies the
056: * implementation of RIF.
057: */
058: public RenderedImage create(ParameterBlock paramBlock,
059: RenderingHints renderHints) {
060: RenderedImage source = paramBlock.getRenderedSource(0);
061: float xTrans = paramBlock.getFloatParameter(0);
062: float yTrans = paramBlock.getFloatParameter(1);
063: Interpolation interp = (Interpolation) paramBlock
064: .getObjectParameter(2);
065:
066: // Get ImageLayout from renderHints if any.
067: ImageLayout layout = RIFUtil.getImageLayoutHint(renderHints);
068:
069: // If there is a layout hint, TranslateIntOpImage can't deal with it
070: if ((Math.abs(xTrans - (int) xTrans) < TOLERANCE)
071: && (Math.abs(yTrans - (int) yTrans) < TOLERANCE)
072: && layout == null) {
073: return new TranslateIntOpImage(source, renderHints,
074: (int) xTrans, (int) yTrans);
075: } else {
076:
077: // Get TileCache from renderHints if any.
078: TileCache cache = RIFUtil.getTileCacheHint(renderHints);
079:
080: // Get BorderExtender from renderHints if any.
081: BorderExtender extender = RIFUtil
082: .getBorderExtenderHint(renderHints);
083:
084: //
085: // Call the Scale operation, since it encapsulates Translate
086: // and is better optimized than Affine.
087: //
088: float xScale = 1.0F;
089: float yScale = 1.0F;
090: SampleModel sm = source.getSampleModel();
091: boolean isBinary = (sm instanceof MultiPixelPackedSampleModel)
092: && (sm.getSampleSize(0) == 1)
093: && (sm.getDataType() == DataBuffer.TYPE_BYTE
094: || sm.getDataType() == DataBuffer.TYPE_USHORT || sm
095: .getDataType() == DataBuffer.TYPE_INT);
096:
097: if (interp instanceof InterpolationNearest) {
098: if (isBinary) {
099: return new ScaleNearestBinaryOpImage(source,
100: extender, renderHints, layout, xScale,
101: yScale, xTrans, yTrans, interp);
102: } else {
103: return new ScaleNearestOpImage(source, extender,
104: renderHints, layout, xScale, yScale,
105: xTrans, yTrans, interp);
106: }
107: } else if (interp instanceof InterpolationBilinear) {
108: if (isBinary) {
109: return new ScaleBilinearBinaryOpImage(source,
110: extender, renderHints, layout, xScale,
111: yScale, xTrans, yTrans, interp);
112: } else {
113: return new ScaleBilinearOpImage(source, extender,
114: renderHints, layout, xScale, yScale,
115: xTrans, yTrans, interp);
116: }
117: } else if ((interp instanceof InterpolationBicubic)
118: || (interp instanceof InterpolationBicubic2)) {
119: return new ScaleBicubicOpImage(source, extender,
120: renderHints, layout, xScale, yScale, xTrans,
121: yTrans, interp);
122: } else {
123: return new ScaleGeneralOpImage(source, extender,
124: renderHints, layout, xScale, yScale, xTrans,
125: yTrans, interp);
126: }
127: }
128: }
129:
130: /**
131: * Creates a new instance of <code>TranslateOpImage</code>
132: * in the renderable layer. This method satisfies the
133: * implementation of CRIF.
134: */
135: public RenderedImage create(RenderContext renderContext,
136: ParameterBlock paramBlock) {
137: return paramBlock.getRenderedSource(0);
138: }
139:
140: /**
141: * Maps the output RenderContext into the RenderContext for the ith
142: * source.
143: * This method satisfies the implementation of CRIF.
144: *
145: * @param i The index of the source image.
146: * @param renderContext The renderContext being applied to the operation.
147: * @param paramBlock The ParameterBlock containing the sources
148: * and the translation factors.
149: * @param image The RenderableImageOp from which this method
150: * was called.
151: */
152: public RenderContext mapRenderContext(int i,
153: RenderContext renderContext, ParameterBlock paramBlock,
154: RenderableImage image) {
155: AffineTransform translate = new AffineTransform();
156: translate.setToTranslation(paramBlock.getFloatParameter(0),
157: paramBlock.getFloatParameter(1));
158:
159: RenderContext RC = (RenderContext) renderContext.clone();
160: AffineTransform usr2dev = RC.getTransform();
161: usr2dev.concatenate(translate);
162: RC.setTransform(usr2dev);
163: return RC;
164: }
165:
166: /**
167: * Gets the bounding box for output of <code>TranslateOpImage</code>.
168: * This method satisfies the implementation of CRIF.
169: */
170: public Rectangle2D getBounds2D(ParameterBlock paramBlock) {
171: RenderableImage source = paramBlock.getRenderableSource(0);
172: float xTrans = paramBlock.getFloatParameter(0);
173: float yTrans = paramBlock.getFloatParameter(1);
174:
175: return new Rectangle2D.Float(source.getMinX() + xTrans, source
176: .getMinY()
177: + yTrans, source.getWidth(), source.getHeight());
178: }
179: }
|