mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-05 04:25:29 -04:00
JPEG Exif/thumbnail refactoring pt II.
This commit is contained in:
parent
85fb9e6af3
commit
0286fa4268
@ -57,31 +57,30 @@ final class EXIFThumbnail {
|
|||||||
private EXIFThumbnail() {
|
private EXIFThumbnail() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static ThumbnailReader from(final EXIF exif, final CompoundDirectory exifMetadata, final ImageReader jpegThumbnailReader, final JPEGSegmentWarningListener listener) throws IOException {
|
static ThumbnailReader from(final EXIF segment, final CompoundDirectory exif, final ImageReader jpegThumbnailReader) throws IOException {
|
||||||
if (exif != null && exifMetadata != null && exifMetadata.directoryCount() == 2) {
|
if (segment != null && exif != null && exif.directoryCount() >= 2) {
|
||||||
ImageInputStream stream = exif.exifData(); // NOTE This is an in-memory stream and must not be closed...
|
ImageInputStream stream = segment.exifData(); // NOTE This is an in-memory stream and must not be closed...
|
||||||
|
|
||||||
Directory ifd1 = exifMetadata.getDirectory(1);
|
Directory ifd1 = exif.getDirectory(1);
|
||||||
|
|
||||||
// Compression: 1 = no compression, 6 = JPEG compression (default)
|
// Compression: 1 = no compression, 6 = JPEG compression (default)
|
||||||
Entry compressionEntry = ifd1.getEntryById(TIFF.TAG_COMPRESSION);
|
Entry compressionEntry = ifd1.getEntryById(TIFF.TAG_COMPRESSION);
|
||||||
int compression = compressionEntry == null ? 6 : ((Number) compressionEntry.getValue()).intValue();
|
int compression = compressionEntry == null ? 6 : ((Number) compressionEntry.getValue()).intValue();
|
||||||
|
|
||||||
switch (compression) {
|
switch (compression) {
|
||||||
case 6:
|
|
||||||
return createJPEGThumbnailReader(exif, jpegThumbnailReader, listener, stream, ifd1);
|
|
||||||
case 1:
|
case 1:
|
||||||
return createUncompressedThumbnailReader(listener, stream, ifd1);
|
return createUncompressedThumbnailReader(stream, ifd1);
|
||||||
|
case 6:
|
||||||
|
return createJPEGThumbnailReader(segment, jpegThumbnailReader, stream, ifd1);
|
||||||
default:
|
default:
|
||||||
listener.warningOccurred("EXIF IFD with unknown thumbnail compression (expected 1 or 6): " + compression);
|
throw new IIOException("EXIF IFD with unknown thumbnail compression (expected 1 or 6): " + compression);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UncompressedThumbnailReader createUncompressedThumbnailReader(JPEGSegmentWarningListener listener, ImageInputStream stream, Directory ifd1) throws IOException {
|
private static UncompressedThumbnailReader createUncompressedThumbnailReader(ImageInputStream stream, Directory ifd1) throws IOException {
|
||||||
Entry stripOffEntry = ifd1.getEntryById(TIFF.TAG_STRIP_OFFSETS);
|
Entry stripOffEntry = ifd1.getEntryById(TIFF.TAG_STRIP_OFFSETS);
|
||||||
Entry width = ifd1.getEntryById(TIFF.TAG_IMAGE_WIDTH);
|
Entry width = ifd1.getEntryById(TIFF.TAG_IMAGE_WIDTH);
|
||||||
Entry height = ifd1.getEntryById(TIFF.TAG_IMAGE_HEIGHT);
|
Entry height = ifd1.getEntryById(TIFF.TAG_IMAGE_HEIGHT);
|
||||||
@ -95,13 +94,9 @@ final class EXIFThumbnail {
|
|||||||
int w = ((Number) width.getValue()).intValue();
|
int w = ((Number) width.getValue()).intValue();
|
||||||
int h = ((Number) height.getValue()).intValue();
|
int h = ((Number) height.getValue()).intValue();
|
||||||
|
|
||||||
// TODO: Decide on warning OR exception!
|
if (bitsPerSample != null && !Arrays.equals((int[]) bitsPerSample.getValue(), new int[] {8, 8, 8})) {
|
||||||
if (bitsPerSample != null) {
|
|
||||||
int[] bpp = (int[]) bitsPerSample.getValue();
|
|
||||||
if (!Arrays.equals(bpp, new int[] {8, 8, 8})) {
|
|
||||||
throw new IIOException("Unknown BitsPerSample value for uncompressed EXIF thumbnail (expected [8, 8, 8]): " + bitsPerSample.getValueAsString());
|
throw new IIOException("Unknown BitsPerSample value for uncompressed EXIF thumbnail (expected [8, 8, 8]): " + bitsPerSample.getValueAsString());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (samplesPerPixel != null && ((Number) samplesPerPixel.getValue()).intValue() != 3) {
|
if (samplesPerPixel != null && ((Number) samplesPerPixel.getValue()).intValue() != 3) {
|
||||||
throw new IIOException("Unknown SamplesPerPixel value for uncompressed EXIF thumbnail (expected 3): " + samplesPerPixel.getValueAsString());
|
throw new IIOException("Unknown SamplesPerPixel value for uncompressed EXIF thumbnail (expected 3): " + samplesPerPixel.getValueAsString());
|
||||||
@ -111,7 +106,7 @@ final class EXIFThumbnail {
|
|||||||
long stripOffset = ((Number) stripOffEntry.getValue()).longValue();
|
long stripOffset = ((Number) stripOffEntry.getValue()).longValue();
|
||||||
|
|
||||||
int thumbLength = w * h * 3;
|
int thumbLength = w * h * 3;
|
||||||
if (stripOffset >= 0 && stripOffset + thumbLength < stream.length()) {
|
if (stripOffset >= 0 && stripOffset + thumbLength <= stream.length()) {
|
||||||
// Read raw image data, either RGB or YCbCr
|
// Read raw image data, either RGB or YCbCr
|
||||||
stream.seek(stripOffset);
|
stream.seek(stripOffset);
|
||||||
byte[] thumbData = new byte[thumbLength];
|
byte[] thumbData = new byte[thumbLength];
|
||||||
@ -135,11 +130,10 @@ final class EXIFThumbnail {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listener.warningOccurred("EXIF IFD with empty or incomplete uncompressed thumbnail");
|
throw new IIOException("EXIF IFD with empty or incomplete uncompressed thumbnail");
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JPEGThumbnailReader createJPEGThumbnailReader(EXIF exif, ImageReader jpegThumbnailReader, JPEGSegmentWarningListener listener, ImageInputStream stream, Directory ifd1) throws IOException {
|
private static JPEGThumbnailReader createJPEGThumbnailReader(EXIF exif, ImageReader jpegThumbnailReader, ImageInputStream stream, Directory ifd1) throws IOException {
|
||||||
Entry jpegOffEntry = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT);
|
Entry jpegOffEntry = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT);
|
||||||
if (jpegOffEntry != null) {
|
if (jpegOffEntry != null) {
|
||||||
Entry jpegLenEntry = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
|
Entry jpegLenEntry = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
|
||||||
@ -152,13 +146,13 @@ final class EXIFThumbnail {
|
|||||||
// Verify first bytes are FFD8
|
// Verify first bytes are FFD8
|
||||||
stream.seek(jpegOffset);
|
stream.seek(jpegOffset);
|
||||||
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
|
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
|
||||||
|
|
||||||
if (stream.readUnsignedShort() == JPEG.SOI) {
|
if (stream.readUnsignedShort() == JPEG.SOI) {
|
||||||
return new JPEGThumbnailReader(jpegThumbnailReader, stream, jpegOffset);
|
return new JPEGThumbnailReader(jpegThumbnailReader, stream, jpegOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listener.warningOccurred("EXIF IFD with empty or incomplete JPEG thumbnail");
|
throw new IIOException("EXIF IFD with empty or incomplete JPEG thumbnail");
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,9 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.plugins.jpeg.ThumbnailReader.UncompressedThumbnailReader;
|
import com.twelvemonkeys.imageio.plugins.jpeg.ThumbnailReader.UncompressedThumbnailReader;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JFIFThumbnail
|
* JFIFThumbnail
|
||||||
*
|
*
|
||||||
@ -43,15 +46,14 @@ final class JFIFThumbnail {
|
|||||||
private JFIFThumbnail() {
|
private JFIFThumbnail() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static ThumbnailReader from(final JFIF segment, final JPEGSegmentWarningListener listener) {
|
static ThumbnailReader from(final JFIF segment) throws IOException {
|
||||||
if (segment != null && segment.xThumbnail > 0 && segment.yThumbnail > 0) {
|
if (segment != null && segment.xThumbnail > 0 && segment.yThumbnail > 0) {
|
||||||
if (segment.thumbnail == null || segment.thumbnail.length < segment.xThumbnail * segment.yThumbnail) {
|
if (segment.thumbnail == null || segment.thumbnail.length < segment.xThumbnail * segment.yThumbnail) {
|
||||||
listener.warningOccurred("Ignoring truncated JFIF thumbnail");
|
throw new IIOException("Truncated JFIF thumbnail");
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return new UncompressedThumbnailReader(segment.xThumbnail, segment.yThumbnail, segment.thumbnail);
|
return new UncompressedThumbnailReader(segment.xThumbnail, segment.yThumbnail, segment.thumbnail);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,9 @@ import com.twelvemonkeys.imageio.plugins.jpeg.ThumbnailReader.JPEGThumbnailReade
|
|||||||
import com.twelvemonkeys.imageio.plugins.jpeg.ThumbnailReader.UncompressedThumbnailReader;
|
import com.twelvemonkeys.imageio.plugins.jpeg.ThumbnailReader.UncompressedThumbnailReader;
|
||||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.ImageReader;
|
import javax.imageio.ImageReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JFXXThumbnailReader
|
* JFXXThumbnailReader
|
||||||
@ -50,7 +52,7 @@ final class JFXXThumbnail {
|
|||||||
private JFXXThumbnail() {
|
private JFXXThumbnail() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static ThumbnailReader from(final JFXX segment, final ImageReader thumbnailReader, final JPEGSegmentWarningListener listener) {
|
static ThumbnailReader from(final JFXX segment, final ImageReader thumbnailReader) throws IOException {
|
||||||
if (segment != null) {
|
if (segment != null) {
|
||||||
if (segment.thumbnail != null && segment.thumbnail.length > 2) {
|
if (segment.thumbnail != null && segment.thumbnail.length > 2) {
|
||||||
switch (segment.extensionCode) {
|
switch (segment.extensionCode) {
|
||||||
@ -64,26 +66,29 @@ final class JFXXThumbnail {
|
|||||||
case JFXX.INDEXED:
|
case JFXX.INDEXED:
|
||||||
int w = segment.thumbnail[0] & 0xff;
|
int w = segment.thumbnail[0] & 0xff;
|
||||||
int h = segment.thumbnail[1] & 0xff;
|
int h = segment.thumbnail[1] & 0xff;
|
||||||
|
|
||||||
if (segment.thumbnail.length >= 2 + 768 + w * h) {
|
if (segment.thumbnail.length >= 2 + 768 + w * h) {
|
||||||
return new IndexedThumbnailReader(w, h, segment.thumbnail, 2, segment.thumbnail, 2 + 768);
|
return new IndexedThumbnailReader(w, h, segment.thumbnail, 2, segment.thumbnail, 2 + 768);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JFXX.RGB:
|
case JFXX.RGB:
|
||||||
w = segment.thumbnail[0] & 0xff;
|
w = segment.thumbnail[0] & 0xff;
|
||||||
h = segment.thumbnail[1] & 0xff;
|
h = segment.thumbnail[1] & 0xff;
|
||||||
|
|
||||||
if (segment.thumbnail.length >= 2 + w * h * 3) {
|
if (segment.thumbnail.length >= 2 + w * h * 3) {
|
||||||
return new UncompressedThumbnailReader(w, h, segment.thumbnail, 2);
|
return new UncompressedThumbnailReader(w, h, segment.thumbnail, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
listener.warningOccurred(String.format("Unknown JFXX extension code: %d, ignoring thumbnail", segment.extensionCode));
|
throw new IIOException(String.format("Unknown JFXX extension code: %d, ignoring thumbnail", segment.extensionCode));
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listener.warningOccurred("JFXX segment truncated, ignoring thumbnail");
|
throw new IIOException("JFXX segment truncated, ignoring thumbnail");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -133,7 +133,7 @@ final class JPEGImage10MetadataCleaner {
|
|||||||
IIOMetadataNode app0JFXX = new IIOMetadataNode("app0JFXX");
|
IIOMetadataNode app0JFXX = new IIOMetadataNode("app0JFXX");
|
||||||
app0JFXX.setAttribute("extensionCode", String.valueOf(jfxx.extensionCode));
|
app0JFXX.setAttribute("extensionCode", String.valueOf(jfxx.extensionCode));
|
||||||
|
|
||||||
ThumbnailReader thumbnailReader = JFXXThumbnail.from(jfxx, reader.getThumbnailReader(), JPEGSegmentWarningListener.NULL_LISTENER);
|
ThumbnailReader thumbnailReader = JFXXThumbnail.from(jfxx, reader.getThumbnailReader());
|
||||||
IIOMetadataNode jfifThumb;
|
IIOMetadataNode jfifThumb;
|
||||||
|
|
||||||
switch (jfxx.extensionCode) {
|
switch (jfxx.extensionCode) {
|
||||||
|
@ -909,17 +909,6 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Util method?
|
|
||||||
static byte[] readFully(DataInput stream, int len) throws IOException {
|
|
||||||
if (len == 0) {
|
|
||||||
throw new IllegalArgumentException("len == 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] data = new byte[len];
|
|
||||||
stream.readFully(data);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
ICC_Profile getEmbeddedICCProfile(final boolean allowBadIndexes) throws IOException {
|
ICC_Profile getEmbeddedICCProfile(final boolean allowBadIndexes) throws IOException {
|
||||||
// ICC v 1.42 (2006) annex B:
|
// ICC v 1.42 (2006) annex B:
|
||||||
// APP2 marker (0xFFE2) + 2 byte length + ASCII 'ICC_PROFILE' + 0 (termination)
|
// APP2 marker (0xFFE2) + 2 byte length + ASCII 'ICC_PROFILE' + 0 (termination)
|
||||||
@ -1086,27 +1075,40 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
if (thumbnails == null) {
|
if (thumbnails == null) {
|
||||||
thumbnails = new ArrayList<>();
|
thumbnails = new ArrayList<>();
|
||||||
|
|
||||||
JPEGSegmentWarningDelegate listenerDelegate = new JPEGSegmentWarningDelegate();
|
|
||||||
|
|
||||||
// Read JFIF thumbnails if present
|
// Read JFIF thumbnails if present
|
||||||
ThumbnailReader thumbnailReader = JFIFThumbnail.from(getJFIF(), listenerDelegate);
|
try {
|
||||||
if (thumbnailReader != null) {
|
ThumbnailReader thumbnail = JFIFThumbnail.from(getJFIF());
|
||||||
thumbnails.add(thumbnailReader);
|
if (thumbnail != null) {
|
||||||
|
thumbnails.add(thumbnail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
processWarningOccurred(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read JFXX thumbnails if present
|
// Read JFXX thumbnails if present
|
||||||
thumbnailReader = JFXXThumbnail.from(getJFXX(), getThumbnailReader(), listenerDelegate);
|
try {
|
||||||
if (thumbnailReader != null) {
|
ThumbnailReader thumbnail = JFXXThumbnail.from(getJFXX(), getThumbnailReader());
|
||||||
thumbnails.add(thumbnailReader);
|
if (thumbnail != null) {
|
||||||
|
thumbnails.add(thumbnail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
processWarningOccurred(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read Exif thumbnails if present
|
// Read Exif thumbnails if present
|
||||||
|
try {
|
||||||
EXIF exif = getExif();
|
EXIF exif = getExif();
|
||||||
thumbnailReader = EXIFThumbnail.from(exif, parseExif(exif), getThumbnailReader(), listenerDelegate);
|
ThumbnailReader thumbnailReader = EXIFThumbnail.from(exif, parseExif(exif), getThumbnailReader());
|
||||||
if (thumbnailReader != null) {
|
if (thumbnailReader != null) {
|
||||||
thumbnails.add(thumbnailReader);
|
thumbnails.add(thumbnailReader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
processWarningOccurred(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageReader getThumbnailReader() throws IOException {
|
ImageReader getThumbnailReader() throws IOException {
|
||||||
|
@ -39,7 +39,6 @@ import java.io.IOException;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractThumbnailReaderTest
|
* AbstractThumbnailReaderTest
|
||||||
@ -53,8 +52,6 @@ public abstract class AbstractThumbnailReaderTest {
|
|||||||
IIORegistry.getDefaultInstance().registerServiceProvider(new URLImageInputStreamSpi());
|
IIORegistry.getDefaultInstance().registerServiceProvider(new URLImageInputStreamSpi());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final JPEGSegmentWarningListener listener = mock(JPEGSegmentWarningListener.class);
|
|
||||||
|
|
||||||
protected abstract ThumbnailReader createReader(ImageInputStream stream) throws IOException;
|
protected abstract ThumbnailReader createReader(ImageInputStream stream) throws IOException;
|
||||||
|
|
||||||
protected final ImageInputStream createStream(final String name) throws IOException {
|
protected final ImageInputStream createStream(final String name) throws IOException {
|
||||||
|
@ -30,14 +30,21 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.jpeg;
|
package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.imageio.metadata.AbstractCompoundDirectory;
|
||||||
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.Entry;
|
||||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
|
||||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.tiff.IFD;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
||||||
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
|
||||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.ImageReader;
|
import javax.imageio.ImageReader;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
@ -45,6 +52,8 @@ import java.awt.image.BufferedImage;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
@ -60,6 +69,153 @@ public class EXIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
|||||||
|
|
||||||
private final ImageReader thumbnailReader = ImageIO.getImageReadersByFormatName("jpeg").next();
|
private final ImageReader thumbnailReader = ImageIO.getImageReadersByFormatName("jpeg").next();
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
thumbnailReader.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromNullSegment() throws IOException {
|
||||||
|
assertNull(EXIFThumbnail.from(null, null, thumbnailReader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromNullIFD() throws IOException {
|
||||||
|
assertNull(EXIFThumbnail.from(new EXIF(new byte[0]), null, thumbnailReader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromEmptyIFD() throws IOException {
|
||||||
|
assertNull(EXIFThumbnail.from(new EXIF(new byte[0]), new EXIFDirectory(), thumbnailReader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromSingleIFD() throws IOException {
|
||||||
|
assertNull(EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList())), thumbnailReader));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IIOException.class)
|
||||||
|
public void testFromMissingThumbnail() throws IOException {
|
||||||
|
EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(Collections.<Entry>emptyList())), thumbnailReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IIOException.class)
|
||||||
|
public void testFromUnsupportedThumbnailCompression() throws IOException {
|
||||||
|
List<TIFFEntry> entries = Collections.singletonList(new TIFFEntry(TIFF.TAG_COMPRESSION, 42));
|
||||||
|
EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IIOException.class)
|
||||||
|
public void testFromMissingOffsetUncompressed() throws IOException {
|
||||||
|
List<TIFFEntry> entries = Arrays.asList(
|
||||||
|
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 16),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 9)
|
||||||
|
);
|
||||||
|
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IIOException.class)
|
||||||
|
public void testFromMissingWidthUncompressed() throws IOException {
|
||||||
|
List<TIFFEntry> entries = Arrays.asList(
|
||||||
|
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||||
|
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 9)
|
||||||
|
);
|
||||||
|
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IIOException.class)
|
||||||
|
public void testFromMissingHeightUncompressed() throws IOException {
|
||||||
|
List<TIFFEntry> entries = Arrays.asList(
|
||||||
|
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||||
|
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 16)
|
||||||
|
);
|
||||||
|
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IIOException.class)
|
||||||
|
public void testFromUnsupportedPhotometricUncompressed() throws IOException {
|
||||||
|
List<TIFFEntry> entries = Arrays.asList(
|
||||||
|
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||||
|
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 16),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 9),
|
||||||
|
new TIFFEntry(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, 42)
|
||||||
|
);
|
||||||
|
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IIOException.class)
|
||||||
|
public void testFromUnsupportedBitsPerSampleUncompressed() throws IOException {
|
||||||
|
List<TIFFEntry> entries = Arrays.asList(
|
||||||
|
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||||
|
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 16),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 9),
|
||||||
|
new TIFFEntry(TIFF.TAG_BITS_PER_SAMPLE, new int[]{5, 6, 5})
|
||||||
|
);
|
||||||
|
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IIOException.class)
|
||||||
|
public void testFromUnsupportedSamplesPerPixelUncompressed() throws IOException {
|
||||||
|
List<TIFFEntry> entries = Arrays.asList(
|
||||||
|
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||||
|
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 160),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 90),
|
||||||
|
new TIFFEntry(TIFF.TAG_SAMPLES_PER_PIXEL, 1)
|
||||||
|
);
|
||||||
|
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IIOException.class)
|
||||||
|
public void testFromTruncatedUncompressed() throws IOException {
|
||||||
|
List<TIFFEntry> entries = Arrays.asList(
|
||||||
|
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||||
|
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 160),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 90)
|
||||||
|
);
|
||||||
|
EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidUncompressed() throws IOException {
|
||||||
|
List<TIFFEntry> entries = Arrays.asList(
|
||||||
|
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||||
|
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 16),
|
||||||
|
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 9)
|
||||||
|
);
|
||||||
|
|
||||||
|
ThumbnailReader reader = EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||||
|
assertNotNull(reader);
|
||||||
|
|
||||||
|
// Sanity check below
|
||||||
|
assertEquals(16, reader.getWidth());
|
||||||
|
assertEquals(9, reader.getHeight());
|
||||||
|
assertNotNull(reader.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IIOException.class)
|
||||||
|
public void testFromMissingOffsetJPEG() throws IOException {
|
||||||
|
List<TIFFEntry> entries = Collections.singletonList(new TIFFEntry(TIFF.TAG_COMPRESSION, 6));
|
||||||
|
EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IIOException.class)
|
||||||
|
public void testFromTruncatedJPEG() throws IOException {
|
||||||
|
List<TIFFEntry> entries = Arrays.asList(
|
||||||
|
new TIFFEntry(TIFF.TAG_COMPRESSION, 6),
|
||||||
|
new TIFFEntry(TIFF.TAG_JPEG_INTERCHANGE_FORMAT, 0)
|
||||||
|
);
|
||||||
|
EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ThumbnailReader createReader(final ImageInputStream stream) throws IOException {
|
protected ThumbnailReader createReader(final ImageInputStream stream) throws IOException {
|
||||||
List<JPEGSegment> segments = JPEGSegmentUtil.readSegments(stream, JPEG.APP1, "Exif");
|
List<JPEGSegment> segments = JPEGSegmentUtil.readSegments(stream, JPEG.APP1, "Exif");
|
||||||
@ -74,7 +230,7 @@ public class EXIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
|||||||
new DataInputStream(data).readFully(exifData);
|
new DataInputStream(data).readFully(exifData);
|
||||||
|
|
||||||
EXIF exif = new EXIF(exifData);
|
EXIF exif = new EXIF(exifData);
|
||||||
return EXIFThumbnail.from(exif, (CompoundDirectory) new TIFFReader().read(exif.exifData()), thumbnailReader, listener);
|
return EXIFThumbnail.from(exif, (CompoundDirectory) new TIFFReader().read(exif.exifData()), thumbnailReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -102,4 +258,10 @@ public class EXIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
|||||||
assertEquals(80, thumbnail.getWidth());
|
assertEquals(80, thumbnail.getWidth());
|
||||||
assertEquals(60, thumbnail.getHeight());
|
assertEquals(60, thumbnail.getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class EXIFDirectory extends AbstractCompoundDirectory {
|
||||||
|
public EXIFDirectory(IFD... ifds) {
|
||||||
|
super(Arrays.asList(ifds));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
@ -43,7 +44,6 @@ import java.io.IOException;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JFIFThumbnailReaderTest
|
* JFIFThumbnailReaderTest
|
||||||
@ -64,44 +64,34 @@ public class JFIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
|||||||
|
|
||||||
JPEGSegment segment = segments.get(0);
|
JPEGSegment segment = segments.get(0);
|
||||||
|
|
||||||
return JFIFThumbnail.from(JFIF.read(new DataInputStream(segment.segmentData()), segment.segmentLength()), listener);
|
return JFIFThumbnail.from(JFIF.read(new DataInputStream(segment.segmentData()), segment.segmentLength()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFromNull() {
|
public void testFromNull() throws IOException {
|
||||||
assertNull(JFIFThumbnail.from(null, listener));
|
assertNull(JFIFThumbnail.from(null));
|
||||||
|
|
||||||
verify(listener, never()).warningOccurred(anyString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFromNullThumbnail() {
|
public void testFromNullThumbnail() throws IOException {
|
||||||
assertNull(JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 0, 0, null), listener));
|
assertNull(JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 0, 0, null)));
|
||||||
|
|
||||||
verify(listener, never()).warningOccurred(anyString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFromEmpty() {
|
public void testFromEmpty() throws IOException {
|
||||||
assertNull(JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 0, 0, new byte[0]), listener));
|
assertNull(JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 0, 0, new byte[0])));
|
||||||
|
|
||||||
verify(listener, never()).warningOccurred(anyString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IIOException.class)
|
||||||
public void testFromTruncated() {
|
public void testFromTruncated() throws IOException {
|
||||||
assertNull(JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 255, 170, new byte[99]), listener));
|
JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 255, 170, new byte[99]));
|
||||||
|
|
||||||
verify(listener, only()).warningOccurred(anyString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFromValid() throws IOException {
|
public void testFromValid() throws IOException {
|
||||||
ThumbnailReader reader = JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 30, 20, new byte[30 * 20 * 3]), listener);
|
ThumbnailReader reader = JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 30, 20, new byte[30 * 20 * 3]));
|
||||||
assertNotNull(reader);
|
assertNotNull(reader);
|
||||||
|
|
||||||
verify(listener, never()).warningOccurred(anyString());
|
|
||||||
|
|
||||||
// Sanity check below
|
// Sanity check below
|
||||||
assertEquals(30, reader.getWidth());
|
assertEquals(30, reader.getWidth());
|
||||||
assertEquals(20, reader.getHeight());
|
assertEquals(20, reader.getHeight());
|
||||||
|
@ -37,6 +37,7 @@ import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
|||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.ImageReader;
|
import javax.imageio.ImageReader;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
@ -46,8 +47,6 @@ import java.io.IOException;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Matchers.anyString;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JFXXThumbnailReaderTest
|
* JFXXThumbnailReaderTest
|
||||||
@ -60,7 +59,7 @@ public class JFXXThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
|||||||
private final ImageReader thumbnailReader = ImageIO.getImageReadersByFormatName("jpeg").next();
|
private final ImageReader thumbnailReader = ImageIO.getImageReadersByFormatName("jpeg").next();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ThumbnailReader createReader(ImageInputStream stream) throws IOException {
|
protected ThumbnailReader createReader(final ImageInputStream stream) throws IOException {
|
||||||
List<JPEGSegment> segments = JPEGSegmentUtil.readSegments(stream, JPEG.APP0, "JFXX");
|
List<JPEGSegment> segments = JPEGSegmentUtil.readSegments(stream, JPEG.APP0, "JFXX");
|
||||||
stream.close();
|
stream.close();
|
||||||
|
|
||||||
@ -68,7 +67,7 @@ public class JFXXThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
|||||||
assertFalse(segments.isEmpty());
|
assertFalse(segments.isEmpty());
|
||||||
|
|
||||||
JPEGSegment jfxx = segments.get(0);
|
JPEGSegment jfxx = segments.get(0);
|
||||||
return JFXXThumbnail.from(JFXX.read(new DataInputStream(jfxx.segmentData()), jfxx.length()), thumbnailReader, listener);
|
return JFXXThumbnail.from(JFXX.read(new DataInputStream(jfxx.segmentData()), jfxx.length()), thumbnailReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -77,51 +76,41 @@ public class JFXXThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFromNull() {
|
public void testFromNull() throws IOException {
|
||||||
assertNull(JFXXThumbnail.from(null, thumbnailReader, listener));
|
assertNull(JFXXThumbnail.from(null, thumbnailReader));
|
||||||
|
|
||||||
verify(listener, never()).warningOccurred(anyString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IIOException.class)
|
||||||
public void testFromNullThumbnail() {
|
public void testFromNullThumbnail() throws IOException {
|
||||||
assertNull(JFXXThumbnail.from(new JFXX(JFXX.JPEG, null), thumbnailReader, listener));
|
JFXXThumbnail.from(new JFXX(JFXX.JPEG, null), thumbnailReader);
|
||||||
|
|
||||||
verify(listener, only()).warningOccurred(anyString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IIOException.class)
|
||||||
public void testFromEmpty() {
|
public void testFromEmpty() throws IOException {
|
||||||
assertNull(JFXXThumbnail.from(new JFXX(JFXX.JPEG, new byte[0]), thumbnailReader, listener));
|
JFXXThumbnail.from(new JFXX(JFXX.JPEG, new byte[0]), thumbnailReader);
|
||||||
|
|
||||||
verify(listener, only()).warningOccurred(anyString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IIOException.class)
|
||||||
public void testFromTruncatedJPEG() {
|
public void testFromTruncatedJPEG() throws IOException {
|
||||||
assertNull(JFXXThumbnail.from(new JFXX(JFXX.JPEG, new byte[99]), thumbnailReader, listener));
|
JFXXThumbnail.from(new JFXX(JFXX.JPEG, new byte[99]), thumbnailReader);
|
||||||
|
|
||||||
verify(listener, only()).warningOccurred(anyString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IIOException.class)
|
||||||
public void testFromTruncatedRGB() {
|
public void testFromTruncatedRGB() throws IOException {
|
||||||
byte[] thumbnail = new byte[765];
|
byte[] thumbnail = new byte[765];
|
||||||
thumbnail[0] = (byte) 160;
|
thumbnail[0] = (byte) 160;
|
||||||
thumbnail[1] = 90;
|
thumbnail[1] = 90;
|
||||||
assertNull(JFXXThumbnail.from(new JFXX(JFXX.RGB, thumbnail), thumbnailReader, listener));
|
|
||||||
|
|
||||||
verify(listener, only()).warningOccurred(anyString());
|
JFXXThumbnail.from(new JFXX(JFXX.RGB, thumbnail), thumbnailReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = IIOException.class)
|
||||||
public void testFromTruncatedIndexed() {
|
public void testFromTruncatedIndexed() throws IOException {
|
||||||
byte[] thumbnail = new byte[365];
|
byte[] thumbnail = new byte[365];
|
||||||
thumbnail[0] = (byte) 160;
|
thumbnail[0] = (byte) 160;
|
||||||
thumbnail[1] = 90;
|
thumbnail[1] = 90;
|
||||||
assertNull(JFXXThumbnail.from(new JFXX(JFXX.INDEXED, thumbnail), thumbnailReader, listener));
|
|
||||||
|
|
||||||
verify(listener, only()).warningOccurred(anyString());
|
JFXXThumbnail.from(new JFXX(JFXX.INDEXED, thumbnail), thumbnailReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -129,11 +118,9 @@ public class JFXXThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
|||||||
byte[] thumbnail = new byte[14];
|
byte[] thumbnail = new byte[14];
|
||||||
thumbnail[0] = 2;
|
thumbnail[0] = 2;
|
||||||
thumbnail[1] = 2;
|
thumbnail[1] = 2;
|
||||||
ThumbnailReader reader = JFXXThumbnail.from(new JFXX(JFXX.RGB, thumbnail), thumbnailReader, listener);
|
ThumbnailReader reader = JFXXThumbnail.from(new JFXX(JFXX.RGB, thumbnail), thumbnailReader);
|
||||||
assertNotNull(reader);
|
assertNotNull(reader);
|
||||||
|
|
||||||
verify(listener, never()).warningOccurred(anyString());
|
|
||||||
|
|
||||||
// Sanity check below
|
// Sanity check below
|
||||||
assertEquals(2, reader.getWidth());
|
assertEquals(2, reader.getWidth());
|
||||||
assertEquals(2, reader.getHeight());
|
assertEquals(2, reader.getHeight());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user