This project has moved. For the latest updates, please go here.

Create a grayscale png image from a byte buffer

Nov 13, 2015 at 9:07 AM
Hello everyone,

I would like to create a grayscale png image from a byte buffer containing the 8bits gray values. The following code show how i do until now. This is clearly not the best way so what is the good one ?

I don't know how to read my one channel pixels byte array .

Thank you for your help.
        //convert raw buffer to grayscale 8 bits png image
        static void SaveGrayscale8bitsPngImage(byte[] pixels, string path)
        {
            MagickReadSettings settings = new MagickReadSettings();
            settings.Width = 640;
            settings.Height = 480;
            settings.PixelStorage = new PixelStorageSettings(StorageType.Char, "R");

            using (MagickImage image = new MagickImage(pixels, settings))
            {
                image.Grayscale(PixelIntensityMethod.Average);
                image.Format = MagickFormat.Png;
                image.SetDefine(MagickFormat.Png, "color-type", "0"); //0 = grayscale image 
                image.SetDefine(MagickFormat.Png, "bit-depth", "8"); //number of bits per index
                image.SetDefine(MagickFormat.Png, "compression-level", "9"); //valid values are 0 through 9, with 0 providing the least but fastest compression and 9 usually providing the best and always the slowest.

                image.Write(path);
            }
        }
Nov 13, 2015 at 12:08 PM
here is a way to do it a bit better:
        //convert raw buffer to grayscale 8 bits png image
        static void SaveGrayscale8bitsPngImage(byte[] pixels, string path)
        {
            MagickReadSettings settings = new MagickReadSettings();
            settings.Width = 640;
            settings.Height = 480;
            settings.PixelStorage = new PixelStorageSettings(StorageType.Char, "R");

            MagickImage imageTmp = new MagickImage(pixels, settings);

            MagickImage image = imageTmp.Separate(Channels.Red).First();
            image.Format = MagickFormat.Png;
            image.SetDefine(MagickFormat.Png, "color-type", "0"); //0 = grayscale image 
            image.SetDefine(MagickFormat.Png, "bit-depth", "8"); //number of bits per index
            image.SetDefine(MagickFormat.Png, "compression-level", "9"); //valid values are 0 through 9, with 0 providing the least but fastest compression and 9 usually providing the best and always the slowest.
            image.Write(path);
        }
Coordinator
Nov 13, 2015 at 12:19 PM
Can you share a file that contains pixel data? Feel free to contact me through CodePlex when you don't want to share it publicly.

I am really surprised that you need to call imageTmp.Separate(Channels.Red). Your image should already have a single channel. What does image.Channels.Count() return in your first example?
Nov 13, 2015 at 12:50 PM
In fact my input is a pixel array (byte[] pixels), I get this array from the camera API i'm using. I just don't know how to transform this array into a MagickImage. How do I tell to Magick.net library that my array is a grayscale (1 channel) 8bits per pixel image ?
Coordinator
Nov 13, 2015 at 1:11 PM
Doing this should be enough:
settings.PixelStorage = new PixelStorageSettings(StorageType.Char, "R");
Are you using the Q8 version of Magick.NET? Do you receive an exception? Can you put the byte array in a file and share it?