KickJava   Java API By Example, From Geeks To Geeks.

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


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
21 import java.awt.color.ColorSpace JavaDoc;
22 import java.awt.image.BandCombineOp JavaDoc;
23 import java.awt.image.BufferedImage JavaDoc;
24 import java.awt.image.ColorConvertOp JavaDoc;
25 import java.awt.image.ColorModel JavaDoc;
26 import java.awt.image.DataBuffer JavaDoc;
27 import java.awt.image.DataBufferInt JavaDoc;
28 import java.awt.image.Raster JavaDoc;
29 import java.awt.image.SampleModel JavaDoc;
30 import java.awt.image.SinglePixelPackedSampleModel JavaDoc;
31 import java.awt.image.WritableRaster JavaDoc;
32
33 import org.apache.batik.ext.awt.image.GraphicsUtil;
34
35 /**
36  * This function will tranform an image from any colorspace into a
37  * luminance image. The alpha channel if any will be copied to the
38  * new image.
39  *
40  * @author <a HREF="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
41  * @version $Id: Any2sRGBRed.java,v 1.10 2004/08/18 07:14:07 vhardy Exp $ */

42 public class Any2sRGBRed extends AbstractRed {
43
44     boolean srcIsLsRGB = false;
45
46     /**
47      * Construct a luminace image from src.
48      *
49      * @param src The image to convert to a luminance image
50      */

51     public Any2sRGBRed(CachableRed src) {
52         super(src,src.getBounds(),
53               fixColorModel(src),
54               fixSampleModel(src),
55               src.getTileGridXOffset(),
56               src.getTileGridYOffset(),
57               null);
58
59         ColorModel JavaDoc srcCM = src.getColorModel();
60         if (srcCM == null) return;
61         ColorSpace JavaDoc srcCS = srcCM.getColorSpace();
62         if (srcCS == ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB))
63             srcIsLsRGB = true;
64     }
65
66     public static boolean is_INT_PACK_COMP(SampleModel JavaDoc sm) {
67         if(!(sm instanceof SinglePixelPackedSampleModel JavaDoc)) return false;
68
69         // Check transfer types
70
if(sm.getDataType() != DataBuffer.TYPE_INT) return false;
71
72         SinglePixelPackedSampleModel JavaDoc sppsm;
73         sppsm = (SinglePixelPackedSampleModel JavaDoc)sm;
74
75         int [] masks = sppsm.getBitMasks();
76         if ((masks.length != 3) && (masks.length != 4)) return false;
77         if(masks[0] != 0x00ff0000) return false;
78         if(masks[1] != 0x0000ff00) return false;
79         if(masks[2] != 0x000000ff) return false;
80         if ((masks.length == 4) &&
81             (masks[3] != 0xff000000)) return false;
82  
83         return true;
84    }
85
86     /**
87      * Exponent for linear to sRGB convertion
88      */

89     private static final double GAMMA = 2.4;
90
91     /**
92      * Lookup tables for RGB lookups. The linearToSRGBLut is used
93      * when noise values are considered to be on a linearScale. The
94      * linearToLinear table is used when the values are considered to
95      * be on the sRGB scale to begin with.
96      */

