-
Bug
-
Resolution: Unresolved
-
P4
-
8, 11, 17, 21, 23, 24, 25
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
It occurs both on Java 8 and Java 23
A DESCRIPTION OF THE PROBLEM :
While an 8-bit greyscale image is recognized correctly, a 4-bit greyscale image (created using: magick test.png -depth 4 -colorspace gray -define png:color-type=0 -define png:bit-depth=4 test.grey.converted-4bit.png)
is recognized as RGB.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a 4-bit grey scale image using Image Magick (starting with an arbitrary color test.png):
magick test.png -depth 4 -colorspace gray -define png:color-type=0 -define png:bit-depth=4 test.grey.converted-4bit.png
2. Execute the code provided in Test Case Code field below.
It shows that ImageReader.getRawImageType(...).getColorModel().getColorSpace().getType() returned 5 (=RGB) instead of the expected 6 (=GRAY).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
17:58:15.942 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - ImageIO.createImageInputStream(/test.grey.converted-4bit.png)
17:58:16.034 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - rawImageType.getColorModel().getColorSpace().getType(): 6 (5=RGB, 6=GRAY, 3=YCbCr)
...
ACTUAL -
17:58:15.942 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - ImageIO.createImageInputStream(/test.grey.converted-4bit.png)
17:58:16.034 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - rawImageType.getColorModel().getColorSpace().getType(): 5 (5=RGB, 6=GRAY, 3=YCbCr)
...
---------- BEGIN SOURCE ----------
ColorSpaceRecognition.java:
package com.mycompany.colorspace.test;
import com.google.common.io.ByteStreams;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.stream.ImageInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ColorSpaceRecognition {
private static final Logger logger = LoggerFactory.getLogger(ColorSpaceRecognition.class);
public static void main(String[] args) throws IOException {
// exported from Gimp as grey 8bit, recognized correctly as Grey
// printColorSpaceInfos("/test.grey.8bit.png");
// magick test.png -depth 4 -colorspace gray -define png:color-type=0 -define png:bit-depth=4 test.grey.converted-4bit.png
printColorSpaceInfos("/test.grey.converted-4bit.png");
}
private static void printColorSpaceInfos(String resourceName) throws IOException {
printRawColorSpace(resourceName);
printNonRawColorSpace(resourceName);
}
private static void printNonRawColorSpace(String resourceName) throws IOException {
logger.debug("ImageIO.read({})", resourceName);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(getResourceAsBytes(resourceName)));
if (image == null) {
throw new RuntimeException("image format not supported");
}
logger.debug(" image.getColorModel().getColorSpace().getType(): {} ({}=RGB, {}=GRAY, {}=YCbCr)",
image.getColorModel().getColorSpace().getType(), ColorSpace.TYPE_RGB, ColorSpace.TYPE_GRAY, ColorSpace.TYPE_YCbCr);
logger.debug(" image.getType(): {}", image.getType());
logger.debug(" image.getColorModel().getPixelSize(): {}",
image.getColorModel().getPixelSize());
logger.debug(" image.getColorModel().getNumColorComponents(): {}",
image.getColorModel().getNumColorComponents());
logger.debug(" image.getColorModel().getComponentSize().length: {}",
image.getColorModel().getComponentSize().length);
for (int i = 0; i < image.getColorModel().getComponentSize().length; i++) {
logger.debug(" image.getColorModel().getComponentSize()[{}]: {}", i,
image.getColorModel().getComponentSize()[i]);
}
logger.debug(" image.getColorModel().getColorSpace().isCS_sRGB(): {}",
image.getColorModel().getColorSpace().isCS_sRGB());
logger.debug(" image.getSampleModel().getNumBands(): {}",
image.getSampleModel().getNumBands());
}
private static void printRawColorSpace(String resourceName) throws IOException {
logger.debug("ImageIO.createImageInputStream({})", resourceName);
try (ImageInputStream input
= ImageIO.createImageInputStream(new ByteArrayInputStream(getResourceAsBytes(resourceName)))) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
if (!readers.hasNext()) {
throw new RuntimeException("image format not supported");
} else {
ImageReader reader = readers.next();
try {
reader.setInput(input);
ImageTypeSpecifier rawImageType = reader.getRawImageType(0);
if (rawImageType == null) {
logger.debug(" rawImageType: null");
} else {
logger.debug(" rawImageType.getColorModel().getColorSpace().getType(): {} ({}=RGB, {}=GRAY, {}=YCbCr)",
rawImageType.getColorModel().getColorSpace().getType(), ColorSpace.TYPE_RGB, ColorSpace.TYPE_GRAY, ColorSpace.TYPE_YCbCr);
logger.debug(" rawImageType.getColorModel().getPixelSize(): {}",
rawImageType.getColorModel().getPixelSize());
logger.debug(" rawImageType.getColorModel().getNumColorComponents(): {}",
rawImageType.getColorModel().getNumColorComponents());
logger.debug(" rawImageType.getColorModel().getComponentSize().length: {}",
rawImageType.getColorModel().getComponentSize().length);
for (int i = 0; i < rawImageType.getColorModel().getComponentSize().length; i++) {
logger.debug(" rawImageType.getColorModel().getComponentSize()[{}]: {}", i,
rawImageType.getColorModel().getComponentSize()[i]);
}
logger.debug(" rawImageType.getColorModel().getColorSpace().isCS_sRGB(): {}",
rawImageType.getColorModel().getColorSpace().isCS_sRGB());
}
} finally {
reader.dispose();
}
}
}
}
private static byte[] getResourceAsBytes(String resourceName) {
return getResourceAsBytes(resourceName, ColorSpaceRecognition.class);
}
private static byte[] getResourceAsBytes(String resourceName, Class<?> clazz) {
try (InputStream in = clazz.getResourceAsStream(resourceName)) {
if (in == null) {
throw new RuntimeException("Resource '" + resourceName
+ "' could not be loaded with ClassLoader for " + clazz.getCanonicalName());
}
return ByteStreams.toByteArray(in);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>colorspace-test-greyscale</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>colorspace-test-greyscale</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<exec.mainClass>com.mycompany.colorspace.test.ColorSpaceRecognition</exec.mainClass>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
</dependencies>
</project>
---------- END SOURCE ----------
It occurs both on Java 8 and Java 23
A DESCRIPTION OF THE PROBLEM :
While an 8-bit greyscale image is recognized correctly, a 4-bit greyscale image (created using: magick test.png -depth 4 -colorspace gray -define png:color-type=0 -define png:bit-depth=4 test.grey.converted-4bit.png)
is recognized as RGB.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a 4-bit grey scale image using Image Magick (starting with an arbitrary color test.png):
magick test.png -depth 4 -colorspace gray -define png:color-type=0 -define png:bit-depth=4 test.grey.converted-4bit.png
2. Execute the code provided in Test Case Code field below.
It shows that ImageReader.getRawImageType(...).getColorModel().getColorSpace().getType() returned 5 (=RGB) instead of the expected 6 (=GRAY).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
17:58:15.942 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - ImageIO.createImageInputStream(/test.grey.converted-4bit.png)
17:58:16.034 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - rawImageType.getColorModel().getColorSpace().getType(): 6 (5=RGB, 6=GRAY, 3=YCbCr)
...
ACTUAL -
17:58:15.942 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - ImageIO.createImageInputStream(/test.grey.converted-4bit.png)
17:58:16.034 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - rawImageType.getColorModel().getColorSpace().getType(): 5 (5=RGB, 6=GRAY, 3=YCbCr)
...
---------- BEGIN SOURCE ----------
ColorSpaceRecognition.java:
package com.mycompany.colorspace.test;
import com.google.common.io.ByteStreams;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.stream.ImageInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ColorSpaceRecognition {
private static final Logger logger = LoggerFactory.getLogger(ColorSpaceRecognition.class);
public static void main(String[] args) throws IOException {
// exported from Gimp as grey 8bit, recognized correctly as Grey
// printColorSpaceInfos("/test.grey.8bit.png");
// magick test.png -depth 4 -colorspace gray -define png:color-type=0 -define png:bit-depth=4 test.grey.converted-4bit.png
printColorSpaceInfos("/test.grey.converted-4bit.png");
}
private static void printColorSpaceInfos(String resourceName) throws IOException {
printRawColorSpace(resourceName);
printNonRawColorSpace(resourceName);
}
private static void printNonRawColorSpace(String resourceName) throws IOException {
logger.debug("ImageIO.read({})", resourceName);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(getResourceAsBytes(resourceName)));
if (image == null) {
throw new RuntimeException("image format not supported");
}
logger.debug(" image.getColorModel().getColorSpace().getType(): {} ({}=RGB, {}=GRAY, {}=YCbCr)",
image.getColorModel().getColorSpace().getType(), ColorSpace.TYPE_RGB, ColorSpace.TYPE_GRAY, ColorSpace.TYPE_YCbCr);
logger.debug(" image.getType(): {}", image.getType());
logger.debug(" image.getColorModel().getPixelSize(): {}",
image.getColorModel().getPixelSize());
logger.debug(" image.getColorModel().getNumColorComponents(): {}",
image.getColorModel().getNumColorComponents());
logger.debug(" image.getColorModel().getComponentSize().length: {}",
image.getColorModel().getComponentSize().length);
for (int i = 0; i < image.getColorModel().getComponentSize().length; i++) {
logger.debug(" image.getColorModel().getComponentSize()[{}]: {}", i,
image.getColorModel().getComponentSize()[i]);
}
logger.debug(" image.getColorModel().getColorSpace().isCS_sRGB(): {}",
image.getColorModel().getColorSpace().isCS_sRGB());
logger.debug(" image.getSampleModel().getNumBands(): {}",
image.getSampleModel().getNumBands());
}
private static void printRawColorSpace(String resourceName) throws IOException {
logger.debug("ImageIO.createImageInputStream({})", resourceName);
try (ImageInputStream input
= ImageIO.createImageInputStream(new ByteArrayInputStream(getResourceAsBytes(resourceName)))) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
if (!readers.hasNext()) {
throw new RuntimeException("image format not supported");
} else {
ImageReader reader = readers.next();
try {
reader.setInput(input);
ImageTypeSpecifier rawImageType = reader.getRawImageType(0);
if (rawImageType == null) {
logger.debug(" rawImageType: null");
} else {
logger.debug(" rawImageType.getColorModel().getColorSpace().getType(): {} ({}=RGB, {}=GRAY, {}=YCbCr)",
rawImageType.getColorModel().getColorSpace().getType(), ColorSpace.TYPE_RGB, ColorSpace.TYPE_GRAY, ColorSpace.TYPE_YCbCr);
logger.debug(" rawImageType.getColorModel().getPixelSize(): {}",
rawImageType.getColorModel().getPixelSize());
logger.debug(" rawImageType.getColorModel().getNumColorComponents(): {}",
rawImageType.getColorModel().getNumColorComponents());
logger.debug(" rawImageType.getColorModel().getComponentSize().length: {}",
rawImageType.getColorModel().getComponentSize().length);
for (int i = 0; i < rawImageType.getColorModel().getComponentSize().length; i++) {
logger.debug(" rawImageType.getColorModel().getComponentSize()[{}]: {}", i,
rawImageType.getColorModel().getComponentSize()[i]);
}
logger.debug(" rawImageType.getColorModel().getColorSpace().isCS_sRGB(): {}",
rawImageType.getColorModel().getColorSpace().isCS_sRGB());
}
} finally {
reader.dispose();
}
}
}
}
private static byte[] getResourceAsBytes(String resourceName) {
return getResourceAsBytes(resourceName, ColorSpaceRecognition.class);
}
private static byte[] getResourceAsBytes(String resourceName, Class<?> clazz) {
try (InputStream in = clazz.getResourceAsStream(resourceName)) {
if (in == null) {
throw new RuntimeException("Resource '" + resourceName
+ "' could not be loaded with ClassLoader for " + clazz.getCanonicalName());
}
return ByteStreams.toByteArray(in);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>colorspace-test-greyscale</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>colorspace-test-greyscale</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<exec.mainClass>com.mycompany.colorspace.test.ColorSpaceRecognition</exec.mainClass>
</properties>
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
</dependencies>
</project>
---------- END SOURCE ----------