7

I'm using the WebImage in MVC3 in order to resize an image. Basically, the purpose of this is to create a thumbnail image of a file that is uploaded. I will have no control over how large the files are originally, so I need to create a thumbnail of the file in order to speed up the "preview" site.

I have some files which need to be uploaded and in size, its around 4Mb which isn't a problem when it comes to uploading. The problem I'm having is creating the thumbnail. I upload the file first and once its saved on the server, I then create a new WebImage object for the thumbnail.

// Save a thumbnail of the file
WebImage image = new WebImage(savedFileName);

// Resize the image
image.Resize(135, 150, true);

// Save the thumbnail
image.Save(FileName);   // <<--- Out of memory exception here

// Dispose of the image
image = null;

When I try to save the file, I get an Out-of-memory exception. Any ideas on how I can resolve this?

7
  • What is the image size (width x height)? Commented Mar 11, 2011 at 10:18
  • The original image is 4000x4724px. Commented Mar 11, 2011 at 10:20
  • Can you please provide a spec of the machine? If it is 24bit image then it takes around 120 MB of memory. Commented Mar 11, 2011 at 10:23
  • 3.04Ghz Intel Processor 64bit, 6Gb RAM. Commented Mar 11, 2011 at 10:24
  • I just looked at the image properties and it is a 32bit JPG image. Commented Mar 11, 2011 at 10:26

5 Answers 5

8

Due to a bug in WebImage, I've had to resort to the code below:

// Save a thumbnail of the file
byte[] fileBytes = System.IO.File.ReadAllBytes(savedFileName);

System.Drawing.Image i;
using (MemoryStream ms = new MemoryStream())
{
    ms.Write(fileBytes, 0, fileBytes.Length);
    i = System.Drawing.Image.FromStream(ms);
}

// Create the thumbnail
System.Drawing.Image thumbnail = i.GetThumbnailImage(135, 150, () => false, IntPtr.Zero);
Sign up to request clarification or add additional context in comments.

Comments

4

I've run into this myself, using WebImage Resize, and found that the issue was a JPG image that was actually a CMYK image. Changing the image mode in PS, to RGB not only reduced the file size that the WebImage Resize method was using, it also performed much faster.

For web usage, I try to ensure all JPG images are RGB and saved in Base Format (as opposed to progressive). This prevents lots of little errors and bugs from occurring.

Comments

3

I was getting an OutOfMemoryException from WebImage.Save() when I try to resize and save a JPG image that is using the CMYK color space.

The workaround I found is to save the image to disk and reload it before resizing.

var logoWebImage = new WebImage(newLogo.InputStream);
// Start workaround: Save and reload to avoid OutOfMemoryException when image color space is CMYK.
logoWebImage.Save(filePath: DataFilePaths.LogoImageFile, imageFormat: "png");
logoWebImage = new WebImage(DataFilePaths.LogoImageFile);
// End workaround
logoWebImage.Resize(300, 300, preserveAspectRatio: true, preventEnlarge: true);
logoWebImage.Save(filePath: DataFilePaths.LogoImageFile, imageFormat: "png");

This is an ugly workaround but it is especially needed when the input image is a logo image. Because designers often deliver logo images that use the CMYK color space because it is better for printing.

Comments

0

OK, this looks like a bug in MVC3. The error you are getting is just a standard GDI+ error when GDI+ tries to access pixels in locations where it does not exist.

I believe issue is in the rounding of the pixels when it calculates aspect ratio so I think if you change 135, 150 to for example 136, 151 it will work.

I might have a look later myself to find the bug in their code and post to them.


UPDATE - Possible Workaround

Try passing true for the 4th parameter:

// Resize the image
image.Resize(135, 150, true, true);

I can actually see the bug in code:

    if (num3 > num4)
    {
        height = (int) Math.Round((double) ((num4 * image.Height) / 100.0));
    }
    else if (num3 < num4)
    {
        width = (int) Math.Round((double) ((num3 * image.Width) / 100.0));
    }

4 Comments

No, this still causes an issue. I also tried to use Crop and take the centre of the picture knowing that these pixels are available, and it caused an out-of-memory exception on that too.
OK, i willl have a look at lunchtime.
Just can you give me stacktrace please and possibly the image which causes the problem if not confidential
It seems the problem is when the file CMYK rather than RGB.
0

I ended up doing this as a workaround:

    public static Image ScaleImage(string fileName, int maxWidth, int maxHeight)
    {
        var image = Image.FromFile(fileName);
        var ratioX = (double)maxWidth / image.Width;
        var ratioY = (double)maxHeight / image.Height;
        var ratio = Math.Min(ratioX, ratioY);

        var newWidth = (int)(image.Width * ratio);
        var newHeight = (int)(image.Height * ratio);

        var newImage = new Bitmap(newWidth, newHeight);
        var g = Graphics.FromImage(newImage);
        g.Clear(Color.White); // matters for transparent images
        g.DrawImage(image, 0, 0, newWidth, newHeight);
        return newImage;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.