skip to Main Content

I’m trying to create a real grayscale image, but when my designer checks the file he is saying that the image remains RGB.

You can see the photoshop print here:
enter image description here

I’ve tried 2 methods so far:

1) Using the MakeGrayScale3 method:

    public static Image MakeGrayscale3(Image original)
    {
        //create a blank bitmap the same size as original
        Bitmap newBitmap = new Bitmap(original.Width, original.Height);
        newBitmap.SetResolution(original.HorizontalResolution, original.VerticalResolution);

        //get a graphics object from the new image
        Graphics g = Graphics.FromImage(newBitmap);

        //create the grayscale ColorMatrix
        ColorMatrix colorMatrix = new ColorMatrix(
           new float[][] 
              {
                 new float[] {.3f, .3f, .3f, 0, 0},
                 new float[] {.59f, .59f, .59f, 0, 0},
                 new float[] {.11f, .11f, .11f, 0, 0},
                 new float[] {0, 0, 0, 1, 0},
                 new float[] {0, 0, 0, 0, 1}
              });

        //create some image attributes
        ImageAttributes attributes = new ImageAttributes();

        //set the color matrix attribute
        attributes.SetColorMatrix(colorMatrix);

        //draw the original image on the new image
        //using the grayscale color matrix
        g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
           0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);

        //dispose the Graphics object
        g.Dispose();
        return newBitmap;
    }

2) Using the ImageMagick.Net library with this code:

                            using (MagickImage image = new MagickImage(file))
                            {
                                image.ColorSpace = ColorSpace.GRAY;

                                image.Write(originalFile);
                            }

If anyone had this problem before or have a clue of what to do to change that..

Thanks!

Original Image:

enter image description here

Result Image (ImageMagick):

enter image description here

Result Image (MakeGrayscale3):

enter image description here

3

Answers


  1. Chosen as BEST ANSWER

    Thanks for all answers but after read the topic that Hans mentioned there they talk about the FreeImageNET library that I'm using to solve my problem.

    Using this code I've managed to save the image as a grayscale image:

    FreeImageAPI.FreeImage.ConvertTo8Bits(newimg)
    

  2. The issue is this line:

    Bitmap newBitmap = new Bitmap(original.Width, original.Height);
    

    If you look at the MSDN page it says:

    This constructor creates a Bitmap with a PixelFormat enumeration value of Format32bppArgb.

    So, you’re just creating another color image. What you need to do is to use a different constructor to force a different format:

    Bitmap newBitmap = new Bitmap( original.Width, original.Height,
                                   PixelFormat.Format8bppIndexed );
    

    But then that gives you another issue – you can’t paint to bitmaps with that pixel format with a Graphics object. There is a PixelFormat.Format16bppGrayScale which appears to work even less.

    So, my suggestion would be to to this manually. Use LockBits to get access to the raw bitmap and do the conversion yourself. It is a little bit more work (i.e. you can’t use the ColorMatrix stuff, and you have to take care to check if the source bitmap is 24 bit or 32 bit), but it will work just fine.

    One issue to be aware of is that it’s not a “real” grayscale format, it’s 8 bit indexed. So you will also have to create a palette. Simply map each of the 256 values to the same, i.e. 0 -> 0, 100 -> 100, 255 -> 255.

    Login or Signup to reply.
  3. The grayscale format used by jpeg isn’t available in the classic System.Drawing classes. It is, however, available in System.Windows.Media. You need to add PresentationCore and WindowsBase as references for using them (this will not be portable on Linux).

    public static void SaveAsGrayscaleJpeg(String loadPath, String savePath)
    {
        using (FileStream fs = new FileStream(savePath, FileMode.Create))
        {
            BitmapSource img = new BitmapImage(new Uri(new FileInfo(loadPath).FullName));
            FormatConvertedBitmap convertImg = new FormatConvertedBitmap(img, PixelFormats.Gray8, null, 0);
            JpegBitmapEncoder encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(convertImg));
            encoder.Save(fs);
        }
    }
    

    As a bonus, this does the grayscale conversion automatically.

    If you’re actually starting from Image/Bitmap class, there are some solutions around for converting between them.

    Also you should pay attention to:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search