38
39
public class PreloaderJPEG extends AbstractImagePreloader implements JPEGConstants {
40
41
private static final int JPG_SIG_LENGTH = 3;
42
private static final int[] BYTES_PER_COMPONENT = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8}; // ignore 0
43
private static final int EXIF = 0x45786966;
44
private static final int II = 0x4949; // Intel
45
private static final int MM = 0x4d4d; // Motorola
46
private static final int X_RESOLUTION = 0x011a;
47
private static final int Y_RESOLUTION = 0x011b;
48
private static final int RESOLUTION_UNIT = 0x0128;
43
51
* @throws ImageException */
83
89
int densityUnits = in.read();
84
90
int xdensity = in.readUnsignedShort();
85
91
int ydensity = in.readUnsignedShort();
86
if (densityUnits == 2) {
89
xdensity * UnitConv.IN2CM,
90
ydensity * UnitConv.IN2CM);
91
} else if (densityUnits == 1) {
93
size.setResolution(xdensity, ydensity);
92
if (size.getDpiHorizontal() == 0) {
93
if (densityUnits == 2) {
96
xdensity * UnitConv.IN2CM,
97
ydensity * UnitConv.IN2CM);
98
} else if (densityUnits == 1) {
100
size.setResolution(xdensity, ydensity);
102
//resolution not specified
103
size.setResolution(context.getSourceResolution());
106
if (size.getWidthPx() != 0) {
107
size.calcSizeFromPixels();
110
in.skipBytes(reclen - 14);
113
// see http://www.media.mit.edu/pia/Research/deepview/exif.html
114
reclen = jpeg.readSegmentLength();
115
int bytesToEnd = reclen - 2;
116
// read Exif Header: 0x.45.78.69.66.00.00
117
int exif = in.readInt(); // 0x.45.78.69.66
118
in.readUnsignedShort(); // 0x.00.00
122
// there may be multiple APP1 segments but we want the Exif one
123
in.skipBytes(bytesToEnd);
127
int currentTIFFOffset = 0;
128
// byte align: 0x.49.49 (19789) means Intel, 0x.4D.4D means Motorola
129
int align = in.readUnsignedShort();
131
currentTIFFOffset += 2;
132
ByteOrder originalByteOrder = in.getByteOrder();
133
// Intel = little, Motorola = big
134
in.setByteOrder(align == MM ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
135
in.skipBytes(2); // 0x.2A.00 (Intel) or 0x.00.2A (Motorola)
137
currentTIFFOffset += 2;
138
int firstIFDOffset = in.readInt();
140
currentTIFFOffset += 4;
141
in.skipBytes(firstIFDOffset - 8);
142
bytesToEnd -= firstIFDOffset - 8;
143
currentTIFFOffset += firstIFDOffset - 8;
144
int directoryEntries = in.readUnsignedShort();
146
currentTIFFOffset += 2;
147
int resolutionOffset = 0;
148
int resolutionFormat = 0;
149
int resolutionUnits = 0;
151
boolean foundResolution = false;
152
for (int j = 0; j < directoryEntries; j++) {
153
int tag = in.readUnsignedShort();
154
if ((tag == X_RESOLUTION || tag == Y_RESOLUTION) && !foundResolution) {
155
// 0x011A (XResolution), 0x011B (YResolution)
156
int format = in.readUnsignedShort();
157
int components = in.readInt();
158
int dataByteLength = components * BYTES_PER_COMPONENT[format];
159
int value = in.readInt();
160
if (dataByteLength > 4) {
161
// value is offset to data value
162
resolutionOffset = value;
164
// value is data value
167
resolutionFormat = format;
168
foundResolution = true;
169
} else if (tag == RESOLUTION_UNIT) {
170
// 0x0128 (ResolutionUnit)
171
int format = in.readUnsignedShort();
172
int components = in.readInt();
173
int dataByteLength = components * BYTES_PER_COMPONENT[format];
174
if (dataByteLength < 5 && format == 3) {
175
int value = in.readUnsignedShort();
177
resolutionUnits = value;
185
currentTIFFOffset += 12;
187
in.readInt(); // not needed, but has thumbnail info
189
currentTIFFOffset += 4;
190
if (resolutionOffset != 0) {
191
in.skipBytes(resolutionOffset - currentTIFFOffset);
192
bytesToEnd -= resolutionOffset - currentTIFFOffset;
193
if (resolutionFormat == 5 || resolutionFormat == 10) {
194
int numerator = in.readInt();
195
int denominator = in.readInt();
196
resolution = numerator / denominator;
200
in.skipBytes(bytesToEnd);
201
in.setByteOrder(originalByteOrder);
202
if (resolutionUnits == 3) {
203
// dots per centimeter
204
size.setResolution(resolution * UnitConv.IN2CM, resolution * UnitConv.IN2CM);
205
} else if (resolutionUnits == 2) {
207
size.setResolution(resolution, resolution);
95
//resolution not specified
96
size.setResolution(context.getSourceResolution());
209
// resolution not specified; set default if not set yet
210
if (size.getDpiHorizontal() == 0) {
211
size.setResolution(context.getSourceResolution());
98
214
if (size.getWidthPx() != 0) {
99
215
size.calcSizeFromPixels();
102
in.skipBytes(reclen - 14);