Question

I'm having a strange problem - I have about 14.5 million bitmap images, that are supposedly uncompressed. I need to convert these bitmaps to JPG and store them in a database.

When I use the classes provided in the .NET System.Drawing library to save the bitmap as a ImageFormat.Jpeg, the resulting JPEG is about twice the size of the original Bitmap. Here is the code:

byte[] bitmapBytes = //get from the db
using(MemoryStream bitmapStream = new MemoryStream(bitmapBytes))
{
   using(Bitmap bitmap = (Bitmap)Bitmap.FromStream(bitmapStream))
   {
       bitmap.Save("jpg.jpg", ImageFormat.Jpeg);
   }
}

I have looked through the HEX of several of these images, and it looks like the compression setting is "none". So I'm assuming they are uncompressed. Additionally, the HEX for the original file has the "BMP" code and the resulting file has the "JFIF" code as you would expect.

The images are black and white, no colors.

Any thoughts as to why this would be happening? Looking for pointers in the right direction...

Edits:

  • I've tried using the alternate overload to save that allows you to specify the quality. No benefit seen.
  • I should also specify that I'm kind of stuck with JPEG to some degree here. This is a legacy system and other parts of the system expect JPEG.

Image attributes:

  • Bitmap dimensions: 152x48
  • Bitmap file size: 1022 bytes
  • JPEG: same dimension
  • JPEG size: 2.2 kb
  • Bitmap info: Indexed, 1 layer (2 colors)
  • Bitmap resolution: 96.012x 96.012 ppi
Was it helpful?

Solution

It's probably because the jpeg images you are saving are now 24bit RGB color images, where the bitmaps are 1 bpp black and white images.

If the bitmaps are 1 bpp, jpeg is probably not the best format to convert them to.

OTHER TIPS

Black and White or Greyscale?

From http://www.faqs.org/faqs/compression-faq/part2/section-6.html:

"JPEG works on either full-color or gray-scale images; it does not handle bilevel (black and white) images, at least not well. It doesn't handle colormapped images either; you have to pre-expand those into an unmapped full-color representation. JPEG works best on "continuous tone" images. Images with many sudden jumps in color values will not compress well."

You need to set an attribute for the encoder to tell it the compression level to use.

See also

You will want to switch to using this overload of Bitmap.Save, so you can specify the EncoderParameter.

As to why your files are getting larger, it may be that your BMP was run length encoded, or using a smaller (not 24 bit) bitmap.

A comparison of sizes for a 2 color 61x64 image:

  • Fax-4 tiff: 268 bytes
  • 2 color bmp (as above): 550 bytes
  • 8 bit jpeg: 1502 bytes
  • 32 bit jpeg (as System.Drawing would create): 2015 bytes

So, if you have to use jpegs, convert them to 8 bit first. Doing that in .Net will be awkward, but there is sample code available on CodeProject and others.

Just wanted to followup with my solution. I was able to get the rest of the system to support PNG format graphics, so what I did was convert the bitmaps into PNG graphics, and make them 1 bit per pixel black and white. This made them small and efficient.

So the problem was that JPGs just don't do few-colors images well.

Just a thought: you say part of your system needs the files to be JPEG files. Is that really true or does it just need the files to have the JPG extension? If so, you could - although it's ugly - just rename the file extension, since the BMP files in your case are smaller.

For example in Windows, you can take a BMP file and change it's extension to JPG, when you open it, Windows doesn't care and displays it properly.

This kb article should show you how to do it

http://support.microsoft.com/kb/324790

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top