KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > ext > awt > image > rendered > AffineRed


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.rendered;
19
20 import java.awt.Point JavaDoc;
21 import java.awt.Rectangle JavaDoc;
22 import java.awt.RenderingHints JavaDoc;
23 import java.awt.Transparency JavaDoc;
24 import java.awt.color.ColorSpace JavaDoc;
25 import java.awt.geom.AffineTransform JavaDoc;
26 import java.awt.geom.NoninvertibleTransformException JavaDoc;
27 import java.awt.geom.Point2D JavaDoc;
28 import java.awt.image.AffineTransformOp JavaDoc;
29 import java.awt.image.BufferedImage JavaDoc;
30 import java.awt.image.ColorModel JavaDoc;
31 import java.awt.image.ComponentColorModel JavaDoc;
32 import java.awt.image.DataBuffer JavaDoc;
33 import java.awt.image.DirectColorModel JavaDoc;
34 import java.awt.image.Raster JavaDoc;
35 import java.awt.image.SampleModel JavaDoc;
36 import java.awt.image.WritableRaster JavaDoc;
37
38 import org.apache.batik.ext.awt.image.GraphicsUtil;
39
40 /**
41  * This is an implementation of an affine operation as a RenderedImage.
42  * Right now the implementation makes use of the AffineBufferedImageOp
43  * to do the work. Eventually this may move to be more tiled in nature.
44  *
45  * @author <a HREF="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
46  * @version $Id: AffineRed.java,v 1.12 2004/08/18 07:14:07 vhardy Exp $ */

