创建大量位图图像并将其保存为每像素图像一位时,物理内存使用异常

本文关键字:图像 一位 物理内存 异常 像素 位图 保存 创建 | 更新日期: 2023-09-27 18:30:50

我正在尝试从 base 1 字符串创建大量每像素 64 位的 bmp 图像并保存。根据要求,在短时间内创建非常大量的图像(在短时间内平均创建50,000到1,00,000个)。我正在使用下面的代码。

  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);
        }
    }

这里的物理内存使用率非常高。通常生成的图像大小为 200x200 到 754x1024 。在一定时间后,物理内存使用量达到极端和内存不足异常被抛出。物理内存每 5-10 秒增加 0.01 GB。请帮助我在内存使用方面优化代码

创建大量位图图像并将其保存为每像素图像一位时,物理内存使用异常

objBitmap上调用LockBits,但你在oneBppBitmap上调用UnlockBits。您应该在调用锁定的同一对象上调用解锁。

至于我在评论中提到的using语句,使用 语句会变成这个

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

在相当于这个

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

这保证了即使抛出异常// Some Code释放操作仍然会发生。您的代码(就像现在一样)如果创建和释放之间的任何函数引发异常,则不会释放其任何对象。

这是一个重写的版本,其中包含我提到的所有更正以及其他一些更正。

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);
        }
    }
}

编辑:如果这真的在你的代码中

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

这就是问题的根源,在释放后,您不应该在类上调用任何方法。这是using的另一个好处,你不能延迟调用方法,因为当你离开using块时,变量会超出范围。