Search code examples
c#.netimage-processingimage-conversion

Is using the .NET Image Conversion enough?


I've seen a lot of people try to code their own image conversion techniques. It often seems to be very complicated, and ends up using GDI+ function calls, and manipulating bits of the image. This has got me wondering if I am missing something in the simplicity of .NET's image conversion call when saving an image. Here's the code I have:

Bitmap tempBmp = new Bitmap("c:\temp\img.jpg");
Bitmap bmp = new Bitmap(tempBmp, 800, 600);
bmp.Save(c:\temp\img.bmp, //extension depends on format
    ImageFormat.Bmp) //These are all the ImageFormats I allow conversion to within the program.  Ignore the syntax for a second ;) 
    ImageFormat.Gif) //or 
    ImageFormat.Jpeg) //or
    ImageFormat.Png) //or
    ImageFormat.Tiff) //or
    ImageFormat.Wmf) //or
    ImageFormat.Bmp)//or
    );

This is all I'm doing in my image conversion. Just setting the location of where the image should be saved, and passing it an ImageFormat type. I've tested it the best I can, but I'm wondering if I am missing anything in this simple format conversion, or if this is sufficient?


Solution

  • System.Drawing.Imaging does give you additional control over the image compression if you pass in the JPEG codec and set the encoder parameter for Quality, which is essentially percent retention.

    Here's a function I use with the parameter "image/jpeg" to get the JPEG codec. (This isn't related to compression per se, but the Image.Save overloads that accept EncoderParameters require ImageCodecInfo instead of ImageFormat.)

    //  assumes an encoder for "image/jpeg" will be available.
    public static ImageCodecInfo GetCodec( string mimeType )
    { 
        ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders(); 
    
        for( int i = 0;  i < encoders.Length;  i++ )
            if( encoders[i].MimeType == mimeType )
                return encoders[i];
    
        return null; 
    }
    

    Then you can set the encoder parameters before saving the image.

    EncoderParameters ep = new EncoderParameters(2);
    ep.Param[0] = new EncoderParameter( Encoder.Quality,    percentRetention ); // 1-100
    ep.Param[1] = new EncoderParameter( Encoder.ColorDepth, colorDepth ); // e.g. 24L
    

    (There are other encoder parameters — see the documentation.

    So, put it all together, and you can say

    image.Save( outFile, GetCodec("image/jpeg"), ep );
    

    (I store the codec and parameters in static values, as they are used over and over again, but I wanted to simplify the example here.)

    Hope this helps!

    EDIT: If you are scaling images, you also have some control over the quality. Yes it is very "black box", but I find that it works well. Here are the "good & slow" settings (which you need to set before you call DrawImage, but you can look up the "quick & dirty" versions.

    // good & slow
    graphics.SmoothingMode      = SmoothingMode.HighQuality;
    graphics.InterpolationMode  = InterpolationMode.HighQualityBicubic;
    graphics.PixelOffsetMode    = PixelOffsetMode.HighQuality;
    graphics.CompositingQuality = CompositingQuality.HighQuality;