简体   繁体   中英

How to get sub image from a sprite sheet into an array

I have a sprite sheet that will be 5x5 and each sprite is 20x20 pixels. I need to get each item of that sprite sheet into an array. I made a for loop but got an error. So I tried defining one of the sub images in the array myself but still get an error. I do not get an error when I don't print an item of that array. I now can not figure out the for loop problem.

Here's my code so far

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;


public class LoopSub extends Component {

    BufferedImage img;
    BufferedImage img2;
    BufferedImage bigImg;
    BufferedImage[] sprites;

    public void paint(Graphics g) {
        g.drawImage(img, 0, 0, null);
        g.drawImage(img2, 18, 0, null); //letter size 20x20 ; set lower to overlap
        g.drawImage(sprites[0], 36, 0, null); //this is whats causing the error

    }

    public LoopSub() {
       try {
           img = ImageIO.read(new File("res/a.png"));
           img2 = ImageIO.read(new File("res/b.png"));



           /////////////////////////////


        bigImg = ImageIO.read(new File("sheet.png"));


        final int width = 20;
        final int height = 20;
        final int rows = 5;
        final int cols = 5;
        sprites = new BufferedImage[rows * cols];



        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                sprites[(i * cols) + j] = bigImg.getSubimage(
                    j * width,
                    i * height,
                    width,
                    height
                );
            }
        }

        sprites[0] = bigImg.getSubimage(1,1,1,1); //where I tried to define the array myself

           /////////////////////////////////////////////


       } catch (IOException e) {
       }

    }

    public Dimension getPreferredSize() { //sets size of screen
        if (img == null) {
             return new Dimension(100,100);
        } else {
           return new Dimension(img.getWidth(null), img.getHeight(null)); //sets size to one image //// change to all images
       }
    }

    public static void main(String[] args) {

        JFrame f = new JFrame("Load Image Sample");

        f.addWindowListener(new WindowAdapter(){
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });

        f.add(new LoopSub());
        f.pack();
        f.setVisible(true);
    }
}

New error message

Exception in thread "main" java.awt.image.RasterFormatException: (x + width) is outside of Raster
    at sun.awt.image.ByteInterleavedRaster.createWritableChild(Unknown Source)
    at java.awt.image.BufferedImage.getSubimage(Unknown Source)
    at LoopSub.<init>(LoopSub.java:48)
    at LoopSub.main(LoopSub.java:85)

When changing j*width to 1 it works fine. So that's the problem. Just don't know why.

You have a NullPointerException , which means that either sprites or sprites[0] is null .

Given that you initialize them in the constructor, it can happens only if there is an IOException occuring in the constructor, because you are catching it, so it doesn't terminate the program.

You should:

  • Never silently ignore an exception, like you are doing here. if you don't do anything useful, at least put a message to print the error like this:

      } catch (IOException e) { e.printStackTrace(); } 
  • Look what is the content of the exception, which contains the root of the problem. Probably the program can not find one of your files for some reason.

Edit : for the RasterFormatException , it means that you are getting out of the limits of the image. More specifically, j * width + width is apparently larger than the width of the image.

Since j is at most 4 and width is 20, then the maximum value that j * width + width can have is 100. Your original image should then be at least 100px wide (and also 100px tall). Check that it is indeed the case.

You can for example print the width this way before the loop:

System.out.println("bigImg width: " + bigImg.getWidth());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM