Bug 823 - AWTTextureIO does not properly interpret a BufferedImage created with BufferedImage.getSubImage()
Summary: AWTTextureIO does not properly interpret a BufferedImage created with Buffere...
Status: UNCONFIRMED
Alias: None
Product: Jogl
Classification: JogAmp
Component: awt (show other bugs)
Version: 2
Hardware: All all
: --- normal
Assignee: Sven Gothel
URL:
Depends on:
Blocks:
 
Reported: 2013-09-02 03:56 CEST by Bill Kuker
Modified: 2013-09-29 21:28 CEST (History)
0 users

See Also:
Type: ---
SCM Refs:
Workaround: ---


Attachments
Test Program for bug (22.44 KB, application/octet-stream)
2013-09-02 05:08 CEST, Bill Kuker
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Bill Kuker 2013-09-02 03:56:58 CEST
java.awt.image.BufferedImage has a function which returns a BufferedImage which is a subimage of the original with dimensions w*h at offset x,y:

    public BufferedImage getSubimage(int x int y, int w, int h)

Rather than creating a copy of the pixel data this function plays games with the returned images Raster and Sample model. AWTTextureIO is not correctly taking into account all of the offsets in the data reported by the buffered image, and therefore any Texture created from a BufferedImage created with a call to

    someImage.getSubimage( x, y, w, h)

looks instead as if it were created from a BufferedImage created with a call to

    someImage.getSubimage( 0, 0, w, h)

instead

JDK 6's GIF writer seems to have the same bug, see http://bugs.sun.com/view_bug.do?bug_id=6795544 for a description of what I think is a very similar bug.

I have confirmed that this problem can be worked around with a function that creates a copy of the sub-image by allocating a new BufferedImage of the correct size, and then copying the pixels into it:

The code 

        tex = AWTTextureIO.newTexture(GLProfile.getDefault(), i.getSubimage(x,y,w,h), false); 

displays incorrectly for x !=0, y != 0 but the code 

        tex = AWTTextureIO.newTexture(GLProfile.getDefault(), workaround(i.getSubimage(x,y,w,h)), false); 

works as expected, given the function 

        private static BufferedImage workaround(BufferedImage i) { 
                BufferedImage d2 = new BufferedImage(i.getWidth(), i.getHeight(), i.getType()); 
                d2.getGraphics().drawImage(i, 0, 0, null); 
                return d2; 
        }

I will look into preparing a very short example program.
Comment 1 Bill Kuker 2013-09-02 05:08:58 CEST
Created attachment 501 [details]
Test Program for bug

This is a simple test program that should reproduce the problem.

A 256x256 texture is loaded, a 128x128 subimage is extracted at offset 128, 128 and used as a texture, once directly and once using the workaround in the ticket.

You should see TWO green squares, but see one red and one green, the green being a product of the workaround, the red being the texture in error.
Comment 2 Bill Kuker 2013-09-02 05:10:38 CEST
Just as a note, I was going crazy trying to reproduce this and discovered that the problem occurs when the image is a JPEG, but not when it is a PNG.
Comment 3 Bill Kuker 2013-09-02 14:22:31 CEST
In AWTTextureIO there is a function, createFromCustom(...), which re-writes the image to a new BufferedImage exactly as the workaround above does. I think that it hits this code for PNG with alpha, but perhaps not for JPEG, explaining the difference between the two image types.

(In reply to comment #2)
> Just as a note, I was going crazy trying to reproduce this and discovered
> that the problem occurs when the image is a JPEG, but not when it is a PNG.
Comment 4 Sven Gothel 2013-09-29 21:28:47 CEST
(In reply to comment #3)
> In AWTTextureIO there is a function, createFromCustom(...), which re-writes
> the image to a new BufferedImage exactly as the workaround above does. I
> think that it hits this code for PNG with alpha, but perhaps not for JPEG,
> explaining the difference between the two image types.
> 
> (In reply to comment #2)
> > Just as a note, I was going crazy trying to reproduce this and discovered
> > that the problem occurs when the image is a JPEG, but not when it is a PNG.

Bill, can you provide a patch ?

Please also note, we consider using our own PNG and JPEG decoder code
as the default - hence it is used by our TextureIO class.
Both are more efficient and expose better performance. The JPEG decoder
is even more compliant.