KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > transcoder > image > PNGTranscoder


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.transcoder.image;
19
20 import java.awt.image.BufferedImage JavaDoc;
21 import java.awt.image.DataBufferInt JavaDoc;
22 import java.awt.image.SinglePixelPackedSampleModel JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.OutputStream JavaDoc;
25
26 import org.apache.batik.ext.awt.image.codec.PNGEncodeParam;
27 import org.apache.batik.ext.awt.image.codec.PNGImageEncoder;
28 import org.apache.batik.ext.awt.image.rendered.IndexImage;
29 import org.apache.batik.transcoder.TranscoderException;
30 import org.apache.batik.transcoder.TranscoderOutput;
31 import org.apache.batik.transcoder.TranscodingHints;
32 import org.apache.batik.transcoder.image.resources.Messages;
33 import org.apache.batik.transcoder.keys.FloatKey;
34 import org.apache.batik.transcoder.keys.IntegerKey;
35
36 /**
37  * This class is an <tt>ImageTranscoder</tt> that produces a PNG image.
38  *
39  * @author <a HREF="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
40  * @version $Id: PNGTranscoder.java,v 1.23 2005/03/27 08:58:36 cam Exp $
41  */

42 public class PNGTranscoder extends ImageTranscoder {
43
44     /**
45      * Constructs a new transcoder that produces png images.
46      */

47     public PNGTranscoder() {
48         hints.put(KEY_FORCE_TRANSPARENT_WHITE, Boolean.FALSE);
49     }
50
51     /**
52      * Creates a new ARGB image with the specified dimension.
53      * @param width the image width in pixels
54      * @param height the image height in pixels
55      */

56     public BufferedImage JavaDoc createImage(int width, int height) {
57         return new BufferedImage JavaDoc(width, height, BufferedImage.TYPE_INT_ARGB);
58     }
59
60     /**
61      * Writes the specified image to the specified output.
62      * @param img the image to write
63      * @param output the output where to store the image
64      * @throws TranscoderException if an error occured while storing the image
65      */

66     public void writeImage(BufferedImage JavaDoc img, TranscoderOutput output)
67             throws TranscoderException {
68
69         OutputStream JavaDoc ostream = output.getOutputStream();
70         if (ostream == null) {
71             throw new TranscoderException(
72                 Messages.formatMessage("png.badoutput", null));
73         }
74
75         //
76
// This is a trick so that viewers which do not support the alpha
77
// channel will see a white background (and not a black one).
78
//
79
boolean forceTransparentWhite = false;
80
81         if (hints.containsKey(KEY_FORCE_TRANSPARENT_WHITE)) {
82             forceTransparentWhite =
83                 ((Boolean JavaDoc)hints.get
84                  (KEY_FORCE_TRANSPARENT_WHITE)).booleanValue();
85         }
86
87         if (forceTransparentWhite) {
88             int w = img.getWidth(), h = img.getHeight();
89             DataBufferInt JavaDoc biDB = (DataBufferInt JavaDoc)img.getRaster().getDataBuffer();
90             int scanStride = ((SinglePixelPackedSampleModel JavaDoc)
91                               img.getSampleModel()).getScanlineStride();
92             int dbOffset = biDB.getOffset();
93             int pixels[] = biDB.getBankData()[0];
94             int p = dbOffset;
95             int adjust = scanStride - w;
96             int a=0, r=0, g=0, b=0, pel=0;
97             for(int i=0; i<h; i++){
98                 for(int j=0; j<w; j++){
99                     pel = pixels[p];
100                     a = (pel >> 24) & 0xff;
101                     r = (pel >> 16) & 0xff;
102                     g = (pel >> 8 ) & 0xff;
103                     b = pel & 0xff;
104                     r = (255*(255 -a) + a*r)/255;
105                     g = (255*(255 -a) + a*g)/255;
106                     b = (255*(255 -a) + a*b)/255;
107                     pixels[p++] =
108                         (a<<24 & 0xff000000) |
109                         (r<<16 & 0xff0000) |
110                         (g<<8 & 0xff00) |
111                         (b & 0xff);
112                 }
113                 p += adjust;
114             }
115         }
116
117         int n=-1;
118         if (hints.containsKey(KEY_INDEXED)) {
119             n=((Integer JavaDoc)hints.get(KEY_INDEXED)).intValue();
120             if (n==1||n==2||n==4||n==8)
121                 //PNGEncodeParam.Palette can handle these numbers only.
122
img = IndexImage.getIndexedImage(img,1<<n);
123         }
124
125         PNGEncodeParam params = PNGEncodeParam.getDefaultEncodeParam(img);
126         if (params instanceof PNGEncodeParam.RGB) {
127             ((PNGEncodeParam.RGB)params).setBackgroundRGB
128                 (new int [] { 255, 255, 255 });
129         }
130
131         // If they specify GAMMA key with a value of '0' then omit
132
// gamma chunk. If they do not provide a GAMMA then just
133
// generate an sRGB chunk. Otherwise supress the sRGB chunk
134
// and just generate gamma and chroma chunks.
135
if (hints.containsKey(KEY_GAMMA)) {
136             float gamma = ((Float JavaDoc)hints.get(KEY_GAMMA)).floatValue();
137             if (gamma > 0) {
138                 params.setGamma(gamma);
139             }
140             params.setChromaticity(DEFAULT_CHROMA);
141         } else {
142             // We generally want an sRGB chunk and our encoding intent
143
// is perceptual
144
params.setSRGBIntent(PNGEncodeParam.INTENT_PERCEPTUAL);
145         }
146
147
148         float PixSzMM = userAgent.getPixelUnitToMillimeter();
149         // num Pixs in 1 Meter
150
int numPix = (int)((1000/PixSzMM)+0.5);
151         params.setPhysicalDimension(numPix, numPix, 1); // 1 means 'pix/meter'
152

153         try {
154             PNGImageEncoder pngEncoder = new PNGImageEncoder(ostream, params);
155             pngEncoder.encode(img);
156             ostream.flush();
157         } catch (IOException JavaDoc ex) {
158             throw new TranscoderException(ex);
159         }
160     }
161
162     // --------------------------------------------------------------------
163
// Keys definition
164
// --------------------------------------------------------------------
165

166     /**
167      * The gamma correction key.
168      *
169      * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
170      * <TR>
171      * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
172      * <TD VALIGN="TOP">KEY_GAMMA</TD></TR>
173      * <TR>
174      * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
175      * <TD VALIGN="TOP">Float</TD></TR>
176      * <TR>
177      * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
178      * <TD VALIGN="TOP">PNGEncodeParam.INTENT_PERCEPTUAL</TD></TR>
179      * <TR>
180      * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
181      * <TD VALIGN="TOP">No</TD></TR>
182      * <TR>
183      * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
184      * <TD VALIGN="TOP">Controls the gamma correction of the png image.
185      * A value of zero for gamma disables the generation
186      * of a gamma chunk. No value causes an sRGB chunk
187      * to be generated.</TD>
188      * </TR>
189      * </TABLE>
190      */

191     public static final TranscodingHints.Key KEY_GAMMA
192         = new FloatKey();
193
194     /**
195      * The default Primary Chromaticities for sRGB imagery.
196      */

197     public static final float[] DEFAULT_CHROMA = {
198         0.31270F, 0.329F, 0.64F, 0.33F, 0.3F, 0.6F, 0.15F, 0.06F
199     };
200
201
202     /**
203      * The color indexed image key to specify number of colors used in
204      * palette.
205      *
206      * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1">
207      * <TR>
208      * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH>
209      * <TD VALIGN="TOP">KEY_INDEXED</TD></TR>
210      * <TR>
211      * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH>
212      * <TD VALIGN="TOP">Integer</TD></TR>
213      * <TR>
214      * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH>
215      * <TD VALIGN="TOP">none/true color image</TD></TR>
216      * <TR>
217      * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH>
218      * <TD VALIGN="TOP">No</TD></TR>
219      * <TR>
220      * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH>
221      * <TD VALIGN="TOP">Turns on the reduction of the image to index
222      * colors by specifying color bit depth, 1,2,4,8. The resultant
223      * PNG will be an indexed PNG with color bit depth specified.</TD>
224      * </TR>
225      * </TABLE>
226      */

227     public static final TranscodingHints.Key KEY_INDEXED
228         = new IntegerKey();
229 }
230
Popular Tags