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

BMPImageReader read error using ImageReadParam with set sourceRectangle

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 7u45, 8, 9
    • Fix Version/s: 9
    • Component/s: client-libs
    • Labels:
    • Subcomponent:
    • Resolved In Build:
      b33
    • CPU:
      x86_64
    • OS:
      windows_7

      Backports

        Description

        FULL PRODUCT VERSION :
        jdk1.7.0_45.zip sources. Runtime used when bag occures:
        java version "1.7.0_45"
        Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
        Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Windows 7 professional, SP1

        EXTRA RELEVANT SYSTEM CONFIGURATION :
        doesnt' matter any hard or soft specifications, pure logical bug due to lack of debugging depth

        A DESCRIPTION OF THE PROBLEM :
        When trying to read some BufferedImage from arbitrarily rectangle from image through using javax.imageio.ImageReader with setting ImageReadParam source read rectangle only 1st call is always sucessfull, all other subsequent ones return invalid colored BufferedImage or even throw EOFException. This bug only occures on BMP rasters reading. JPG and PNG works correctly, GIF format was not tested. ImageReader instance (for BMP) is get by call to javax.imageio.ImageIO.getImageReadersBySuffix( "BMP" ).getNext().

        The problem cause is due to logical bug when in subsequent calls source stream is not positioned to the 1st byte after BMP header as expected by class code logic. To solve this bug, you can insert
        follow code line just before comment line at source file line #780 (in BMPImageReader.java)

                ...
        iis.seek( bitmapOffset ); //++ BUG fix (insert before source line #780)
                // There should only be one tile (line #780).
                switch(imageType) {

                case VERSION_2_1_BIT:
                    // no compression
                    read1Bit(bdata);
                    break;
                ...


        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        1. Get ImageReader for BMP raster format using some image stream
        2. Set rectangle for ImageReadParam (param)
        3. Use param to read part of image at least twice time

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Each read returns requested rectangle from image. So it works for all valid image types except BMP.
        ACTUAL -
        1st read returns requested image rectangle as BufferedImage.
        All subsequent reads returns some strange image or even throw EOFException. It depends on color model of input image. 32 bit BMP usually throw EOFException on 2nd read and follow ones.

        ERROR MESSAGES/STACK TRACES THAT OCCUR :
        java.io.EOFException
        at javax.imageio.stream.ImageInputStreamImpl.readFully(ImageInputStreamImpl.java:353)
        at javax.imageio.stream.ImageInputStreamImpl.readFully(ImageInputStreamImpl.java:405)
        at com.sun.imageio.plugins.bmp.BMPImageReader.read32Bit(BMPImageReader.java:1345)
        at com.sun.imageio.plugins.bmp.BMPImageReader.read(BMPImageReader.java:851)
        at ru.ts.tests.TestImageRectangleRead.main(TestImageRectangleRead.java:67)

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        package tests;

        import javax.imageio.ImageIO;
        import javax.imageio.ImageReadParam;
        import javax.imageio.stream.FileImageInputStream;
        import java.awt.*;
        import java.awt.image.BufferedImage;
        import java.io.File;
        import java.util.Iterator;

        public class TestImageRectangleRead
        {
        public static void main( String[] args )
        {
        System.out.println( "+++ TEST rectangle sub-image API +++" );
        if ( args.length == 0 )
        System.out.println( "Expected file paths not found" );

        javax.imageio.ImageReader reader;

        for ( String path : args )
        {
        System.out.println( "Processing file \"" + path + "\"" );
        try
        {
        File file = new File( path );
        FileImageInputStream iis = new FileImageInputStream( file );

        int pntIndex = path.lastIndexOf( '.' );
        if ( pntIndex < 0 || pntIndex >= path.length() )
        {
        System.err.println( "Input path doesn't have known extension, skipping" );
        continue;
        }
        String ext = path.substring( pntIndex + 1 );
        System.out.println( "Extension is \"" + ext + "\"" );

        // Find corresponding reader
        Iterator iter = ImageIO.getImageReadersBySuffix( ext );
        reader = null;
        if ( iter.hasNext() )
        reader = (javax.imageio.ImageReader) iter.next();
        else
        {
        System.err.println( "Reader for \""+ext +"\" not found by call to ImageIO.getImageReadersBySuffix( \"" + ext + "\" ), skipping" );
        continue;
        }
        reader.setInput( iis );
        ImageReadParam param = reader.getDefaultReadParam();
        int w = reader.getWidth( 0 );
        int h = reader.getHeight( 0 );
        System.out.println( "Image successfully opened, w=" + w + ", h=" + h );
        // read UL corner
        System.out.println( "Read UL corner and write it to disk" );
        Rectangle ulRect = new Rectangle( 0, 0, w/2, h/2);
        param.setSourceRegion( ulRect );
        BufferedImage bi = reader.read( 0, param );
        final String ulpath = "C:/temp/ULCorner." + ext;
        if ( ImageIO.write( bi, ext, new File( ulpath ) ) )
        System.out.println( "New UL file successfully stored: \"" + ulpath + "\"" );
        else
        System.err.println( "No no appropriate writer was found, file not created" );
        // read LR corner
        System.out.println( "Read LR corner and write it to disk" );
        Rectangle lrRect = new Rectangle( w/2, h/2, w/2, h/2 );
        param.setSourceRegion( lrRect );
        bi = reader.read( 0, param );
        final String lrpath = "C:/temp/LRCorner." + ext;
        if ( ImageIO.write( bi, ext, new File( lrpath ) ) )
        System.out.println( "New LR file successfully stored: \"" + lrpath + "\"" );
        else
        System.err.println( "No no appropriate writer was found, file not created" );
        }
        catch ( Exception e )
        {
        e.printStackTrace();
        }
        }
        }
        }

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

        CUSTOMER SUBMITTED WORKAROUND :
        Creates MyBMPImageReader.java as copy of BMPImageReader.java and fix bug by insertion new code line before original source line 780 (sources of SDK version 1.45)

          iis.seek( bitmapOffset ); //++ BUG fix, insert before line #780

        Use in any way this new class except of reader returned by call to
        ImageIO.getImageReadersBySuffix( "BMP" )

          Attachments

            Issue Links

              Activity

                People

                Assignee:
                bae Andrew Brygin
                Reporter:
                webbuggrp Webbug Group
                Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                  Dates

                  Created:
                  Updated:
                  Resolved: