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

[macosx] JPEGImageReader incorrectly identifies YCbCr JPEGs as RGB in standard metadata

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 9
    • 8u25
    • client-libs
    • b100
    • x86
    • os_x

      FULL PRODUCT VERSION :
      java version "1.8.0_25"
      Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
      Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      OS X Yosemite, 10.10.2 (14C109)
      However, this bug is NOT OS related.


      A DESCRIPTION OF THE PROBLEM :
      The class com.sun.imageio.plugins.jpeg.JPEGMetadata contains the following code in the getStandardChromaNode() method (lines 872-887 in my version, comments by me), that is clearly incorrect from reading the source, as n unique ids can never fit in the range [1...n-1] (also detected in test program below).

              boolean idsAreJFIF = true;

              for (int i = 0; i < sof.componentSpecs.length; i++) {
                  int id = sof.componentSpecs[i].componentId;
                  if ((id < 1) || (id >= sof.componentSpecs.length)) { // <-- limits n ids to range [1...n-1]
                      idsAreJFIF = false;
                  }
              }

              if (idsAreJFIF) { // <-- Can never be true
                  csType.setAttribute("name", "YCbCr");
                  if (numChannels == 4) {
                      hasAlpha = true;
                  }
                  return chroma;
              }

      The code above will only return YCbCr color space if the SOF segment contains duplicate component ids, but this will only happen in broken files, and probably should not be allowed.

      Instead, the code should test for less than 1 or greater than sof.compSpecs.length, like this:

                  if ((id < 1) || (id > sof.componentSpecs.length)) {
                      idsAreJFIF = false;
                  }


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Download sample files in YCbCr format, that are not JFIF JPEGs (the first is an Exif file, the second file is neither Exif nor JFIF)
      https://github.com/haraldk/TwelveMonkeys/blob/master/imageio/imageio-jpeg/src/test/resources/jpeg/exif-rgb-thumbnail-sony-d700.jpghttps://github.com/haraldk/TwelveMonkeys/blob/master/imageio/imageio-jpeg/src/test/resources/jpeg/no-jfif-ycbcr.jpg

      2. Compile and run the submitted code (under "Source code for an executable test case").

      3. Observe the program output (see "Expected Result" vs "Actual Result").

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The program should output:

      reader: class com.sun.imageio.plugins.jpeg.JPEGImageReader
      metadata: class com.sun.imageio.plugins.jpeg.JPEGMetadata
      colorSpaceType.getAttribute("name"): YCbCr
      ACTUAL -
      The program outputs:

      reader: class com.sun.imageio.plugins.jpeg.JPEGImageReader
      metadata: class com.sun.imageio.plugins.jpeg.JPEGMetadata
      colorSpaceType.getAttribute("name"): RGB

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import javax.imageio.ImageIO;
      import javax.imageio.ImageReader;
      import javax.imageio.metadata.IIOMetadata;
      import javax.imageio.metadata.IIOMetadataFormatImpl;
      import javax.imageio.metadata.IIOMetadataNode;
      import javax.imageio.stream.ImageInputStream;
      import java.io.File;
      import java.io.IOException;

      public class JPEGStandardMetadataBug {
          public static void main(String[] args) throws IOException {
              ImageInputStream stream = ImageIO.createImageInputStream(new File(args[0]));
              ImageReader reader = ImageIO.getImageReaders(stream).next();
              reader.setInput(stream);
              IIOMetadata metadata = reader.getImageMetadata(0);

              System.out.println("reader: " + reader.getClass());
              System.out.println("metadata: " + metadata.getClass());

              IIOMetadataNode standardTree = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
              IIOMetadataNode colorSpaceType = (IIOMetadataNode) standardTree.getElementsByTagName("ColorSpaceType").item(0);

              System.out.println("colorSpaceType.getAttribute(\"name\"): " + colorSpaceType.getAttribute("name"));
          }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      None found so far.

      (One could parse the stream again, inspecting the JPEG segments and re-creating the metadata from scratch, that is however, quite a bit of work, and not viable at the moment).

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

              Created:
              Updated:
              Resolved: