0

I just wrote a function that takes a directory, creates a new "resizedDirectory" (if it does not exist), resizes every .bmp, and saves it to "resizedDirectory". This is the first time I've written a function like this (used the internet for some parts), here is the code:

protected void directorySelected(object sender, EventArgs e) {
    // Make sure the directory exists
    if (Directory.Exists(inputDirectory.Text)) {
        string[] filePaths = Directory.GetFiles(inputDirectory.Text);

        // Determine if there are any files in inputDirectory
        if (filePaths.Length == 0) messageLog.InnerHtml = "<strong>No files found in:</strong> "+inputDirectory.Text;
        else {
            // Determine if "resizedDirectory" exists, create it if it does not exist
            string resizedDirectory = inputDirectory.Text+"\\"+"resizedDirectory";
            if (!Directory.Exists(resizedDirectory)) {
                Directory.CreateDirectory(resizedDirectory);
                messageLog.InnerHtml = "<strong>Created:</strong> "+resizedDirectory+"<br/><br/>";
            }

            // For each file in inputDirectory...
            for (var i = 0; i < filePaths.Length; i++) {
                string[] extensionSplit = filePaths[i].Split('.');

                // Make sure filePath[i] ends with the appropriate extension
                if (extensionSplit.Length == 2 && extensionSplit[1].Equals("bmp")) {
                    Bitmap currImage = new Bitmap(filePaths[i]);
                    messageLog.InnerHtml += "<strong>"+i.ToString()+":</strong> "+filePaths[i]+"<br/><div class='indent'>";

                    // Calculate new dimensions
                    int newWidth = maxWidth;
                    int newHeight = maxHeight;
                    if (currImage.Width > currImage.Height) newHeight = (int)(((float)maxWidth)/((float)currImage.Width)*currImage.Height);
                    else newWidth = (int)(((float)maxHeight)/((float)currImage.Height)*currImage.Width);
                    messageLog.InnerHtml += "<strong>Old dimensions:</strong> ("+currImage.Width+","+currImage.Height+")<br/><strong>New dimensions:</strong> ("+newWidth+", "+newHeight+")<br/>";

                    // Settings before saving
                    Bitmap targetImage = new Bitmap(newWidth, newHeight);
                    using (Graphics g = Graphics.FromImage(targetImage)) {
                        g.CompositingQuality = CompositingQuality.HighQuality;
                        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        g.SmoothingMode = SmoothingMode.HighQuality;
                        g.DrawImage(currImage, 0, 0, newWidth, newHeight);
                    }
                    ImageCodecInfo ici = this.GetEncoderInfo(ImageFormat.Bmp);
                    Encoder eq = Encoder.Quality;
                    EncoderParameters eps = new EncoderParameters(1);
                    EncoderParameter ep = new EncoderParameter(eq, 100L); // 100L is the higest quality (goes from 0 - 100)
                    eps.Param[0] = ep;

                    // Save image
                    string targetPath = resizedDirectory+"\\foo"+i.ToString()+".bmp";
                    targetImage.Save(targetPath, ici, eps);
                    messageLog.InnerHtml += "<strong>Saved:</strong> "+targetPath+"</div><br/>";
                }
                else messageLog.InnerHtml += "<strong>IGNORED "+i.ToString()+":</strong> "+filePaths[i]+"<br/>";
            }
        }
    }
    else if (inputDirectory.Text.Equals("")) messageLog.InnerHtml = "<strong>No directory specified</strong>";
    else messageLog.InnerHtml = "<strong>Cannot find:</strong> "+inputDirectory.Text;
}

protected ImageCodecInfo GetEncoderInfo(ImageFormat format) {
    return ImageCodecInfo.GetImageDecoders().SingleOrDefault(c => c.FormatID == format.Guid);
}

This worked fine with small .bmps. The problem is that the directories of .bmps I need to convert are huge, an example .bmp is 16073 x 13231 (or 608MB). I tried the code with a little .bmp and one of the huge .bmps and it made "resizedDirectory", created a new resized .bmp of the little one there, and then crashed with the message "Out of memory".

How should I go about resizing the huge .bmps?

Edit: It fails on one huge .bmp (but not on small ones)

1
  • Please re-tag your question: this is not "asp-classic"... Commented Aug 6, 2013 at 5:46

2 Answers 2

1

First, test your code with single bitmaps. Although they are big, you may find that your program can still process them one at a time, in which case you won't need to do much to get it working. (If it doesn't work for a single massive image, then you will need to start looking for a different image loading or processing library than the built-in .net classes)

If it works for one image but not a sequence of them, then make sure you release all memory used by one bitmap before you try to load the next one. Essentially you need to call currImage.Dispose(); after all your processing of the bitmap (inside the end of your loop) to release the memory it is using.

However, the proper way of achieving this is to write the processing code inside a using block, which will automatically call Dispose for you (even if an exception is thrown):

using (Bitmap currImage = new Bitmap(filePaths[i]))
{
    // Process the bitmap here
}

You will need to do a similar thing for targetImage to be sure it is also disposed after it has been written.

This will release all memory used by the bitmap as soon as you finish processing it so it is available for the next bitmap to use.

Sign up to request clarification or add additional context in comments.

Comments

0

All GDI + resources must be disposed. I think the problem is your USING statement is not disposing of the Graphics object. It's a mistake I've made many time myself :)

http://msdn.microsoft.com/en-us/library/system.drawing.graphics.dispose.aspx

g.Dispose();

1 Comment

this is innacurate. The whole point of using is that it disposes the object when you leave its scope

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.