crowso
crowso

Reputation: 2087

convert 8 bit color bmp image to 8 bit grayscale bmp

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

Answers (5)

klijo
klijo

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

user1118321
user1118321

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

radu florescu
radu florescu

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

Hans Passant
Hans Passant

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

Emmanuel N
Emmanuel N

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

Related Questions