努力处理位图对象的基础字节以删除图像的透明度。
我有一个静态删除透明度方法,该方法采用一个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()的任何颜色

10-08 08:41
查看更多