-1

我有一个小函数,它将位图中的像素从给定颜色重新着色为新的给定颜色。

我对代码的问题如下:

1)该函数给出的结果是重新映射白色像素,因为我有一个阈值,所以不应该考虑......(除非我定义了这个计算错误)

2)当给出某些颜色时,例如在从函数返回的图像中看到 LimeGreen 奇怪的结果(我相信这是由于加法或减法情况下字节类型的溢出)

我正在使用的基本图像可以在这里找到:

http://www.freeimagehosting.net/uploads/c8745a9de1.png

我得到的结果可以在这里找到:

freeimagehosting.net/uploads/fa48e5a0eb.png (调用 Color.Magenta 作为 remapColor,Color.Red 作为 newColor,似乎影响了白色像素并且渐变的末端没有正确着色)

freeimagehosting.net/uploads/8faec6a569.png (调用 Color.Magenta 作为 remapColor,Color.Yellow 作为 newColor,似乎影响了白色像素并且渐变的末端没有正确着色)

freeimagehosting.net/uploads/2efd4c04aa.png (调用 Color.Magenta 作为 remapColor,Color.Blue 作为 newColor,似乎渐变不正确着色)

freeimagehosting.net/uploads/defdf04e16.png (调用 Color.Magenta 作为 remapColor,Color.Teal 作为 newColor,似乎影响了白色像素并且没有正确计算渐变)

我对这段代码的功能如下:根据建议更新

public unsafe static Bitmap RecolorImage(Bitmap original, Color remapColor, Color newColor)
    {
        Bitmap result = new Bitmap(original.Width, original.Height);

        //lock the original bitmap in memory
        BitmapData originalData = original.LockBits(
           new Rectangle(0, 0, original.Width, original.Height),
           ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

        //lock the new bitmap in memory
        BitmapData newData = result.LockBits(
           new Rectangle(0, 0, original.Width, original.Height),
           ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

        //set the number of bytes per pixel
        int pixelSize = 4;

        int rthreshold = 128;
        int gthreshold = 128;
        int bthreshold = 128;

        for (int y = 0; y < original.Height; y++)
        {
            //get the data from the original image
            byte* oRow = (byte*)originalData.Scan0 + (y * originalData.Stride);

            //get the data from the new image
            byte* nRow = (byte*)newData.Scan0 + (y * newData.Stride);

            for (int x = 0; x < original.Width; x++)
            {
                //examine the rgb values
                byte r = (byte)((oRow[x * pixelSize]));
                byte g = (byte)((oRow[x * pixelSize + 1]));
                byte b = (byte)((oRow[x * pixelSize + 2]));
                byte a = (byte)((oRow[x * pixelSize + 3]));

                if (a > 0 && 
                    Math.Abs(remapColor.R - r) <= rthreshold &&
                    Math.Abs(remapColor.B - b) <= bthreshold &&
                    Math.Abs(remapColor.G - g) <= gthreshold 
                    )
                {
                    if (newColor.R == 0)
                    {
                        r = 0;
                    }
                    else
                    {
                        if (newColor.R > remapColor.R)
                            r = (byte)(r - newColor.R);
                        else
                            r = (byte)(r + newColor.R);
                    }

                    if (newColor.G == 0)
                    {
                        g = 0;
                    }
                    else
                    {
                        if (newColor.G > remapColor.G)
                            g = (byte)(g - newColor.G);
                        else
                            g = (byte)(g + newColor.G);
                    }

                    if (newColor.B == 0)
                    {
                        b = 0;
                    }
                    else
                    {
                        if (newColor.B > remapColor.B)
                            b = (byte)(b - newColor.B);
                        else
                            b = (byte)(b + newColor.B);
                    }
                }


                //set the new image's pixel remaped pixel color
                nRow[x * pixelSize] = b; //B
                nRow[x * pixelSize + 1] = g; //G
                nRow[x * pixelSize + 2] = r; //R
                nRow[x * pixelSize + 3] = a; //A
            }
        }

        original.UnlockBits(originalData);
        result.UnlockBits(newData);


        return result;
    }        

是什么赋予了....

我正在尝试做的事情可能吗?

它可靠吗?

我的代码中只有一个错误吗?

有没有更好的方法来使用渐变在位图上实现这种“可重新映射技术”?

感谢您的时间。

4

2 回答 2

0

看起来您的阈值测试不正确。走这条线:

remapColor.R - r <= rthreshold

如果当前像素是白色的,那么r将是 255,并且无论是什么remapColor.Rrthreshold是,测试都将始终为真。

我认为Math.Abs(remapColor.R - r)可能会奏效。

而且您的字节值超出范围可能是正确的。修复阈值测试可能会阻止这种情况发生。否则,请尝试设置一些边界检查以查看它发生的位置。

于 2010-07-13T18:17:19.383 回答
0

我已经决定,尽管如果我研究有关色彩空间的各种材料及其支持理论,这可能是可能的。似乎这将比一些快速阈值计算和对 remapColor 的规范化多一点。

我将建议不要对光栅位图图像执行这种类型的修改,而是以矢量形式修改图形。

该过程应该是这样的:

图形是在设计师正在使用的任何成像套件中创建的。

它们被保存为矢量格式,例如 SVG,这将允许使用 SVG 渲染引擎 ( http://svg.codeplex.com/ )以编程方式命名、遍历和更改可自定义的路径(如果需要,还可以使用更多颜色)

使用此解决方案,如果支持,我们可以将 SVG 直接输出到浏览器并直接在客户端上进行修改,或者在需要时使用服务器并输出为 PNG。

我觉得这种安排将为我们提供比我最初打算一起破解的更灵活和更强大的解决方案。

谢谢你们的时间!

于 2010-07-14T12:34:02.900 回答