getSubimage(...)如何工作?

时间:2014-12-14 22:35:16

标签: java image

我试图从BufferedImage中提取图像的一部分。我该怎么做呢?它不允许我为y设置一个大于零的值。

例如:

getSubimage(0,0,theImage.getWidth(),theImage.getHeight()); //OK
getSubimage(0,(int)theImage.getHeight()/2,theImage.getWidth(), theImage.getHeight()); //ERROR!

以下是错误消息:

Exception in thread "main" java.awt.image.RasterFormatException: (y + height) is outside of Raster
at sun.awt.image.ByteInterleavedRaster.createWritableChild(Unknown Source)
at java.awt.image.BufferedImage.getSubimage(Unknown Source)
at Loop.renderImages(Loop.java:147)
at Loop.run(Loop.java:122)
at Driver.main(Driver.java:9)

这是整个代码。我知道它很乱......编码还是新手。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.*;

import javax.imageio.ImageIO;


public class Loop implements Runnable{

//458 = max right boundary
private static long now, lastSecond, lastFrame, deltaSecond, deltaFrame;
private boolean on = true;
private static final long second = 1000000000;
private static final int FPS = 60;
private static final long frame = second/FPS;
private static int currentFPS, framesCurrentSecond, totalFrames, seconds;
private static boolean running = true;
private static int SCPosX, SCPosY;
private static int SCXOffset, SCYOffset, bottomOffset = 120;
private static int gameWidth = FrameBuilder.WIDTH;
private static int gameHeight = FrameBuilder.HEIGHT;
private int score;
private static BufferedImage spaceCraft, spaceCraft2;
private static ImageBufferer IB;
private static FrameBuilder fb;
private Thread spaceShipThread = new Thread();
private static int boundaryLeft, boundaryRight, boundaryUp, boundaryDown;
private static boolean moveUp = false, moveDown = false, moveRight = false, moveLeft = false;
private static boolean fireMainCannon = false;
private static long cannonTick = second/3;
private static long deltaCannonTick = 0;
private static final int healthMax = 458;
private Timer animationTimer;
private static BufferedImage starOne, starOneSub;
private static int starOneY = 0, starOneStart, starOneEnd;

public Loop()
{
    File S1 = new File("C:\\Users\\Andrew\\Documents\\star1.png");
    try {
        starOne = ImageIO.read(S1);
    } catch (IOException e) {
        e.printStackTrace();
    }
    starOneStart = (int)starOne.getHeight() - starOne.getHeight();
    starOneEnd = starOne.getHeight();
    animationTimer = new Timer(80, new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e) {
            on = !on;
        }

    });
    Timer starOneTimer = new Timer(100, new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            if(starOneStart > 0 && starOneEnd > 0)
            {
                starOneStart--;
                starOneEnd--;
            }
            else
            {
                starOneStart = starOne.getHeight()-((int)starOne.getHeight()/4);
                starOneEnd = starOne.getHeight();
            }
        }

    });
    starOneTimer.start();
    animationTimer.start();

    SCXOffset = 0;
    SCYOffset = 0;
    spawnSpaceShip();



    IB = new ImageBufferer();
    fb = new FrameBuilder();
    fb.c.addKeyListener(new Controls());
    fb.setDefaultComponents();
    score = 0;


    boundaryLeft = 24;
    boundaryRight = gameWidth-spaceCraft.getWidth()-64;
    boundaryDown = gameHeight-bottomOffset;
    SCPosX = (gameWidth/2)-(spaceCraft.getWidth()+16);
    SCPosY = boundaryDown - spaceCraft.getHeight()/2;
    boundaryUp = -5;

    now = System.nanoTime();
    lastSecond = now;
    lastFrame = now;
    seconds = 0;
    framesCurrentSecond = 0;
    totalFrames = 0;

}

