Title: Add GetPixel and SetPixel methods to the Bitmap24 class in C#
This example adds GetPixel and SetPixel methods to the Bitmap24 class described in the post Use the Bitmap24 class to manipulate image pixels very quickly in C#. Unfortunately that class only allows you manipulate pixel values in a one-dimensional byte array. It's easy enough to process every pixel in the same way, but working with the pixels in rows and columns is cumbersome.
Each pixel's data is stored in order: blue, green, red, and each pixel uses 3 bytes to store its color data. For example, the first three bytes give the first pixel's color components.
To find the bytes representing the pixel at position (x, y), the program skips y times the bitmap's stride. (Recall that the stride is the number of bytes per row.) It then adds 3 times the x value. The result gives the index of the pixel's blue byte. Add 1 to get the green byte or 2 to get the red byte.
The version of the Bitmap24 class provided by this example provides GetPixel, SetPixel, GetRed, SetRed, GetGreen, SetGreen, GetBlue, and SetBlue methods to make working with pixels easier.
// Provide easy access to the color values.
public void GetPixel(int x, int y,
out byte red, out byte green, out byte blue)
{
int i = y * m_BitmapData.Stride + x * 3;
blue = ImageBytes[i++];
green = ImageBytes[i++];
red = ImageBytes[i];
}
public void SetPixel(int x, int y,
byte red, byte green, byte blue)
{
int i = y * m_BitmapData.Stride + x * 3;
ImageBytes[i++] = blue;
ImageBytes[i++] = green;
ImageBytes[i] = red;
}
public byte GetRed(int x, int y)
{
int i = y * m_BitmapData.Stride + x * 3;
return ImageBytes[i + 2];
}
public void SetRed(int x, int y, byte red)
{
int i = y * m_BitmapData.Stride + x * 3;
ImageBytes[i + 2] = red;
}
public byte GetGreen(int x, int y)
{
int i = y * m_BitmapData.Stride + x * 3;
return ImageBytes[i + 1];
}
public void SetGreen(int x, int y, byte green)
{
int i = y * m_BitmapData.Stride + x * 3;
ImageBytes[i + 1] = green;
}
public byte GetBlue(int x, int y)
{
int i = y * m_BitmapData.Stride + x * 3;
return ImageBytes[i];
}
public void SetBlue(int x, int y, byte blue)
{
int i = y * m_BitmapData.Stride + x * 3;
ImageBytes[i] = blue;
}
These methods simply calculate the position of the appropriate bytes in the one-dimensional ImageBytes array and then get or set the appropriate byte.
The following code shows how the program uses the GetPixel and SetPixel methods to color the image's four quarters differently.
private void btnQuarter_Click(object sender, EventArgs e)
{
Bitmap bm = new Bitmap(picHidden.Image);
Cursor = Cursors.WaitCursor;
Stopwatch watch = new Stopwatch();
watch.Start();
// Make a Bitmap24 object.
Bitmap24 bm24 = new Bitmap24(bm);
// Lock the bitmap.
bm24.LockBitmap();
// Invert the pixels.
int xmid = bm24.Width / 2;
int ymid = bm24.Height / 2;
for (int y = 0; y < ymid; y++)
{
for (int x = 0; x < xmid; x++)
{
bm24.SetGreen(x, y, 0);
bm24.SetBlue(x, y, 0);
}
}
for (int y = ymid; y < bm24.Height; y++)
{
for (int x = 0; x < xmid; x++)
{
bm24.SetRed(x, y, 0);
bm24.SetGreen(x, y, 0);
}
}
for (int y = 0; y < ymid; y++)
{
for (int x = xmid; x < bm24.Width; x++)
{
bm24.SetRed(x, y, 0);
bm24.SetBlue(x, y, 0);
}
}
byte red, green, blue;
for (int y = ymid; y < bm24.Height; y++)
{
for (int x = xmid; x < bm24.Width; x++)
{
red = (byte)(255 - bm24.GetRed(x, y));
green = (byte)(255 - bm24.GetGreen(x, y));
blue = (byte)(255 - bm24.GetBlue(x, y));
bm24.SetPixel(x, y, red, green, blue);
}
}
// Unlock the bitmap.
bm24.UnlockBitmap();
picVisible.Image = bm;
watch.Stop();
Cursor = Cursors.Default;
lblElapsed.Text =
watch.Elapsed.TotalSeconds.ToString("0.000000") +
" seconds";
}
This code calculates the image's X and Y midpoints. In the image's first three quadrants, the code uses the SetRed, SetGreen, and SetBlue methods to zero out some of the pixels' color components. In the final quadrant, the code inverts the image's pixels.
Download the example to experiment with it and to see additional details.
|