首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >位图的快速对比算法

位图的快速对比算法
EN

Stack Overflow用户
提问于 2012-01-24 17:04:06
回答 2查看 15.5K关注 0票数 7

我有一个工具,跟踪条滑块控制,用于调整图像的亮度,对比度,伽马等。

当用户拖动滑块时,我正在尝试实时更新我的图像。亮度和伽马算法是一个可接受的速度(约170毫秒)。但对比算法约380 is。

基本上,我的表单是一个带有滑块的工具窗口。每次更新图像时,它都会向重新绘制新图像的父级发送一个事件。工具窗口将原始的未经修改的图像锁定在内存中,因此我始终可以访问它的字节。因此,基本上,每次滑块(例如对比度滑块)的ValueChanged事件发生更改时,我都会这样做。

工作(目标)位图的

  • LockBits作为Format24bppRgb (原始位图在Format24bppRgb中,位到byte[]数组
  • 检查我正在执行的操作(选择哪个滑块)
  • 使用以下代码进行对比:

代码:

代码语言:javascript
运行
复制
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,而不是单个循环。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-24 17:20:20

取决于您正在运行的机器,您的技术可能会非常慢。如果您使用的是没有FPU的ARM系统,那么每次操作都需要相当长的时间。由于您要对每个字节应用相同的操作,一种更快的技术是为对比度级别创建一个256条目查找表,然后通过该表翻译每个图像字节。然后,您的循环将如下所示:

代码语言:javascript
运行
复制
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]];
}
票数 14
EN

Stack Overflow用户

发布于 2012-01-25 11:36:46

@BitBank回答了你的问题,我想补充一下,如果你追求性能,你应该考虑你的代码,得到像素数据,然后设置它。

使用指针的完整工作代码( for循环代码中指向@BitBank的道具):

代码语言:javascript
运行
复制
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设置图像像素数据,您会发现效果更好。

这应该比当前代码执行得更快,并且减少了内存占用,这在处理非常大的图像时是很好的。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8990926

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档