Unusual physical memory usage where huge numbers of bitmaps are created and stored as one bit per pixel

I am trying to create a large number of 1 bit per pixel BMP images from a base 64 string and save. According to the requirement, a very large number of images are created in a short period of time (on average from 50,000 to 1,000,000 in a short time). I am using the below code.

  public void CreateoneBppImageAndSave(String base64ImageString,String ImagePathToSave)
    {
        byte[] byteArray = Convert.FromBase64String(base64ImageString);

        System.Drawing.Image img = byteArrayToImage(byteArray);
        Bitmap objBitmap = new Bitmap(img);

        BitmapData bmpData = objBitmap.LockBits(new Rectangle(0, 0, objBitmap.Width, objBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format1bppIndexed);
        Bitmap oneBppBitmap = new Bitmap(objBitmap.Width, objBitmap.Height, bmpData.Stride, System.Drawing.Imaging.PixelFormat.Format1bppIndexed, bmpData.Scan0);

        oneBppBitmap.Save(ImagePathToSave, ImageFormat.Bmp);
        img.Dispose();
        objBitmap.Dispose();
        objBitmap.UnlockBits(bmpData);
        oneBppBitmap.Dispose();
    }

    private Image byteArrayToImage(byte[] byteArrayIn)
    {
        using (MemoryStream ms = new MemoryStream(byteArrayIn))
        {
            return Image.FromStream(ms);
        }
    }

      

The physical memory usage will be very high here. Typically images are generated in sizes from 200x200 to 754x1024. After a certain period of time, the physical memory increases to extreme and exclusion from memory . Physical memory increases by 0.01 GB every 5-10 seconds. Please help me optimize the code in terms of memory usage .

+3


source to share


1 answer


You call LockBits

on objBitmap

, but you call UnlockBits

on oneBppBitmap

. You have to call the unlock on the same object that you called the lock.

In terms of statements using

, as I mentioned in the comments, the using statement turns this

using(SomeType obj = new SomeType())
{
   // Some code
}

      

the equivalent of this

SomeType obj = new SomeType())
try
{
    // Some code
}
finally
{
    obj.Dispose();
}

      

This ensures that even if an exception is thrown in // Some Code

, the dispose action will still occur. Your code, as it is now, will not delete any of its objects if any of your functions throws an exception between creation and deletion.



Here's a rewritten version with all the fixes I mentioned plus a few others.

public void CreateoneBppImageAndSave(String base64ImageString,String ImagePathToSave)
{
    byte[] byteArray = Convert.FromBase64String(base64ImageString);

    using(Image img = byteArrayToImage(byteArray))
    using(Bitmap objBitmap = new Bitmap(img))
    {    
        BitmapData bmpData = objBitmap.LockBits(new Rectangle(0, 0, objBitmap.Width, objBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format1bppIndexed);
        try
        {
            using(Bitmap oneBppBitmap = new Bitmap(objBitmap.Width, objBitmap.Height, bmpData.Stride, System.Drawing.Imaging.PixelFormat.Format1bppIndexed, bmpData.Scan0))
            {        
                oneBppBitmap.Save(ImagePathToSave, ImageFormat.Bmp);
            }
        }
        finally
        {
            //put the unlock in a finally to make sure it happens.
            objBitmap.UnlockBits(bmpData);
        }
    }
}

      


EDIT: If this is indeed in your code

objBitmap.Dispose();
objBitmap.UnlockBits(bmpData);

      

This is the source of your problem, you shouldn't call any methods on the class after you have selected. This is another advantage using

, you cannot call methods later because the variable is out of scope when you leave the block using

.

+4


source







All Articles