Link to home
Start Free TrialLog in
Avatar of JAMES
JAMES

asked on

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.
Avatar of AlexFM
AlexFM

ASKER CERTIFIED SOLUTION
Avatar of AlexFM
AlexFM

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of JAMES

ASKER

Cool - many thanks.

James.
Correction in BitsToBitmapMonochrome function:

if (data.Stride == width * 3)

should be

if (data.Stride == width)
Avatar of JAMES

ASKER

Thanks.
Avatar of JAMES

ASKER

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.
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.

Avatar of JAMES

ASKER

I *think* it works but the result looks different to when I "save as" to Monochrome in MS Paint.
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;
        }
    }
Avatar of JAMES

ASKER

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.
It is just result of my "online" correction, Format32bppArgb is correct.
But i want to change the bitmap image to 1 Bpp Monochrome.  as like in MS paint