public void run() {
    while(running)
    {
        now = System.nanoTime();
        deltaSecond = now - lastSecond;
        deltaFrame = now - lastFrame;
        if(deltaFrame >= frame)
        {
            handleSpaceCraft(SCXOffset, SCYOffset);
            renderImages(IB.getImages(), IB.getXCoords(), IB.getYCoords());
            IB.clearLists();
            lastFrame = now;
            framesCurrentSecond++;

        }
        if(deltaSecond >= second)
        {
            lastSecond = now;
            seconds++;
            totalFrames += framesCurrentSecond;
            System.out.println("FPS: " + framesCurrentSecond + " TOTAL: " + totalFrames);
            framesCurrentSecond = 0;
        }
    }
}
public void renderImages(ArrayList<BufferedImage> images, ArrayList<Integer> x, ArrayList<Integer> y)
{
    BufferStrategy bs = FrameBuilder.getCanvas().getBufferStrategy();
    if(bs==null)
    {
        FrameBuilder.getCanvas().createBufferStrategy(3);
        return;
    }
    Graphics g = bs.getDrawGraphics();
    starOneSub = starOne.getSubimage(0, (int)starOne.getHeight()/2, starOne.getWidth(), starOneEnd);
    for(int i = 0; i < images.size(); i++)
    {
        g.drawImage(starOneSub, 0, 0, starOneSub.getWidth()+500, starOneSub.getHeight()+600,null);
        g.setColor(Color.RED);
        g.fillRect(24, gameHeight-72, SpaceCraft.maxHealth*4, 20);
        g.setColor(Color.GREEN);
        g.fillRect(24, gameHeight-72, SpaceCraft.health*(4) , 20);
        g.drawImage(images.get(i), x.get(i), y.get(i) , images.get(i).getWidth()+32, images.get(i).getHeight()+32, null);
        g.dispose();

    }
    bs.show();
}
public void handleSpaceCraft(int x, int y)
{
    if(moveUp)
    {
        SCYOffset-=10;
        if(SCPosY+SCYOffset <= boundaryUp)
            SCYOffset+=10;
    }
    if(moveDown)
    {
        SCYOffset+=10;
        if(SCPosY+SCYOffset >= boundaryDown)
            SCYOffset-=10;
    }
    if(moveRight)
    {
        SCXOffset+=7;
        if(SCPosX+SCXOffset >= boundaryRight)
            SCXOffset-=7;
    }
    if(moveLeft)
    {
        SCXOffset-=7;
        if(SCPosX+SCXOffset <= boundaryLeft)
            SCXOffset+=7;
    }
    if(on)
        IB.addImage(spaceCraft, SCPosX+SCXOffset, SCPosY+SCYOffset);
    else
        IB.addImage(spaceCraft2, SCPosX+SCXOffset, SCPosY+SCYOffset);
}
public class Controls implements KeyListener
{

    @Override
    public void keyTyped(KeyEvent e) 
    {

    }

    @Override
    public void keyPressed(KeyEvent e) 
    {
        int key = e.getKeyCode();
        if(key == KeyEvent.VK_W)
            moveUp = true;
        if(key == KeyEvent.VK_A)
            moveLeft = true;
        if(key == KeyEvent.VK_D)
            moveRight = true;
        if(key == KeyEvent.VK_S)
            moveDown = true;
        if(key == KeyEvent.VK_SPACE)
            fireMainCannon = true;
    }

    @Override
    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();
        if(key == KeyEvent.VK_S)
            moveDown = false;
        if(key == KeyEvent.VK_D)
            moveRight = false;
        if(key == KeyEvent.VK_W)
            moveUp = false;
        if(key == KeyEvent.VK_A)
            moveLeft = false;   
        if(key == KeyEvent.VK_SPACE)
        {
            fireMainCannon = false;
        }

    }
}
public void spawnSpaceShip()
{
    File SC1 = new File("C:\\Users\\Andrew\\Documents\\spaceCraftGray1.png");
    File SC2 = new File("C:\\Users\\Andrew\\Documents\\spaceCraftGray2.png");
    try {
        spaceCraft = ImageIO.read(SC1);
        spaceCraft2 = ImageIO.read(SC2);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

1 个答案:

答案 0 :(得分:2)

根据您调用该函数的方式,看起来您假设您通过了左上角,然后是右下角。

如果您查看该方法的Javadoc,您会发现参数为x,y,w,h

也就是说,首先使用x,y提供左上角,然后提供宽度和高度。因此,如果您尝试获取图像的下半部分,则正确的调用是将提供的高度减半。

getSubimage(0,(int)theImage.getHeight()/2,theImage.getWidth(), theImage.getHeight() / 2);