【问题标题】:Delete alpha chanel on bitmap c# (Slicing image of solid color only)删除位图c#上的alpha通道(仅限纯色切片图像)
【发布时间】:2012-04-05 01:23:15
【问题描述】:

我想得到两张图片之间的区别

我使用这个源代码:

 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 具有相同的分辨率(这是正确的,因为我在创建新位图时设置了),但我的图像具有透明颜色,我想获得结果图像仅限纯色。

让我们说 - 如果 480x320 中的纯色结果图像(纯色像素)具有 100x100 字段,我应该只获得分辨率为 100x100 的纯色位图。

简单地说,我只需要获得以纯色和 alpha chanel 为边界的矩形。

谢谢!

【问题讨论】:

  • 当您遇到 alpha 通道 > 0 的像素时,您需要扫描图像并跟踪边界(假设您有矩形部分,这很容易)。还要注意GetPixelSetPixel 像狗一样慢。真是一只慢热的狗。如果他们为您工作,并且您知道您的输入图像将始终非常小,那很好。如果图像的大小未知,我认为深入研究unsafe 上下文并通过LockBits 获取指向图像缓冲区的指针并不是过早的优化。
  • 谢谢,是的,我知道。这将用于创建一个包,而不是在运行时使用(仅一次计算)
  • 哦,又一个图像处理技巧;按行扫描图像,而不是像现在这样按列扫描。这里的假设是您的图像数据按行存储在数组中(这几乎总是正确的)。数据的局部性在这里很重要。您的代码目前可能不会导致 CPU 缓存中充满相邻数据。您将在每次迭代中刷新和填充缓存,这意味着从主内存中获取数据的行程更长。如果你按行循环它会。
  • @EdS。你能写下你的提示作为答案吗?它对其他人可能有用。谢谢

标签: c# image-processing bitmap


【解决方案1】:

请看我下面写的课程:

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 通道的图像 - 这是众多解决方案之一。

【讨论】:

  • 注意:关于执行速度请参见上面的 cmets。
猜你喜欢
  • 2014-11-28
  • 2021-08-30
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
  • 1970-01-01
  • 2017-10-11
  • 1970-01-01
  • 2012-11-08
相关资源
最近更新 更多