1 /*
2  * $RCSfile: TranslateCRIF.java,v $
3  *
4  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
5  *
6  * Use is subject to license terms.
7  *
8  * $Revision: 1.1 $
9  * $Date: 2005/02/11 04:56:45 $
10  * $State: Exp $
11  */
12 package com.lightcrafts.media.jai.opimage;
13 import java.awt.RenderingHints;
14 import java.awt.geom.Rectangle2D;
15 import java.awt.geom.AffineTransform;
16 import java.awt.image.DataBuffer;
17 import java.awt.image.MultiPixelPackedSampleModel;
18 import java.awt.image.SampleModel;
19 import java.awt.image.RenderedImage;
20 import java.awt.image.renderable.ParameterBlock;
21 import java.awt.image.renderable.RenderableImage;
22 import java.awt.image.renderable.RenderContext;
23 import com.lightcrafts.mediax.jai.BorderExtender;
24 import com.lightcrafts.mediax.jai.ImageLayout;
25 import com.lightcrafts.mediax.jai.Interpolation;
26 import com.lightcrafts.mediax.jai.InterpolationNearest;
27 import com.lightcrafts.mediax.jai.InterpolationBilinear;
28 import com.lightcrafts.mediax.jai.InterpolationBicubic;
29 import com.lightcrafts.mediax.jai.InterpolationBicubic2;
30 import com.lightcrafts.mediax.jai.TileCache;
31 import com.lightcrafts.mediax.jai.CRIFImpl;
32 
33 /**
34  * This image factory supports image operator <code>TranslateOpImage</code>
35  * in the rendered and renderable image layers.
36  *
37  * @see TranslateOpImage
38  */
39 public class TranslateCRIF extends CRIFImpl {
40 
41     private static final float TOLERANCE = 0.01F;
42 
43     /** Constructor. */
TranslateCRIF()44     public TranslateCRIF() {
45         super("translate");
46     }
47 
48     /**
49      * Creates a new instance of <code>TranslateOpImage</code>
50      * in the rendered layer. This method satisfies the
51      * implementation of RIF.
52      */
create(ParameterBlock paramBlock, RenderingHints renderHints)53     public RenderedImage create(ParameterBlock paramBlock,
54                                 RenderingHints renderHints) {
55         RenderedImage source = paramBlock.getRenderedSource(0);
56         float xTrans = paramBlock.getFloatParameter(0);
57         float yTrans = paramBlock.getFloatParameter(1);
58         Interpolation interp = (Interpolation)
59             paramBlock.getObjectParameter(2);
60 
61 	// Get ImageLayout from renderHints if any.
62 	ImageLayout layout = RIFUtil.getImageLayoutHint(renderHints);
63 
64 	// If there is a layout hint, TranslateIntOpImage can't deal with it
65         if ((Math.abs(xTrans - (int)xTrans) < TOLERANCE) &&
66             (Math.abs(yTrans - (int)yTrans) < TOLERANCE) &&
67 	    layout == null) {
68             return new TranslateIntOpImage(source,
69 					   renderHints,
70 					   (int)xTrans,
71 					   (int)yTrans);
72         } else {
73 
74             // Get TileCache from renderHints if any.
75             TileCache cache = RIFUtil.getTileCacheHint(renderHints);
76 
77             // Get BorderExtender from renderHints if any.
78             BorderExtender extender =
79                 RIFUtil.getBorderExtenderHint(renderHints);
80 
81             //
82             // Call the Scale operation, since it encapsulates Translate
83             // and is better optimized than Affine.
84             //
85             float xScale = 1.0F;
86             float yScale = 1.0F;
87 	    SampleModel sm = source.getSampleModel();
88 	    boolean isBinary =
89 	      (sm instanceof MultiPixelPackedSampleModel) &&
90 	      (sm.getSampleSize(0) == 1) &&
91 	      (sm.getDataType() == DataBuffer.TYPE_BYTE ||
92 	       sm.getDataType() == DataBuffer.TYPE_USHORT ||
93 	       sm.getDataType() == DataBuffer.TYPE_INT);
94 
95             if (interp instanceof InterpolationNearest)
96 	    {
97 	      if (isBinary)
98 	      {
99 		return new ScaleNearestBinaryOpImage(source,
100 						     extender,
101 						     renderHints,
102 						     layout,
103 						     xScale,
104 						     yScale,
105 						     xTrans,
106 						     yTrans,
107 						     interp);
108 	      }
109 	      else
110 	      {
111 		return new ScaleNearestOpImage(source,
112 					       extender,
113 					       renderHints,
114 					       layout,
115 					       xScale, yScale,
116 					       xTrans, yTrans,
117 					       interp);
118 	      }
119             }
120 	    else
121 	      if (interp instanceof InterpolationBilinear)
122 	      {
123 		if (isBinary)
124 		{
125 		  return new ScaleBilinearBinaryOpImage(source,
126 							extender,
127 							renderHints,
128 							layout,
129 							xScale,
130 							yScale,
131 							xTrans,
132 							yTrans,
133 							interp);
134 		}
135 		else
136 		{
137 		  return new ScaleBilinearOpImage(source,
138 						  extender,
139 						  renderHints,
140 						  layout,
141 						  xScale, yScale,
142 						  xTrans, yTrans,
143 						  interp);
144 		}
145 	      }
146 	      else
147 		if ((interp instanceof InterpolationBicubic) ||
148                        (interp instanceof InterpolationBicubic2))
149 		{
150 		  return new ScaleBicubicOpImage(source,
151 						 extender,
152 						 renderHints,
153 						 layout,
154 						 xScale, yScale,
155 						 xTrans, yTrans,
156 						 interp);
157 		}
158 		else
159 		{
160 		  return new ScaleGeneralOpImage(source, extender,
161 						 renderHints,
162 						 layout,
163 						 xScale, yScale,
164 						 xTrans, yTrans,
165 						 interp);
166 		}
167         }
168     }
169 
170     /**
171      * Creates a new instance of <code>TranslateOpImage</code>
172      * in the renderable layer. This method satisfies the
173      * implementation of CRIF.
174      */
create(RenderContext renderContext, ParameterBlock paramBlock)175     public RenderedImage create(RenderContext renderContext,
176                                 ParameterBlock paramBlock) {
177         return paramBlock.getRenderedSource(0);
178     }
179 
180     /**
181      * Maps the output RenderContext into the RenderContext for the ith
182      * source.
183      * This method satisfies the implementation of CRIF.
184      *
185      * @param i               The index of the source image.
186      * @param renderContext   The renderContext being applied to the operation.
187      * @param paramBlock      The ParameterBlock containing the sources
188      *                        and the translation factors.
189      * @param image           The RenderableImageOp from which this method
190      *                        was called.
191      */
mapRenderContext(int i, RenderContext renderContext, ParameterBlock paramBlock, RenderableImage image)192     public RenderContext mapRenderContext(int i,
193                                           RenderContext renderContext,
194 					  ParameterBlock paramBlock,
195 					  RenderableImage image) {
196 	AffineTransform translate = new AffineTransform();
197 	translate.setToTranslation(paramBlock.getFloatParameter(0),
198 				   paramBlock.getFloatParameter(1));
199 
200         RenderContext RC = (RenderContext)renderContext.clone();
201         AffineTransform usr2dev = RC.getTransform();
202         usr2dev.concatenate(translate);
203 	RC.setTransform(usr2dev);
204 	return RC;
205     }
206 
207     /**
208      * Gets the bounding box for output of <code>TranslateOpImage</code>.
209      * This method satisfies the implementation of CRIF.
210      */
getBounds2D(ParameterBlock paramBlock)211     public Rectangle2D getBounds2D(ParameterBlock paramBlock) {
212         RenderableImage source = paramBlock.getRenderableSource(0);
213         float xTrans = paramBlock.getFloatParameter(0);
214         float yTrans = paramBlock.getFloatParameter(1);
215 
216         return new Rectangle2D.Float(source.getMinX() + xTrans,
217                                      source.getMinY() + yTrans,
218                                      source.getWidth(),
219                                      source.getHeight());
220     }
221 }
222