使用Graphics.DrawImage()绘制带有透明度/Alpha通道的图像

22

我正在复制一张图片。(我的实际代码正在调整图片大小,但这与我的问题无关。)我的代码大致如下。

Image src = ...

using (Image dest = new Bitmap(width, height))
{
    Graphics graph = Graphics.FromImage(dest);
    graph.InterpolationMode = InterpolationMode.HighQualityBicubic;
    graph.DrawImage(src, 0, 0, width, height);
    dest.Save(filename, saveFormat);
}

这似乎效果很好,除非从带有透明度的图像(例如GIF)或带有Alpha通道的图像(例如PNG)中加载src

我该如何让DrawImage()将透明度/Alpha通道传输到新图像,并在保存文件时保留它们?


1
问题是 saveFormat 变量的值是什么?它应该是 PixelFormat.Format32bppArgb(或另一种带有 alpha 通道处理的格式)。也可以尝试:using (Image dest = new Bitmap(width, height, PixelFormat.Format32bppArgb)) - Lukasz M
这似乎适用于alpha通道,但不适用于GIF透明度。saveFormat将根据输入文件的格式而变化。如果输入文件不支持alpha通道,则可以安全地假定图像不包含alpha通道像素。 - Jonathan Wood
那么,对于GIF文件,saveFormat的值是什么呢? :) - Lukasz M
在这种情况下,它是 ImageFormat.Gif - Jonathan Wood
感谢您的快速回复。与此同时,我已经找到了一篇关于GIF透明度的文章。请查看:http://support.microsoft.com/kb/319061。我想基本上您只需要获取图像的调色板,并将保存在第一个索引中的颜色设置为透明即可。 - Lukasz M
显示剩余8条评论
2个回答

30

这段描述相当含糊不清,你漏掉了很多细节。透明度的最大问题在于它是看不见的。你跳过了几个步骤,没有明确指定新位图的像素格式,也没有进行初始化,并且没有说明输出格式。有些格式不支持透明度。因此,让我们制作一个更加清晰明了的版本。从在paint.net中看起来像这样的PNG图像开始:

图片描述

使用以下代码:

        using (var src = new Bitmap("c:/temp/trans.png"))
        using (var bmp = new Bitmap(100, 100, PixelFormat.Format32bppPArgb)) 
        using (var gr = Graphics.FromImage(bmp)) {
            gr.Clear(Color.Blue);
            gr.DrawImage(src, new Rectangle(0, 0, bmp.Width, bmp.Height));
            bmp.Save("c:/temp/result.png", ImageFormat.Png);
        }

生成如下图所示的图片:

在此输入图片描述

你可以清晰地看到蓝色的背景,说明透明效果生效了。


1
我的意图是支持与输入文件匹配的任何格式。我认为我说得很明确。只是这段代码不是只支持一种文件类型的。也许我需要一堆代码来处理每种文件类型——我不知道。我确实尝试过像你这样指定PixelFormat,但是当文件类型是带透明度的GIF时似乎会导致错误。事实上,有些变化似乎在没有指定PixelFormat的情况下可以很好地使用PNG。 - Jonathan Wood
@JonathanWood 使用旧位图的宽度和高度创建一个新的位图,并使用所需的新格式。最好在using语句中,创建一个Graphics对象 FromImage(你的新位图)DrawImage(你的旧位图) - user1881400

0
我发现这个线程是因为我遇到了同样的问题(即DrawImage没有复制alpha通道),但在我的情况下,这只是因为我忽视了我使用了PixelFormat.Format32bppRgb而不是PixelFormat.Format32bppArgb。所以基本上就像Lukasz M在评论中说的那样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接