仿射变换旋转,缓冲图像被切断

时间:2012-10-19 00:17:36

标签: rotation bufferedimage cut affinetransform

我正在制作游戏,最近遇到了使用仿射变换旋转缓冲图像时出现的问题。图像围绕自己的中心旋转。例如,当旋转45度时,向上和向左的角被切掉,所有位于低于图像原始x或y位置的像素都不会显示。

这是我用来旋转bufferedimage的代码:

setRad();
AffineTransform at = new AffineTransform();
at.rotate(-rad, width/2, height/2);
AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
bImage = op.filter(startImage, null);

setRad()根据x和y速度给出角度 startImage是加载的图像
bImage是返回主班的人。

我认为解决这个问题的方法是扩大图像文件,在它周围添加空白空间,这样我就不会使用角落来切割。但这会降低性能,如果可能的话我宁愿坚持使用合适的解决方案。希望一切都清楚!

// Snorbird

1 个答案:

答案 0 :(得分:1)

问题是你的源图像并不完全是二次方的。 使用at.rotate(-rad, width/2, height/2);实施AffineTransform轮换时,它与:

相同
at.translate(width/2,height/2);
at.rotate(rads);
at.translate(-width/2,-height/2);

因此,当它执行最后一行时,它会转换为原点。如果宽度大于y(反之亦然),则变换的原点将被转换为比较大长度的边更小的距离。

例如,如果您的宽度为30且高度为60,则原点将设置为(-15,-30)变换原始设置的位置。因此,当你将它翻译成90度时,图像将以“宽度”60和“高度”30结束,但根据原点,图像原始底部将被绘制在(-30,0),所以它在-15轴上溢出了AffineTransform。然后这部分图像将被剪切。

要更正此问题,您可以改为使用以下代码:

    double degreesToRotate = 90;
    double locationX =bufferedImage.getWidth() / 2;
    double locationY = bufferedImage.getHeight() / 2;

    double diff = Math.abs(bufferedImage.getWidth() - bufferedImage.getHeight());

    //To correct the set of origin point and the overflow
    double rotationRequired = Math.toRadians(degreesToRotate);
    double unitX = Math.abs(Math.cos(rotationRequired));
    double unitY = Math.abs(Math.sin(rotationRequired));

    double correctUx = unitX;
    double correctUy = unitY;

    //if the height is greater than the width, so you have to 'change' the axis to correct the overflow
    if(bufferedImage.getWidth() < bufferedImage.getHeight()){
        correctUx = unitY;
        correctUy = unitX;
    }

    int posAffineTransformOpX = posX-(int)(locationX)-(int)(correctUx*diff);
    int posAffineTransformOpY = posY-(int)(locationY)-(int)(correctUy*diff);

    //translate the image center to same diff that dislocates the origin, to correct its point set
    AffineTransform objTrans = new AffineTransform();
    objTrans.translate(correctUx*diff, correctUy*diff);
    objTrans.rotate(rotationRequired, locationX, locationY);

    AffineTransformOp op = new AffineTransformOp(objTrans, AffineTransformOp.TYPE_BILINEAR);

    // Drawing the rotated image at the required drawing locations
    graphic2dObj.drawImage(op.filter(bufferedImage, null), posAffineTransformOpX, posAffineTransformOpY, null);

希望有所帮助。