How can I color pixels that are not black in bitmap in yellow using LockBits?

为君一笑 提交于 2019-11-28 14:08:56

How about simply testing the bytes and setting them accordingly?

Byte r1, g1, b1;
r1 = rgbValues1[counter];         // should be + 2 !!
b1 = rgbValues1[counter + 1];     // should be + 0 !!
g1 = rgbValues1[counter + 2];     // should be + 1 !!

if (r1 + b1 + g1 == 0 ) 
{
    r1 = 255;
    g1 = 255;
}

Of course this assumes a real black and a basic yellow are ok with you..

If you need more control, you need a bit more code like

if (r1 + b1 + g1 < threshold)

for shades of black, and for the yellows maybe:

    r1 = myYellow_R;
    g1 = myYellow_G;
    b1 = myYellow_B;

BTW: You need to check on those indices; the last time I looked the data in the LockBits array were reversed: not RGB, (let alone RBG as you have it) but BGR! (And for 32bpp BGRA !)

Since you are using that old method, please also make sure your pixel format is ok; if it is 32bpp you'll need a few simple modifications.

The following should work on formats with un-indexed 8 byte colors, which is what you are using:

public static class BitmapHelper
{
    //http://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Advanced/PixelFormat.cs
    //http://msdn.microsoft.com/en-us/magazine/cc534995.aspx#id0070035
    private static void GetPixelFormatData(this PixelFormat pixelFormat, out byte bitsPerPixel, out byte bitsPerChannel, out bool hasAlpha, out bool premultiplyAlpha)
    {
        switch (pixelFormat)
        {
            //Specifies that the format is 24 bits per pixel; 8 bits each are used for the red, green, and blue components.
            case PixelFormat.Format24bppRgb:
                ///       Specifies that pixel format is 24 bits per pixel. The
                ///       color information specifies 16777216 shades of color of which 8 bits are red, 8
                ///       bits are green and 8 bits are blue.
                bitsPerPixel = 24;
                bitsPerChannel = 8;
                hasAlpha = false;
                premultiplyAlpha = false;
                break;

            //Specifies that the format is 32 bits per pixel; 8 bits each are used for the alpha, red, green, and blue components.
            case PixelFormat.Format32bppArgb:
                bitsPerPixel = 32;
                bitsPerChannel = 8;
                hasAlpha = true;
                premultiplyAlpha = false;
                break;

            //Specifies that the format is 32 bits per pixel; 8 bits each are used for the alpha, red, green, and blue components. The red, green, and blue components are premultiplied, according to the alpha component.
            case PixelFormat.Format32bppPArgb:
                bitsPerPixel = 32;
                bitsPerChannel = 8;
                hasAlpha = true;
                premultiplyAlpha = true;
                break;

            //Specifies that the format is 32 bits per pixel; 8 bits each are used for the red, green, and blue components. The remaining 8 bits are not used.
            case PixelFormat.Format32bppRgb:
                bitsPerPixel = 32;
                bitsPerChannel = 8;
                hasAlpha = false;
                premultiplyAlpha = false;
                break;

            //Specifies that the format is 48 bits per pixel; 16 bits each are used for the red, green, and blue components.
            case PixelFormat.Format48bppRgb:
                bitsPerPixel = 48;
                bitsPerChannel = 16;
                hasAlpha = false;
                premultiplyAlpha = false;
                break;

            //Specifies that the format is 64 bits per pixel; 16 bits each are used for the alpha, red, green, and blue components.
            case PixelFormat.Format64bppArgb:
                bitsPerPixel = 64;
                bitsPerChannel = 16;
                hasAlpha = true;
                premultiplyAlpha = false;
                break;

            //Specifies that the format is 64 bits per pixel; 16 bits each are used for the alpha, red, green, and blue components. The red, green, and blue components are premultiplied according to the alpha component.
            case PixelFormat.Format64bppPArgb:
                bitsPerPixel = 64;
                bitsPerChannel = 16;
                hasAlpha = true;
                premultiplyAlpha = true;
                break;

            default:
                throw new ArgumentException("Unsupported Pixel Format " + pixelFormat.ToString());
        }
    }

    // Derived by experimentation.
    const int BlueIndex = 0;
    const int GreenIndex = 1;
    const int RedIndex = 2;
    const int AlphaIndex = 3;

    public delegate bool TransformColorFunc(ref byte r, ref byte g, ref byte b, ref byte a);

    public static void PaintSafe(Bitmap bmp, TransformColorFunc filter)
    {
        BitmapData bData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);
        try
        {
            byte bitsPerPixel;
            byte bitsPerChannel;
            bool hasAlpha;
            bool premultiplyAlpha;
            bmp.PixelFormat.GetPixelFormatData(out bitsPerPixel, out bitsPerChannel, out hasAlpha, out premultiplyAlpha);
            if (bitsPerChannel != 8)
                throw new ArgumentException();
            if ((bitsPerPixel % 8) != 0)
                throw new ArgumentException();
            if ((!hasAlpha && bitsPerPixel < 24) || (hasAlpha && bitsPerPixel < 32))
                throw new ArgumentException();

            int size = bData.Stride * bData.Height;
            byte[] data = new byte[size];

            System.Runtime.InteropServices.Marshal.Copy(bData.Scan0, data, 0, size);
            for (int iPixel = 0; iPixel < size; iPixel += bitsPerPixel / 8)
            {
                // Format is b, g, r, [a if present.]
                byte b = data[iPixel + BlueIndex];
                byte g = data[iPixel + GreenIndex];
                byte r = data[iPixel + RedIndex];
                byte a;
                if (hasAlpha)
                    a = data[iPixel + AlphaIndex];
                else
                    a = 255;
                if (filter(ref r, ref g, ref b, ref a))
                {
                    // Format is b, g, r, [a if present.]
                    data[iPixel + BlueIndex] = b;
                    data[iPixel + GreenIndex] = g;
                    data[iPixel + RedIndex] = r;
                    if (hasAlpha)
                        data[iPixel + AlphaIndex] = a;
                }
            }
            System.Runtime.InteropServices.Marshal.Copy(data, 0, bData.Scan0, data.Length);
        }
        finally
        {
            bmp.UnlockBits(bData);
        }
    }
}

Then call it like:

    static bool TransformNonBlackToYellow(ref byte r, ref byte g, ref byte b, ref byte a)
    {
        if (r != 0 || g != 0 || b != 0)
        {
            r = 255;
            g = 255;
            b = 0;
            a = 255;
            return true;
        }
        return false;
    }

    BitmapHelper.PaintSafe(bitmap, TransformNonBlackToYellow);

Note I didn't have my filter function take a Color because constructing a Color struct from Argb values can be oddly slow.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!