c#中的无损位图旋转

本文关键字:位图 旋转 | 更新日期: 2023-09-27 18:06:58

我在一个表单应用程序中制作一款自上而下的赛车游戏(我知道这是非常无效的,但这是一个学校项目,老师说只能是表单应用程序)。我有一个小车位图,我想把它旋转x度。我已经找到了一种方法,做到了这一点,但我的问题是,几次旋转后,位图开始变得非常模糊,严重影响性能。有没有一种方法可以使这个算法更有效,而不是指数级地失去质量?

这是旋转方法:

public Bitmap RotateImage(Image image, PointF offset, float angle)
{
    float sin = (float)Math.Abs(Math.Sin(angle * Math.PI / 180.0));
    float cos = (float)Math.Abs(Math.Cos(angle * Math.PI / 180.0));
    float ImgWidth = sin * bmp.Height + cos * bmp.Width;
    float ImgHeight = sin * bmp.Width + cos * bmp.Height;
    Bitmap rotatedBmp = new Bitmap((int)ImgWidth,(int) ImgHeight);
    Graphics g = Graphics.FromImage(rotatedBmp);
    g.TranslateTransform(offset.X, offset.Y);
    g.RotateTransform(angle);
    g.TranslateTransform(-offset.X, -offset.Y);
    g.DrawImage(image, new PointF(0, 0));
    return rotatedBmp;
}

c#中的无损位图旋转

请勿在旋转后覆盖原始源图像。

将角度存储为绝对角度,而不是与上一帧的偏移量

最后,每帧从头开始旋转原始源图像,然后绘制结果。

唯一的无损旋转是旋转90度的倍数。在任何其他角度都不可能进行无损旋转。

编辑

同样,没有必要在它自己的缓冲区中保留旋转图像的中间副本。您可以直接将旋转后的汽车绘制到屏幕上。

如果我错了,你绝对需要缓冲汽车的旋转图像,你可以计算旋转图像所需的最大大小并重用缓冲区。您可以通过计算对角线图像大小,并将其用于宽度高度,然后在新缓冲区中居中绘制汽车。

像这样:(未经测试)

        double maxSize = Math.Sqrt(bmpCp.Width * bmpCp.Width + bmpCp.Height * bmpCp.Height);
        Bitmap rotatedBmp = new Bitmap((int)maxSize, (int)maxSize, pf);
        //...
        gBmp.DrawImage(bmpCp, new PointF((maxSize - bmpCp.Width) / 2.0,
                                         (maxSize - bmpCp.Height) / 2.0));