mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 12:05:29 -04:00
JPEG Exif/thumbnail fixes.
(cherry picked from commit fbc738f2d4836e82315831774c0e722a4984e967)
This commit is contained in:
parent
efe5f3c34a
commit
d5e664cdcc
@ -30,37 +30,6 @@
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.color.ICC_ColorSpace;
|
||||
import java.awt.color.ICC_Profile;
|
||||
import java.awt.image.*;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.SequenceInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.event.IIOReadUpdateListener;
|
||||
import javax.imageio.event.IIOReadWarningListener;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||
import javax.imageio.metadata.IIOMetadataNode;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
|
||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||
import com.twelvemonkeys.imageio.color.ColorSpaces;
|
||||
import com.twelvemonkeys.imageio.color.YCbCrConverter;
|
||||
@ -72,7 +41,6 @@ import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
||||
import com.twelvemonkeys.imageio.stream.BufferedImageInputStream;
|
||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||
@ -80,6 +48,24 @@ import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
import com.twelvemonkeys.xml.XMLSerializer;
|
||||
|
||||
import javax.imageio.*;
|
||||
import javax.imageio.event.IIOReadUpdateListener;
|
||||
import javax.imageio.event.IIOReadWarningListener;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||
import javax.imageio.metadata.IIOMetadataNode;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.color.ICC_ColorSpace;
|
||||
import java.awt.color.ICC_Profile;
|
||||
import java.awt.image.*;
|
||||
import java.io.*;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A JPEG {@code ImageReader} implementation based on the JRE {@code JPEGImageReader},
|
||||
* that adds support and properly handles cases where the JRE version throws exceptions.
|
||||
@ -140,7 +126,7 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
private List<Segment> segments;
|
||||
|
||||
private int currentStreamIndex = 0;
|
||||
private List<Long> streamOffsets = new ArrayList<>();
|
||||
private final List<Long> streamOffsets = new ArrayList<>();
|
||||
|
||||
protected JPEGImageReader(final ImageReaderSpi provider, final ImageReader delegate) {
|
||||
super(provider);
|
||||
@ -197,10 +183,10 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (IIOException ignore) {
|
||||
catch (IIOException e) {
|
||||
// May happen if no SOF is found, in case we'll just fall through
|
||||
if (DEBUG) {
|
||||
ignore.printStackTrace();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@ -747,26 +733,26 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
long lastKnownSOIOffset = streamOffsets.get(streamOffsets.size() - 1);
|
||||
imageInput.seek(lastKnownSOIOffset);
|
||||
|
||||
try (ImageInputStream stream = new BufferedImageInputStream(imageInput)) { // Extreme (10s -> 50ms) speedup if imageInput is FileIIS
|
||||
try {
|
||||
for (int i = streamOffsets.size() - 1; i < imageIndex; i++) {
|
||||
long start = 0;
|
||||
|
||||
if (DEBUG) {
|
||||
start = System.currentTimeMillis();
|
||||
System.out.println(String.format("Start seeking for image index %d", i + 1));
|
||||
System.out.printf("Start seeking for image index %d%n", i + 1);
|
||||
}
|
||||
|
||||
// Need to skip over segments, as they may contain JPEG markers (eg. JFXX or EXIF thumbnail)
|
||||
JPEGSegmentUtil.readSegments(stream, Collections.<Integer, List<String>>emptyMap());
|
||||
JPEGSegmentUtil.readSegments(imageInput, Collections.<Integer, List<String>>emptyMap());
|
||||
|
||||
// Now, search for EOI and following SOI...
|
||||
int marker;
|
||||
while ((marker = stream.read()) != -1) {
|
||||
if (marker == 0xFF && (0xFF00 | stream.readUnsignedByte()) == JPEG.EOI) {
|
||||
while ((marker = imageInput.read()) != -1) {
|
||||
if (marker == 0xFF && (0xFF00 | imageInput.readUnsignedByte()) == JPEG.EOI) {
|
||||
// Found EOI, now the SOI should be nearby...
|
||||
while ((marker = stream.read()) != -1) {
|
||||
if (marker == 0xFF && (0xFF00 | stream.readUnsignedByte()) == JPEG.SOI) {
|
||||
long nextSOIOffset = stream.getStreamPosition() - 2;
|
||||
while ((marker = imageInput.read()) != -1) {
|
||||
if (marker == 0xFF && (0xFF00 | imageInput.readUnsignedByte()) == JPEG.SOI) {
|
||||
long nextSOIOffset = imageInput.getStreamPosition() - 2;
|
||||
imageInput.seek(nextSOIOffset);
|
||||
streamOffsets.add(nextSOIOffset);
|
||||
|
||||
@ -780,10 +766,9 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println(String.format("Seek in %d ms", System.currentTimeMillis() - start));
|
||||
System.out.printf("Seek in %d ms%n", System.currentTimeMillis() - start);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (EOFException eof) {
|
||||
IndexOutOfBoundsException ioobe = new IndexOutOfBoundsException("Image index " + imageIndex + " not found in stream");
|
||||
@ -843,9 +828,9 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
|
||||
return JPEGSegmentUtil.readSegments(imageInput, JPEGSegmentUtil.ALL_SEGMENTS);
|
||||
}
|
||||
catch (IIOException | IllegalArgumentException ignore) {
|
||||
catch (IIOException | IllegalArgumentException e) {
|
||||
if (DEBUG) {
|
||||
ignore.printStackTrace();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@ -1162,6 +1147,7 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
if (jpegLength > 0 && jpegOffset + jpegLength <= stream.length()) {
|
||||
// Verify first bytes are FFD8
|
||||
stream.seek(jpegOffset);
|
||||
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
|
||||
if (stream.readUnsignedShort() == JPEG.SOI) {
|
||||
thumbnails.add(new EXIFThumbnailReader(thumbnailProgressDelegator, getThumbnailReader(), 0, thumbnails.size(), ifd1, stream));
|
||||
}
|
||||
@ -1189,7 +1175,9 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
// EXIFThumbnailReader?
|
||||
thumbnails.add(new EXIFThumbnailReader(thumbnailProgressDelegator, getThumbnailReader(), 0, thumbnails.size(), ifd1, stream));
|
||||
}
|
||||
|
||||
else {
|
||||
processWarningOccurred("EXIF IFD with empty or incomplete uncompressed thumbnail");
|
||||
}
|
||||
}
|
||||
else {
|
||||
processWarningOccurred("EXIF IFD with uncompressed thumbnail missing StripOffsets tag");
|
||||
@ -1246,7 +1234,15 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
public BufferedImage readThumbnail(int imageIndex, int thumbnailIndex) throws IOException {
|
||||
checkThumbnailBounds(imageIndex, thumbnailIndex);
|
||||
|
||||
return thumbnails.get(thumbnailIndex).read();
|
||||
// processThumbnailStarted(imageIndex, thumbnailIndex);
|
||||
// processThumbnailProgress(0f);
|
||||
|
||||
BufferedImage thumbnail = thumbnails.get(thumbnailIndex).read();;
|
||||
|
||||
// processThumbnailProgress(100f);
|
||||
// processThumbnailComplete();
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
// Metadata
|
||||
@ -1423,7 +1419,7 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
final String arg = args[argIdx];
|
||||
|
||||
if (arg.charAt(0) == '-') {
|
||||
if (arg.equals("-s") || arg.equals("--subsample") && args.length > argIdx) {
|
||||
if (arg.equals("-s") || arg.equals("--subsample") && args.length > argIdx + 1) {
|
||||
String[] sub = args[++argIdx].split(",");
|
||||
|
||||
try {
|
||||
@ -1442,7 +1438,7 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
System.err.println("Bad sub sampling (x,y): '" + args[argIdx] + "'");
|
||||
}
|
||||
}
|
||||
else if (arg.equals("-r") || arg.equals("--roi") && args.length > argIdx) {
|
||||
else if (arg.equals("-r") || arg.equals("--roi") && args.length > argIdx + 1) {
|
||||
String[] region = args[++argIdx].split(",");
|
||||
|
||||
try {
|
||||
|
Loading…
x
Reference in New Issue
Block a user