旋转位图时奇怪的包装

时间:2014-07-10 23:45:27

标签: java matrix rotation transform pixel

我开始为游戏开发一个自定义Image类,它包含三个基本字段,宽度,高度和一维的int的一维数组,它们按以下顺序表示颜色。

大约两天前我开始尝试旋转图像,我能够通过将其转换为BufferedImage,使用Graphics2D旋转并将其转换回我自己的Image类来实现,但是setRGB和getRGB似乎太慢了当我必须旋转大约10-20个64 * 64像素的图像时,计算机开始努力维持fps。

很自然地,我开始开发自己的图像旋转功能,我在gamedev.stackexchange上发现了一篇很棒的帖子。

https://gamedev.stackexchange.com/questions/67613/how-can-i-rotate-a-bitmap-without-d3d-or-opengl

答案清楚地解释了即使使用不同的旋转点(我打算稍后实施)也应该如何旋转图像。

然而,当遵循他解释的那个类似的公式时(由于使用不同的坐标系我不得不改变) 我发现自己在顶部得到一个奇怪的包装

示例(55度):http://i.imgur.com/BBq83wV.png(黑色区域代表图像大小)

所以我试图从顶部分散图像,然后添加

yDstPixel += this.height*sin;

哪种方法有效,但现在图像被剪切了一半而不是包裹

示例(35度):http://i.imgur.com/Ap4aqrn.png

我几乎可以肯定解决方案非常简单,但我似乎无法弄清楚,正确方向的推动将会受到赞赏。

public Bitmap getRotatedCopy(double radians){
    if(radians==0 || radians==(2*Math.PI)) return this;

    double sin = Math.abs(Math.sin(radians));
    double cos = Math.abs(Math.cos(radians));

    int newWidth  = (int) (this.width * cos + this.height * sin);
    int newHeight = (int) (this.width * sin + this.height * cos);

    Bitmap returnMap = new Bitmap(newWidth,newHeight); //set size of the returned bitmap to the smallest size possible
    returnMap.fill(0xFF000000);
    for (int y = 0; y < this.height; y++){
        for(int x = 0; x < this.width; x++){


            int srcPixel = x + (y * this.width);
            int color= this.pixels[srcPixel];
            if(color>0) continue;

            int xDstPixel = (int) Math.abs((x * cos + y * sin));
            int yDstPixel = (int) Math.abs((x * sin - y * cos));

            //yDstPixel += this.height*sin;

            int dstPixel = xDstPixel + (yDstPixel * newWidth);

            returnMap.pixels[dstPixel]=color;
        }
    }

    return returnMap;
}

1 个答案:

答案 0 :(得分:0)

您需要实施您计划稍后执行的操作,即在旋转后设置旋转原点和平移。

我修改了您的代码以添加它们。 (我没有测试运行它,但希望它有效。)请参考下面的代码:

int newWidth  = (int) (this.width * cos + this.height * sin);
int newHeight = (int) (this.width * sin + this.height * cos);

// After setting the new width and height...

// set rotation origin
double rox = this.width/2;
double roy = this.height/2;

// set translation center
double tcx = newWidth/2;
double tcy = newHeight/2;

Bitmap returnMap = new Bitmap(newWidth,newHeight);
returnMap.fill(0xFF000000);
for (int y = 0; y < this.height; y++){

    double yy = y - roy;

    for(int x = 0; x < this.width; x++){

        double xx = x - rox;

        int srcPixel = x + (y * this.width);
        int color= this.pixels[srcPixel];
        if(color>0) continue;

        // following two lines are modified
        int xDstPixel = (int) (xx * cos + yy * sin) + tcx;
        int yDstPixel = (int) (xx * sin - yy * cos) + tcy;

        // prevent negative index : maybe it is not needed at all
        if (xDstPixel<0 || yDstPixel<0)
            continue;

        int dstPixel = xDstPixel + (yDstPixel * newWidth);

        returnMap.pixels[dstPixel]=color;
    }
}