c#System.Drawing.Image内存不足异常

c#System.Drawing.Image内存不足异常,c#,image,out-of-memory,C#,Image,Out Of Memory,我想创建一个pdf与2个图像。其中一个图像是文本,另一个是要在第一个图像上绘制的水印。嗯,当我加载第一幅图像时,一切都正常,但是我尝试加载水印图像并获得“内存不足”异常。我有内存(打印出来的内存使用量大约为20MB),可以在我的电脑中打开图像(我使用的是从谷歌上拿的一个,只是为了测试,直到我没有得到真正的图像) 我得到异常的代码如下: using (System.Drawing.Image imgOriginal = System.Drawing.Image.FromFile(sO

我想创建一个pdf与2个图像。其中一个图像是文本,另一个是要在第一个图像上绘制的水印。嗯,当我加载第一幅图像时,一切都正常,但是我尝试加载水印图像并获得“内存不足”异常。我有内存(打印出来的内存使用量大约为20MB),可以在我的电脑中打开图像(我使用的是从谷歌上拿的一个,只是为了测试,直到我没有得到真正的图像)

我得到异常的代码如下:

      using (System.Drawing.Image imgOriginal = System.Drawing.Image.FromFile(sOriginalPath, true))
      {
        using (System.Drawing.Image imgLogo = System.Drawing.Image.FromFile(sLogoPath, true)) //This is where it throws the exception
        {
          using (Graphics gra = Graphics.FromImage(imgOriginal))
          {
            Bitmap bmLogo = new Bitmap(imgLogo);
            int nWidth = bmLogo.Size.Width;
            int nHeight = bmLogo.Size.Height;
            int nLeft = (imgOriginal.Width / 2) - (nWidth / 2);
            int nTop = (imgOriginal.Height / 2) - (nHeight / 2);
            gra.DrawImage(bmLogo, nLeft, nTop, nWidth, nHeight);
          }
          return imgOriginal;
        }
      }
我见过其他类似我的问题,但是:

  • 似乎没有记忆问题
  • 这似乎没有图像问题
你能帮我吗?谢谢:)

问题 您正在构建一个对象

  using (System.Drawing.Image imgOriginal = System.Drawing.Image.FromFile(sOriginalPath, true))
然后您将返回它…但它已被处置…您不需要通过使用…将其展开来处置该对象。无论消耗了什么,都需要处置该对象

其他问题
bitmap
也是内存泄漏,需要使用隐式调用的
dispose
将其包装起来


最后一个函数示例
示例控制台应用程序演示 我已经测试了下面的代码,它按预期工作

using System.Drawing;

namespace SO_Test
{
    class Program
    {
        static void Main(string[] args)
        {
            using(Image newImage = GetImage("C:\\Users\\username\\Pictures\\image.png", "C:\\Users\\username\\Pictures\\watermark.jpg"))
            {
                newImage.Save("C:\\Users\\username\\Pictures\\newImage.png");
            }
        }

        static Image GetImage(string sOriginalPath, string sLogoPath)
        {
            Image imgOriginal = Image.FromFile(sOriginalPath, true);
            using (Image imgLogo = Image.FromFile(sLogoPath, true)) //This is where it throws the exception
            {
                using (Graphics gra = Graphics.FromImage(imgOriginal))
                {
                    using (Bitmap bmLogo = new Bitmap(imgLogo))
                    {
                        int nWidth = bmLogo.Size.Width;
                        int nHeight = bmLogo.Size.Height;
                        int nLeft = (imgOriginal.Width/2) - (nWidth/2);
                        int nTop = (imgOriginal.Height/2) - (nHeight/2);
                        gra.DrawImage(bmLogo, nLeft, nTop, nWidth, nHeight);
                    }
                }
            }
            return imgOriginal;
        }
    }
}

首先转换Byte[]格式,然后转换为ConverBase64格式。下面的代码可能会解决您的问题

          using (Graphics gra = Graphics.FromImage(imgOriginal))
          {
            Bitmap bmLogo = new Bitmap(imgLogo);
            int nWidth = bmLogo.Size.Width;
            int nHeight = bmLogo.Size.Height;
            int nLeft = (imgOriginal.Width / 2) - (nWidth / 2);
            int nTop = (imgOriginal.Height / 2) - (nHeight / 2);
            gra.DrawImage(bmLogo, nLeft, nTop, nWidth, nHeight);

           // Convert the image to byte[]
           System.IO.MemoryStream stream = new System.IO.MemoryStream();
           bitmap.Save(bmLogo, System.Drawing.Imaging.ImageFormat.Bmp);
           byte[] imageBytes = bmLogo.ToArray();

          // Convert byte[] to Base64 String
         string base64String = Convert.ToBase64String(imageBytes);

        // Write the bytes (as a Base64 string
        return base64String;

        }

