KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > ext > awt > image > renderable > DisplacementMapRable8Bit


1 /*
2
3    Copyright 2001,2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.ext.awt.image.renderable;
19
20 import java.awt.RenderingHints JavaDoc;
21 import java.awt.Shape JavaDoc;
22 import java.awt.geom.AffineTransform JavaDoc;
23 import java.awt.geom.Rectangle2D JavaDoc;
24 import java.awt.image.RenderedImage JavaDoc;
25 import java.awt.image.renderable.RenderContext JavaDoc;
26 import java.util.List JavaDoc;
27
28 import org.apache.batik.ext.awt.image.ARGBChannel;
29 import org.apache.batik.ext.awt.image.GraphicsUtil;
30 import org.apache.batik.ext.awt.image.rendered.AffineRed;
31 import org.apache.batik.ext.awt.image.rendered.CachableRed;
32 import org.apache.batik.ext.awt.image.rendered.DisplacementMapRed;
33
34 /**
35  * Implements a DisplacementMap operation, which takes pixel values from
36  * another image to spatially displace the input image
37  *
38  * @author <a HREF="mailto:sheng.pei@eng.sun.com">Sheng Pei</a>
39  * @version $Id: DisplacementMapRable8Bit.java,v 1.13 2005/03/27 08:58:33 cam Exp $
40  */

