Using GetPixel and SetPixel is easy but very slow so I'm trying to using LockBits.
I have this method I did long time ago to compare between two images:
public static Bitmap FastComparison(Bitmap bmp1,Bitmap bmp2)
{
tolerancenumeric = 15;
int tolerance = tolerancenumeric * tolerancenumeric +
tolerancenumeric * tolerancenumeric +
tolerancenumeric * tolerancenumeric; //dr * dr + dg * dg + db * db;
bmp3 = new Bitmap(512,512);
PixelFormat pxf = PixelFormat.Format24bppRgb;
Rectangle rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
BitmapData bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadWrite, pxf);
BitmapData bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadWrite, pxf);
BitmapData bmpData3 = bmp3.LockBits(rect, ImageLockMode.ReadWrite, pxf);
IntPtr ptr1 = bmpData1.Scan0;
IntPtr ptr2 = bmpData2.Scan0;
IntPtr ptr3 = bmpData3.Scan0;
int numBytes = bmpData1.Stride * bmp1.Height;
byte[] rgbValues1 = new byte[numBytes];
Marshal.Copy(ptr1, rgbValues1, 0, numBytes);
bmp1.UnlockBits(bmpData1);
byte[] rgbValues2 = new byte[numBytes];
Marshal.Copy(ptr2, rgbValues2, 0, numBytes);
bmp2.UnlockBits(bmpData2);
for (int counter = 0; counter < rgbValues1.Length; counter += 3)
{
int dr, dg, db;
dr = (int)rgbValues2[counter] - (int)rgbValues1[counter];
dg = (int)rgbValues2[counter + 1] - (int)rgbValues1[counter + 1];
db = (int)rgbValues2[counter + 2] - (int)rgbValues1[counter + 2];
int error = dr * dr + dg * dg + db * db;
int y, x;
y = (counter / 3) / 512;
x = (counter - y * 512 * 3)/3;
if ((x == 479) && (y == 474))
{
Byte r1, g1, b1, r2, g2, b2;
r1 = rgbValues1[counter];
b1 = rgbValues1[counter+1];
g1 = rgbValues1[counter+2];
r2 = rgbValues2[counter];
b2 = rgbValues2[counter+1];
g2 = rgbValues2[counter+2];
}
if (error < tolerance)
{
rgbValues1[counter] = 0;
rgbValues1[counter + 1] = 0;
rgbValues1[counter + 2] = 0;
}
}
Marshal.Copy(rgbValues1, 0, ptr3, numBytes);
bmp3.UnlockBits(bmpData3);
return bmp3;
}
But now I want to use also LockBits but with one image and to color all the pixels that are not black in yellow.
I started new method:
public Bitmap ChangeColors(Bitmap bmp1)
{
bmpColors = new Bitmap(512, 512);
PixelFormat pxf = PixelFormat.Format24bppRgb;
Rectangle rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
BitmapData bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadWrite, pxf);
IntPtr ptr1 = bmpData1.Scan0;
int numBytes = bmpData1.Stride * bmp1.Height;
byte[] rgbValues1 = new byte[numBytes];
Marshal.Copy(ptr1, rgbValues1, 0, numBytes);
bmp1.UnlockBits(bmpData1);
for (int counter = 0; counter < rgbValues1.Length; counter += 3)
{
int y, x;
y = (counter / 3) / 512;
x = (counter - y * 512 * 3) / 3;
Byte r1, g1, b1;
r1 = rgbValues1[counter];
b1 = rgbValues1[counter + 1];
g1 = rgbValues1[counter + 2];
}
return bmpColors;
}
But not sure how to make it so the bitmap bmpColors will be the original one but with all pixels that are not black in yellow.
How about simply testing the bytes and setting them accordingly?
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
for shades of black, and for the yellows maybe:
BTW: You need to check on those indices; the last time I looked the data in the LockBits array were reversed: not
RGB
, (let aloneRBG
as you have it) butBGR
! (And for 32bppBGRA
!)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:
Then call it like:
Note I didn't have my filter function take a Color because constructing a Color struct from Argb values can be oddly slow.