我发现在之前的程序功能中,一个文件是在与水印图像完全相同的路径中创建的,所以当我试图将其作为图像打开时,它给了我一个错误

解决这个问题后,我注意到我的代码还有另一个问题,我的imgOriginal被返回,但因为我使用了

using (System.Drawing.Image imgOriginal = System.Drawing.Image.FromFile(sOriginalPath, true))
物体正在被处理,所以我失去了我的形象。为了解决这个问题,我将我的函数更新为:

    public static String WatermarkFromFile(string sOriginalPath, string sLogoPath)
    {
        using (System.Drawing.Image imgOriginal = System.Drawing.Image.FromFile(sOriginalPath, true))
        {
            using (System.Drawing.Image imgLogo = System.Drawing.Image.FromFile(sLogoPath, true))
            {
                using (Graphics gra = Graphics.FromImage(imgOriginal))
                {
                    Bitmap bmLogo = new Bitmap(imgLogo);
                    int nWidth = bmLogo.Size.Width;
                    int nHeight = bmLogo.Size.Height;
                    int nLeft = (imgOriginal.Width / 2) - (nWidth / 2);
                    int nTop = (imgOriginal.Height / 2) - (nHeight / 2);
                    gra.DrawImage(bmLogo, nLeft, nTop, nWidth, nHeight);
                }
                string name = Path.GetFileName(sOriginalPath);
                string id = Guid.NewGuid().ToString("N");
                string sImage = ConfigurationManager.AppSettings["ApplicationPath"] + "\\watermark_" + id + "_" + name;
                imgOriginal.Save(sImage, imgOriginal.RawFormat);
                return sImage;
            }
        }
        return null;
    }

那么这个徽标图像大小是多少?sLogoPath是否等于sOriginalPath?请检查您的图像格式。确保图像没有以某种方式损坏。这也可能导致OutOfMemoryException。请参见@Valentin no,sOriginalPath是带有文本的文件,sLogoPath是带有水印的文件。其中有两个内存泄漏,
Bitmap
MemoryStream
应在处理完它们后处理。我的函数在该部分之前引发异常。在我的问题中,我在抛出异常的地方添加了一条注释。我发现在上一个函数中,我创建了一个与sLogoPath具有相同名称和路径的文件,因此当我尝试生成图像时,我得到了错误。我解决了这个问题,因为上面的一条评论要求提供一个可运行的示例。当我把这个函数从程序的其他部分(不是我自己做的)分离出来时,一切都很好,所以我开始回顾并发现问题所在。不管怎样,谢谢你:DYou也帮了我,因为后来我又出现了一个错误,因为图像正在被处理,然后我返回了它。因此,我将图像保存在一个临时文件中,并返回该路径。谢谢你的帮助。
    public static String WatermarkFromFile(string sOriginalPath, string sLogoPath)
    {
        using (System.Drawing.Image imgOriginal = System.Drawing.Image.FromFile(sOriginalPath, true))
        {
            using (System.Drawing.Image imgLogo = System.Drawing.Image.FromFile(sLogoPath, true))
            {
                using (Graphics gra = Graphics.FromImage(imgOriginal))
                {
                    Bitmap bmLogo = new Bitmap(imgLogo);
                    int nWidth = bmLogo.Size.Width;
                    int nHeight = bmLogo.Size.Height;
                    int nLeft = (imgOriginal.Width / 2) - (nWidth / 2);
                    int nTop = (imgOriginal.Height / 2) - (nHeight / 2);
                    gra.DrawImage(bmLogo, nLeft, nTop, nWidth, nHeight);
                }
                string name = Path.GetFileName(sOriginalPath);
                string id = Guid.NewGuid().ToString("N");
                string sImage = ConfigurationManager.AppSettings["ApplicationPath"] + "\\watermark_" + id + "_" + name;
                imgOriginal.Save(sImage, imgOriginal.RawFormat);
                return sImage;
            }
        }
        return null;
    }