Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3072
  • Last Modified:

Convert bitmap from 24 bit to monochrome.

Hi,

Is there an "easy" way of converting a 24 bit bitmap to a monochrome image (the same as "save as - monochrome" in mspaint for example).

Thanks.

James.
0
JAMES
Asked:
JAMES
  • 6
  • 5
1 Solution
 
AlexFMCommented:
This is pure .NET way:

using System.Drawing.Imaging;
using System.Runtime.InteropServices;


        Bitmap ConvertRGB24ToMonochrome(Bitmap source)
        {
            if ( source.PixelFormat != PixelFormat.Format24bppRgb )
            {
                return null;
            }

            Byte[] colorBytes = BitmapToBytesRGB24(source);

            if ( colorBytes == null )
            {
                 return null;
            }

            Byte[] monoBytes = new Byte[source.Width * source.Height];

            int j = 0;

            for ( int i = 0; i < source.Width * source.Height; i++ )
            {
                monoBytes[i] = (Byte)(0.3f * (float)colorBytes[j + 2] + 0.59f * (float)colorBytes[j + 1] + 0.11f * (float)colorBytes[j]);

                j += 3;
            }

            return BitsToBitmapMonochrome(monoBytes, source.Width, source.Height);
        }

        // Create monochrome bitmap from Byte array
        Bitmap BitsToBitmapMonochrome(Byte[] bytes, int width, int height)
        {
            if (bytes.GetLength(0) < width * height)
            {
                return null;
            }

            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
            int i;

            bmp.Palette = GetGrayScalePalette();
           
            //for (i = 0; i < 256; i++)
            //{
            //    bmp.Palette.Entries[i] = Color.FromArgb(i, i, i);
            //}
           

            BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.WriteOnly, bmp.PixelFormat);


            if (data.Stride == width * 3)
            {
                Marshal.Copy(bytes, 0, data.Scan0, width * height);
            }
            else
            {
                for (i = 0; i < bmp.Height; i++)
                {
                    IntPtr p = new IntPtr(data.Scan0.ToInt32() + data.Stride * i);
                    Marshal.Copy(bytes, i * bmp.Width, p, bmp.Width);
                }
            }

            bmp.UnlockBits(data);

            return bmp;
        }


        // Create Byte array from RGB24 bitmap
        Byte[] BitmapToBytesRGB24(Bitmap bmp)
        {
            if ( bmp.PixelFormat != PixelFormat.Format24bppRgb )
            {
                return null;
            }

            int i;
            int length = bmp.Width * bmp.Height * 3;

            Byte[] bytes = new Byte[length];

            BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.ReadOnly, bmp.PixelFormat);

            if (data.Stride == bmp.Width * 3)
            {
                Marshal.Copy(data.Scan0, bytes, 0, length);
            }
            else
            {
                for ( i = 0; i < bmp.Height; i++ )
                {
                    IntPtr p = new IntPtr(data.Scan0.ToInt32() + data.Stride * i);
                    Marshal.Copy(p, bytes, i * bmp.Width * 3, bmp.Width * 3);
                }
            }

            bmp.UnlockBits(data);

            return bytes;
        }


        ColorPalette GetGrayScalePalette()
        {
            Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed);

            ColorPalette monoPalette = bmp.Palette;

            Color[] entries = monoPalette.Entries;

            for ( int i = 0; i < 256; i++ )
            {
                entries[i] = Color.FromArgb(i, i, i);
            }

            return monoPalette;
        }
    }
0
 
JAMESAuthor Commented:
Cool - many thanks.

James.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
AlexFMCommented:
Correction in BitsToBitmapMonochrome function:

if (data.Stride == width * 3)

should be

if (data.Stride == width)
0
 
JAMESAuthor Commented:
Thanks.
0
 
JAMESAuthor Commented:
Alex,

Not sure if you still see any messages posted here now this one is closed but after using the above method I have discovered the PixelFormat of captured bitmaps is PixelFormat.Format32bppArgb.

Should I be able to use the same routine anyway (after altering the initial check which returns null) ?

Thanks.

James.
0
 
AlexFMCommented:
You can create RGB24 bitmap, explicitly providing PixelFormat parameter to Bitmap constructor, for capturing code. Try this, if it doesn't work, I will post code for 32 bpp bitmap.

0
 
JAMESAuthor Commented:
I *think* it works but the result looks different to when I "save as" to Monochrome in MS Paint.
0
 
AlexFMCommented:
Changed without test, hope it will work:

        Bitmap ConvertRGB32ToMonochrome(Bitmap source)
        {
            if ( source.PixelFormat != PixelFormat.Format32bppRgb )
            {
                return null;
            }

            Byte[] colorBytes = BitmapToBytesRGB32(source);

            if ( colorBytes == null )
            {
                 return null;
            }

            Byte[] monoBytes = new Byte[source.Width * source.Height];

            int j = 0;

            for ( int i = 0; i < source.Width * source.Height; i++ )
            {
                monoBytes[i] = (Byte)(0.3f * (float)colorBytes[j + 2] + 0.59f * (float)colorBytes[j + 1] + 0.11f * (float)colorBytes[j]);

                j += 4;
            }

            return BitsToBitmapMonochrome(monoBytes, source.Width, source.Height);
        }

        // Create monochrome bitmap from Byte array
        Bitmap BitsToBitmapMonochrome(Byte[] bytes, int width, int height)
        {
            if (bytes.GetLength(0) < width * height)
            {
                return null;
            }

            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
            int i;

            bmp.Palette = GetGrayScalePalette();
           
            BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.WriteOnly, bmp.PixelFormat);


            if (data.Stride == width)
            {
                Marshal.Copy(bytes, 0, data.Scan0, width * height);
            }
            else
            {
                for (i = 0; i < bmp.Height; i++)
                {
                    IntPtr p = new IntPtr(data.Scan0.ToInt32() + data.Stride * i);
                    Marshal.Copy(bytes, i * bmp.Width, p, bmp.Width);
                }
            }

            bmp.UnlockBits(data);

            return bmp;
        }


        // Create Byte array from RGB32 bitmap
        Byte[] BitmapToBytesRGB32(Bitmap bmp)
        {
            if ( bmp.PixelFormat != PixelFormat.Format32bppRgb )
            {
                return null;
            }

            int i;
            int length = bmp.Width * bmp.Height * 4;

            Byte[] bytes = new Byte[length];

            BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.ReadOnly, bmp.PixelFormat);

            if (data.Stride == bmp.Width * 4)
            {
                Marshal.Copy(data.Scan0, bytes, 0, length);
            }
            else
            {
                for ( i = 0; i < bmp.Height; i++ )
                {
                    IntPtr p = new IntPtr(data.Scan0.ToInt32() + data.Stride * i);
                    Marshal.Copy(p, bytes, i * bmp.Width * 4, bmp.Width * 4);
                }
            }

            bmp.UnlockBits(data);

            return bytes;
        }


        ColorPalette GetGrayScalePalette()
        {
            Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed);

            ColorPalette monoPalette = bmp.Palette;

            Color[] entries = monoPalette.Entries;

            for ( int i = 0; i < 256; i++ )
            {
                entries[i] = Color.FromArgb(i, i, i);
            }

            return monoPalette;
        }
    }
0
 
JAMESAuthor Commented:
Does it matter you are using Format32bppRBG but my pixelformat is Format32bppArgb ?

Sorry to possibly be asking dumb questions but this level of image manipulation is new to me.

Many thanks.

james.
0
 
AlexFMCommented:
It is just result of my "online" correction, Format32bppArgb is correct.
0
 
vikasparashar320Commented:
But i want to change the bitmap image to 1 Bpp Monochrome.  as like in MS paint
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 6
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now