如何将BufferedImage旋转为对象本身

时间:2015-06-05 13:17:07

标签: java eclipse frame-rate

我在旋转每个图像时遇到性能问题,在绘制它时FPS从1400下降到6.我可以在创建后立即旋转BufferedImage对象,所以计算只发生一次吗?

有我的网格控件类:(绘图类,问题方法是drawRotated())

package cs.meowxiik.universes.graphics;

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.util.Observer;

import cs.meowxiik.universes.map.Map;
import cs.meowxiik.universes.map.Tile;

public class GridControl {

    int width;
    int height;
    int xcells;
    int ycells;
    int cellWidth;
    int cellHeight;

    int maxZoom = 80;
    int minZoom = 30;
    private Map activeMap;

    public GridControl(int width, int height, int xcells, int ycells) {
            this.width = width;
            this.height = height;
            this.xcells = xcells;
            this.ycells = ycells;
            cellWidth = width / xcells;
            cellHeight= height/ ycells;
    }

    public GridControl(int width, int height, int cellWidth, int cellHeight, int thisDoesntMatterJustForOverloading) {
            this.width = width;
            this.height = height;
            this.cellWidth = cellWidth;
            this.cellHeight = cellHeight;
            xcells = width / cellWidth;
            ycells = height / cellHeight;
    }

    public void drawGrid(Graphics g){
            for(int i = 0; i < xcells; i++){
                    for(int ii = 0; ii <ycells; ii++){
                            g.drawRect(i * cellWidth, ii * cellHeight, cellWidth, cellHeight);
                    }
            }
    }

    public int getCellSize() {
            return cellWidth;
    }

    public void editCellSize(int i) {
            if(i == 0)return;
            System.out.println("Resizing: " + i);
            //Pokud je i menší jak 0 -> člověk se pokouší přibližovat
            if(i < 0 && xcells > maxZoom)return;
            if(i > 0 && xcells < minZoom)return;
            this.cellWidth += i;
            this.cellHeight += i;
            xcells = width / cellWidth;
            ycells = height / cellHeight;
    }

    public void setActiveMap(Map map){
            this.activeMap = map;
    }

    public void drawMap(Graphics g, Canvas canvas){
            if(activeMap != null){
                    for(int i = 0; i < xcells; i++){
                            for(int ii = 0; ii <ycells; ii++){
                                    drawRotated(activeMap.getTiles()[i][ii].getTexture(),activeMap.getTiles()[i][ii].getDegrees(), i*cellWidth, ii*cellWidth,canvas, g, null);
                                    //ImageObserver observer = null;
                                    //g.drawImage(activeMap.getTiles()[i][ii].getTexture(), i*cellWidth, ii*cellWidth, observer);
                            }
                    }
            }
    }

    public Tile getTileByCoordinate(int x, int y){
            int cellx = x / this.cellWidth;
            int celly = y / this.cellHeight;
            return activeMap.getTiles()[cellx][celly];
    }

    public boolean isWalkable(int x, int y){
            return getTileByCoordinate(x,y).getWalkable();
    }

    public void drawRotated(BufferedImage img,double rotationRequired,int x,int y,Canvas canvas, Graphics g, Observer observer){
            //double rotationRequired = Math.toRadians(degrees);
            double locationX = img.getWidth() / 2;
            double locationY = img.getHeight() / 2;
            AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
            AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);

            // Drawing the rotated image at the required drawing locations
            g.drawImage(op.filter(img, null), x, y, null);
    }}

我的瓷砖方法:

public class Tile {

    boolean walkable;
    BufferedImage image;
    double radians;
    int ID; //0 - floor, 1 - wall

    public Tile(boolean walkable, BufferedImage image, int ID) {
            this.walkable = walkable;
            this.image = image;
            this.ID = ID;
    }

    public BufferedImage getTexture() {
            return image;
    }

    public boolean getWalkable() {
            return walkable;
    }

    public int getDegrees() {
            return (int) Math.toDegrees(radians);
    }

    public int getID() {
            return ID;
    }