41 public class DisplacementMapRable8Bit
42     extends AbstractColorInterpolationRable
43     implements DisplacementMapRable {
44
45     /**
46      * Displacement scale factor
47      */

48     private double scale;
49
50     /**
51      * Defines which channel in the second source is used
52      * to displace along the x axis
53      */

54     private ARGBChannel xChannelSelector;
55
56     /**
57      * Defines which channel in the second source is used
58      * to displace along the y axis.
59      */

60     private ARGBChannel yChannelSelector;
61
62     public DisplacementMapRable8Bit(List JavaDoc sources,
63                                     double scale,
64                                     ARGBChannel xChannelSelector,
65                                     ARGBChannel yChannelSelector){
66         setSources(sources);
67         setScale(scale);
68         setXChannelSelector(xChannelSelector);
69         setYChannelSelector(yChannelSelector);
70     }
71
72     public Rectangle2D JavaDoc getBounds2D(){
73         return ((Filter)(getSources().elementAt(0))).getBounds2D();
74     }
75
76     /**
77      * The displacement scale factor
78      * @param scale can be any number.
79      */

80     public void setScale(double scale){
81         touch();
82         this.scale = scale;
83     }
84
85     /**
86      * Returns the displacement scale factor
87      */

88     public double getScale(){
89         return scale;
90     }
91
92     /**
93      * Sets this filter sources.
94      */

95     public void setSources(List JavaDoc sources){
96         if(sources.size() != 2){
97             throw new IllegalArgumentException JavaDoc();
98         }
99         init(sources, null);
100     }
101
102     /**
103      * Select which component values will be used
104      * for displacement along the X axis
105      * @param xChannelSelector value is among R,
106      * G, B and A.
107      */

108     public void setXChannelSelector(ARGBChannel xChannelSelector){
109         if(xChannelSelector == null){
110             throw new IllegalArgumentException JavaDoc();
111         }
112         touch();
113         this.xChannelSelector = xChannelSelector;
114     }
115
116     /**
117      * Returns the xChannelSelector
118      */

119     public ARGBChannel getXChannelSelector(){
120         return xChannelSelector;
121     }
122
123     /**
124      * Select which component values will be used
125      * for displacement along the Y axis
126      * @param yChannelSelector value is among R,
127      * G, B and A.
128      */

129     public void setYChannelSelector(ARGBChannel yChannelSelector){
130         if(yChannelSelector == null){
131             throw new IllegalArgumentException JavaDoc();
132         }
133         touch();
134         this.yChannelSelector = yChannelSelector;
135     }
136
137     /**
138      * Returns the yChannelSelector
139      */

140     public ARGBChannel getYChannelSelector(){
141         return yChannelSelector;
142     }
143
144     public RenderedImage JavaDoc createRendering(RenderContext JavaDoc rc) {
145         // The source image to be displaced.
146
Filter displaced = (Filter)getSources().elementAt(0);
147         // The map giving the displacement.
148
Filter map = (Filter)getSources().elementAt(1);
149
150         RenderingHints JavaDoc rh = rc.getRenderingHints();
151         if (rh == null) rh = new RenderingHints JavaDoc(null);
152
153         // update the current affine transform
154
AffineTransform JavaDoc at = rc.getTransform();
155
156         // This splits out the scale from the rest of
157
// the transformation.
158
double sx = at.getScaleX();
159         double sy = at.getScaleY();
160
161         double shx = at.getShearX();
162         double shy = at.getShearY();
163
164         double tx = at.getTranslateX();
165         double ty = at.getTranslateY();
166
167         // The Scale is the "hypotonose" of the matrix vectors.
168
double atScaleX = Math.sqrt(sx*sx + shy*shy);
169         double atScaleY = Math.sqrt(sy*sy + shx*shx);
170
171         // Now, apply the filter
172
//
173
float scaleX = (float)(scale*atScaleX);
174         float scaleY = (float)(scale*atScaleY);
175
176         // If both scale factors are zero then we don't
177
// affect the source image so just return it...
178
if ((scaleX == 0) && (scaleY == 0))
179             return displaced.createRendering(rc);
180
181         // if ((scaleX > 255) || (scaleY > 255)) {
182
// System.out.println("Scales: [" + scaleX + ", " + scaleY + "]");
183
// }
184

185         AffineTransform JavaDoc srcAt
186             = AffineTransform.getScaleInstance(atScaleX, atScaleY);
187
188         Shape JavaDoc origAOI = rc.getAreaOfInterest();
189         if (origAOI == null)
190             origAOI = getBounds2D();
191
192         Rectangle2D JavaDoc aoiR = origAOI.getBounds2D();
193
194         RenderContext JavaDoc srcRc = new RenderContext JavaDoc(srcAt, aoiR, rh);
195         RenderedImage JavaDoc mapRed = map.createRendering(srcRc);
196
197         if (mapRed == null) return null;
198
199         // Grow the area of interest in user space. to account for
200
// the max surround needs of displacement map.
201
aoiR = new Rectangle2D.Double JavaDoc(aoiR.getX() - scale/2,
202                                       aoiR.getY() - scale/2,
203                                       aoiR.getWidth() + scale,
204                                       aoiR.getHeight() + scale);
205
206         Rectangle2D JavaDoc displacedRect = displaced.getBounds2D();
207         if (aoiR.intersects(displacedRect) == false)
208             return null;
209
210         aoiR = aoiR.createIntersection(displacedRect);
211         srcRc = new RenderContext JavaDoc(srcAt, aoiR, rh);
212         RenderedImage JavaDoc displacedRed = displaced.createRendering(srcRc);
213
214         if (displacedRed == null) return null;
215
216         mapRed = convertSourceCS(mapRed);
217
218         //
219
// Build a Displacement Map Red from the two sources
220
//
221

222         CachableRed cr = new DisplacementMapRed
223             (GraphicsUtil.wrap(displacedRed),
224              GraphicsUtil.wrap(mapRed),
225              xChannelSelector, yChannelSelector,
226              scaleX, scaleY, rh);
227         //
228
// Apply the non scaling part of the transform now,
229
// if different from identity.
230
//
231
AffineTransform JavaDoc resAt
232             = new AffineTransform JavaDoc(sx/atScaleX, shy/atScaleX,
233                                   shx/atScaleY, sy/atScaleY,
234                                   tx, ty);
235
236         if(!resAt.isIdentity())
237             cr = new AffineRed(cr, resAt, rh);
238
239         return cr;
240
241
242     }
243
244     /**
245      * Returns the region of input data is is required to generate
246      * outputRgn.
247      * @param srcIndex The source to do the dependency calculation for.
248      * @param outputRgn The region of output you are interested in
249      * generating dependencies for. The is given in the user coordiate
250      * system for this node.
251      * @return The region of input required. This is in the user
252      * coordinate system for the source indicated by srcIndex.
253      */

254     public Shape JavaDoc getDependencyRegion(int srcIndex, Rectangle2D JavaDoc outputRgn){
255         // NOTE: This needs to grow the region!!!
256
// Morphology actually needs a larger area of input than
257
// it outputs.
258
return super.getDependencyRegion(srcIndex, outputRgn);
259     }
260
261     /**
262      * This calculates the region of output that is affected by a change
263      * in a region of input.
264      * @param srcIndex The input that inputRgn reflects changes in.
265      * @param inputRgn the region of input that has changed, used to
266      * calculate the returned shape. This is given in the user
267      * coordinate system of the source indicated by srcIndex.
268      * @return The region of output that would be invalid given
269      * a change to inputRgn of the source selected by srcIndex.
270      * this is in the user coordinate system of this node.
271      */

272     public Shape JavaDoc getDirtyRegion(int srcIndex, Rectangle2D JavaDoc inputRgn){
273         // NOTE: This needs to grow the region!!!
274
// Changes in the input region affect a larger area of
275
// output than the input.
276
return super.getDirtyRegion(srcIndex, inputRgn);
277     }
278
279 }
280
Popular Tags