97     private static final int linearToSRGBLut[] = new int[256];
98     static {
99         final double scale = 1.0/255;
100         final double exp = 1.0/GAMMA;
101         // System.out.print("L2S: ");
102
for(int i=0; i<256; i++){
103             double value = i*scale;
104             if(value <= 0.0031308)
105                 value *= 12.92;
106             else
107                 value = 1.055 * Math.pow(value, exp) - 0.055;
108             
109             linearToSRGBLut[i] = (int)Math.round(value*255.);
110             // System.out.print(linearToSRGBLut[i] + ",");
111
}
112         // System.out.println("");
113
}
114      
115     public static WritableRaster JavaDoc applyLut_INT(WritableRaster JavaDoc wr,
116                                               final int []lut) {
117         SinglePixelPackedSampleModel JavaDoc sm =
118             (SinglePixelPackedSampleModel JavaDoc)wr.getSampleModel();
119         DataBufferInt JavaDoc db = (DataBufferInt JavaDoc)wr.getDataBuffer();
120
121         final int srcBase
122             = (db.getOffset() +
123                sm.getOffset(wr.getMinX()-wr.getSampleModelTranslateX(),
124                             wr.getMinY()-wr.getSampleModelTranslateY()));
125         // Access the pixel data array
126
final int pixels[] = db.getBankData()[0];
127         final int width = wr.getWidth();
128         final int height = wr.getHeight();
129         final int scanStride = sm.getScanlineStride();
130
131         int end, pix;
132
133         // For alpha premult we need to multiply all comps.
134
for (int y=0; y<height; y++) {
135             int sp = srcBase + y*scanStride;
136             end = sp + width;
137
138             while (sp<end) {
139                 pix = pixels[sp];
140                 pixels[sp] =
141                     (( pix &0xFF000000)|
142                      (lut[(pix>>>16)&0xFF]<<16) |
143                      (lut[(pix>>> 8)&0xFF]<< 8) |
144                      (lut[(pix )&0xFF] ));
145                 sp++;
146             }
147         }
148
149         return wr;
150     }
151
152     public WritableRaster JavaDoc copyData(WritableRaster JavaDoc wr) {
153
154         // Get my source.
155
CachableRed src = (CachableRed)getSources().get(0);
156         ColorModel JavaDoc srcCM = src.getColorModel();
157         SampleModel JavaDoc srcSM = src.getSampleModel();
158
159
160         // Fast case, Linear SRGB source, INT Pack writable raster...
161
if (srcIsLsRGB &&
162             is_INT_PACK_COMP(wr.getSampleModel())) {
163             src.copyData(wr);
164             if (srcCM.hasAlpha())
165                 GraphicsUtil.coerceData(wr, srcCM, false);
166             applyLut_INT(wr, linearToSRGBLut);
167             return wr;
168         }
169
170         if (srcCM == null) {
171             // We don't really know much about this source, let's
172
// guess based on the number of bands...
173

174             float [][] matrix = null;
175             switch (srcSM.getNumBands()) {
176             case 1:
177                 matrix = new float[1][3];
178                 matrix[0][0] = 1; // Red
179
matrix[0][1] = 1; // Grn
180
matrix[0][2] = 1; // Blu
181
break;
182             case 2:
183                 matrix = new float[2][4];
184                 matrix[0][0] = 1; // Red
185
matrix[0][1] = 1; // Grn
186
matrix[0][2] = 1; // Blu
187
matrix[1][3] = 1; // Alpha
188
break;
189             case 3:
190                 matrix = new float[3][3];
191                 matrix[0][0] = 1; // Red
192
matrix[1][1] = 1; // Grn
193
matrix[2][2] = 1; // Blu
194
break;
195             default:
196                 matrix = new float[srcSM.getNumBands()][4];
197                 matrix[0][0] = 1; // Red
198
matrix[1][1] = 1; // Grn
199
matrix[2][2] = 1; // Blu
200
matrix[3][3] = 1; // Alpha
201
break;
202             }
203             Raster JavaDoc srcRas = src.getData(wr.getBounds());
204             BandCombineOp JavaDoc op = new BandCombineOp JavaDoc(matrix, null);
205             op.filter(srcRas, wr);
206         } else {
207             ColorModel JavaDoc dstCM = getColorModel();
208             if (srcCM.getColorSpace() == dstCM.getColorSpace()) {
209                 // No transform needed, just reformat data...
210
// System.out.println("Bypassing");
211

212                 if (is_INT_PACK_COMP(srcSM))
213                     src.copyData(wr);
214                 else
215                     GraphicsUtil.copyData(src.getData(wr.getBounds()), wr);
216
217                 return wr;
218             }
219
220             Raster JavaDoc srcRas = src.getData(wr.getBounds());
221             WritableRaster JavaDoc srcWr = (WritableRaster JavaDoc)srcRas;
222
223             // Divide out alpha if we have it. We need to do this since
224
// the color convert may not be a linear operation which may
225
// lead to out of range values.
226
ColorModel JavaDoc srcBICM = srcCM;
227             if (srcCM.hasAlpha())
228                 srcBICM = GraphicsUtil.coerceData(srcWr, srcCM, false);
229
230             BufferedImage JavaDoc srcBI, dstBI;
231             srcBI = new BufferedImage JavaDoc(srcBICM,
232                                       srcWr.createWritableTranslatedChild(0,0),
233                                       false,
234                                       null);
235
236             // System.out.println("src: " + srcBI.getWidth() + "x" +
237
// srcBI.getHeight());
238

239             ColorConvertOp JavaDoc op = new ColorConvertOp JavaDoc(dstCM.getColorSpace(),
240                                                    null);
241             dstBI = op.filter(srcBI, null);
242
243             // System.out.println("After filter:");
244

245             WritableRaster JavaDoc wr00 = wr.createWritableTranslatedChild(0,0);
246             for (int i=0; i<dstCM.getColorSpace().getNumComponents(); i++)
247                 copyBand(dstBI.getRaster(), i, wr00, i);
248
249             if (dstCM.hasAlpha())
250                 copyBand(srcWr, srcSM.getNumBands()-1,
251                          wr, getSampleModel().getNumBands()-1);
252         }
253         return wr;
254     }
255
256         /**
257          * This function 'fixes' the source's color model. Right now
258          * it just selects if it should have one or two bands based on
259          * if the source had an alpha channel.
260          */

