Reputation: 4002
For Bitmap
, there is a MakeTransparent
method, is there one similar for changing one color to another?
// This sets Color.White to transparent
Bitmap myBitmap = new Bitmap(sr.Stream);
myBitmap.MakeTransparent(System.Drawing.Color.White);
Is there something that can do something like this?
Bitmap myBitmap = new Bitmap(sr.Stream);
myBitmap.ChangeColor(System.Drawing.Color.Black, System.Drawing.Color.Gray);
Upvotes: 10
Views: 12795
Reputation: 455
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.
Upvotes: 4
Reputation: 7189
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
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.
Upvotes: -1
Reputation: 43300
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);
Upvotes: 11
Reputation: 1690
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.
Upvotes: -2