2011-07-27 46 views
3

在操纵Bitmap对象的基础字节以消除图像的透明度方面苦苦挣扎。 我有一个静态移除透明​​度的方法,采用一个位图对象,培训相关代码:http://pastebin.com/ZjjPSdx8C#中的位图字节操作

现在,当我把这种基于文件的位图对象,该位不被突变。如果我理解正确的话,这是因为它是基于一个文件按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! 显然我做错了什么,希望有人可以帮忙!

+1

与你的问题没有直接关系,但是如果'File'对象有一个美妙的'ReadAllBytes()'方法''System.IO.File.ReadAllBytes()' –

回答

4

编辑:

从文件加载这样时,你可以解决你的不变位的问题:

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); 

所以它实际上是我给你以下,解决您的透明度问题,这不符合您的需求速度的代码。的(5.6 seconds g.FromImage vs 6.4 seconds yours with 1000 gifs @ 543x341)

理论上

但是,如果你能做到的负荷,并在通过g.FromImage同时复制,我有速度,你可以让你更快,当你将复制和删除透明度相同的功能。如果您在不改写图像的情况下加载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()

+0

想想更大的图片! –

+0

是的,原来是这样做的,但是想挤出更多的速度。托管方法比MakeSafe和CleanTransparent的组合速度慢大约50%。如果没有安全措施(尽管承认它没有这个功能就行不通了),它的速度慢了300%。 我会处理很多图像,以便速度差异很重要...(百万)。 – user865864

+0

请参阅我上面的编辑。 –

0

我想尝试WriteableBitmap类。我听说只是为了使用托管代码进行像素操作而创建的。