1

I'm trying to get a portion of an Image using JavaFX, but the code fails when y = 1.

Here is the code:

public static Image crop(Image src, int col, int row) { PixelReader r = src.getPixelReader(); int sx = col * Grid.SIZE; // start x int sy = row * Grid.SIZE; // start y int ex = sx + Grid.SIZE; // end x int ey = sy + Grid.SIZE; // end y int rx = 0; // x to be written int ry = 0; // y to be written System.out.println(sx + ", " + sy + ", " + ex + ", " + ey); WritableImage out = new WritableImage(Grid.SIZE, Grid.SIZE); PixelWriter w = out.getPixelWriter(); for(int y = sy; y < ey; y++, ry++) { for(int x = sx; x < ex; x++, rx++) { int c = r.getArgb(x, y); w.setArgb(rx, ry, c); System.out.println(rx + ", " + ry + ", " + x + ", " + y); } } return out; } 

Everything goes well, until the y's in the loop become 1, then this happens:

Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: 32, 1 at com.sun.prism.Image$BaseAccessor.getIndex(Unknown Source) at com.sun.prism.Image$BaseAccessor.setArgb(Unknown Source) at com.sun.prism.Image.setArgb(Unknown Source) at javafx.scene.image.WritableImage$2.setArgb(Unknown Source) 

I have no idea what is wrong. I will give any other information I can.

6
  • Can you explain what Grid.SIZE is and what col and row are supposed to represent in this method? Typically to crop you would expect a start x and y, a width, and height. Two parameters doesn't seem enough. Commented Mar 17, 2016 at 23:13
  • @James_D Grid.SIZE equals 32. It is supposed to represent the width and height of the image to be cropped, and the col and row are the column and row to start cropping on Commented Mar 17, 2016 at 23:15
  • So why are you doing sx = col * Grid.SIZE? Commented Mar 17, 2016 at 23:16
  • To get the starting position of the crop. It is supposed to be cropping a spritesheet. If col equals 1, the crop will start at x = 32. Commented Mar 17, 2016 at 23:22
  • Ah, OK. I didn't understand what you meant by "row and column to start cropping on". Commented Mar 17, 2016 at 23:25

1 Answer 1

1

You're getting the index out of bounds exception because you're not resetting rx to 0 when you begin each new row.

However, if you want a Grid.SIZE by Grid.SIZE crop of src, starting at (col, row), the easier (and potentially better-performing) way to do it is:

public static Image crop(Image src, int col, int row) { PixelReader r = src.getPixelReader(); PixelFormat<IntBuffer> pixelFormat = PixelFormat.getIntArgbInstance() ; int[] pixels = new int[Grid.SIZE * Grid.SIZE]; r.getPixels(col * Grid.SIZE, row * Grid.SIZE, Grid.SIZE, Grid.SIZE, pixelFormat, pixels, 0, Grid.SIZE); WritableImage out = new WritableImage(Grid.SIZE, Grid.SIZE); PixelWriter w = out.getPixelWriter(); w.setPixels(0, 0, Grid.SIZE, Grid.SIZE, pixelFormat, pixels, 0, Grid.SIZE); return out ; } 

Obviously this will fail if (col+1)*Grid.SIZE > src.getWidth() or (row+1)*Grid.SIZE > src.getHeight(), which you could check for in the method and throw an IllegalArgumentException if you wanted.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! That worked, with a few changes. PixelFormat<IntBuffer> should be WritablePixelFormat<IntBuffer>, and PixelFormat.createIntArgbInstance() to PixelFormat.getIntArgbInstance().
Oops, yes, fixed the method name. But you only need a PixelFormat, not a WritablePixelFormat. Also figured out why you are getting the exception.
Yes I just noticed that. It's good that it is better performing, because this method is running every time I get a sprite, and the game runs at 60 fps!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.