2012-04-05 51 views
1

我想两个图像删除阿尔法通道(纯色的切片图像只)

我用这个源代码之间的区别:

public Bitmap GetDifference(Bitmap bm1, Bitmap bm2) 
     { 

      if (bm1.Size != bm2.Size) 
       throw new ArgumentException("exception"); 


      var resultImage = new Bitmap(bm1.Width, bm1.Height); 

      using (Graphics g = Graphics.FromImage(resultImage)) 
       g.Clear(Color.Transparent); 


      for (int w = 0; w < bm1.Width; w++) 
      { 
       for (int h = 0; h < bm1.Height; h++) 
       { 
        var bm2Color = bm2.GetPixel(w, h); 
        if (IsColorsDifferent(bm1.GetPixel(w, h), bm2Color)) 
        { 
         resultImage.SetPixel(w, h, bm2Color);      
        }     
       } 
      } 

      return resultImage; 
     } 


     bool IsColorsDifferent(Color c1, Color c2) 
     { 
      return c1 != c2; 
     } 

此源工作对我好,但我有以下问题:

例如,如果我选择分辨率为480x320的图像,我的resultImage具有相同的分辨率(这是corect,因为我在创建新位图时设置),但我的图像具有透明色,而我只想用纯色获得结果图像。让我们说 - 如果在480x320的固体结果图像(纯色像素)有100x100场,我应该得到这个坚实的位图,分辨率为100x100。

简而言之,我只需要得到与纯色和阿尔法香奈儿一切接壤的矩形。

谢谢!

+3

当你遇到alpha通道> 0的像素时(假设你有矩形部分,这很容易),你将需要扫描图像并跟踪边界。另外请注意,'GetPixel'和'SetPixel'作为一只狗很慢。一只非常慢的狗。如果他们为你工作,并且你知道你的输入图像总是很小,那就好了。如果图像的大小是未知的,我不认为这是不成熟的优化,深入研究'不安全的'上下文,并通过'LockBits'获取指向图像缓冲区的指针。 – 2012-04-05 01:27:52

+0

谢谢,是的,我知道。这将被用于创建一个包并且不会在运行时使用(只有一次性计算) – 2012-04-05 01:31:52

+1

哦,另一个图像处理提示;像现在这样,按行扫描图像,而不是列。这里的假设是你的图像数据以行方式存储在一个数组中(这几乎总是为真)。数据的地点在这里很重要。您的代码当前可能不会导致CPU缓存充满相邻数据。您将在每次迭代时刷新并填充缓存,这意味着需要更长时间从主内存抓取数据。如果你循环行明智会。 – 2012-04-05 01:35:51

回答

0

请参阅我下面写的类:

class ProcessingImage 
    {   
     public Bitmap GetDifference(Bitmap bm1, Bitmap bm2) 
     {    
      if (bm1.Size != bm2.Size) 
       throw new ArgumentException("Images must have one size"); 

      var resultImage = new Bitmap(bm1.Width, bm1.Height); 

      using (Graphics g = Graphics.FromImage(resultImage)) 
       g.Clear(Color.Transparent); 

      int min_height = int.MaxValue; 
      int min_width = int.MaxValue; 
      int max_height = -1; 
      int max_width = -1; 

      for (int w = 0; w < bm1.Width; w++) 
       for (int h = 0; h < bm1.Height; h++) 
       { 
        var bm2Color = bm2.GetPixel(w, h); 
        if (IsColorsDifferent(bm1.GetPixel(w, h), bm2Color)) 
        { 
         resultImage.SetPixel(w, h, bm2Color); 
         if (h < min_height) min_height = h; 
         if (w < min_width) min_width = w; 
         if (h > max_height) max_height = h; 
         if (w > max_width) max_width = w; 
        }      
       } 

      max_height = max_height + 1; //Needed for get valid max height point, otherwise we lost one pixel. 
      max_width = max_width + 1;  //Needed for get valid max width point, otherwise we lost one pixel. 


      // Calculate original size for image without alpha chanel. 

      int size_h = max_height - min_height; 
      int size_w = max_width - min_width; 

      var resizeImage = new Bitmap(size_w, size_h); // Creaete bitmap with new size. 

      for (int w = 0; w < resultImage.Width; w++) 
       for (int h = 0; h < resultImage.Height; h++) 
       { 
        var color = resultImage.GetPixel(w, h); 
        if (color.A != 0) 
        { 
         // Move each pixels at a distance calculate before. 
         int x = w - min_width; 
         int y = h - min_height; 
         resizeImage.SetPixel(x, y, color); 
        } 
       }   

      return resizeImage; 
     } 

     bool IsColorsDifferent(Color c1, Color c2) 
     { 
      return c1 != c2; 
     } 
    } 

我想,这个类可以修改优化,但现在它的作品好。如果你需要原始大小的图像而没有alpha通道 - 这是许多解决方案之一。

+0

注意:请参阅上面关于执行速度的注释。 – 2012-04-07 13:23:12