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

BMPMetadata returns invalid PhysicalPixelSpacing

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 9
    • 7
    • client-libs
    • b92
    • x86
    • windows_7

        FULL PRODUCT VERSION :
        java version "1.7.0_05"
        Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
        Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows [versão 6.1.7601]

        A DESCRIPTION OF THE PROBLEM :
        I`m using the default BMP plugin (com.sun.imageio.plugins.bmp.BMPImageReader) to read BMP images, and I need to get the resolution information from it`s the metadata (com.sun.imageio.plugins.bmp.BMPMetadata).

        When I navigate the Standard Metadata Tree (javax_imageio_1.0 / Dimension / VerticalPhysicalPixelSpacing -or- javax_imageio_1.0 / Dimension / HorizontalPhysicalPixelSpacing), the pixel sizes are always set to zero.

        I have checked the source code, and I found the bug in the method BMPMetadata.getStandardDimensionNode():

        subNode = new IIOMetadataNode("HorizontalPhysicalPixelSpacing");
        subNode.setAttribute("value", "" + (1 / xPixelsPerMeter * 1000));
        node.appendChild(subNode);

        subNode = new IIOMetadataNode("VerticalPhysicalPixelSpacing");
        subNode.setAttribute("value", "" + (1 / yPixelsPerMeter * 1000));
        node.appendChild(subNode);


        Essentially, the integer division (1 / xPixelsPerMeter) truncates the result, returning zero. It must be perform the calculation with floating point.

        I suggest rewriting it as:
        subNode.setAttribute("value", "" + (1000.0 / xPixelsPerMeter));
        subNode.setAttribute("value", "" + (1000.0 / yPixelsPerMeter));

        Apparently this bug has been around un-noticed for a long time, all versions of the BMPMetadata source found have the same bug.


        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Just use ImageIO to read the Standard Metadata from a BMP file.
        A sample is provided to display the Standard Metadata Tree from a file called "image.bmp"

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        For a 500-DPI image, I expected to get the following pixel dimension nodes:
        <....>
        <HorizontalPhysicalPixelSpacing value="0.05"/>
        <VerticalPhysicalPixelSpacing value="0.05"/>
        <....>
        ACTUAL -
        <....>
        <HorizontalPhysicalPixelSpacing value="0"/>
        <VerticalPhysicalPixelSpacing value="0"/>
        <....>

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.io.FileInputStream;
        import java.io.InputStream;
        import java.util.Iterator;

        import javax.imageio.ImageIO;
        import javax.imageio.ImageReader;
        import javax.imageio.metadata.IIOMetadata;
        import javax.imageio.stream.ImageInputStream;

        import org.w3c.dom.NamedNodeMap;
        import org.w3c.dom.Node;
        import org.w3c.dom.NodeList;

        public class BMPMetadataTest {
        public static void printTree(Node doc, int ident) {
        for (int i=0; i<ident; i++)
        System.out.print("\t");
        System.out.print("<"+doc.getNodeName());
        NamedNodeMap cl = doc.getAttributes();
        for (int i = 0; i < cl.getLength(); i++) {
        Node node = cl.item(i);
        System.out.print(" " + node.getNodeName() + "=\"" + node.getNodeValue() + "\"");
        }
        NodeList nl = doc.getChildNodes();
        if (nl.getLength()==0) {
        System.out.println("/>");
        } else {
        System.out.println(">");
        for (int i = 0; i < nl.getLength(); i++) {
        Node node = nl.item(i);
        printTree(node, ident+1);
        }
        for (int i=0; i<ident; i++)
        System.out.print("\t");
        System.out.println("</"+doc.getNodeName()+">");
        }
        }

        public static void ShowBMPMetadata(InputStream inputStream) throws Exception {
        ImageInputStream imageInput = ImageIO.createImageInputStream(inputStream);
        for (Iterator<ImageReader> it = ImageIO.getImageReaders(imageInput); it.hasNext(); ) {
        ImageReader reader = it.next();
        reader.setInput(imageInput);
        IIOMetadata metadata = reader.getImageMetadata(0);
        Node rootNode = metadata.getAsTree("javax_imageio_1.0");
        printTree(rootNode, 0);
        }
        }

        public static void main(String[] args) throws Exception {
        ShowBMPMetadata(new FileInputStream("image.bmp"));
        }
        }

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

        CUSTOMER SUBMITTED WORKAROUND :
        I have provided a fix in the description, but it is difficult to "workaround" it - Specially considering I didn't plan to write BMP-specific code

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

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: