gpt4 book ai didi

c# - 为什么使用 Lockbits 编辑图像仍然需要 7 秒?

转载 作者:太空宇宙 更新时间:2023-11-03 18:12:07 29 4
gpt4 key购买 nike

我的应用程序

我正在编写一个需要将 RGB 转换为灰度图像的应用程序。
转换有效,但转换 3648 * 2736 像素的图像大约需要 7 秒。
我知道 set 和 getpixel 需要一些时间。
但是我认为即使图像不小,如果您使用 Lockbits 也不应该花这么长时间。 (如果有错请纠正我)。
也许我只是在我的代码中犯了一个致命的错误。

代码

public static long ConvertToGrayScaleV2(Bitmap imageColor, bool useHDTVConversion)
{
Stopwatch stpw = new Stopwatch();
stpw.Start();
System.Drawing.Imaging.BitmapData imageColorData = imageColor.LockBits(new Rectangle(new Point(0, 0), imageColor.Size),
System.Drawing.Imaging.ImageLockMode.ReadWrite, imageColor.PixelFormat);

IntPtr PtrColor = imageColorData.Scan0;
int strideColor = imageColorData.Stride;
byte[] byteImageColor = new byte[Math.Abs(strideColor) * imageColor.Height];
System.Runtime.InteropServices.Marshal.Copy(PtrColor, byteImageColor, 0, Math.Abs(strideColor) * imageColor.Height);

int bytesPerPixel = getBytesPerPixel(imageColor);
byte value;
if (bytesPerPixel == -1)
throw new Exception("Can't get bytes per pixel because it is not defined for this image format.");
for (int x = 0, position; x < imageColor.Width * imageColor.Height; x++)
{
position = x * bytesPerPixel;
if (useHDTVConversion)
{
value = (byte)(byteImageColor[position] * 0.0722 + byteImageColor[position + 1] * 0.7152 + byteImageColor[position + 2] * 0.2126);
}
else
{
value = (byte)(byteImageColor[position] * 0.114 + byteImageColor[position + 1] * 0.587 + byteImageColor[position + 2] * 0.299);
}
byteImageColor[position] = value;
byteImageColor[position+1] = value;
byteImageColor[position+2] = value;

}

System.Runtime.InteropServices.Marshal.Copy(byteImageColor, 0, PtrColor, Math.Abs(strideColor) * imageColor.Height);
imageColor.UnlockBits(imageColorData);
stpw.Stop();
return stpw.ElapsedMilliseconds;
}

public static int getBytesPerPixel(Image img)
{
switch (img.PixelFormat)
{
case System.Drawing.Imaging.PixelFormat.Format16bppArgb1555: return 2;
case System.Drawing.Imaging.PixelFormat.Format16bppGrayScale: return 2;
case System.Drawing.Imaging.PixelFormat.Format16bppRgb555: return 2;
case System.Drawing.Imaging.PixelFormat.Format16bppRgb565: return 2;
case System.Drawing.Imaging.PixelFormat.Format1bppIndexed: return 1;
case System.Drawing.Imaging.PixelFormat.Format24bppRgb: return 3;
case System.Drawing.Imaging.PixelFormat.Format32bppArgb: return 4;
case System.Drawing.Imaging.PixelFormat.Format32bppPArgb: return 4;
case System.Drawing.Imaging.PixelFormat.Format32bppRgb: return 4;
case System.Drawing.Imaging.PixelFormat.Format48bppRgb: return 6;
case System.Drawing.Imaging.PixelFormat.Format4bppIndexed: return 1;
case System.Drawing.Imaging.PixelFormat.Format64bppArgb: return 8;
case System.Drawing.Imaging.PixelFormat.Format64bppPArgb: return 8;
case System.Drawing.Imaging.PixelFormat.Format8bppIndexed: return 1;
default: return -1;
}

}

最佳答案

我知道这是旧的,但有一些可能有值(value)的观点:
imageColor.Width * imageColor.Height是一项昂贵的操作,您运行的次数比您需要的次数多近 1000 万次 (3648 * 2736)。

  • for循环正在重新计算 每次迭代
  • 不仅如此,CLR 还必须导航到 Bitmap 对象的 Width。和 Height房产 每个 在这 1000 万次中也是如此。这比您每次尝试在位图上运行时所需的操作多 3000 万次。

  • 改变:
    for (int x = 0, position; x < imageColor.Width * imageColor.Height; x++)
    {
    ...
    }

    到:
    var heightWidth = imageColor.Width * imageColor.Height;
    for (int x = 0, position; x < heightWidth; x++)
    {
    ...
    }

    如果您缓存三种不同操作(R、G、B,有 255 个可能值)的所有潜在结果,并使用查找新值而不是计算新值 1000 万次,您还将看到巨大的性能提升.

    这是完整的、非常快速的代码(比 ColorMatrix 快得多)。请注意,我已将所有可能的预先计算的值移动到局部变量中,并且在循环中涉及的工作绝对最少。
                    var lookupR = new byte[256];
    var lookupG = new byte[256];
    var lookupB = new byte[256];
    var rVal = hdtv ? 0.114 : 0.0722;
    var gVal = hdtv ? 0.587 : 0.7152;
    var bVal = hdtv ? 0.299 : 0.2126;
    for (var originalValue = 0; originalValue < 256; originalValue++)
    {
    var r = (byte)(originalValue * rVal);
    var g = (byte)(originalValue * gVal);
    var b = (byte)(originalValue * bVal);
    // Just in case...
    if (r > 255) r = 255;
    if (g > 255) g = 255;
    if (b > 255) b = 255;
    lookupR[originalValue] = r;
    lookupG[originalValue] = g;
    lookupB[originalValue] = b;
    }
    unsafe
    {
    var pointer = (byte*)(void*)bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
    var bytesPerPixel = getBytesPerPixel(bitmap);
    var heightWidth = bitmap.Width * bitmap.Height;
    for (var y = 0; y < heightWidth; ++y)
    {
    var value = (byte) (lookupR[pointer[0]] + lookupG[pointer[1]] + lookupB[pointer[2]]);
    pointer[0] = value;
    pointer[1] = value;
    pointer[2] = value;
    pointer += bytesPerPixel;
    }
    bitmap.UnlockBits();
    }
    break;

    关于c# - 为什么使用 Lockbits 编辑图像仍然需要 7 秒?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12806531/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com