mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-02 19:15:29 -04:00
TMI-18: Better filtering of APP segments, now only takes 'Exif' APP1 segments into account.
+ Updated failing test.
This commit is contained in:
parent
08b5891298
commit
2f07329296
@ -29,11 +29,13 @@
|
||||
package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.ImageInputStreamImpl;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -90,7 +92,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
int marker = stream.readUnsignedShort();
|
||||
|
||||
// TODO: Refactor to make various segments optional, we probably only want the "Adobe" APP14 segment, 'Exif' APP1 and very few others
|
||||
if (isAppSegmentMarker(marker) && marker != JPEG.APP0 && marker != JPEG.APP1 && marker != JPEG.APP14) {
|
||||
if (isAppSegmentMarker(marker) && marker != JPEG.APP0 && !(marker == JPEG.APP1 && isAppSegmentWithId("Exif", stream)) && marker != JPEG.APP14) {
|
||||
int length = stream.readUnsignedShort(); // Length including length field itself
|
||||
stream.seek(realPosition + 2 + length); // Skip marker (2) + length
|
||||
}
|
||||
@ -138,6 +140,38 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
return segment;
|
||||
}
|
||||
|
||||
private static boolean isAppSegmentWithId(String segmentId, ImageInputStream stream) throws IOException {
|
||||
Validate.notNull(segmentId, "segmentId");
|
||||
|
||||
stream.mark();
|
||||
|
||||
try {
|
||||
int length = stream.readUnsignedShort(); // Length including length field itself
|
||||
|
||||
byte[] data = new byte[Math.max(20, length - 2)];
|
||||
stream.readFully(data);
|
||||
|
||||
return segmentId.equals(asNullTerminatedAsciiString(data, 0));
|
||||
}
|
||||
finally {
|
||||
stream.reset();
|
||||
}
|
||||
}
|
||||
|
||||
static String asNullTerminatedAsciiString(final byte[] data, final int offset) {
|
||||
for (int i = 0; i < data.length - offset; i++) {
|
||||
if (data[i] == 0 || i > 255) {
|
||||
return asAsciiString(data, offset, offset + i);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static String asAsciiString(final byte[] data, final int offset, final int length) {
|
||||
return new String(data, offset, length, Charset.forName("ascii"));
|
||||
}
|
||||
|
||||
private void streamInit() throws IOException {
|
||||
stream.seek(0);
|
||||
|
||||
|
@ -102,7 +102,7 @@ public class JPEGSegmentImageInputStreamTest {
|
||||
|
||||
assertThat(length, new LessOrEqual<Long>(10203l)); // In no case should length increase
|
||||
|
||||
assertEquals(9495l, length); // May change, if more chunks are passed to reader...
|
||||
assertEquals(9625l, length); // May change, if more chunks are passed to reader...
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -110,14 +110,17 @@ public class JPEGSegmentImageInputStreamTest {
|
||||
ImageInputStream stream = new JPEGSegmentImageInputStream(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/no-image-types-rgb-us-web-coated-v2-ms-photogallery-exif.jpg")));
|
||||
List<JPEGSegment> appSegments = JPEGSegmentUtil.readSegments(stream, JPEGSegmentUtil.APP_SEGMENTS);
|
||||
|
||||
assertEquals(2, appSegments.size());
|
||||
assertEquals(3, appSegments.size());
|
||||
|
||||
assertEquals(JPEG.APP0, appSegments.get(0).marker());
|
||||
assertEquals("JFIF", appSegments.get(0).identifier());
|
||||
|
||||
assertEquals(JPEG.APP14, appSegments.get(1).marker());
|
||||
assertEquals("Adobe", appSegments.get(1).identifier());
|
||||
assertEquals(JPEG.APP1, appSegments.get(1).marker());
|
||||
assertEquals("Exif", appSegments.get(1).identifier());
|
||||
|
||||
// And thus, no Exif, no ICC_PROFILE or other segments
|
||||
assertEquals(JPEG.APP14, appSegments.get(2).marker());
|
||||
assertEquals("Adobe", appSegments.get(2).identifier());
|
||||
|
||||
// And thus, no XMP, no ICC_PROFILE or other segments
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user