47 public class AffineRed extends AbstractRed {
48
49     RenderingHints JavaDoc hints;
50     AffineTransform JavaDoc src2me;
51     AffineTransform JavaDoc me2src;
52
53     public AffineTransform JavaDoc getTransform() {
54         return (AffineTransform JavaDoc)src2me.clone();
55     }
56
57     public CachableRed getSource() {
58         return (CachableRed)getSources().get(0);
59     }
60
61     public AffineRed(CachableRed src,
62                      AffineTransform JavaDoc src2me,
63                      RenderingHints JavaDoc hints) {
64         super(); // We _must_ call init...
65

66         this.src2me = src2me;
67         this.hints = hints;
68
69         try {
70             me2src = src2me.createInverse();
71         } catch (NoninvertibleTransformException JavaDoc nite) {
72             me2src = null;
73         }
74
75         // Calculate my bounds by applying the affine transform to
76
// my input data..codec/
77
Rectangle JavaDoc srcBounds = src.getBounds();
78         // srcBounds.grow(-1,-1);
79
Rectangle JavaDoc myBounds;
80         myBounds = src2me.createTransformedShape(srcBounds).getBounds();
81
82         // If the output buffer is not premultiplied in certain cases it
83
// fails to properly divide out the Alpha (it always does
84
// the affine on premultiplied data), hence you get ugly
85
// back aliasing effects...
86
ColorModel JavaDoc cm = fixColorModel(src);
87
88         // fix my sample model so it makes sense given my size.
89
SampleModel JavaDoc sm = fixSampleModel(src, cm, myBounds);
90
91         Point2D JavaDoc pt = new Point2D.Float JavaDoc(src.getTileGridXOffset(),
92                                        src.getTileGridYOffset());
93         pt = src2me.transform(pt, null);
94         
95         // Finish initializing our base class...
96
init(src, myBounds, cm, sm,
97              (int)pt.getX(), (int)pt.getY(), null);
98     }
99
100     public WritableRaster JavaDoc copyData(WritableRaster JavaDoc wr) {
101
102         // System.out.println("Affine CopyData:" + wr);
103

104         // copyToRaster(wr);
105
PadRed.ZeroRecter zr = PadRed.ZeroRecter.getZeroRecter(wr);
106         zr.zeroRect(new Rectangle JavaDoc(wr.getMinX(), wr.getMinY(),
107                                   wr.getWidth(), wr.getHeight()));
108         genRect(wr);
109         return wr;
110     }
111
112     public Raster JavaDoc getTile(int x, int y) {
113         if (me2src == null)
114             return null;
115
116         int tx = tileGridXOff+x*tileWidth;
117         int ty = tileGridYOff+y*tileHeight;
118         Point JavaDoc pt = new Point JavaDoc(tx, ty);
119         WritableRaster JavaDoc wr = Raster.createWritableRaster(sm, pt);
120         genRect(wr);
121         
122         return wr;
123     }
124
125     public void genRect(WritableRaster JavaDoc wr) {
126         if (me2src == null)
127             return;
128
129         Rectangle JavaDoc srcR
130             = me2src.createTransformedShape(wr.getBounds()).getBounds();
131
132         // System.out.println("Affine wrR: " + wr.getBounds());
133
// System.out.println("Affine srcR: " + srcR);
134

135         // Outset by two pixels so we get context for interpolation...
136
srcR.setBounds(srcR.x-1, srcR.y-1, srcR.width+2, srcR.height+2);
137
138         // Don't try and get data from src that it doesn't have...
139
CachableRed src = (CachableRed)getSources().get(0);
140
141         // Raster srcRas = src.getData(srcR);
142

143         if (srcR.intersects(src.getBounds()) == false)
144             return;
145         Raster JavaDoc srcRas = src.getData(srcR.intersection(src.getBounds()));
146
147         if (srcRas == null)
148             return;
149
150         // This works around the problem that the buffered ops
151
// completely ignore the coords of the Rasters passed in.
152
AffineTransform JavaDoc aff = (AffineTransform JavaDoc)src2me.clone();
153
154         // Translate what is at 0,0 (which will be what our current
155
// minX/Y is) to our current minX,minY.
156
aff.concatenate(AffineTransform.getTranslateInstance
157                         (srcRas.getMinX(), srcRas.getMinY()));
158
159         Point2D JavaDoc srcPt = new Point2D.Float JavaDoc(wr.getMinX(), wr.getMinY());
160         srcPt = me2src.transform(srcPt, null);
161
162         Point2D JavaDoc destPt = new Point2D.Double JavaDoc(srcPt.getX()-srcRas.getMinX(),
163                                             srcPt.getY()-srcRas.getMinY());
164
165         destPt = aff.transform(destPt, null);
166
167
168         // Translate what will be at minX,minY to zero, zero
169
// which where java2d will think the real minX,minY is.
170
aff.preConcatenate(AffineTransform.getTranslateInstance
171                            (-destPt.getX(), -destPt.getY()));
172
173         AffineTransformOp JavaDoc op = new AffineTransformOp JavaDoc(aff, hints);
174
175         BufferedImage JavaDoc srcBI, myBI;
176         ColorModel JavaDoc srcCM = src.getColorModel();
177         ColorModel JavaDoc myCM = getColorModel();
178
179         WritableRaster JavaDoc srcWR = (WritableRaster JavaDoc)srcRas;
180         // If the output buffer is not premultiplied in certain cases
181
// it fails to properly divide out the Alpha (it always does
182
// the affine on premultiplied data). We help it out by
183
// premultiplying for it.
184
srcCM = GraphicsUtil.coerceData(srcWR, srcCM, true);
185         srcBI = new BufferedImage JavaDoc(srcCM,
186                                   srcWR.createWritableTranslatedChild(0,0),
187                                   srcCM.isAlphaPremultiplied(), null);
188
189         myBI = new BufferedImage JavaDoc(myCM,wr.createWritableTranslatedChild(0,0),
190                                  myCM.isAlphaPremultiplied(), null);
191
192         op.filter(srcBI, myBI);
193
194         // if ((count % 40) == 0) {
195
// org.apache.batik.ImageDisplay.showImage("Src: " , srcBI);
196
// org.apache.batik.ImageDisplay.showImage("Dst: " , myBI);
197
// }
198
// count++;
199
}
200
201     // int count=0;
202

203     protected static ColorModel JavaDoc fixColorModel(CachableRed src) {
204         ColorModel JavaDoc cm = src.getColorModel();
205
206         if (cm.hasAlpha()) {
207             if (!cm.isAlphaPremultiplied())
208                 cm = GraphicsUtil.coerceColorModel(cm, true);
209             return cm;
210         }
211
212         ColorSpace JavaDoc cs = cm.getColorSpace();
213
214         int b = src.getSampleModel().getNumBands()+1;
215         if (b == 4) {
216             int [] masks = new int[4];
217             for (int i=0; i < b-1; i++)
218                 masks[i] = 0xFF0000 >> (8*i);
219             masks[3] = 0xFF << (8*(b-1));
220
221             return new DirectColorModel JavaDoc(cs, 8*b, masks[0], masks[1],
222                                         masks[2], masks[3],
223                                         true, DataBuffer.TYPE_INT);
224         }
225
226         int [] bits = new int[b];
227         for (int i=0; i<b; i++)
228             bits[i] = 8;
229         return new ComponentColorModel JavaDoc(cs, bits, true, true,
230                                        Transparency.TRANSLUCENT,
231                                        DataBuffer.TYPE_INT);
232         
233     }
234
235     /**
236          * This function 'fixes' the source's sample model.
237          * right now it just ensures that the sample model isn't
238          * much larger than my width.
239          */

240     protected SampleModel JavaDoc fixSampleModel(CachableRed src,
241                                          ColorModel JavaDoc cm,
242                                          Rectangle JavaDoc bounds) {
243         SampleModel JavaDoc sm = src.getSampleModel();
244         int defSz = AbstractTiledRed.getDefaultTileSize();
245
246         int w = sm.getWidth();
247         if (w < defSz) w = defSz;
248         if (w > bounds.width) w = bounds.width;
249         int h = sm.getHeight();
250         if (h < defSz) h = defSz;
251         if (h > bounds.height) h = bounds.height;
252
253         if ((w <= 0) || (h <= 0)) {
254             w = 1;
255             h = 1;
256         }
257
258         return cm.createCompatibleSampleModel(w, h);
259     }
260 }
261
Popular Tags