c# Out of Memory Exception with System.Drawing.Ima

2019-07-15 01:01发布

I wanna create a pdf with 2 images. One of the image is a text and the other is a watermark to draw on top of the first one. Well when I load the first image everything is ok but then I try to load the watermark image and get the "Out of Memory" exception. I've got memory (printed the memory usage was like 20MB) and can open the image in my computer (I'm using one I took from google just to test until I don't get the real one).

Image I'm using to test this feature

The code where I get the exception is this one:

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

I've seen the other questions like mine but:

  • It doesn't seem memory problem
  • It doesn't seem image problem

Can you help me? Thanks :)

3条回答
劫难
2楼-- · 2019-07-15 01:23

Well I found out that in previous functions of the program a file was being created in the exact same path as the watermark image and so when I tried to open it up as a image it gave me an error.

After solving this problem I notice my code had another problem, my imgOriginal was being returned but because I was using the

using (System.Drawing.Image imgOriginal = System.Drawing.Image.FromFile(sOriginalPath, true))

the object was being disposed and so I was loosing my image. To solve this I updated my function to this:

    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;
    }
查看更多
地球回转人心会变
3楼-- · 2019-07-15 01:30

first convert Byte[] format after that conver base64 format try below code may its solve your problem,

          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;

        }
查看更多
我想做一个坏孩纸
4楼-- · 2019-07-15 01:34

Issue

You are building an object

  using (System.Drawing.Image imgOriginal = System.Drawing.Image.FromFile(sOriginalPath, true))

Then you are returning it...but it is already disposed of...you need to not dispose of the object by unwrapping it with a using...whatever consumes this will need to dispose of the object.

Other Issue

bitmap is also a memory leak and needs to be wrapped with a using or dispose called implicitly.


Final Function Example

public System.Drawing.Image GetImage(string sOriginalPath, string sLogoPath)
{
  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))
    {
      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;
}

Example Console App Demo

I've tested the below and it worked as expected.

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;
        }
    }
}
查看更多
登录 后发表回答