4

I need to process and save images in their original bpp (1 - for BnW, 8 - for gray, 24 - color). After processing I always have 24bpp (due to processing with Aforge.Net). I pass original bpp to saving function and I'm using the next code for saving:

private static Bitmap changePixelFormat(Bitmap input, PixelFormat format)
    {
        Bitmap retval = new Bitmap(input.Width, input.Height, format);
        retval.SetResolution(input.HorizontalResolution, input.VerticalResolution);
        Graphics g = Graphics.FromImage(retval);
        g.DrawImage(input, 0, 0);
        g.Dispose();
        return retval;
    }

When I pass:

PixelFormat.Format8bppIndexed

I'm getting an exception: "Graphics object can't create image in indexed pixel format" in the line:

Graphics g = Graphics.FromImage(retval);

I've tried the next code:

Bitmap s = new Bitmap("gray.jpg");
        Bitmap NewPicture = s.Clone(new Rectangle(0, 0, s.Width, s.Height),                   PixelFormat.Format8bppIndexed);

After this "NewImage" has PixelFormat 8bppIndexed, but when I'm saving NewImage:

NewPicture.Save("hello.jpg", ImageFormat.Jpeg);

hello.jpg has 24bpp.

I need to keep bpp and image format of original image.

Why Bitmap.Save ignores PixelFormat of Bitmap?

=======================================================

Thanks guys, I've found a solution: http://freeimage.sourceforge.net/license.html

With help of this free library it is possible to save images (especially JPEG ) to Grayscale 8-bit.

xZ6a33YaYEfmv
  • 1,816
  • 4
  • 24
  • 43
  • So, what's the question? Why does `Bitmap.Save` ignore the `PixelFormat` of the image being saved? Or how do I get around the exception thrown by `Graphics.FromImage` with an indexed pixel format? – Cody Gray - on strike Jan 13 '11 at 12:13
  • Sorry, I haven't added a question. The question is: "Why Bitmap.Save ignores PixelFormat of Bitmap?" – xZ6a33YaYEfmv Jan 13 '11 at 12:17
  • You will have to save it as a GIF, if you want 8bit indexed. – leppie Jan 13 '11 at 12:23
  • Why? I have gray JPEG (source image) and I need to save it to gray JPEG. I can't change ImageFormat. – xZ6a33YaYEfmv Jan 13 '11 at 12:27
  • @ieaglle: It's not clear *why* you need to save the image in an indexed file format. If you just need a gray JPEG, why not use a different `PixelFormat`, such as "Format16bppGrayScale"? – Cody Gray - on strike Jan 13 '11 at 12:30
  • All I need is to keep bpp and image format of the original image. I've tried "Format16bppGrayScale" on 24bpp image but I'm getting exception: "Memory is insufficient" also in the line "Graphics g = Graphics.FromImage(retval);" – xZ6a33YaYEfmv Jan 13 '11 at 12:38
  • @ieaglle Maby filename extension is wrong. Maybe someone renamed it to .jpg and real file extension is .gif. Can you check that file structure is really jpeg ? – HABJAN Jan 13 '11 at 13:17
  • 3
    You cannot get this going with GDI+, it has very weak support for indexed pixel formats. And there just isn't much point to it, it was important back in the Windows 3 days. When the operating system was as large as the desktop wallpaper image you use today. – Hans Passant Jan 13 '11 at 14:36
  • 2
    @HansPassant there's still point to it if you work with very large bitmaps (example: http://www.naturalearthdata.com/downloads/10m-raster-data/10m-gray-earth/) – Igor Brejc Feb 06 '14 at 10:09

4 Answers4

5

I'm almost positive that the JPEG image format doesn't support indexed images. So even though you created the image specifying PixelFormat.Format8bppIndexed, GDI+ is converting it to a different format when you attempt to save it as a JPEG. In this case, you've already determined that's 24 bpp.

Instead, you need to save the image as a BMP or GIF. For example:

NewPicture.Save("hello.jpg", ImageFormat.Bmp);

See the table of image file formats supporting indexed color here on Wikipedia.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
4

Here is the code that will convert a Bitmap to 1bpp/8bpp bitmap. 1bpp/8bpp in C#.

In your changePixelFormat method you can check what fixel format it needs to be converted to, then if it's 1bpp or 8 bpp then use code from link and for all other formats use your code.

Graphics.FromImage documentation has remarks:

If the image has an indexed pixel format, this method throws an exception with the message, "A Graphics object cannot be created from an image that has an indexed pixel format." The indexed pixel formats are shown in the following list.

Format1bppIndexed

Format4bppIndexed

Format8bppIndexed

NEW PART:

This is what i found after short googling:

8bpp greyscale images and 8bpp jpg is not supported with gdiplus version 1.0. There is a new version of gdiplus in Windows 7 that supports greyscale images and more enhanced codec support.

8bpp indexed jpeg images are supported with Microsoft's WIC API.

You can try it yourself by downloading the WIC explorer from Microsoft's download site.

GDI+ 8 bit load/save bug

Standard JPEG only supports 24-bit image.

HABJAN
  • 9,212
  • 3
  • 35
  • 59
0

Use Graphics class for non indexed image. UseBitmap.LockBits and Bitmap.UnlockBits when processing indexed images

DavidW
  • 1
0

If you're looking for a true 8-bit grayscale bitmap image then I made a detailed StackOverflow post about it. It will work on any operating system (Windows/Mac/Linux), not just Windows 7. I hope it helps.

Community
  • 1
  • 1
Brent Matzelle
  • 4,073
  • 3
  • 28
  • 27