KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > image > JpegImage


1 /*
2  * $Id: JpegImage.java,v 1.1.2.3 2003/02/25 13:38:22 jeremias Exp $
3  * ============================================================================
4  * The Apache Software License, Version 1.1
5  * ============================================================================
6  *
7  * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modifica-
10  * tion, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if any, must
20  * include the following acknowledgment: "This product includes software
21  * developed by the Apache Software Foundation (http://www.apache.org/)."
22  * Alternately, this acknowledgment may appear in the software itself, if
23  * and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. The names "FOP" and "Apache Software Foundation" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * apache@apache.org.
29  *
30  * 5. Products derived from this software may not be called "Apache", nor may
31  * "Apache" appear in their name, without prior written permission of the
32  * Apache Software Foundation.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  * ============================================================================
45  *
46  * This software consists of voluntary contributions made by many individuals
47  * on behalf of the Apache Software Foundation and was originally created by
48  * James Tauber <jtauber@jtauber.com>. For more information on the Apache
49  * Software Foundation, please see <http://www.apache.org/>.
50  */

51 package org.apache.fop.image;
52
53 // Java
54
import java.net.URL JavaDoc;
55 import java.io.ByteArrayOutputStream JavaDoc;
56 import java.io.InputStream JavaDoc;
57
58 // FOP
59
import org.apache.fop.datatypes.ColorSpace;
60 import org.apache.fop.pdf.DCTFilter;
61 import org.apache.fop.image.analyser.ImageReader;
62
63 /**
64  * FopImage object for JPEG images, Using Java native classes.
65  * @author Eric Dalquist
66  * @see AbstractFopImage
67  * @see FopImage
68  */

