source: josm/trunk/src/com/kitfox/svg/batik/GraphicsUtil.java@ 6235

Last change on this file since 6235 was 4256, checked in by bastiK, 14 years ago

see #6560 - basic svg support, includes kitfox svgsalamander, r 98, patched

File size: 13.3 KB
Line 
1/*****************************************************************************
2 * Copyright (C) The Apache Software Foundation. All rights reserved. *
3 * ------------------------------------------------------------------------- *
4 * This software is published under the terms of the Apache Software License *
5 * version 1.1, a copy of which has been included with this distribution in *
6 * the LICENSE file. *
7 *****************************************************************************/
8
9package com.kitfox.svg.batik;
10
11import java.awt.Color;
12import java.awt.Composite;
13import java.awt.Graphics2D;
14import java.awt.GraphicsConfiguration;
15import java.awt.GraphicsDevice;
16import java.awt.Point;
17import java.awt.Rectangle;
18import java.awt.RenderingHints;
19import java.awt.Shape;
20import java.awt.color.ColorSpace;
21import java.awt.geom.AffineTransform;
22import java.awt.geom.Rectangle2D;
23import java.awt.image.BufferedImage;
24import java.awt.image.ColorModel;
25import java.awt.image.ComponentSampleModel;
26import java.awt.image.DataBuffer;
27import java.awt.image.DataBufferByte;
28import java.awt.image.DataBufferInt;
29import java.awt.image.DataBufferShort;
30import java.awt.image.DataBufferUShort;
31import java.awt.image.DirectColorModel;
32import java.awt.image.Raster;
33import java.awt.image.RenderedImage;
34import java.awt.image.SampleModel;
35import java.awt.image.SinglePixelPackedSampleModel;
36import java.awt.image.WritableRaster;
37import java.awt.image.renderable.RenderContext;
38import java.awt.image.renderable.RenderableImage;
39import java.lang.ref.Reference;
40import java.lang.ref.WeakReference;
41
42/**
43 *
44 * @author kitfox
45 */
46public class GraphicsUtil
47{
48
49 /** Creates a new instance of GraphicsUtil */
50 public GraphicsUtil()
51 {
52 }
53
54 /**
55 * Create a new ColorModel with it's alpha premultiplied state matching
56 * newAlphaPreMult.
57 * @param cm The ColorModel to change the alpha premult state of.
58 * @param newAlphaPreMult The new state of alpha premult.
59 * @return A new colorModel that has isAlphaPremultiplied()
60 * equal to newAlphaPreMult.
61 */
62 public static ColorModel coerceColorModel(ColorModel cm, boolean newAlphaPreMult)
63 {
64 if (cm.isAlphaPremultiplied() == newAlphaPreMult)
65 return cm;
66
67 // Easiest way to build proper colormodel for new Alpha state...
68 // Eventually this should switch on known ColorModel types and
69 // only fall back on this hack when the CM type is unknown.
70 WritableRaster wr = cm.createCompatibleWritableRaster(1,1);
71 return cm.coerceData(wr, newAlphaPreMult);
72 }
73
74 /**
75 * Coerces data within a bufferedImage to match newAlphaPreMult,
76 * Note that this can not change the colormodel of bi so you
77 *
78 * @param wr The raster to change the state of.
79 * @param cm The colormodel currently associated with data in wr.
80 * @param newAlphaPreMult The desired state of alpha Premult for raster.
81 * @return A new colormodel that matches newAlphaPreMult.
82 */
83 public static ColorModel coerceData(WritableRaster wr, ColorModel cm, boolean newAlphaPreMult)
84 {
85
86 // System.out.println("CoerceData: " + cm.isAlphaPremultiplied() +
87 // " Out: " + newAlphaPreMult);
88 if (cm.hasAlpha()== false)
89 // Nothing to do no alpha channel
90 return cm;
91
92 if (cm.isAlphaPremultiplied() == newAlphaPreMult)
93 // nothing to do alpha state matches...
94 return cm;
95
96 // System.out.println("CoerceData: " + wr.getSampleModel());
97
98 int [] pixel = null;
99 int bands = wr.getNumBands();
100 float norm;
101 if (newAlphaPreMult)
102 {
103 if (is_BYTE_COMP_Data(wr.getSampleModel()))
104 mult_BYTE_COMP_Data(wr);
105 else if (is_INT_PACK_Data(wr.getSampleModel(), true))
106 mult_INT_PACK_Data(wr);
107 else
108 {
109 norm = 1f/255f;
110 int x0, x1, y0, y1, a, b;
111 float alpha;
112 x0 = wr.getMinX();
113 x1 = x0+wr.getWidth();
114 y0 = wr.getMinY();
115 y1 = y0+wr.getHeight();
116 for (int y=y0; y<y1; y++)
117 for (int x=x0; x<x1; x++)
118 {
119 pixel = wr.getPixel(x,y,pixel);
120 a = pixel[bands-1];
121 if ((a >= 0) && (a < 255))
122 {
123 alpha = a*norm;
124 for (b=0; b<bands-1; b++)
125 pixel[b] = (int)(pixel[b]*alpha+0.5f);
126 wr.setPixel(x,y,pixel);
127 }
128 }
129 }
130 } else
131 {
132 if (is_BYTE_COMP_Data(wr.getSampleModel()))
133 divide_BYTE_COMP_Data(wr);
134 else if (is_INT_PACK_Data(wr.getSampleModel(), true))
135 divide_INT_PACK_Data(wr);
136 else
137 {
138 int x0, x1, y0, y1, a, b;
139 float ialpha;
140 x0 = wr.getMinX();
141 x1 = x0+wr.getWidth();
142 y0 = wr.getMinY();
143 y1 = y0+wr.getHeight();
144 for (int y=y0; y<y1; y++)
145 for (int x=x0; x<x1; x++)
146 {
147 pixel = wr.getPixel(x,y,pixel);
148 a = pixel[bands-1];
149 if ((a > 0) && (a < 255))
150 {
151 ialpha = 255/(float)a;
152 for (b=0; b<bands-1; b++)
153 pixel[b] = (int)(pixel[b]*ialpha+0.5f);
154 wr.setPixel(x,y,pixel);
155 }
156 }
157 }
158 }
159
160 return coerceColorModel(cm, newAlphaPreMult);
161 }
162
163
164 public static boolean is_INT_PACK_Data(SampleModel sm,
165 boolean requireAlpha)
166 {
167 // Check ColorModel is of type DirectColorModel
168 if(!(sm instanceof SinglePixelPackedSampleModel)) return false;
169
170 // Check transfer type
171 if(sm.getDataType() != DataBuffer.TYPE_INT) return false;
172
173 SinglePixelPackedSampleModel sppsm;
174 sppsm = (SinglePixelPackedSampleModel)sm;
175
176 int [] masks = sppsm.getBitMasks();
177 if (masks.length == 3)
178 {
179 if (requireAlpha) return false;
180 } else if (masks.length != 4)
181 return false;
182
183 if(masks[0] != 0x00ff0000) return false;
184 if(masks[1] != 0x0000ff00) return false;
185 if(masks[2] != 0x000000ff) return false;
186 if ((masks.length == 4) &&
187 (masks[3] != 0xff000000)) return false;
188
189 return true;
190 }
191
192 protected static void mult_INT_PACK_Data(WritableRaster wr)
193 {
194 // System.out.println("Multiply Int: " + wr);
195
196 SinglePixelPackedSampleModel sppsm;
197 sppsm = (SinglePixelPackedSampleModel)wr.getSampleModel();
198
199 final int width = wr.getWidth();
200
201 final int scanStride = sppsm.getScanlineStride();
202 DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
203 final int base
204 = (db.getOffset() +
205 sppsm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(),
206 wr.getMinY()-wr.getSampleModelTranslateY()));
207 int n=0;
208 // Access the pixel data array
209 final int pixels[] = db.getBankData()[0];
210 for (int y=0; y<wr.getHeight(); y++)
211 {
212 int sp = base + y*scanStride;
213 final int end = sp + width;
214 while (sp < end)
215 {
216 int pixel = pixels[sp];
217 int a = pixel>>>24;
218 if ((a>=0) && (a<255))
219 {
220 pixels[sp] = ((a << 24) |
221 ((((pixel&0xFF0000)*a)>>8)&0xFF0000) |
222 ((((pixel&0x00FF00)*a)>>8)&0x00FF00) |
223 ((((pixel&0x0000FF)*a)>>8)&0x0000FF));
224 }
225 sp++;
226 }
227 }
228 }
229
230 protected static void divide_INT_PACK_Data(WritableRaster wr)
231 {
232 // System.out.println("Divide Int");
233
234 SinglePixelPackedSampleModel sppsm;
235 sppsm = (SinglePixelPackedSampleModel)wr.getSampleModel();
236
237 final int width = wr.getWidth();
238
239 final int scanStride = sppsm.getScanlineStride();
240 DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
241 final int base
242 = (db.getOffset() +
243 sppsm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(),
244 wr.getMinY()-wr.getSampleModelTranslateY()));
245 int pixel, a, aFP, n=0;
246 // Access the pixel data array
247 final int pixels[] = db.getBankData()[0];
248 for (int y=0; y<wr.getHeight(); y++)
249 {
250 int sp = base + y*scanStride;
251 final int end = sp + width;
252 while (sp < end)
253 {
254 pixel = pixels[sp];
255 a = pixel>>>24;
256 if (a<=0)
257 {
258 pixels[sp] = 0x00FFFFFF;
259 }
260 else if (a<255)
261 {
262 aFP = (0x00FF0000/a);
263 pixels[sp] =
264 ((a << 24) |
265 (((((pixel&0xFF0000)>>16)*aFP)&0xFF0000) ) |
266 (((((pixel&0x00FF00)>>8) *aFP)&0xFF0000)>>8 ) |
267 (((((pixel&0x0000FF)) *aFP)&0xFF0000)>>16));
268 }
269 sp++;
270 }
271 }
272 }
273
274 public static boolean is_BYTE_COMP_Data(SampleModel sm)
275 {
276 // Check ColorModel is of type DirectColorModel
277 if(!(sm instanceof ComponentSampleModel)) return false;
278
279 // Check transfer type
280 if(sm.getDataType() != DataBuffer.TYPE_BYTE) return false;
281
282 return true;
283 }
284
285 protected static void mult_BYTE_COMP_Data(WritableRaster wr)
286 {
287 // System.out.println("Multiply Int: " + wr);
288
289 ComponentSampleModel csm;
290 csm = (ComponentSampleModel)wr.getSampleModel();
291
292 final int width = wr.getWidth();
293
294 final int scanStride = csm.getScanlineStride();
295 final int pixStride = csm.getPixelStride();
296 final int [] bandOff = csm.getBandOffsets();
297
298 DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
299 final int base
300 = (db.getOffset() +
301 csm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(),
302 wr.getMinY()-wr.getSampleModelTranslateY()));
303
304
305 int a=0;
306 int aOff = bandOff[bandOff.length-1];
307 int bands = bandOff.length-1;
308 int b, i;
309
310 // Access the pixel data array
311 final byte pixels[] = db.getBankData()[0];
312 for (int y=0; y<wr.getHeight(); y++)
313 {
314 int sp = base + y*scanStride;
315 final int end = sp + width*pixStride;
316 while (sp < end)
317 {
318 a = pixels[sp+aOff]&0xFF;
319 if (a!=0xFF)
320 for (b=0; b<bands; b++)
321 {
322 i = sp+bandOff[b];
323 pixels[i] = (byte)(((pixels[i]&0xFF)*a)>>8);
324 }
325 sp+=pixStride;
326 }
327 }
328 }
329
330 protected static void divide_BYTE_COMP_Data(WritableRaster wr)
331 {
332 // System.out.println("Multiply Int: " + wr);
333
334 ComponentSampleModel csm;
335 csm = (ComponentSampleModel)wr.getSampleModel();
336
337 final int width = wr.getWidth();
338
339 final int scanStride = csm.getScanlineStride();
340 final int pixStride = csm.getPixelStride();
341 final int [] bandOff = csm.getBandOffsets();
342
343 DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
344 final int base
345 = (db.getOffset() +
346 csm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(),
347 wr.getMinY()-wr.getSampleModelTranslateY()));
348
349
350 int a=0;
351 int aOff = bandOff[bandOff.length-1];
352 int bands = bandOff.length-1;
353 int b, i;
354 // Access the pixel data array
355 final byte pixels[] = db.getBankData()[0];
356 for (int y=0; y<wr.getHeight(); y++)
357 {
358 int sp = base + y*scanStride;
359 final int end = sp + width*pixStride;
360 while (sp < end)
361 {
362 a = pixels[sp+aOff]&0xFF;
363 if (a==0)
364 {
365 for (b=0; b<bands; b++)
366 pixels[sp+bandOff[b]] = (byte)0xFF;
367 } else if (a<255)
368 {
369 int aFP = (0x00FF0000/a);
370 for (b=0; b<bands; b++)
371 {
372 i = sp+bandOff[b];
373 pixels[i] = (byte)(((pixels[i]&0xFF)*aFP)>>>16);
374 }
375 }
376 sp+=pixStride;
377 }
378 }
379 }
380
381
382}
Note: See TracBrowser for help on using the repository browser.