【问题标题】:Color invert performance boost for Tiff images - C# [duplicate]Tiff 图像的颜色反转性能提升 - C# [重复]
【发布时间】:2015-10-09 15:07:56
【问题描述】:

我正在使用 Winforms。在我的表单中,我有一个图片框,用于加载 tiff 文档。我使用下面的代码在按钮单击时在文档中来回反转颜色。我的代码的问题是,它非常慢。如何更快地转换图像的颜色?

图片信息:

  • 图像尺寸:8.5 x 11 英寸
  • 像素密度:300 x 300 像素/英寸
  • 像素尺寸 - 2550 x 3300 像素(通常是因为我打开不同的文档进行查看)

    private void button1_Click(object sender, EventArgs e)
    {
        Bitmap pic = new Bitmap(pictureBox1.Image);
        for (int y = 0; (y <= (pic.Height - 1)); y++)
        {
            for (int x = 0; (x <= (pic.Width - 1)); x++)
            {
                Color inv = pic.GetPixel(x, y);
                inv = Color.FromArgb(255, (255 - inv.R), (255 - inv.G), (255 - inv.B));
                pic.SetPixel(x, y, inv);
            }
        }
        pictureBox1.Image = pic;
    
    }
    

【问题讨论】:

  • 您是否尝试搜索类似 "invert color fast c#" 之类的内容? Click.
  • 需要多少时间?图片的平均高度和宽度是多少?
  • 好吧,您的代码会在每个像素上进行迭代,以便在单击按钮后再次反转。您是否想过(在内存中)存储(在内存中)同一图像的两个版本(正常和反转)并通过单击按钮来切换它们?

标签: c# .net winforms colors


【解决方案1】:

GetPixel 和 SetPixel 真的很慢,原因太多了。此外,嵌套循环通常是一个坏主意。查看以下链接以获得更快的实现(不是最佳但更接近)

http://www.codeproject.com/Articles/1989/Image-Processing-for-Dummies-with-C-and-GDI-Part

它涉及使用不安全的代码和图像的 LockPixel 方法。

链接中的代码(需要在项目设置中允许不安全代码)

public static bool Invert(Bitmap b)
{
    // GDI+ still lies to us - the return format is BGR, NOT RGB. 
    BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), 
    ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); 
    int stride = bmData.Stride; 
    System.IntPtr Scan0 = bmData.Scan0; 
    unsafe 
    { 
        byte * p = (byte *)(void *)Scan0;
        int nOffset = stride - b.Width*3; 
        int nWidth = b.Width * 3;
        for(int y=0;y < b.Height;++y)
        {
            for(int x=0; x < nWidth; ++x )
            {
                p[0] = (byte)(255-p[0]);
                ++p;
            }
            p += nOffset;
        }
    }

    b.UnlockBits(bmData);

    return true;
}

如果由于您有不同的图像格式而导致此代码无法正常工作,那么您需要根据像素大小修改某些部分。 (示例中为常数 3) 您可以通过以下方式计算得到:

int pixelSize = imageData.Stride/image.Width;

替换

PixelFormat.Format24bppRgb 

b.PixelFormat

【讨论】:

  • 如何将代码与按钮单击事件一起使用? @CSharpie
  • 只要调用 Invert((Bitmap)pictureBox1.Image);如果那不更新 pictureBox1.Refresh();
  • 我必须添加小 Refresh();反转后((位图)pictureBox1.Image);谢谢你的帮助。代码执行速度非常快。
【解决方案2】:

看看这个问题:

Inverting image returns a black image

Dan 在his solution 中使用带有图像属性的颜色矩阵。

这是你将如何使用它(未经测试):

声明您的颜色矩阵,这样您就不必每次都重新定义它:

    System.Drawing.Imaging.ColorMatrix m_colorMatrix;

    private void Init()
    {
        // create the negative color matrix
        m_colorMatrix = new System.Drawing.Imaging.ColorMatrix(new float[][] {
            new float[] {-1, 0, 0, 0, 0},
            new float[] {0, -1, 0, 0, 0},
            new float[] {0, 0, -1, 0, 0},
            new float[] {0, 0, 0, 1, 0},
            new float[] {1, 1, 1, 0, 1}
        });
    }

现在,在您的按钮 Click 事件中,提供您的图片框控件:

    private void Button_Click(object sender, EventArgs e) {
        var source = new Bitmap(pictureBox1.Image);
        //create a blank bitmap the same size as original
        var bmpInvert = new Bitmap(source.Width, source.Height);

        //get a graphics object from the new image
        using (var g = Graphics.FromImage(bmpInvert))
        {

            // create some image attributes
            var attributes = new System.Drawing.Imaging.ImageAttributes();

            attributes.SetColorMatrix(m_colorMatrix);

            g.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height),
                        0, 0, source.Width, source.Height, GraphicsUnit.Pixel, attributes);

            pictureBox1.Image = bmpInvert;
        }
    }

由于我已将 Graphics 对象包含在 using 块中,因此您不应像他那样调用 Dispose 方法。

这可能会得到你需要的东西,但我没有任何东西可以测试它。

【讨论】:

  • Dans 代码看起来不错,但我不知道如何通过单击按钮调用他的代码。
  • @taji01 ,看看编辑后的版本,有代码。 +1 如果有帮助;如果它解决了您的问题,请稍后标记为答案。
  • 当我运行代码并单击按钮时。 System.Drawing.dll 中出现“System.ArgumentException”类型的未处理异常
  • 异常出现在哪一行?消息的文本是什么?这可能是一个简单的修复。
猜你喜欢
  • 2021-03-16
  • 2021-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 2013-12-20
  • 1970-01-01
  • 2019-07-13
相关资源
最近更新 更多