我有一个工具,跟踪条滑块控制,用于调整图像的亮度,对比度,伽马等。
当用户拖动滑块时,我正在尝试实时更新我的图像。亮度和伽马算法是一个可接受的速度(约170毫秒)。但对比算法约380 is。
基本上,我的表单是一个带有滑块的工具窗口。每次更新图像时,它都会向重新绘制新图像的父级发送一个事件。工具窗口将原始的未经修改的图像锁定在内存中,因此我始终可以访问它的字节。因此,基本上,每次滑块(例如对比度滑块)的ValueChanged事件发生更改时,我都会这样做。
工作(目标)位图的
代码:
double newValue = 0;
double c = (100.0 + contrast) / 100.0;
c *= c;
for (int i = 0; i < sourcePixels.Length; i++)
{
newValue = sourcePixels[i];
newValue /= 255.0;
newValue -= 0.5;
newValue *= c;
newValue += 0.5;
newValue *= 255;
if (newValue < 0)
newValue = 0;
if (newValue > 255)
newValue = 255;
destPixels[i] = (byte)newValue;
}我读过一次关于使用整数而不是浮点值来提高对比速度的文章,但是我再也找不到那篇文章了。
我尝试使用不安全的代码(指针),但实际上注意到速度下降了。我认为这是因为代码使用嵌套的for循环来迭代x和y,而不是单个循环。
发布于 2012-01-24 17:20:20
取决于您正在运行的机器,您的技术可能会非常慢。如果您使用的是没有FPU的ARM系统,那么每次操作都需要相当长的时间。由于您要对每个字节应用相同的操作,一种更快的技术是为对比度级别创建一个256条目查找表,然后通过该表翻译每个图像字节。然后,您的循环将如下所示:
byte contrast_lookup[256];
double newValue = 0;
double c = (100.0 + contrast) / 100.0;
c *= c;
for (int i = 0; i < 256; i++)
{
newValue = (double)i;
newValue /= 255.0;
newValue -= 0.5;
newValue *= c;
newValue += 0.5;
newValue *= 255;
if (newValue < 0)
newValue = 0;
if (newValue > 255)
newValue = 255;
contrast_lookup[i] = (byte)newValue;
}
for (int i = 0; i < sourcePixels.Length; i++)
{
destPixels[i] = contrast_lookup[sourcePixels[i]];
}发布于 2012-01-25 11:36:46
@BitBank回答了你的问题,我想补充一下,如果你追求性能,你应该考虑你的代码,得到像素数据,然后设置它。
使用指针的完整工作代码( for循环代码中指向@BitBank的道具):
private unsafe void ApplyContrast(double contrast, Bitmap bmp)
{
byte[] contrast_lookup = new byte[256];
double newValue = 0;
double c = (100.0 + contrast) / 100.0;
c *= c;
for (int i = 0; i < 256; i++)
{
newValue = (double)i;
newValue /= 255.0;
newValue -= 0.5;
newValue *= c;
newValue += 0.5;
newValue *= 255;
if (newValue < 0)
newValue = 0;
if (newValue > 255)
newValue = 255;
contrast_lookup[i] = (byte)newValue;
}
var bitmapdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
int PixelSize = 4;
for (int y = 0; y < bitmapdata.Height; y++)
{
byte* destPixels = (byte*)bitmapdata.Scan0 + (y * bitmapdata.Stride);
for (int x = 0; x < bitmapdata.Width; x++)
{
destPixels[x * PixelSize] = contrast_lookup[destPixels[x * PixelSize]]; // B
destPixels[x * PixelSize + 1] = contrast_lookup[destPixels[x * PixelSize + 1]]; // G
destPixels[x * PixelSize + 2] = contrast_lookup[destPixels[x * PixelSize + 2]]; // R
//destPixels[x * PixelSize + 3] = contrast_lookup[destPixels[x * PixelSize + 3]]; //A
}
}
bmp.UnlockBits(bitmapdata);
}如果您使用Marshal.Copy设置图像像素数据,您会发现效果更好。
这应该比当前代码执行得更快,并且减少了内存占用,这在处理非常大的图像时是很好的。
https://stackoverflow.com/questions/8990926
复制相似问题