KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > svggen > SVGLookupOp


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.svggen;
19
20 import java.awt.Rectangle JavaDoc;
21 import java.awt.image.BufferedImageOp JavaDoc;
22 import java.awt.image.ByteLookupTable JavaDoc;
23 import java.awt.image.LookupOp JavaDoc;
24 import java.awt.image.LookupTable JavaDoc;
25
26 import org.w3c.dom.Document JavaDoc;
27 import org.w3c.dom.Element JavaDoc;
28
29 /**
30  * Utility class that converts a LookupOp object into
31  * an SVG filter descriptor. The SVG filter corresponding
32  * to a LookupOp is an feComponentTransfer, with a type
33  * set to 'table', the tableValues set to the content
34  * of the lookup table.
35  *
36  * @author <a HREF="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
37  * @version $Id: SVGLookupOp.java,v 1.17 2005/03/27 08:58:35 cam Exp $
38  * @see org.apache.batik.svggen.SVGBufferedImageOp
39  */

40 public class SVGLookupOp extends AbstractSVGFilterConverter {
41     /**
42      * Gamma for linear to sRGB convertion
43      */

44     private static final double GAMMA = 1./2.4;
45
46     /**
47      * Lookup table for linear to sRGB value
48      * forward and backward mapping
49      */

50     private static final int linearToSRGBLut[] = new int[256];
51     private static final int sRGBToLinear[] = new int[256];
52
53     static {
54         for(int i=0; i<256; i++) {
55             // linear to sRGB
56
float value = i/255f;
57             if (value <= 0.0031308) {
58                 value *= 12.92f;
59             } else {
60                 value = 1.055f * ((float) Math.pow(value, GAMMA)) - 0.055f;
61             }
62             linearToSRGBLut[i] = Math.round(value*255);
63
64             // sRGB to linear
65
value = i/255f;
66             if(value <= 0.04045){
67                 value /= 12.92f;
68             } else {
69                 value = (float)Math.pow((value + 0.055f)/1.055f, 1/GAMMA);
70             }
71
72             sRGBToLinear[i] = Math.round(value*255);
73         }
74     }
75
76     /**
77      * @param generatorContext used to build Elements
78      */

79     public SVGLookupOp(SVGGeneratorContext generatorContext) {
80         super(generatorContext);
81     }
82
83     /**
84      * Converts a Java 2D API BufferedImageOp into
85      * a set of attribute/value pairs and related definitions
86      *
87      * @param filter BufferedImageOp filter to be converted
88      * @param filterRect Rectangle, in device space, that defines the area
89      * to which filtering applies. May be null, meaning that the
90      * area is undefined.
91      * @return descriptor of the attributes required to represent
92      * the input filter
93      * @see org.apache.batik.svggen.SVGFilterDescriptor
94      */

95     public SVGFilterDescriptor toSVG(BufferedImageOp JavaDoc filter,
96                                      Rectangle JavaDoc filterRect) {
97         if (filter instanceof LookupOp JavaDoc)
98             return toSVG((LookupOp JavaDoc)filter);
99         else
100             return null;
101     }
102
103     /**
104      * @param lookupOp the LookupOp to be converted
105      * @return a description of the SVG filter corresponding to
106      * lookupOp. The definition of the feComponentTransfer
107      * filter in put in feComponentTransferDefSet
108      */

109     public SVGFilterDescriptor toSVG(LookupOp JavaDoc lookupOp) {
110         // Reuse definition if lookupOp has already been converted
111
SVGFilterDescriptor filterDesc =
112             (SVGFilterDescriptor)descMap.get(lookupOp);
113
114         Document JavaDoc domFactory = generatorContext.domFactory;
115
116         if (filterDesc == null) {
117             //
118
// First time filter is converted: create its corresponding
119
// SVG filter
120
//
121
Element JavaDoc filterDef = domFactory.createElementNS(SVG_NAMESPACE_URI,
122                                                            SVG_FILTER_TAG);
123             Element JavaDoc feComponentTransferDef =
124                 domFactory.createElementNS(SVG_NAMESPACE_URI,
125                                            SVG_FE_COMPONENT_TRANSFER_TAG);
126
127             // Append transfer function for each component, setting
128
// the attributes corresponding to the scale and offset.
129
// Because we are using a LookupOp as a BufferedImageOp,
130
// the number of lookup table must be:
131
// + 1, in which case the same lookup is applied to the
132
// Red, Green and Blue components,
133
// + 3, in which case the lookup tables apply to the
134
// Red, Green and Blue components
135
// + 4, in which case the lookup tables apply to the
136
// Red, Green, Blue and Alpha components
137
String JavaDoc lookupTables[] = convertLookupTables(lookupOp);
138
139             Element JavaDoc feFuncR = domFactory.createElementNS(SVG_NAMESPACE_URI,
140                                                          SVG_FE_FUNC_R_TAG);
141             Element JavaDoc feFuncG = domFactory.createElementNS(SVG_NAMESPACE_URI,
142                                                          SVG_FE_FUNC_G_TAG);
143             Element JavaDoc feFuncB = domFactory.createElementNS(SVG_NAMESPACE_URI,
144                                                          SVG_FE_FUNC_B_TAG);
145             Element JavaDoc feFuncA = null;
146             String JavaDoc type = SVG_TABLE_VALUE;
147
148             if(lookupTables.length == 1){
149                 feFuncR.setAttributeNS(null, SVG_TYPE_ATTRIBUTE, type);
150                 feFuncG.setAttributeNS(null, SVG_TYPE_ATTRIBUTE, type);
151                 feFuncB.setAttributeNS(null, SVG_TYPE_ATTRIBUTE, type);
152                 feFuncR.setAttributeNS(null, SVG_TABLE_VALUES_ATTRIBUTE,
153                                        lookupTables[0]);
154                 feFuncG.setAttributeNS(null, SVG_TABLE_VALUES_ATTRIBUTE,
155                                        lookupTables[0]);
156                 feFuncB.setAttributeNS(null, SVG_TABLE_VALUES_ATTRIBUTE,
157                                        lookupTables[0]);
158             }
159             else if(lookupTables.length >= 3){
160                 feFuncR.setAttributeNS(null, SVG_TYPE_ATTRIBUTE, type);
161                 feFuncG.setAttributeNS(null, SVG_TYPE_ATTRIBUTE, type);
162                 feFuncB.setAttributeNS(null, SVG_TYPE_ATTRIBUTE, type);
163                 feFuncR.setAttributeNS(null, SVG_TABLE_VALUES_ATTRIBUTE,
164                                        lookupTables[0]);
165                 feFuncG.setAttributeNS(null, SVG_TABLE_VALUES_ATTRIBUTE,
166                                        lookupTables[1]);
167                 feFuncB.setAttributeNS(null, SVG_TABLE_VALUES_ATTRIBUTE,
168                                        lookupTables[2]);
169
170                 if(lookupTables.length == 4){
171                     feFuncA = domFactory.createElementNS(SVG_NAMESPACE_URI,
172                                                          SVG_FE_FUNC_A_TAG);
173                     feFuncA.setAttributeNS(null, SVG_TYPE_ATTRIBUTE, type);
174                     feFuncA.setAttributeNS(null, SVG_TABLE_VALUES_ATTRIBUTE,
175                                            lookupTables[3]);
176                 }
177             }
178
179             feComponentTransferDef.appendChild(feFuncR);
180             feComponentTransferDef.appendChild(feFuncG);
181             feComponentTransferDef.appendChild(feFuncB);
182             if(feFuncA != null)
183                 feComponentTransferDef.appendChild(feFuncA);
184
185             filterDef.appendChild(feComponentTransferDef);
186
187             filterDef.
188                 setAttributeNS(null, ATTR_ID,
189                                generatorContext.idGenerator.
190                                generateID(ID_PREFIX_FE_COMPONENT_TRANSFER));
191             //
192
// Create a filter descriptor
193
//
194

195             // Process filter attribute
196
StringBuffer JavaDoc filterAttrBuf = new StringBuffer JavaDoc(URL_PREFIX);
197             filterAttrBuf.append(SIGN_POUND);
198             filterAttrBuf.append(filterDef.getAttributeNS(null, ATTR_ID));
199             filterAttrBuf.append(URL_SUFFIX);
200
201             filterDesc = new SVGFilterDescriptor(filterAttrBuf.toString(),
202                                                  filterDef);
203
204             defSet.add(filterDef);
205             descMap.put(lookupOp, filterDesc);
206         }
207
208         return filterDesc;
209     }
210
211     /**
212      * Converts the filter's LookupTable into an array of corresponding SVG
213      * table strings
214      */

215     private String JavaDoc[] convertLookupTables(LookupOp JavaDoc lookupOp){
216         LookupTable JavaDoc lookupTable = lookupOp.getTable();
217         int nComponents = lookupTable.getNumComponents();
218
219         if((nComponents != 1) && (nComponents != 3) && (nComponents != 4))
220             throw new SVGGraphics2DRuntimeException(ERR_ILLEGAL_BUFFERED_IMAGE_LOOKUP_OP);
221
222         StringBuffer JavaDoc lookupTableBuf[] = new StringBuffer JavaDoc[nComponents];
223         for(int i=0; i<nComponents; i++)
224             lookupTableBuf[i] = new StringBuffer JavaDoc();
225
226         if(!(lookupTable instanceof ByteLookupTable JavaDoc)){
227             int src[] = new int[nComponents];
228             int dest[] = new int[nComponents];
229             int offset = lookupTable.getOffset();
230
231             // Offsets are used for constrained sources. Therefore,
232
// the lookup values should never be used under offset.
233
// There is no SVG equivalent for this behavior.
234
// These values are mapped to identity.
235
for(int i=0; i<offset; i++){
236                 // Fill in string buffers
237
for(int j=0; j<nComponents; j++){
238                     // lookupTableBuf[j].append(Integer.toString(i));
239
lookupTableBuf[j].append(doubleString(i/255.));
240                     lookupTableBuf[j].append(SPACE);
241                 }
242             }
243
244             for(int i=offset; i<=255; i++){
245                 // Fill in source array
246
for(int j=0; j<nComponents; j++) src[j] = i;
247
248                 // Get destination values
249
lookupTable.lookupPixel(src, dest);
250
251                 // Fill in string buffers
252
for(int j=0; j<nComponents; j++){
253                     lookupTableBuf[j].append(doubleString(dest[j]/255.));
254                     // lookupTableBuf[j].append(Integer.toString(dest[j]));
255
lookupTableBuf[j].append(SPACE);
256                 }
257             }
258         }
259         else{
260             byte src[] = new byte[nComponents];
261             byte dest[] = new byte[nComponents];
262
263             int offset = lookupTable.getOffset();
264
265             // Offsets are used for constrained sources. Therefore,
266
// the lookup values should never be used under offset.
267
// There is no SVG equivalent for this behavior.
268
// These values are mapped to identity.
269
for(int i=0; i<offset; i++){
270                 // Fill in string buffers
271
for(int j=0; j<nComponents; j++){
272                     // lookupTableBuf[j].append(Integer.toString(i));
273
lookupTableBuf[j].append(doubleString(i/255.));
274                     lookupTableBuf[j].append(SPACE);
275                 }
276             }
277             for(int i=0; i<=255; i++){
278                 // Fill in source array
279
for(int j=0; j<nComponents; j++) {
280                     src[j] = (byte)(0xff & i);
281                 }
282
283                 // Get destination values
284
((ByteLookupTable JavaDoc)lookupTable).lookupPixel(src, dest);
285
286                 // Fill in string buffers
287
for(int j=0; j<nComponents; j++){
288                     lookupTableBuf[j].append(doubleString((0xff & dest[j])/255.));
289                     lookupTableBuf[j].append(SPACE);
290                 }
291             }
292         }
293
294         String JavaDoc lookupTables[] = new String JavaDoc[nComponents];
295         for(int i=0; i<nComponents; i++)
296             lookupTables[i] = lookupTableBuf[i].toString().trim();
297
298         /*for(int i=0; i<lookupTables.length; i++){
299             System.out.println(lookupTables[i]);
300             }*/

301
302         return lookupTables;
303     }
304 }
305
Popular Tags