For some days I have been trying to optimize an image processing program (cropping, rotate, changing brightness and undo) written in c# 4.0. Getting suggestions from google I have optimized the code in many ways. At first some disposable objects hadn’t been disposed that’s why exception was shown. But I have tried to dispose all disposable objects. Still the program is showing out of memory exceptions. That’s why I have uploaded the program for better solutions. Please download from the link

http://www.box.com/s/8eab0f3669ec4d79e3fc

My machine configuration: Core 2 Duo, 2 GB RAM, Windows XP service pack 3

Follow the steps:

Run the program

Load multiple images (at least 6) (each image is 3.5 MB or greater)

Double click on an image, crop (right click) and save. Do the same operation for other images. See what happens. It will show out of memory exceptions.

If any other operations (e.g. changing brightness) is done repeatedly (again and again) then it also shows out of memory exception.

I am eagerly waiting for your reply.

class ImageProcessingHandler
  {
    CurrentImageHandler objCurrImageHandler;

    int brightnessValue = 0;

    public ImageProcessingHandler(Bitmap currBmp)
    {
        objCurrImageHandler = new CurrentImageHandler();

        if (objCurrImageHandler.CurrentBitmap != null)
        {
            objCurrImageHandler.CurrentBitmap.Dispose();
            objCurrImageHandler.CurrentBitmap = null;
        }

        objCurrImageHandler.CurrentBitmap = new Bitmap(currBmp);
    }

    public Bitmap rotateImage()
    {
        try
        {
            objCurrImageHandler.CurrentRotationHandler.Flip(RotateFlipType.Rotate90FlipNone);

        }
        catch (Exception ex)
        {
            //MessageBox.Show("Error occured: " + ex.Message, "Image Processing", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        return objCurrImageHandler.CurrentBitmap;
    }


    public Bitmap cropImageCustom(Rectangle cropArea)
    {
        objCurrImageHandler.RestorePrevious();

        using (Bitmap bmpImage = new Bitmap(objCurrImageHandler.CurrentBitmap))
        {

            Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat);
            objCurrImageHandler.CurrentBitmap.Dispose();
            objCurrImageHandler.CurrentBitmap = new Bitmap(bmpCrop);
            bmpCrop.Dispose();
        }

        return objCurrImageHandler.CurrentBitmap;

    }

    public Bitmap increaseBrightness()
    {

        brightnessValue = 10;
        objCurrImageHandler.CurrentBrightnessHandler.SetBrightness(brightnessValue);

        return objCurrImageHandler.CurrentBitmap;
    }


    public Bitmap undoImage()
    {

        objCurrImageHandler.ResetBitmap();
        return objCurrImageHandler.CurrentBitmap;
    }

    public void saveImage()
    {

        string fileName = ""; // "CommonInformation.TEMP_IMAGE_PATH + CommonInformation.selectedPageNumber.ToString() + ".jpg"";

        if (File.Exists(fileName))
        {
            File.Delete(fileName);
        }

        objCurrImageHandler.CurrentBitmap.Save(fileName, ImageFormat.Jpeg);
        objCurrImageHandler.CurrentBitmap.Dispose();

    }
 }

public class CurrentImageHandler
  { 
    ImageHandler imageHandler;
    public CurrentImageHandler(ImageHandler imageHandler)
    {
        this.imageHandler = imageHandler;
    }

    public void Flip(RotateFlipType rotateFlipType)
    {
        imageHandler.RestorePrevious();
        this.imageHandler.CurrentBitmap.RotateFlip(rotateFlipType);

    }

    public void SetBrightness(int brightness)
    {
        imageHandler.RestorePrevious();
        if (brightness < -255) brightness = -255;
        if (brightness > 255) brightness = 255;
        ColorMatrix cMatrix = new ColorMatrix(CurrentColorMatrix.Array);
        cMatrix.Matrix40 = cMatrix.Matrix41 = cMatrix.Matrix42 = brightness / 255.0F;
        imageHandler.ProcessBitmap(cMatrix);
    }

}

public class ImageHandler
  {
    private Bitmap _currentBitmap;
    private Bitmap _bitmapbeforeProcessing;

    public Bitmap CurrentBitmap
    {
        get
        {
            if (_currentBitmap == null)
            {
                _currentBitmap = new Bitmap(1, 1);
            }
            return _currentBitmap;
        }
        set { _currentBitmap = value; }
    }

    public string CurrentBitmapPath { get; set; }

    public void ResetBitmap()
    {
        if (_currentBitmap != null && _bitmapbeforeProcessing != null)
        {
            using (Bitmap temp = (Bitmap)_currentBitmap.Clone())
            {
                this.CurrentBitmap.Dispose();
                this.CurrentBitmap = (Bitmap)_bitmapbeforeProcessing.Clone();
                _bitmapbeforeProcessing = (Bitmap)temp.Clone();

            }

        }
    }

    internal void RestorePrevious()
    {
        if (_bitmapbeforeProcessing != null)
        {
            _bitmapbeforeProcessing.Dispose();
            _bitmapbeforeProcessing = null;
        }
        _bitmapbeforeProcessing = new Bitmap(_currentBitmap);
    }

    internal void ProcessBitmap(ColorMatrix colorMatrix)
    {
        using (Bitmap bmap = new Bitmap(_currentBitmap.Width, _currentBitmap.Height))
        {
            using (ImageAttributes imgAttributes = new ImageAttributes())
            {
                imgAttributes.SetColorMatrix(colorMatrix);
                using (Graphics g = Graphics.FromImage(bmap))
                {
                    g.InterpolationMode = InterpolationMode.NearestNeighbor;
                    g.DrawImage(_currentBitmap, new Rectangle(0, 0, _currentBitmap.Width, _currentBitmap.Height), 0, 0, _currentBitmap.Width, _currentBitmap.Height, GraphicsUnit.Pixel, imgAttributes);
                }
            }

            if (_currentBitmap != null)
                _currentBitmap.Dispose();

            _currentBitmap = (Bitmap)bmap.Clone();
        }

    }
}

If these are the only objects here and there's no recursive functions in there, your problem is that the bitmaps are too big. There's simply no place for hidden references to stick around. (These images: are they 3.5 MB compressed, before they're loaded? Or are they 3.5 MB as bitmaps?)

You might be able to make your program survive by forcing a garbage collection at certain times.

Edited 4 Years Ago by Rashakil Fol

These images: are they 3.5 MB compressed, before they're loaded? Or are they 3.5 MB as bitmaps?)

They are 3.5 MB as JPEG. resolution is 5100 x 6540

This article has been dead for over six months. Start a new discussion instead.