    public void setTexture(BufferedImage image, int degrees) {
            this.image = image;
            this.radians = Math.toRadians(degrees);
    }
}

我的地图创建者:(旋转部分坏了,我稍后会解决,现在我需要解决我的6-FPS问题)

package cs.meowxiik.universes.map;

import cs.meowxiik.universes.graphics.GraphicsManager;


public class MapCreator {

    GraphicsManager graphics;

    public MapCreator(GraphicsManager graphics) {
            this.graphics = graphics;
    }

    public Map getSpaceStationMap(){
            Map map;
            int x = 32;
            int y = 18;
            Tile[][] tiles = new Tile[x][y];
            for(int i = 0; i < x; i++){
                    for(int ii = 0; ii < y; ii++){
                            tiles[i][ii] = new Tile(true, graphics.floor, 0);
                    }
            }

            for(int i = 0; i < x; i++){
                    for(int ii = 0; ii < y; ii++){
                            if(i == 0 || ii == 0 || i == x-1 || ii == y-1)tiles[i][ii] = new Tile(false,graphics.stWallZero, 1); //tiles.get(i).set(ii, new Tile(false,graphics.wall));
                    }
            }

            for(int i = 0; i < x; i++){
                    for(int ii = 0; ii < y; ii++){
                            if(tiles[i][ii].getID() == 0)break;
                            boolean connectedUp = false;
                            boolean connectedLeft = false;
                            boolean connectedRight = false;
                            boolean connectedBottom = false;
                            if(i + 1 < tiles.length)
                                    if(tiles[i + 1][ii + 0].getID() == 1)
                                            connectedRight = true;
                            if(i != 0)                                     
                                    if(tiles[i - 1][ii + 0].getID() == 1)
                                            connectedLeft = true;
                            if(ii + 1 < tiles[i].length)
                                    if(tiles[i + 0][ii + 1].getID() == 1)
                                            connectedBottom = true;
                            if(ii != 0)                                    
                                    if(tiles[i + 0][ii - 1].getID() == 1)
                                            connectedUp = true;

                            if(connectedUp && !(connectedLeft || connectedRight || connectedBottom))tiles[i][ii].setTexture(graphics.stWallOne, 0);
                            if(connectedLeft && !(connectedUp || connectedRight || connectedBottom))tiles[i][ii].setTexture(graphics.stWallOne, 90);
                            if(connectedRight && !(connectedUp || connectedLeft || connectedBottom))tiles[i][ii].setTexture(graphics.stWallOne, 180);
                            if(connectedBottom && !(connectedUp || connectedRight || connectedLeft))tiles[i][ii].setTexture(graphics.stWallOne, 270);

                            if((connectedUp && connectedBottom) && !(connectedLeft || connectedRight))tiles[i][ii].setTexture(graphics.stWallTwo, 90);
                            if(!(connectedUp && connectedBottom) && !(connectedLeft || connectedRight))tiles[i][ii].setTexture(graphics.stWallTwo, 0);
                    }
            }

            map = new Map(x,y,tiles);
            return map;
    }

}

1 个答案:

答案 0 :(得分:2)

鉴于此代码

  public void drawRotated(BufferedImage img,double rotationRequired,int x,int y,Canvas canvas, Graphics g, Observer observer) {
        //double rotationRequired = Math.toRadians(degrees);
        double locationX = img.getWidth() / 2;
        double locationY = img.getHeight() / 2;
        AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
        AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);

        BufferedImage rotatedImage = op.filter(img, null); // my edit here

        // Drawing the rotated image at the required drawing locations
        g.drawImage(rotatedImage , x, y, null);
    }

图像旋转到rotatedImage只取决于它的大小(宽度/高度)和所需的旋转。

从我的代码阅读中,所需的轮换基本上是固定的。当调用setTexture Title方法时,旋转是已知的。

正是这种情况,可以在rotatedImage方法中计算setTexture。只需创建一个存储计算出的旋转图像的新属性。不要破坏原件。

如果setTexture经常调用drawRotated,则无法提供您想要的性能提升。