努力处理位图对象的基础字节以删除图像的透明度。
我有一个静态删除透明度方法,该方法采用一个Bitmap对象,相关代码:http://pastebin.com/ZjjPSdx8
现在,当我使用基于File的Bitmap对象调用它时,该位图不会发生突变。如果我理解正确,那是因为它基于http://support.microsoft.com/kb/814675的文件
因此创建了一种复制位图的方法:
http://pastebin.com/9rXRJ6cx
private Bitmap LoadBmp(string name)
{
Assembly asm = Assembly.GetExecutingAssembly();
string loc = Path.GetDirectoryName(asm.Location);
string path = Path.Combine(loc, "Images\\" + name);
Bitmap notsafe = (Bitmap)Bitmap.FromFile(path);
return ImageProcessor.SafeBitmap(notsafe);
...
一切都很好。适用于PNG,但不适用于GIF。他们可怕地出来
扭曲了。
尝试了将文件写入字节数组的另一种方法,然后将位图基于此:
byte[] b = new byte[2048];
int c;
byte[] imgArr;
using (FileStream fs = new FileStream(path, FileMode.Open))
{
using (MemoryStream ms = new MemoryStream())
{
while ((c = fs.Read(b, 0, b.Length)) > 0)
ms.Write(b, 0, c);
imgArr = ms.ToArray();
}
}
return (Bitmap)Bitmap.FromStream(new MemoryStream(imgArr));
这不会扭曲gif。但是我的删除透明方法不再适用于PNG!
显然我做错了,希望有人可以帮忙!
最佳答案
编辑:
从这样的文件加载时,可以解决不可变的位图问题:var bmp = new Bitmap(Image.FromFile("C:\bmp.bmp"))
这样可以避免您必须执行任何Marshal.Copy(速度很慢),也可以解决GIF残缺和变形的问题。如果需要的话,执行此操作的内部.NET代码如下:
g = Graphics.FromImage(this);
g.Clear(Color.Transparent);
g.DrawImage(original, 0, 0, width, height);
因此本质上是我在下面提供的用于解决透明度问题的代码,这些代码无法满足您的速度需求。
但是,如果您可以通过g.FromImage同时加载和复制,则我的速度为
(5.6 seconds g.FromImage vs 6.4 seconds yours with 1000 gifs @ 543x341)
从理论上讲,如果将复制和删除透明度结合到同一功能中,则可以使速度更快。如果在不重写图像的情况下加载GIF,则它将采用不同的像素格式,实际上是
8bppindexed
,这意味着您的功能将无法正常使用。无论哪种方式,上面的解决方案都可以在使用CheckIfTransparent函数时解决该问题,下面的解决方案(我必须对其进行了一些编辑)可以更快地完成。如果这样做,我可能会花一些时间来寻找。我觉得这个问题很有趣。我确实注意到您删除Alpha的算法并不完全准确。我不确定确切的位置,但是与透明渐变一起使用时,您的算法看起来不对。使用直接GDI的人看起来像预期的那样。我将确保您正确转换了颜色。
如果您只想删除png或gif上的透明度,请执行所有这些
Marshal.Copy
和不安全的代码,为什么不创建一个新的位图,将背景绘制为白色,然后在上面覆盖现有的png / gif?似乎不太复杂的代码。编辑:像这样:
public static Bitmap ManagedSafeBitmap(string file)
{
using (var img = Image.FromFile(file))
{
var bmp = new Bitmap(img.Width, img.Height);
bmp.SetResolution(img.HorizontalResolution, img.VerticalResolution);
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.White);
g.DrawImage(img, 0, 0);
}
return bmp;
}
}
这将为您提供带有白色背景的新图像,并将源图像置于该图像的顶部,从而有效地将所有透明像素更改为
Color.White
或您要通过g.Clear()
的任何颜色