views:

106

answers:

3

Hi,

I am loading a JPG image from hard disk into a byte[]. Is there a way to resize the image (reduce resolution) without the need to put it in a Bitmap object?

thanks

+3  A: 

There are always ways but whether they are better... a JPG is a compressed image format which means that to do any image manipulation on it you need something to interpret that data. The bimap object will do this for you but if you want to go another route you'll need to look into understanding the jpeg spec, creating some kind of parser, etc. It might be that there are shortcuts that can be used without needing to do full intepretation of the original jpg but I think it would be a bad idea.

Oh, and not to forget there are different file formats for JPG apparently (JFIF and EXIF) that you will ened to understand...

I'd think very hard before avoiding objects that are specifically designed for the sort of thing you are trying to do.

Chris
EXIF is not a jpeg format. EXIF is meta data added to any image format. See http://en.wikipedia.org/wiki/Exchangeable_image_file_format
Philip Smith
@Philip Smith: Never said it was a jpeg format, just that it was a file format. If you are loading the jpg from disk you still need to know how the file is structured so you can get at the image data and the meta data and whatever else.
Chris
+1  A: 

A .jpeg file is just a bag o' bytes without a JPEG decoder. There's one built into the Bitmap class, it does a fine job decoding .jpeg files. The result is a Bitmap object, you can't get around that.

And it supports resizing through the Graphics class as well as the Bitmap(Image, Size) constructor. But yes, making a .jpeg image smaller often produces a file that's larger. That's an unavoidable side-effect of Graphics.Interpolation mode. It tries to improve the appearance of the reduced image by running the pixels through a filter. The Bicubic filter does an excellent job of it.

Looks great to the human eye, doesn't look so great to the JPEG encoder. The filter produces interpolated pixel colors, designed to avoid making image details disappear completely when the size is reduced. These blended pixel values however make it harder on the encoder to compress the image, thus producing a larger file.

You can tinker with Graphics.InterpolationMode and select a lower quality filter. Produces a poorer image, but easier to compress. I doubt you'll appreciate the result though.

Hans Passant
+1  A: 

Here's what I'm doing.

And no, I don't think you can resize an image without first processing it in-memory (i.e. in a Bitmap of some kind).

Decent quality resizing involves using an interpolation/extrapolation algorithm; it can't just be "pick out every n pixels", unless you can settle with nearest neighbor.

Here's some explanation: http://www.cambridgeincolour.com/tutorials/image-interpolation.htm

protected virtual byte[] Resize(byte[] data, int width, int height) {
var inStream = new MemoryStream(data);
var outStream = new MemoryStream();

var bmp = System.Drawing.Bitmap.FromStream(inStream);
var th = bmp.GetThumbnailImage(width, height, null, IntPtr.Zero);
th.Save(outStream, System.Drawing.Imaging.ImageFormat.Jpeg);
return outStream.ToArray(); }
Rei Miyasaka