#326: Support for JFIF JPEG with non-spec 8 bit grayscale thumbnail.

This commit is contained in:
Harald Kuhr 2017-02-27 20:58:23 +01:00
parent d8d179204f
commit 97cd8a955f
5 changed files with 31 additions and 7 deletions

View File

@ -30,7 +30,9 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
import java.io.*;
import java.io.DataInput;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
@ -111,7 +113,7 @@ final class JFIF extends Application {
buffer.getShort() & 0xffff,
x = buffer.get() & 0xff,
y = buffer.get() & 0xff,
getBytes(buffer, x * y * 3),
getBytes(buffer, Math.min(buffer.remaining(), x * y * 3)),
bytes
);
}

View File

@ -74,8 +74,17 @@ abstract class ThumbnailReader {
static protected BufferedImage readRawThumbnail(final byte[] thumbnail, final int size, final int offset, int w, int h) {
DataBufferByte buffer = new DataBufferByte(thumbnail, size, offset);
WritableRaster raster = Raster.createInterleavedRaster(buffer, w, h, w * 3, 3, new int[] {0, 1, 2}, null);
ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
WritableRaster raster;
ColorModel cm;
if (thumbnail.length == w * h) {
raster = Raster.createInterleavedRaster(buffer, w, h, w, 1, new int[] {0}, null);
cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
}
else {
raster = Raster.createInterleavedRaster(buffer, w, h, w * 3, 3, new int[] {0, 1, 2}, null);
cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
}
return new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
}

View File

@ -41,9 +41,7 @@ import java.io.IOException;
import java.util.List;
import static org.junit.Assert.*;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.*;
/**
* JFIFThumbnailReaderTest
@ -78,6 +76,20 @@ public class JFIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
assertEquals(122, thumbnail.getHeight());
}
@Test
public void testReadNonSpecGray() throws IOException {
ThumbnailReader reader = createReader(mock(ThumbnailReadProgressListener.class), 0, 0, createStream("/jpeg/jfif-grayscale-thumbnail.jpg"));
assertEquals(127, reader.getWidth());
assertEquals(76, reader.getHeight());
BufferedImage thumbnail = reader.read();
assertNotNull(thumbnail);
assertEquals(BufferedImage.TYPE_BYTE_GRAY, thumbnail.getType());
assertEquals(127, thumbnail.getWidth());
assertEquals(76, thumbnail.getHeight());
}
@Test
public void testProgressListenerRaw() throws IOException {
ThumbnailReadProgressListener listener = mock(ThumbnailReadProgressListener.class);

View File

@ -97,6 +97,7 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
new TestData(getClassLoaderResource("/jpeg/jfif-bogus-empty-jfif-segment.jpg"), new Dimension(942, 714)),
new TestData(getClassLoaderResource("/jpeg/app-marker-missing-null-term.jpg"), new Dimension(200, 150)),
new TestData(getClassLoaderResource("/jpeg/jfif-16bit-dqt.jpg"), new Dimension(204, 131)),
new TestData(getClassLoaderResource("/jpeg/jfif-grayscale-thumbnail.jpg"), new Dimension(2547, 1537)), // Non-compliant JFIF with 8 bit grayscale thumbnail
new TestData(getClassLoaderResource("/jpeg-lossless/8_ls.jpg"), new Dimension(800, 535)), // Lossless gray, 8 bit
new TestData(getClassLoaderResource("/jpeg-lossless/16_ls.jpg"), new Dimension(800, 535)), // Lossless gray, 16 bit
new TestData(getClassLoaderResource("/jpeg-lossless/24_ls.jpg"), new Dimension(800, 535)), // Lossless RGB, 8 bit per component (24 bit)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB