#573: Always return RAWImageType for JPEG.

+ Bonus: Fix luma to gray conversion
This commit is contained in:
Harald Kuhr
2021-04-10 11:44:09 +02:00
parent b67975eef7
commit 419ffc9373
7 changed files with 340 additions and 126 deletions
@@ -63,7 +63,7 @@ public class FastCMYKToRGBTest {
assertNotNull(pixel);
assertEquals(3, pixel.length);
byte[] expected = {(byte) 255, (byte) 255, (byte) 255};
assertTrue(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), Arrays.equals(expected, pixel));
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
}
@Test
@@ -95,7 +95,7 @@ public class FastCMYKToRGBTest {
assertNotNull(pixel);
assertEquals(3, pixel.length);
byte[] expected = {(byte) 0, (byte) 0, (byte) 0};
assertTrue(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), Arrays.equals(expected, pixel));
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
}
}
@@ -134,7 +134,7 @@ public class FastCMYKToRGBTest {
assertNotNull(pixel);
assertEquals(3, pixel.length);
byte[] expected = {(byte) (255 - i), (byte) i, (byte) (127 - i)};
assertTrue(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), Arrays.equals(expected, pixel));
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
}
}
@@ -153,7 +153,7 @@ public class FastCMYKToRGBTest {
assertNotNull(pixel);
assertEquals(3, pixel.length);
byte[] expected = {(byte) (255 - i), (byte) i, (byte) (127 - i)};
assertTrue(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), Arrays.equals(expected, pixel));
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
}
}
@@ -172,7 +172,7 @@ public class FastCMYKToRGBTest {
assertNotNull(pixel);
assertEquals(4, pixel.length);
byte[] expected = {(byte) (255 - i), (byte) i, (byte) (127 - i), (byte) 0xff};
assertTrue(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), Arrays.equals(expected, pixel));
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
}
}
@@ -31,6 +31,7 @@
package com.twelvemonkeys.imageio.plugins.jpeg;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.lang.StringUtil;
import org.hamcrest.core.IsInstanceOf;
@@ -55,6 +56,7 @@ import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.io.*;
import java.util.List;
@@ -140,11 +142,6 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
// More test data in specific tests below
}
@Override
protected boolean allowsNullRawImageType() {
return true;
}
@Override
protected List<String> getFormatNames() {
return Arrays.asList("JPEG", "jpeg", "JPG", "jpg",
@@ -422,8 +419,8 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
}
@Test
public void testYCbCrNotSubsampledNonstandardChannelIndexes() throws IOException {
// Regression: Make sure 3 channel, non-subsampled JFIF, defaults to YCbCr, even if unstandard channel indexes
public void testYCbCrNotSubsampledNonstandardComponentIds() throws IOException {
// Regression: Make sure 3 channel, non-subsampled JFIF, defaults to YCbCr, even if nonstandard component ids
JPEGImageReader reader = createReader();
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/jfif-ycbcr-no-subsampling-intel.jpg"))) {
reader.setInput(stream);
@@ -1235,6 +1232,56 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
}
}
@Test
public void testRGBANoGrayImageTypes() throws IOException {
JPEGImageReader reader = createReader();
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/adobe-unknown-rgb-ids.jpg")));
Iterator<ImageTypeSpecifier> imageTypes = reader.getImageTypes(0);
while (imageTypes.hasNext()) {
ImageTypeSpecifier specifier = imageTypes.next();
assertNotEquals("RGB JPEGs can't be decoded as Gray as it has no luminance (Y) component", ColorSpace.TYPE_GRAY, specifier.getColorModel().getColorSpace().getType());
}
reader.dispose();
}
@Test(expected = Exception.class)
public void testRGBAsGray() throws IOException {
final JPEGImageReader reader = createReader();
try {
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/adobe-unknown-rgb-ids.jpg")));
assertEquals(225, reader.getWidth(0));
assertEquals(156, reader.getHeight(0));
final ImageReadParam param = reader.getDefaultReadParam();
param.setSourceRegion(new Rectangle(0, 0, 225, 8));
param.setDestinationType(ImageTypeSpecifiers.createGrayscale(8, DataBuffer.TYPE_BYTE));
// Should ideally throw IIOException due to destination type mismatch, but throws IllegalArgumentException...
reader.read(0, param);
}
finally {
reader.dispose();
}
}
@Test
public void testYCbCrAsGray() throws IOException {
JPEGImageReader reader = createReader();
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/jfif-ycbcr-no-subsampling-intel.jpg")));
ImageReadParam param = reader.getDefaultReadParam();
param.setDestinationType(ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY));
BufferedImage image = reader.read(0, param);
assertNotNull(image);
assertEquals(BufferedImage.TYPE_BYTE_GRAY, image.getType());
}
/**
* Slightly fuzzy RGB equals method. Tolerance +/-5 steps.
*/
@@ -1818,7 +1865,7 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
reader.setInput(ImageIO.createImageInputStream(getClassLoaderResource("/jpeg/exif-jfif-app13-app14ycck-3channel.jpg")));
ImageTypeSpecifier rawType = reader.getRawImageType(0);
assertNull(rawType); // But no exception, please...
assertNotNull(rawType); // As of Java 9, use RGB for YCC and CMYK for YCCK
}
finally {
reader.dispose();
@@ -0,0 +1,79 @@
package com.twelvemonkeys.imageio.plugins.jpeg;
import org.junit.Test;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.util.Arrays;
import static org.junit.Assert.*;
/**
* LumaToGrayTest.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haraldk$
* @version $Id: LumaToGrayTest.java,v 1.0 10/04/2021 haraldk Exp$
*/
public class LumaToGrayTest {
@Test
public void testConvertByteYcc() {
LumaToGray convert = new LumaToGray();
WritableRaster input = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 1, 1, 3, null);
WritableRaster result = null;
byte[] pixel = null;
for (int i = 0; i < 255; i++) {
input.setDataElements(0, 0, new byte[] {(byte) i, (byte) (255 - i), (byte) (127 + i)});
result = convert.filter(input, result);
pixel = (byte[]) result.getDataElements(0, 0, pixel);
assertNotNull(pixel);
assertEquals(1, pixel.length);
byte[] expected = {(byte) i};
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
}
}
@Test
public void testConvertByteYccK() {
LumaToGray convert = new LumaToGray();
WritableRaster input = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 1, 1, 4, null);
WritableRaster result = null;
byte[] pixel = null;
for (int i = 0; i < 255; i++) {
input.setDataElements(0, 0, new byte[] {(byte) i, (byte) (255 - i), (byte) (127 + i), (byte) 255});
result = convert.filter(input, result);
pixel = (byte[]) result.getDataElements(0, 0, pixel);
assertNotNull(pixel);
assertEquals(1, pixel.length);
byte[] expected = {(byte) i};
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
}
}
@Test
public void testConvertByteYccA() {
LumaToGray convert = new LumaToGray();
WritableRaster input = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 1, 1, 4, null);
WritableRaster result = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 1, 1, 2, null);
byte[] pixel = null;
for (int i = 0; i < 255; i++) {
input.setDataElements(0, 0, new byte[] {(byte) i, (byte) 255, (byte) (127 + i), (byte) (255 - i)});
result = convert.filter(input, result);
pixel = (byte[]) result.getDataElements(0, 0, pixel);
assertNotNull(pixel);
assertEquals(2, pixel.length);
byte[] expected = {(byte) i, (byte) (255 - i)};
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
}
}
}