Can you change one colour to another in an Bitmap image?

前端 未结 4 1929
别跟我提以往
别跟我提以往 2021-01-02 12:53

For Bitmap, there is a MakeTransparent method, is there one similar for changing one color to another?

// This sets Color.White to          


        
相关标签:
4条回答
  • 2021-01-02 13:32

    Lifting the code from this answer:

    public static class BitmapExtensions
    {
        public static Bitmap ChangeColor(this Bitmap image, Color fromColor, Color toColor)
        {
            ImageAttributes attributes = new ImageAttributes();
            attributes.SetRemapTable(new ColorMap[]
            {
                new ColorMap()
                {
                    OldColor = fromColor,
                    NewColor = toColor,
                }
            }, ColorAdjustType.Bitmap);
    
            using (Graphics g = Graphics.FromImage(image))
            {
                g.DrawImage(
                    image,
                    new Rectangle(Point.Empty, image.Size),
                    0, 0, image.Width, image.Height,
                    GraphicsUnit.Pixel,
                    attributes);
            }
    
            return image;
        }
    }
    

    While I haven't benchmarked it, this should be faster than any solution that's doing GetPixel/SetPixel in a loop. It's also a bit more straightforward.

    0 讨论(0)
  • 2021-01-02 13:35

    Through curiosity to Yorye Nathan's comment, This is an extension that I created by modifying http://msdn.microsoft.com/en-GB/library/ms229672(v=vs.90).aspx.

    It can turn all pixels in a bitmap from one colour to another.

    public static class BitmapExt
    {
        public static void ChangeColour(this Bitmap bmp, byte inColourR, byte inColourG, byte inColourB, byte outColourR, byte outColourG, byte outColourB)
        {
            // Specify a pixel format.
            PixelFormat pxf = PixelFormat.Format24bppRgb;
    
            // Lock the bitmap's bits.
            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
            BitmapData bmpData =
            bmp.LockBits(rect, ImageLockMode.ReadWrite,
                         pxf);
    
            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;
    
            // Declare an array to hold the bytes of the bitmap. 
            // int numBytes = bmp.Width * bmp.Height * 3; 
            int numBytes = bmpData.Stride * bmp.Height;
            byte[] rgbValues = new byte[numBytes];
    
            // Copy the RGB values into the array.
            Marshal.Copy(ptr, rgbValues, 0, numBytes);
    
            // Manipulate the bitmap
            for (int counter = 0; counter < rgbValues.Length; counter += 3)
            {
                if (rgbValues[counter] == inColourR &&
                    rgbValues[counter + 1] == inColourG &&
                    rgbValues[counter + 2] == inColourB)
    
                 {
                    rgbValues[counter] = outColourR;
                    rgbValues[counter + 1] = outColourG;
                    rgbValues[counter + 2] = outColourB;
                 }
            }
    
            // Copy the RGB values back to the bitmap
            Marshal.Copy(rgbValues, 0, ptr, numBytes);
    
            // Unlock the bits.
            bmp.UnlockBits(bmpData);
        }
    }
    

    called by bmp.ChangeColour(0,128,0,0,0,0);

    0 讨论(0)
  • 2021-01-02 13:41

    You can use SetPixel for that:

    private void ChangeColor(Bitmap s, System.Drawing.Color source, System.Drawing.Color target)
    {
        for (int x = 0; x < s.Width; x++)
        {
            for (int y = 0; y < s.Height; y++)
            {
                if (s.GetPixel(x, y) == source)
                    s.SetPixel(x, y, target);
            }                
        }
    }
    

    GetPixel and SetPixel are wrappers around gdiplus.dll functions GdipBitmapGetPixel and GdipBitmapSetPixel accordingly

    Remarks:

    Depending on the format of the bitmap, GdipBitmapGetPixel might not return the same value as was set by GdipBitmapSetPixel. For example, if you call GdipBitmapSetPixel on a Bitmap object whose pixel format is 32bppPARGB, the pixel's RGB components are premultiplied. A subsequent call to GdipBitmapGetPixel might return a different value because of rounding. Also, if you call GdipBitmapSetPixel on a Bitmap object whose color depth is 16 bits per pixel, information could be lost during the conversion from 32 to 16 bits, and a subsequent call to GdipBitmapGetPixel might return a different value.

    0 讨论(0)
  • 2021-01-02 13:51

    You need a library that provides a way to modify the color space of an image without having to work with pixels. LeadTools has a pretty extensive image library that you can use that supports color space modifications, including swapping colors.

    0 讨论(0)
提交回复
热议问题