Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8352859

Monochome binary images are recognized as RGB instead of grey (or binary)

XMLWordPrintable

      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 as ColorSpace.TYPE_GRAY, an 1-bit monochrome image is recognized as ColorSpace.TYPE_RGB.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Create a binary image (i.e. an image that only contains black and white and no other greyscale values) from a color image as following:
      magick test.24bit.png test.converted.pbm
      magick test.converted.pbm test.converted.monochrome.png
      2. Execute code further below


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      While the BufferedImage.getType() returns 12 which corresponds to BufferedImage.TYPE_BYTE_BINARY, both ImageReader.getRawImageType(...).getColorModel().getColorSpace().getType() returned the same result as ImageIO.read(...).getColorModel().getColorSpace().getType() which is TYPE_RGB.
      More appropriate would be to return ColorSpace.TYPE_GRAY (because like grey images, binary images have only a single color channel).
      (An alternative could be to introduce another enum value which would represent a monochrome binary (i.e. representing only black and white) images).

      ACTUAL -
      ImageReader.getRawImageType(...).getColorModel().getColorSpace().getType() returned the same result as ImageIO.read(...).getColorModel().getColorSpace().getType() which is TYPE_RGB.
      You will seee the following output from the test program in the attached zip:
      16:38:10.751 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - ImageIO.createImageInputStream(/test.converted.monochrome.png)
      16:38:10.927 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - rawImageType.getColorModel().getColorSpace().getType(): 5 (5=RGB, 6=GRAY, 3=YCbCr)
      16:38:10.927 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - rawImageType.getColorModel().getPixelSize(): 1
      16:38:10.927 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - rawImageType.getColorModel().getNumColorComponents(): 3
      ...
      16:38:10.927 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - rawImageType.getColorModel().getColorSpace().isCS_sRGB(): true
      16:38:10.927 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - ImageIO.read(/test.converted.monochrome.png)
      16:38:10.937 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - image.getColorModel().getColorSpace().getType(): 5 (5=RGB, 6=GRAY, 3=YCbCr)
      16:38:10.937 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - image.getType(): 12
      16:38:10.937 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - image.getColorModel().getPixelSize(): 1
      ...
      16:38:10.937 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - image.getColorModel().getColorSpace().isCS_sRGB(): true
      16:38:10.937 [main] DEBUG com.mycompany.colorspace.test.ColorSpaceRecognition - image.getSampleModel().getNumBands(): 1


      ---------- BEGIN SOURCE ----------
      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 {
              // Created using:
              // magick test.24bit.png test.converted.pbm
      // magick test.converted.pbm test.converted.monochrome.png
              printColorSpaceInfos("/test.converted.monochrome.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);
              }
          }
      }

      ---------- END SOURCE ----------

            jdv Jayathirth D V
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: