Tiff图像的色彩反转性能提升 - C#

时间:2015-10-09 15:07:56

标签: c# .net winforms colors invert

我正在使用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;
    
    }
    

2 个答案:

答案 0 :(得分:2)

由于太多原因,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

答案 1 :(得分:1)

看看这个问题:

Inverting image returns a black image

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

以下是您将如何使用它(未经测试):

声明您的Color Matrix,这样您就不必每次都重新定义它:

    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事件中,提供Picture Box控件:

    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对象包含在使用块中,因此您不应该像他一样调用Dispose方法。

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