2014-12-14 2 views
0

Я пытаюсь извлечь часть изображения из BufferedImage. Как мне это сделать? Это не позволяет мне поставить значение для y, которое больше нуля.Как работает getSubimage (...)?

Ex:

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(); 
    } 
} 

}

+0

Если вы увеличиваете y, вам не нужно уменьшать высоту, о которой вы просите, иначе вы запрашиваете данные за пределами изображения. Что означает «это не позволяет мне»? Опишите, что именно происходит. –

+0

Это не позволяет поставить значение y больше высоты изображения, что имеет смысл. Значение y должно находиться в диапазоне '[0, height)'. – Vulcan

ответ

1

Основываясь на том, как вы вызвавшей функцию, это выглядит, как вы предполагая, что вы передаете в верхнем левом углу, затем в правом нижнем углу.

Если вы посмотрите на Javadoc для этого метода, вы увидите, что параметры: x,y,w,h.

То есть, сначала укажите верхний левый угол, используя x,y, а затем укажите ширину и высоту. Следовательно, если вы пытаетесь получить нижнюю половину изображения, правильным вызовом является уменьшение наполовину установленной высоты.

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

Спасибо! Я предположил неправильно. – user2603506

+0

@ user2603506, добро пожаловать. Примите этот ответ, если он решит ваш вопрос. – merlin2011

Смежные вопросы