views:

2213

answers:

4

I have very large images (jpg) and i want to write a csharp program to loop through the files and reduce the size of each image by 75%.

I tried this:

Image thumbNail = image.GetThumbnailImage(800, 600, null, new IntPtr());

but the file size is still very large.

Is there anyway to create thumbnails and have the filesize be much smaller?

A: 

Compress your image. For thumbnails, JPEG is sufficient, as you're not looking for quality.

Image thumbNail = image.GetThumbnailImage(800, 600, null, new IntPtr());

thumbNail.Save(fileName, ImageFormat.Jpeg);
strager
how do i compress an image from csharp?
ooo
+5  A: 
private void CompressAndSaveImage(Image img, string fileName, 
        long quality) {
    EncoderParameters parameters = new EncoderParameters(1);
    parameters.Param[0] = new EncoderParameter(Encoder.Quality, quality);
    img.Save(fileName, GetCodecInfo("image/jpeg"), parameters);
}

private static ImageCodecInfo GetCodecInfo(string mimeType) {
    foreach (ImageCodecInfo encoder in ImageCodecInfo.GetImageEncoders())
        if (encoder.MimeType == mimeType)
            return encoder;
    throw new ArgumentOutOfRangeException(
        string.Format("'{0}' not supported", mimeType));
}

Usage:

Image myImg = Image.FromFile(@"C:\Test.jpg");
CompressAndSaveImage(myImg, @"C:\Test2.jpg", 10);

That will compress Test.jpg with a quality of 10 and save it as Test2.jpg.

EDIT: Might be better as an extension method:

private static void SaveCompressed(this Image img, string fileName, 
        long quality) {
    EncoderParameters parameters = new EncoderParameters(1);
    parameters.Param[0] = new EncoderParameter(Encoder.Quality, quality);
    img.Save(fileName, GetCodecInfo("image/jpeg"), parameters);
}

Usage:

Image myImg = Image.FromFile(@"C:\Test.jpg");
myImg.SaveCompressed(@"C:\Test2.jpg", 10);
David Brown
can you have this function return an Image type as i need to keep to a certain interface
ooo
Compression takes place when the file is saved. You can still use your GetThumbnailImage code, but rather than call Image.Save, you should call Image.SaveCompressed. AKAIK, you can't compress an Image object directly and then return it.
David Brown
You don't need to save in a file, as you can save it in a memory stream and recreate the bitmap from the memory stream, discarding the stream afterwards.This way, you can return the `Image` while reducing it size.
Paulo Santos
Hi David, I ran the code you pasted above but it gives me an ArgumentException saying 'Parameter is not valid'. Any idea what could be wrong ? I using a ditto copy from your code above !!
Binder
Ok, caught the culprit, I needed to pass 10 as 10L
Binder
A: 

From GetThumbnailImage's documentation:

If the Image contains an embedded thumbnail image, this method retrieves the embedded thumbnail and scales it to the requested size. If the Image does not contain an embedded thumbnail image, this method creates a thumbnail image by scaling the main image.

I'd suggest you use smaller width and height values. Try:

// reduce the size of each image by 75% from original 800x600
Image thumbNail = image..GetThumbnailImage(200, 150, null, IntPtr.Zero);

See sample code.

Also read the documentation:

The GetThumbnailImage method works well when the requested thumbnail image has a size of about 120 x 120 pixels. If you request a large thumbnail image (for example, 300 x 300) from an Image that has an embedded thumbnail, there could be a noticeable loss of quality in the thumbnail image. It might be better to scale the main image (instead of scaling the embedded thumbnail) by calling the DrawImage method.

I think you may want to take a look at the scaling API.

dirkgently
+1  A: 

ImageMagick is a command line tool which is hugely powerful for doing image manipulation. I've used it for resizing large images and thumbnail creation in circumstances where the aspect ratio of the source image is unknown or is unreliable. ImageMagick is able to resize images to a specific height or width while maintaining the original aspect ratio of your picture. It can also add space around an image if required. All in all very powerful and a nice abstraction from having to deal with .nets Image APIs. To use the imageMagick command line tool from within C# I recommend using the System.Diagnostics.ProcessStartInfo object like so:

ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = @"C:\Program Files\ImageMagick-6.5.0-Q16\convert.exe";
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.Arguments = string.Format("-size x{0} \"{1}\" -thumbnail 200x140 -background transparent -gravity center -extent 200x140 \"{2}\"", heightToResizeTo, originalTempFileLocation, resizedTempFileLocation);

Process p = new Process();
p.StartInfo = psi;
p.Start();
p.WaitForExit();

Using the scale% paramater you can easily reduce the size of your image by 75%

Dav Evans