Storm
Storm

Reputation: 4445

Strange GDI+ behaviour

I have made a method to CompressImageSize according to Image quality. The code for it is

public static Image CompressImage(string imagePath, long quality)
{
    Image srcImg = LoadImage(imagePath);
    //Image srcImg = Image.FromFile(imagePath);

    EncoderParameters parameters = new EncoderParameters(1);
    parameters.Param[0] = new EncoderParameter(Encoder.Quality, quality);

    ImageCodecInfo encoder = GetCodecInfo("image/jpeg");

    srcImg.Save("d:\\creatives\\abcd123.jpg", encoder, parameters);
}

public static Image LoadImage(string filename)
{
    using (FileStream fs = new FileStream(filename, FileMode.Open))
    {
        return(Image.FromStream(fs));
    }
}

Now, when i run this code as is it gives me a 'Generic GDI+ exception' while saving the srcImg(last line in func #1), BUT when i uncomment the 2nd line and load the image using Image.FromFile everything works fine.

Why ??

Upvotes: 0

Views: 143

Answers (6)

Mandrake
Mandrake

Reputation: 361

Fix , but for me the Dispose call is a bug in .net framework...

public static Image CompressImage(string imagePath, long quality)
{
    Image srcImg = LoadImage(imagePath);
    //Image srcImg = Image.FromFile(imagePath);

    EncoderParameters parameters = new EncoderParameters(1);
    parameters.Param[0] = new EncoderParameter(Encoder.Quality, quality);

    ImageCodecInfo encoder = GetCodecInfo("image/jpeg");

    srcImg.Save("d:\\creatives\\abcd123.jpg", encoder, parameters);
srcImg.Dispose();
}

Upvotes: 0

Akash Kava
Akash Kava

Reputation: 39916

There are various issues with Image.FromFile()...

Image srcImg = Image.FromFile(imagePath);

The above statement will not close the file stream and that will create problems if you want to access file again or delete it. I would write your function this way.

public static Image CompressImage(string imagePath, long quality)
{
    using(FileStream fs = File.OpenRead(imagePath)){
       Image srcImg = Image.FromStream(fs);    

       EncoderParameters parameters = new EncoderParameters(1);    
       parameters.Param[0] = new EncoderParameter(Encoder.Quality, quality);    
       ImageCodecInfo encoder = GetCodecInfo("image/jpeg");    
       srcImg.Save("d:\\creatives\\abcd123.jpg", encoder, parameters);
    }
}

This will guarentee that my file will be closed at the end of using scope.

Upvotes: 0

AndreyAkinshin
AndreyAkinshin

Reputation: 19021

You should rewrite your code:

public static Image LoadImage(string filename)
{
    FileStream fs = new FileStream(filename, FileMode.Open);        
    return Image.FromStream(fs);        
}

Construction using is wrong in this case because FileStream needs to be alive for using your Image.

Upvotes: 0

Locksfree
Locksfree

Reputation: 2702

According to MSDN:

Remarks: You must keep the stream open for the lifetime of the Image.

Here your stream is in a using block and thus closed before the end of the lifetime of the image.

Upvotes: 3

bzlm
bzlm

Reputation: 9727

In the end of LoadImage, the FileStream containing the Image is disposed. This is too soon; the file stream needs to be alive for use by the method calling LoadImage.

See using on MSDN.

Upvotes: 0

Dave Markle
Dave Markle

Reputation: 97701

A wild guess... Image is IDisposable. Are you calling this in a loop or something? Try putting your Image itself in a using() block?

Upvotes: 0

Related Questions