彩色反转性能提升Tiff图像- c#
本文关键字:Tiff 图像 性能 彩色 | 更新日期: 2023-09-27 18:17:08
我用的是Winforms。在我的表单中,我有一个图片框,我加载tiff文档。我使用下面的代码在按钮单击时在文档中来回反转颜色。我的代码的问题是,它是非常缓慢的。如何更快地转换图像的颜色?
图片信息:
- 图片尺寸:8.5 x 11英寸
- 像素密度:300 × 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; }
由于太多原因,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
看一下这个问题:
反转图像返回黑色图像
Dan在他的解决方案中使用了带有图像属性的颜色矩阵。
下面是你如何使用它(未经测试):
声明你的颜色矩阵,这样你就不必每次都重新定义它了:
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}
});
}
现在,在按钮单击事件中,提供图片框控件:
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对象is,因此您不应该像他那样调用Dispose
方法。
这可能会得到你需要的东西,但我没有任何东西可以测试。