2012-03-25 47 views
4

我发现this code关于如何将颜色过滤器应用于C#中的位图对象。它的问题是它使用不安全的代码来实现这一点。有没有一种管理,安全的方式来做同样的事情?我知道我可以使用像AForge.NET或类似的库,但我希望有一个简单的方法来应用一个彩色滤镜。我需要的只是简单的颜色替换,用黄色代替白色像素。有什么建议么?将颜色过滤器应用到位图对象

回答

4

您可以随时使用安全的GetPixel和SetPixel方法,但在许多像素上使用时会很慢,这就是您使用不安全方法使用指向位图内存指针的原因。 不安全是做到这一点的方法。

如果您的位图非常小,并且您不关心性能,请使用GetPixel和SetPixel方法。

private void ReplaceColor(Bitmap bitmap, Color originalColor, Color replacementColor) 
    { 
     for (var y = 0; y < bitmap.Height; y++) 
     { 
      for (var x = 0; x < bitmap.Width; x++) 
      { 
       if (bitmap.GetPixel(x, y) == originalColor) 
       { 
        bitmap.SetPixel(x, y, replacementColor); 
       } 
      } 
     } 
    } 

    private unsafe void ReplaceColorUnsafe(Bitmap bitmap, byte[] originalColor, byte[] replacementColor) 
    { 
     if (originalColor.Length != replacementColor.Length) 
     { 
      throw new ArgumentException("Original and Replacement arguments are in different pixel formats."); 
     } 

     if (originalColor.SequenceEqual(replacementColor)) 
     { 
      return; 
     } 

     var data = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size), 
            ImageLockMode.ReadWrite, 
            bitmap.PixelFormat); 

     var bpp = Image.GetPixelFormatSize(data.PixelFormat); 

     if (originalColor.Length != bpp) 
     { 
      throw new ArgumentException("Original and Replacement arguments and the bitmap are in different pixel format."); 
     } 

     var start = (byte*)data.Scan0; 
     var end = start + data.Stride; 

     for (var px = start; px < end; px += bpp) 
     { 
      var match = true; 

      for (var bit = 0; bit < bpp; bit++) 
      { 
       if (px[bit] != originalColor[bit]) 
       { 
        match = false; 
        break; 
       } 
      } 

      if (!match) 
      { 
       continue; 
      } 

      for (var bit = 0; bit < bpp; bit++) 
      { 
       px[bit] = replacementColor[bit]; 
      } 
     } 

     bitmap.UnlockBits(data); 
    } 

用法是:

 this.ReplaceColor(myBitmap, Color.White, Color.Yellow); // SLOW 

OR

 var orgRGB = new byte[] { 255, 255, 255 }; // White (in RGB format) 
     var repRGB = new byte[] { 255, 255, 0 }; // Yellow (in RGB format) 

     var orgARGB = new byte[] { 255, 255, 255, 255 }; // White (in ARGB format) 
     var repARGB = new byte[] { 255, 255, 255, 0 }; // Yellow (in ARGB format) 

     var orgRGBA = new byte[] { 255, 255, 255, 255 }; // White (in RGBA format) 
     var repRGBA = new byte[] { 255, 255, 0, 255 }; // Yellow (in RGBA format) 

     var orgBytes = orgRGB; // or ARGB or RGBA, depending on bitmap's pixel format 
     var repBytes = repRGB; // or ARGB or RGBA, depending on bitmap's pixel format 

     this.ReplaceColorUnsafe(myBitmap, orgBytes, repBytes); // FAST 
+0

我对此方法的速度有点担心,但我尝试过了,它实际上是相当快的。至少对于我在做什么而言!感谢这个解决方案! – Icemanind 2012-03-25 17:25:28

+0

位图位阻是快速执行此操作的常用方法。乐意效劳。 – SimpleVar 2012-03-25 19:59:09

+0

这是我可以使用并行扩展为了使它的工作速度两倍? – Icemanind 2012-03-25 22:35:34