private ImageSize determineSize(ImageInputStream in, ImageContext context)
throws IOException, ImageException {
in.mark();
try {
ImageSize size = new ImageSize();
JPEGFile jpeg = new JPEGFile(in);
//TODO Read resolution from EXIF if there's no APP0
//(for example with JPEGs from digicams)
while (true) {
int segID = jpeg.readMarkerSegment();
//System.out.println("Segment: " + Integer.toHexString(segID));
switch (segID) {
case SOI:
case NULL:
break;
case APP0:
int reclen = jpeg.readSegmentLength();
in.skipBytes(7);
int densityUnits = in.read();
int xdensity = in.readUnsignedShort();
int ydensity = in.readUnsignedShort();
if (densityUnits == 2) {
//dots per centimeter
size.setResolution(xdensity * 28.3464567 / 72, ydensity * 28.3464567 / 72);
//TODO Why is 28.3464567 used for cm to inch conversion?
//We normally use 25.4.
} else if (densityUnits == 1) {
//dots per inch
size.setResolution(xdensity, ydensity);
} else {
//resolution not specified
size.setResolution(context.getSourceResolution());
}
if (size.getWidthPx() != 0) {
size.calcSizeFromPixels();
return size;
}
in.skipBytes(reclen - 14);
break;
case SOF0:
case SOF1:
case SOF2: // SOF2 and SOFA are only supported by PDF 1.3
case SOFA:
reclen = jpeg.readSegmentLength();
in.skipBytes(1);
int height = in.readUnsignedShort();
int width = in.readUnsignedShort();
size.setSizeInPixels(width, height);
if (size.getDpiHorizontal() != 0) {
size.calcSizeFromPixels();
return size;
}
in.skipBytes(reclen - 7);
break;
case SOS:
case EOI:
//Break as early as possible (we don't want to read the whole file here)
if (size.getDpiHorizontal() == 0) {
size.setResolution(context.getSourceResolution());
size.calcSizeFromPixels();
}
return size;
default:
jpeg.skipCurrentMarkerSegment();
}