替换位图/图像中特定颜色的高效方法

4
在我的灰度图像中,我需要找到特定的值并用一些颜色(例如黄色)替换它。这是我现在拥有的代码,但它不够快。有没有更有效的方法来实现这个目标呢?我已经阅读了关于ColorMatrix类的内容,但找不到只替换单个值而不影响整个图像的方法。
unsafe
{
    byte stlThres = 115;

    int bytePerPixel = Image.GetPixelFormatSize(kpImageViewer1.Image.PixelFormat) / 8;
    var data = kpImageViewer1.Image.LockBits(new Rectangle(0, 0, kpImageViewer1.Image.Width, kpImageViewer1.Image.Height), ImageLockMode.WriteOnly, kpImageViewer1.Image.PixelFormat);
    for (int y = 0; y < data.Height; y++)
    {
        byte* row = (byte*)data.Scan0 + (y * data.Stride);

        for (int x = 0; x < data.Width; x++, row += bytePerPixel)
        {
            if (row[0] == stlThres)
            {
                row[0] = 0; //b
                row[1] = 255; //g
                row[2] = 255; //r
                if (bytePerPixel == 4)
                {
                    row[3] = 255; //a
                }
            }
        }
    }
    kpImageViewer1.Image.UnlockBits(data);
}

你可以尝试使用BitBlt。这里有一个VB示例:http://www.vbaccelerator.com/home/VB/Tips/Replace_One_Colour_With_Another_in_a_Picture/article.asp - mbeckish
1
非常微小的调整可能是将您的data.Scan0data.Widthdata.StrideBytePerPixel == 4检查完全移出循环,因为它们在循环期间实际上是常量(最后一个意味着您必须复制基本循环结构)。这可能会提供微小的(但有可能是可测量的)改进,具体取决于调用频率和位图大小。 - Chris Sinclair
添加图片的你的结果和实际结果 - KF2
1个回答

1
在4通道图像的情况下,每个像素为4字节(每通道8位),您可以使用一个256项查找表,通过索引row[0]并将所有四个通道同时分配为单个32位int

好的观点,但四通道图像非常罕见,我添加了此检查只是为了兼容性。所以现在我缺少Int24类型 :D - VladL
在三通道图像的情况下,您可以尝试同时处理4个像素,并使用一些位掩码将它们视为3个“int”。 - Adi Shavit
请问您能否举个例子? - VladL
我不确定这真的值得花费这个精力。只需将4通道测试从循环外移除,并保持循环紧凑即可。 - Adi Shavit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接