69 public class JpegImage extends AbstractFopImage {
70     boolean hasAPPEMarker = false;
71     boolean found_icc_profile = false;
72     boolean found_dimensions = false;
73
74     public JpegImage(URL JavaDoc href) throws FopImageException {
75         super(href);
76     }
77
78     public JpegImage(URL JavaDoc href,
79                      ImageReader imgReader) throws FopImageException {
80         super(href, imgReader);
81     }
82
83     protected void loadImage() throws FopImageException {
84         ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
85         ByteArrayOutputStream JavaDoc iccStream = new ByteArrayOutputStream JavaDoc();
86         InputStream JavaDoc inStream;
87         this.m_colorSpace = new ColorSpace(ColorSpace.DEVICE_UNKNOWN);
88         byte[] readBuf = new byte[4096];
89         int bytes_read;
90         int index = 0;
91         boolean cont = true;
92
93         this.m_compressionType = new DCTFilter();
94         this.m_compressionType.setApplied(true);
95
96         try {
97             inStream = this.m_href.openStream();
98
99             while ((bytes_read = inStream.read(readBuf)) != -1) {
100                 baos.write(readBuf, 0, bytes_read);
101             }
102         } catch (java.io.IOException JavaDoc ex) {
103             throw new FopImageException("Error while loading image " +
104                                         this.m_href.toString() + " : " + ex.getClass() +
105                                         " - " + ex.getMessage());
106         }
107
108         this.m_bitmaps = baos.toByteArray();
109         this.m_bitsPerPixel = 8;
110         this.m_isTransparent = false;
111
112         if (this.m_bitmaps.length > (index + 2) &&
113                 uByte(this.m_bitmaps[index]) == 255 &&
114                 uByte(this.m_bitmaps[index + 1]) == 216) {
115             index += 2;
116
117             while (index < this.m_bitmaps.length && cont) {
118                 //check to be sure this is the begining of a header
119
if (this.m_bitmaps.length > (index + 2) &&
120                         uByte(this.m_bitmaps[index]) == 255) {
121
122                     //192 or 194 are the header bytes that contain the jpeg width height and color depth.
123
if (uByte(this.m_bitmaps[index + 1]) == 192 ||
124                             uByte(this.m_bitmaps[index + 1]) == 194) {
125
126                         this.m_height = calcBytes(this.m_bitmaps[index + 5],
127                                                   this.m_bitmaps[index + 6]);
128                         this.m_width = calcBytes(this.m_bitmaps[index + 7],
129                                                  this.m_bitmaps[index + 8]);
130
131                         if (this.m_bitmaps[index + 9] == 1) {
132                             this.m_colorSpace.setColorSpace(ColorSpace.DEVICE_GRAY);
133                         } else if (this.m_bitmaps[index + 9] == 3) {
134                             this.m_colorSpace.setColorSpace(ColorSpace.DEVICE_RGB);
135                         } else if (this.m_bitmaps[index + 9] == 4) {
136                             this.m_colorSpace.setColorSpace(ColorSpace.DEVICE_CMYK);
137                         }
138
139                         found_dimensions = true;
140                         if (found_icc_profile) {
141                             cont = false;
142                             break;
143                         }
144                         index += calcBytes(this.m_bitmaps[index + 2],
145                                            this.m_bitmaps[index + 3]) + 2;
146
147                     } else if (uByte(this.m_bitmaps[index+1]) == 226 &&
148                                this.m_bitmaps.length > (index+60)) {
149                         // Check if ICC profile
150
byte[] icc_string = new byte[11];
151                         System.arraycopy(this.m_bitmaps, index+4, icc_string, 0, 11);
152
153                         /*
154                         byte[] acsp = new byte[4];
155                         System.arraycopy(this.m_bitmaps, index+18+36, acsp, 0, 4);
156                         boolean first_chunk = false;
157                         if ("acsp".equals(new String(acsp))) {
158                             System.out.println("1st icc chunk");
159                             first_chunk = true;
160                         }
161                         */

162                         if ("ICC_PROFILE".equals(new String JavaDoc(icc_string))){
163                             int chunkSize = calcBytes(this.m_bitmaps[index + 2],
164                                                       this.m_bitmaps[index + 3]) + 2;
165
166                             iccStream.write(this.m_bitmaps, index+16, chunkSize - 18); // eller 18..
167
}
168
169                         index += calcBytes(this.m_bitmaps[index + 2],
170                                            this.m_bitmaps[index + 3]) + 2;
171                       // Check for Adobe APPE Marker
172
} else if ((uByte(this.m_bitmaps[index]) == 0xff &&
173                                 uByte(this.m_bitmaps[index+1]) == 0xee &&
174                                 uByte(this.m_bitmaps[index+2]) == 0 &&
175                                 uByte(this.m_bitmaps[index+3]) == 14 &&
176                                 "Adobe".equals(new String JavaDoc(this.m_bitmaps, index+4, 5)))) {
177                         // The reason for reading the APPE marker is that photoshop
178
// generates cmyk jpeg's with inverted values. The correct thing
179
// to do would be to interpret the values in the marker, but for now
180
// only assume that if APPE marker is present and colorspace is CMYK,
181
// the image is inverted.
182
hasAPPEMarker = true;
183
184                         index += calcBytes(this.m_bitmaps[index + 2],
185                                            this.m_bitmaps[index + 3]) + 2;
186                     } else {
187                         index += calcBytes(this.m_bitmaps[index + 2],
188                                            this.m_bitmaps[index + 3]) + 2;
189                     }
190
191
192                 } else {
193                     cont = false;
194                     /*
195                     throw new FopImageException(
196                       "\n2 Error while loading image " +
197                       this.m_href.toString() + " : JpegImage - Invalid JPEG Header (bad header byte).");
198                       */

199                 }
200             }
201         } else {
202             throw new FopImageException( "\n1 Error while loading image " +
203                                          this.m_href.toString() + " : JpegImage - Invalid JPEG Header.");
204         }
205         if (iccStream.size() > 0) {
206             byte[] align = new byte[((iccStream.size()) % 8) + 8];
207             try {iccStream.write(align);} catch (Exception JavaDoc e) {
208                 throw new FopImageException( "\n1 Error while loading image " +
209                               this.m_href.toString() + " : " + e.getMessage());
210             }
211             this.m_colorSpace.setICCProfile(iccStream.toByteArray());
212         }
213
214         if (hasAPPEMarker && this.m_colorSpace.getColorSpace() == ColorSpace.DEVICE_CMYK)
215             this.m_invertImage = true;
216     }
217
218     private int calcBytes(byte bOne, byte bTwo) {
219         return (uByte(bOne) * 256) + uByte(bTwo);
220     }
221
222     private int uByte(byte bIn) {
223         if (bIn < 0) {
224             return 256 + bIn;
225         } else {
226             return bIn;
227         }
228     }
229 }
230
231
232
Popular Tags