2

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

这是我用于旋转缓冲图像的代码:

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 是返回到主类的图像。

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

//打鼾鸟

4

1 回答 1

1

问题是您的源图像不完全是二次的。当您使用 实现 AffineTransform 旋转时at.rotate(-rad, width/2, height/2);,它与以下内容相同:

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),所以它在 X 轴上溢出了 -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);

希望它有所帮助。

于 2016-04-06T19:51:58.197 回答