~hjd/ubuntu/wily/xmlgraphics-commons/debian-merged

« back to all changes in this revision

Viewing changes to src/java/org/apache/xmlgraphics/image/loader/impl/PreloaderJPEG.java

  • Committer: Hans Joachim Desserud
  • Date: 2015-11-11 18:22:53 UTC
  • mfrom: (9.1.5 sid)
  • Revision ID: hans_joachim_desserud-20151111182253-zwi0frfm97j0wddn
  * Merge from Debian unstable.  Remaining changes:
    - d/control: Drop dependencies required for unit testing as they
      include libmockito-java which would pull maven into main, disable unit
      test execution.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 * limitations under the License.
16
16
 */
17
17
 
18
 
/* $Id: PreloaderJPEG.java 696949 2008-09-19 07:13:02Z jeremias $ */
 
18
/* $Id: PreloaderJPEG.java 1681698 2015-05-26 07:49:35Z ssteiner $ */
19
19
 
20
20
package org.apache.xmlgraphics.image.loader.impl;
21
21
 
22
22
import java.io.IOException;
 
23
import java.nio.ByteOrder;
23
24
 
24
25
import javax.imageio.stream.ImageInputStream;
25
26
import javax.xml.transform.Source;
38
39
public class PreloaderJPEG extends AbstractImagePreloader implements JPEGConstants {
39
40
 
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;
41
49
 
42
50
    /** {@inheritDoc}
43
51
     * @throws ImageException */
68
76
            ImageSize size = new ImageSize();
69
77
            JPEGFile jpeg = new JPEGFile(in);
70
78
 
71
 
            //TODO Read resolution from EXIF if there's no APP0
72
 
            //(for example with JPEGs from digicams)
73
79
            while (true) {
74
80
                int segID = jpeg.readMarkerSegment();
75
81
                //System.out.println("Segment: " + Integer.toHexString(segID));
83
89
                    int densityUnits = in.read();
84
90
                    int xdensity = in.readUnsignedShort();
85
91
                    int ydensity = in.readUnsignedShort();
86
 
                    if (densityUnits == 2) {
87
 
                        //dots per centimeter
88
 
                        size.setResolution(
89
 
                                xdensity * UnitConv.IN2CM,
90
 
                                ydensity * UnitConv.IN2CM);
91
 
                    } else if (densityUnits == 1) {
92
 
                        //dots per inch
93
 
                        size.setResolution(xdensity, ydensity);
 
92
                    if (size.getDpiHorizontal() == 0) {
 
93
                        if (densityUnits == 2) {
 
94
                            //dots per centimeter
 
95
                            size.setResolution(
 
96
                                    xdensity * UnitConv.IN2CM,
 
97
                                    ydensity * UnitConv.IN2CM);
 
98
                        } else if (densityUnits == 1) {
 
99
                            //dots per inch
 
100
                            size.setResolution(xdensity, ydensity);
 
101
                        } else {
 
102
                            //resolution not specified
 
103
                            size.setResolution(context.getSourceResolution());
 
104
                        }
 
105
                    }
 
106
                    if (size.getWidthPx() != 0) {
 
107
                        size.calcSizeFromPixels();
 
108
                        return size;
 
109
                    }
 
110
                    in.skipBytes(reclen - 14);
 
111
                    break;
 
112
                case APP1:
 
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
 
119
                    // in.skipBytes(6);
 
120
                    bytesToEnd -= 6;
 
121
                    if (exif != EXIF) {
 
122
                        // there may be multiple APP1 segments but we want the Exif one
 
123
                        in.skipBytes(bytesToEnd);
 
124
                        break;
 
125
                    }
 
126
                    // start TIFF data
 
127
                    int currentTIFFOffset = 0;
 
128
                    // byte align: 0x.49.49 (19789) means Intel, 0x.4D.4D means Motorola
 
129
                    int align = in.readUnsignedShort();
 
130
                    bytesToEnd -= 2;
 
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)
 
136
                    bytesToEnd -= 2;
 
137
                    currentTIFFOffset += 2;
 
138
                    int firstIFDOffset = in.readInt();
 
139
                    bytesToEnd -= 4;
 
140
                    currentTIFFOffset += 4;
 
141
                    in.skipBytes(firstIFDOffset - 8);
 
142
                    bytesToEnd -= firstIFDOffset - 8;
 
143
                    currentTIFFOffset += firstIFDOffset - 8;
 
144
                    int directoryEntries = in.readUnsignedShort();
 
145
                    bytesToEnd -= 2;
 
146
                    currentTIFFOffset += 2;
 
147
                    int resolutionOffset = 0;
 
148
                    int resolutionFormat = 0;
 
149
                    int resolutionUnits = 0;
 
150
                    int resolution = 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;
 
163
                            } else {
 
164
                                // value is data value
 
165
                                resolution = value;
 
166
                            }
 
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();
 
176
                                in.skipBytes(2);
 
177
                                resolutionUnits = value;
 
178
                            } else {
 
179
                                in.skipBytes(4);
 
180
                            }
 
181
                        } else {
 
182
                            in.skipBytes(10);
 
183
                        }
 
184
                        bytesToEnd -= 12;
 
185
                        currentTIFFOffset += 12;
 
186
                    }
 
187
                    in.readInt(); // not needed, but has thumbnail info
 
188
                    bytesToEnd -= 4;
 
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;
 
197
                            bytesToEnd -= 8;
 
198
                        }
 
199
                    }
 
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) {
 
206
                        // dots per inch
 
207
                        size.setResolution(resolution, resolution);
94
208
                    } else {
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());
 
212
                        }
97
213
                    }
98
214
                    if (size.getWidthPx() != 0) {
99
215
                        size.calcSizeFromPixels();
100
216
                        return size;
101
217
                    }
102
 
                    in.skipBytes(reclen - 14);
103
218
                    break;
104
219
                case SOF0:
105
220
                case SOF1:
118
233
                    break;
119
234
                case SOS:
120
235
                case EOI:
121
 
                    //Break as early as possible (we don't want to read the whole file here)
 
236
                    // Break as early as possible (we don't want to read the whole file here)
122
237
                    if (size.getDpiHorizontal() == 0) {
123
238
                        size.setResolution(context.getSourceResolution());
124
239
                        size.calcSizeFromPixels();