【问题标题】:Image shows in the background after rotating旋转后图像在背景中显示
【发布时间】:2018-12-22 14:37:39
【问题描述】:

我编写了一个旋转图像的函数,以使其快速(这对于旋转数百张照片非常重要)我没有在每次旋转图像时都制作新的位图。但是,这导致旧照片出现在背景中,如果不创建会减慢一切的新位图,我怎么能解决这个问题!

    public static Image RotateImage(Image img, float rotationAngle)
    {
        using (Graphics graphics = Graphics.FromImage(img))
        {
            graphics.TranslateTransform((float)img.Width / 2, (float)img.Height / 2);
            graphics.RotateTransform(rotationAngle);
            graphics.TranslateTransform(-(float)img.Width / 2, -(float)img.Height / 2);
            graphics.DrawImage(img, new Point(0, 0));
        }
        return img;
    }

【问题讨论】:

  • 我已经更新了答案。

标签: c# image graphics bitmap rotation


【解决方案1】:

如果没有额外的代码,我认为这是不可能的。

Graphics 与图像关联,因此绘图会改变图像。

因此,您需要有第二张图片。 创建一个空的(或精确的副本)并没有那么慢..

这样想:当您同时更改旧像素时,它们会从哪里来?所以你需要有两个缓冲区。 (但是是的,在内部,已经有第二个缓冲区,否则结果会更奇怪。但你无法控制它的使用..)

如果您确实需要避免使用第二张图片,您可以创建一个 GraphicsPathPolygon 来覆盖旋转后的所有图片,并用您的背景颜色填充它。.

但由于旋转图像需要更多空间来容纳旋转的角,因此您可能需要第二张更大的图像。..

更新:这是一个如何清除/裁剪旋转图像之外区域的示例。它使用了GraphicsPath,我首先在其中添加了一个巨大的矩形,然后是目标矩形。这样一个被切掉,只有外部区域被填充:

public static Image RotateImage(Image img, float rotationAngle)
{
    using (Graphics graphics = Graphics.FromImage(img))
    {
        graphics.TranslateTransform((float)img.Width / 2, (float)img.Height / 2);
        graphics.RotateTransform(rotationAngle);
        graphics.TranslateTransform(-(float)img.Width / 2, -(float)img.Height / 2);
        graphics.DrawImage(img, new Point(0, 0));

        GraphicsPath gp = new GraphicsPath();
        GraphicsUnit gu = GraphicsUnit.Pixel;
        gp.AddRectangle(graphics.ClipBounds);
        gp.AddRectangle(img.GetBounds(ref gu));
        graphics.FillPath(Brushes.White, gp);
    }
    return img;
}

请注意,您不能使用 透明 画笔,因为 GDI+ 不会绘制完全透明的。相反,您需要

  1. CompositingMode从默认的SourceOver设置为SourceCopy
  2. 用非常鲜明的颜色填充,而不是在你的图像中,可能是Fuchsia
  3. 使用MakeTransparent

graphics.CompositingMode = CompositingMode.SourceCopy;
..
graphics.FillPath(Brushes.Fuchsia, gp);
((Bitmap)img).MakeTransparent(Color.Fuchsia);

请注意,并非所有应用程序都能很好地显示透明度.. Photoshop 当然可以..:

【讨论】:

  • 只是想知道,这是否比创建新位图更高效、更快?
  • 这比创建新位图要快得多,非常感谢!
【解决方案2】:

你可以使用Graphics Clear()方法

【讨论】:

  • 它覆盖了一切,我只需要覆盖背景