getColor() crashes for a flipped image

Issue #42 new
Егор Смирнов
created an issue

getColor() method contains following code:

if (textureWidth < 0) {
    x = xo - x;
} else {
 x = xo + x;
} 

For a flipped image, xo equals image width, so for x = 0 new x value is also equal to width, and this leads to ArrayIndexOutOfBoundsException. Should be

x = xo - x - 1;

here.

Comments (5)

  1. Егор Смирнов reporter

    Seems that I am a bit mistaken, bug is caused by combination of flip and scale (intro.png is a rectangular 800x300 image):

     Image img = new Image(getClass().getClassLoader().getResourceAsStream("sprites/story/intro.png"), "intro", false);
            Image flipped = img.getFlippedCopy(true, true).getScaledCopy(1.2f);
            final int width = flipped.getWidth();
            final int height = flipped.getHeight();
            for (int x = 0; x < width; ++x) {
    
                for (int y = 0; y < height; ++y) {
                    Color c = flipped.getColor(x, y);
                }
            }
    

    This code gives:

    java.lang.ArrayIndexOutOfBoundsException: -672
        at org.newdawn.slick.Image.getColor(Image.java:1367) ~[slick.jar:na]
        at ru.game.aurora.application.AuroraGame.initGameAndGUI(AuroraGame.java:174) ~[Aurora/:na]
        at de.lessvoid.nifty.slick2d.NiftyOverlayGame.init(NiftyOverlayGame.java:66) ~[nifty-slick-renderer-1.3.2.jar:na]
        at org.newdawn.slick.AppGameContainer.setup(AppGameContainer.java:393) ~[slick.jar:na]
        at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:317) ~[slick.jar:na]
        at ru.game.aurora.application.AuroraGame.main(AuroraGame.java:343) ~[Aurora/:na]
    
  2. Nico

    The problem seem to be in getScaledCopy() actually. It wasn't paying attention to textureOffsetX/Y and textureWidth/Height which are only used when the image is flipped. In that case getScaledCopy() should also scale those values.

    That fixed the ArrayIndexOutOfBoundsException, but unfortunately there's another problem: getScaledCopy() doesn't seem to scale the actual texture underneath, meaning that getColor() will fail as it's still working on the previous (unscaled) image.

  3. Nico

    Further investigations reveal that:

    • For a given image (of say size 100x100) a texture is built with the nearest power of two (128x128 in this case)
    • The gap between the image width (100) and the texture width (128) is just left empty (black)
    • If you scale the image, the underlying texture is not resized:
      • If you downscale it, the image just get clipped
      • If you upscale it, the texture gets repeated

    All this can be seen by playing with the ImageTest test class.

    So in practice I don't think Image.getColor(x,y) makes a lot of sense, since it applies to the underlying texture data, not the actual image. With the previous example of the 100x100 image if you call getColor(110, 110) it doesn't fail but instead you'll get Color.black. That's quite confusing.

    Then if you upscale the image, assuming a working getColor() implementation, you'll get the color of the underlying "wrapped" texture, rather than a scaled version of it.

  4. Log in to comment