Reputation: 2087
This is my bitmap object
Bitmap b = new Bitmap(columns, rows, PixelFormat.Format8bppIndexed);
BitmapData bmd = b.LockBits(new Rectangle(0, 0, columns, rows), ImageLockMode.ReadWrite, b.PixelFormat);
How do i convert this into a 8 bit grayscale bitmap ?
Upvotes: 4
Views: 11954
Reputation: 16431
hi you could change the color palette to a grayscale one
although the following code is in Vb.net. You could easily convert it to C#
Private Function GetGrayScalePalette() As ColorPalette
Dim bmp As Bitmap = New Bitmap(1, 1, Imaging.PixelFormat.Format8bppIndexed)
Dim monoPalette As ColorPalette = bmp.Palette
Dim entries() As Color = monoPalette.Entries
Dim i As Integer
For i = 0 To 256 - 1 Step i + 1
entries(i) = Color.FromArgb(i, i, i)
Next
Return monoPalette
End Function
Original Source -> http://social.msdn.microsoft.com/Forums/en-us/vblanguage/thread/500f7827-06cf-4646-a4a1-e075c16bbb38
Upvotes: 2
Reputation: 26355
Note that if you want to do the same conversion as modern HDTVs, you'll want to use the Rec. 709 coefficients for the conversion. The ones provided above (.3, .59, .11) are (almost) the Rec. 601 (standard def) coefficients. The Rec. 709 coefficients are gray = 0.2126 R' + 0.7152 G' + 0.0722 B', where R', G', and B' are the gamma adjusted red, green, and blue components.
Upvotes: 2
Reputation: 4353
Check this link out. We did this at university and it works.
It is all you need with input and output.
Upvotes: 0
Reputation: 941465
Yes, no need to change the pixels, just the palette is fine. ColorPalette is a flaky type, this sample code worked well:
var bmp = Image.FromFile("c:/temp/8bpp.bmp");
if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format8bppIndexed) throw new InvalidOperationException();
var newPalette = bmp.Palette;
for (int index = 0; index < bmp.Palette.Entries.Length; ++index) {
var entry = bmp.Palette.Entries[index];
var gray = (int)(0.30 * entry.R + 0.59 * entry.G + 0.11 * entry.B);
newPalette.Entries[index] = Color.FromArgb(gray, gray, gray);
}
bmp.Palette = newPalette; // Yes, assignment to self is intended
if (pictureBox1.Image != null) pictureBox1.Image.Dispose();
pictureBox1.Image = bmp;
I don't actually recommend you use this code, indexed pixel formats are a pita to deal with. You'll find a fast and more general color-to-grayscale conversion in this answer.
Upvotes: 5
Reputation: 7449
Something like:
Bitmap b = new Bitmap(columns, rows, PixelFormat.Format8bppIndexed);
for (int i = 0; i < columns; i++)
{
for (int x = 0; x < rows; x++)
{
Color oc = b.GetPixel(i, x);
int grayScale = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11));
Color nc = Color.FromArgb(oc.A, grayScale, grayScale, grayScale);
b.SetPixel(i, x, nc);
}
}
BitmapData bmd = b.LockBits(new Rectangle(0, 0, columns, rows), ImageLockMode.ReadWrite, b.PixelFormat);
Upvotes: 3