1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
/*
* $Id$
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the
* LICENSE file included with these sources.
*/
package org.apache.fop.image;
// Java
import java.net.URL;
import java.awt.image.ImageProducer;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.color.ICC_ColorSpace;
// FOP
import org.apache.fop.image.analyser.ImageReader;
import org.apache.fop.fo.FOUserAgent;
/**
* FopImage object for JPEG images, Using Java native classes.
* @author Eric Dalquist
* @see AbstractFopImage
* @see FopImage
*/
public class JpegImage extends AbstractFopImage {
ICC_Profile iccProfile = null;
boolean found_icc_profile = false;
boolean found_dimensions = false;
public JpegImage(URL href, FopImage.ImageInfo imgReader) {
super(href, imgReader);
}
protected boolean loadOriginalData(FOUserAgent ua) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayOutputStream iccStream = new ByteArrayOutputStream();
InputStream inStream;
byte[] readBuf = new byte[4096];
int bytes_read;
int index = 0;
boolean cont = true;
try {
inStream = this.m_href.openStream();
while ((bytes_read = inStream.read(readBuf)) != -1) {
baos.write(readBuf, 0, bytes_read);
}
} catch (java.io.IOException ex) {
ua.getLogger().error("Error while loading image " +
this.m_href.toString() + " : " + ex.getClass() +
" - " + ex.getMessage(), ex);
return false;
}
this.m_bitmaps = baos.toByteArray();
this.m_bitsPerPixel = 8;
this.m_isTransparent = false;
if (this.m_bitmaps.length > (index + 2) &&
uByte(this.m_bitmaps[index]) == 255 &&
uByte(this.m_bitmaps[index + 1]) == 216) {
index += 2;
while (index < this.m_bitmaps.length && cont) {
//check to be sure this is the begining of a header
if (this.m_bitmaps.length > (index + 2) &&
uByte(this.m_bitmaps[index]) == 255) {
//192 or 194 are the header bytes that contain the jpeg width height and color depth.
if (uByte(this.m_bitmaps[index + 1]) == 192 ||
uByte(this.m_bitmaps[index + 1]) == 194) {
this.m_height = calcBytes(this.m_bitmaps[index + 5],
this.m_bitmaps[index + 6]);
this.m_width = calcBytes(this.m_bitmaps[index + 7],
this.m_bitmaps[index + 8]);
if (this.m_bitmaps[index + 9] == 1) {
this.m_colorSpace = ColorSpace.getInstance(
ColorSpace.CS_GRAY);
} else if (this.m_bitmaps[index + 9] == 3) {
this.m_colorSpace = ColorSpace.getInstance(
ColorSpace.CS_LINEAR_RGB);
} else if (this.m_bitmaps[index + 9] == 4) {
// howto create CMYK color space
this.m_colorSpace = ColorSpace.getInstance(
ColorSpace.CS_CIEXYZ);
} else {
ua.getLogger().error("Unknown ColorSpace for image: "
+ this.m_href.toString());
return false;
}
found_dimensions = true;
if (found_icc_profile) {
cont = false;
break;
}
index += calcBytes(this.m_bitmaps[index + 2],
this.m_bitmaps[index + 3]) + 2;
} else if (uByte(this.m_bitmaps[index + 1]) ==
226 && this.m_bitmaps.length > (index + 60)) {
// Check if ICC profile
byte[] icc_string = new byte[11];
System.arraycopy(this.m_bitmaps, index + 4,
icc_string, 0, 11);
if ("ICC_PROFILE".equals(new String(icc_string))) {
int chunkSize = calcBytes(
this.m_bitmaps[index + 2],
this.m_bitmaps[index + 3]) + 2;
if (iccStream.size() == 0)
iccStream.write(this.m_bitmaps,
index + 18, chunkSize - 20);
else
iccStream.write(this.m_bitmaps,
index + 16, chunkSize - 18);
}
index += calcBytes(this.m_bitmaps[index + 2],
this.m_bitmaps[index + 3]) + 2;
} else {
index += calcBytes(this.m_bitmaps[index + 2],
this.m_bitmaps[index + 3]) + 2;
}
} else {
cont = false;
}
}
} else {
ua.getLogger().error( "1 Error while loading image " +
this.m_href.toString() +
" : JpegImage - Invalid JPEG Header.");
return false;
}
if (iccStream.size() > 0) {
byte[] align = new byte[((iccStream.size()) % 8) + 8];
try {
iccStream.write(align);
} catch (Exception e) {
ua.getLogger().error( "1 Error while loading image " +
this.m_href.toString() + " : " +
e.getMessage(), e);
return false;
}
iccProfile = ICC_Profile.getInstance(iccStream.toByteArray());
} else if(this.m_colorSpace == null) {
ua.getLogger().error("ColorSpace not specified for image: "
+ this.m_href.toString());
return false;
}
return true;
}
public ICC_Profile getICCProfile() {
return iccProfile;
}
private int calcBytes(byte bOne, byte bTwo) {
return (uByte(bOne) * 256) + uByte(bTwo);
}
private int uByte(byte bIn) {
if (bIn < 0) {
return 256 + bIn;
} else {
return bIn;
}
}
}
|