我正在使用Winforms。在我的表格中,我有一个图片框,我加载tiff文件。我使用下面的代码在按钮单击时在文档中来回反转颜色。我的代码的问题是,它非常慢。如何更快地转换图像的颜色?
图片信息:
像素尺寸 - 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;
}
答案 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
方法。
这可能会得到你所需要的东西,但我没有任何东西可以测试它。