261     protected static ColorModel JavaDoc fixColorModel(CachableRed src) {
262         ColorModel JavaDoc cm = src.getColorModel();
263         if (cm != null) {
264             if (cm.hasAlpha())
265                 return GraphicsUtil.sRGB_Unpre;
266
267             return GraphicsUtil.sRGB;
268         }
269         else {
270             // No ColorModel so try to make some intelligent
271
// decisions based just on the number of bands...
272
// 1 bands -> replicated into RGB
273
// 2 bands -> Band 0 replicated into RGB & Band 1 -> alpha premult
274
// 3 bands -> sRGB (not-linear?)
275
// 4 bands -> sRGB premult (not-linear?)
276
SampleModel JavaDoc sm = src.getSampleModel();
277
278             switch (sm.getNumBands()) {
279             case 1:
280                 return GraphicsUtil.sRGB;
281             case 2:
282                 return GraphicsUtil.sRGB_Unpre;
283             case 3:
284                 return GraphicsUtil.sRGB;
285             }
286             return GraphicsUtil.sRGB_Unpre;
287         }
288     }
289
290     /**
291      * This function 'fixes' the source's sample model.
292      * Right now it just selects if it should have 3 or 4 bands
293      * based on if the source had an alpha channel.
294      */

295     protected static SampleModel JavaDoc fixSampleModel(CachableRed src) {
296         SampleModel JavaDoc sm = src.getSampleModel();
297         ColorModel JavaDoc cm = src.getColorModel();
298
299         boolean alpha = false;
300
301         if (cm != null)
302             alpha = cm.hasAlpha();
303         else {
304             switch (sm.getNumBands()) {
305             case 1: case 3:
306                 alpha = false;
307                 break;
308             default:
309                 alpha = true;
310                 break;
311             }
312         }
313         if (alpha)
314             return new SinglePixelPackedSampleModel JavaDoc
315                 (DataBuffer.TYPE_INT,
316                  sm.getWidth(),
317                  sm.getHeight(),
318                  new int [] {0xFF0000, 0xFF00, 0xFF, 0xFF000000});
319         else
320             return new SinglePixelPackedSampleModel JavaDoc
321                 (DataBuffer.TYPE_INT,
322                  sm.getWidth(),
323                  sm.getHeight(),
324                  new int [] {0xFF0000, 0xFF00, 0xFF});
325     }
326 }
327
Popular Tags