/// <summary> /// (see http://stackoverflow.com/questions/16346212/can-you-change-one-colour-to-another-in-an-bitmap-image /// and https://msdn.microsoft.com/en-GB/library/ms229672%28v=vs.90%29.aspx) /// </summary> /// <param name="bmp"></param> /// <param name="inColourR"></param> /// <param name="inColourG"></param> /// <param name="inColourB"></param> /// <param name="outColourR"></param> /// <param name="outColourG"></param> /// <param name="outColourB"></param> internal unsafe static Bitmap changeColour(this Bitmap original, Color oldColor, Color newColor, int Tolerance = 0,enPixelCompare CompareType = enPixelCompare.pc_RGB_all) { byte inColourR_max, inColourG_max, inColourB_max; byte inColourR_min, inColourG_min, inColourB_min; byte outColourR, outColourG, outColourB; int tempValue; //create a clone of the original Bitmap newBitmap = (Bitmap)original.Clone(); tempValue = (int)oldColor.R + Tolerance; inColourR_max = (tempValue > 255) ? (byte)255 : (byte)tempValue ; tempValue = (int)oldColor.G + Tolerance; inColourG_max = (tempValue > 255) ? (byte)255 : (byte)tempValue ; tempValue = (int)oldColor.B + Tolerance; inColourB_max = (tempValue > 255) ? (byte)255 : (byte)tempValue ; tempValue = (int)oldColor.R - Tolerance; inColourR_min = (tempValue < 0) ? (byte)0 : (byte)tempValue ; tempValue = (int)oldColor.G - Tolerance; inColourG_min = (tempValue < 0) ? (byte)0: (byte)tempValue ; tempValue = (int)oldColor.B - Tolerance; inColourB_min = (tempValue < 0) ? (byte)0 : (byte)tempValue ; outColourR = newColor.R; outColourG = newColor.G; outColourB = newColor.B; // Specify a pixel format. PixelFormat pxf = original.PixelFormat; // Lock the bitmap's bits. Rectangle rect = new Rectangle(0, 0, newBitmap.Width, newBitmap.Height); BitmapData bmpData = newBitmap.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 = newBitmap.Width * newBitmap.Height * 3; int numBytes = bmpData.Stride * newBitmap.Height; byte[] rgbValues = new byte[numBytes]; // Copy the RGB values into the array. Marshal.Copy(ptr, rgbValues, 0, numBytes); double newColorBrightness = (double)(newColor.R+newColor.R+newColor.B+newColor.G+newColor.G+newColor.G)/6.0; // Manipulate the bitmap for (int line = 0; line < bmpData.Height ; line += 1) { for (int pixel = 0; (pixel+3) < bmpData.Stride ; pixel += 3) { int currentPixel = line * bmpData.Stride + pixel; switch (CompareType) { case enPixelCompare.pc_RGB_all: if (((rgbValues[currentPixel] >= inColourB_min) && (rgbValues[currentPixel] <= inColourB_max)) && ((rgbValues[currentPixel + 1] >= inColourG_min) && (rgbValues[currentPixel + 1] <= inColourG_max)) && ((rgbValues[currentPixel + 2] >= inColourR_min) && (rgbValues[currentPixel + 2] <= inColourR_max))) { rgbValues[currentPixel] = outColourB; rgbValues[currentPixel + 1] = outColourG; rgbValues[currentPixel + 2] = outColourR; } break; case enPixelCompare.pc_RGB_single: if (((rgbValues[currentPixel] >= inColourB_min) && (rgbValues[currentPixel] <= inColourB_max)) || ((rgbValues[currentPixel + 1] >= inColourG_min) && (rgbValues[currentPixel + 1] <= inColourG_max)) || ((rgbValues[currentPixel + 2] >= inColourR_min) && (rgbValues[currentPixel + 2] <= inColourR_max))) { rgbValues[currentPixel] = outColourB; rgbValues[currentPixel + 1] = outColourG; rgbValues[currentPixel + 2] = outColourR; } break; case enPixelCompare.pc_Brightness: double currentBrighness = (double)(rgbValues[currentPixel + 2]+rgbValues[currentPixel + 2]+ rgbValues[currentPixel] + rgbValues[currentPixel + 1]+rgbValues[currentPixel + 1]+rgbValues[currentPixel + 1]) /6.0; if (Math.Abs(currentBrighness - newColorBrightness) <= Tolerance) { rgbValues[currentPixel] = outColourB; rgbValues[currentPixel + 1] = outColourG; rgbValues[currentPixel + 2] = outColourR; } break; } } } // Copy the RGB values back to the bitmap Marshal.Copy(rgbValues, 0, ptr, numBytes); // Unlock the bits. newBitmap.UnlockBits(bmpData); return newBitmap; }
/// <summary> /// (see http://stackoverflow.com/questions/16346212/can-you-change-one-colour-to-another-in-an-bitmap-image /// and https://msdn.microsoft.com/en-GB/library/ms229672%28v=vs.90%29.aspx) /// </summary> /// <param name="bmp"></param> /// <param name="inColourR"></param> /// <param name="inColourG"></param> /// <param name="inColourB"></param> /// <param name="outColourR"></param> /// <param name="outColourG"></param> /// <param name="outColourB"></param> internal unsafe static Bitmap changeColour(this Bitmap original, Color oldColor, Color newColor, int Tolerance = 0, enPixelCompare CompareType = enPixelCompare.pc_RGB_all) { byte inColourR_max, inColourG_max, inColourB_max; byte inColourR_min, inColourG_min, inColourB_min; byte outColourR, outColourG, outColourB; int tempValue; //create a clone of the original Bitmap newBitmap = (Bitmap)original.Clone(); tempValue = (int)oldColor.R + Tolerance; inColourR_max = (tempValue > 255) ? (byte)255 : (byte)tempValue; tempValue = (int)oldColor.G + Tolerance; inColourG_max = (tempValue > 255) ? (byte)255 : (byte)tempValue; tempValue = (int)oldColor.B + Tolerance; inColourB_max = (tempValue > 255) ? (byte)255 : (byte)tempValue; tempValue = (int)oldColor.R - Tolerance; inColourR_min = (tempValue < 0) ? (byte)0 : (byte)tempValue; tempValue = (int)oldColor.G - Tolerance; inColourG_min = (tempValue < 0) ? (byte)0: (byte)tempValue; tempValue = (int)oldColor.B - Tolerance; inColourB_min = (tempValue < 0) ? (byte)0 : (byte)tempValue; outColourR = newColor.R; outColourG = newColor.G; outColourB = newColor.B; // Specify a pixel format. PixelFormat pxf = original.PixelFormat; // Lock the bitmap's bits. Rectangle rect = new Rectangle(0, 0, newBitmap.Width, newBitmap.Height); BitmapData bmpData = newBitmap.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 = newBitmap.Width * newBitmap.Height * 3; int numBytes = bmpData.Stride * newBitmap.Height; byte[] rgbValues = new byte[numBytes]; // Copy the RGB values into the array. Marshal.Copy(ptr, rgbValues, 0, numBytes); double newColorBrightness = (double)(newColor.R + newColor.R + newColor.B + newColor.G + newColor.G + newColor.G) / 6.0; // Manipulate the bitmap for (int line = 0; line < bmpData.Height; line += 1) { for (int pixel = 0; (pixel + 3) < bmpData.Stride; pixel += 3) { int currentPixel = line * bmpData.Stride + pixel; switch (CompareType) { case enPixelCompare.pc_RGB_all: if (((rgbValues[currentPixel] >= inColourB_min) && (rgbValues[currentPixel] <= inColourB_max)) && ((rgbValues[currentPixel + 1] >= inColourG_min) && (rgbValues[currentPixel + 1] <= inColourG_max)) && ((rgbValues[currentPixel + 2] >= inColourR_min) && (rgbValues[currentPixel + 2] <= inColourR_max))) { rgbValues[currentPixel] = outColourB; rgbValues[currentPixel + 1] = outColourG; rgbValues[currentPixel + 2] = outColourR; } break; case enPixelCompare.pc_RGB_single: if (((rgbValues[currentPixel] >= inColourB_min) && (rgbValues[currentPixel] <= inColourB_max)) || ((rgbValues[currentPixel + 1] >= inColourG_min) && (rgbValues[currentPixel + 1] <= inColourG_max)) || ((rgbValues[currentPixel + 2] >= inColourR_min) && (rgbValues[currentPixel + 2] <= inColourR_max))) { rgbValues[currentPixel] = outColourB; rgbValues[currentPixel + 1] = outColourG; rgbValues[currentPixel + 2] = outColourR; } break; case enPixelCompare.pc_Brightness: double currentBrighness = (double)(rgbValues[currentPixel + 2] + rgbValues[currentPixel + 2] + rgbValues[currentPixel] + rgbValues[currentPixel + 1] + rgbValues[currentPixel + 1] + rgbValues[currentPixel + 1]) / 6.0; if (Math.Abs(currentBrighness - newColorBrightness) <= Tolerance) { rgbValues[currentPixel] = outColourB; rgbValues[currentPixel + 1] = outColourG; rgbValues[currentPixel + 2] = outColourR; } break; } } } // Copy the RGB values back to the bitmap Marshal.Copy(rgbValues, 0, ptr, numBytes); // Unlock the bits. newBitmap.UnlockBits(bmpData); return(newBitmap); }