2

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 :)

patricia
  • 1,075
  • 1
  • 16
  • 44
  • So what is this logo image size? – Evk Apr 06 '16 at 17:28
  • Does sLogoPath equal to sOriginalPath? – Valentin Apr 06 '16 at 17:29
  • Check your image format. – Prabhat Sinha Apr 06 '16 at 17:31
  • Ensure that the image is not corrupt in some way. This could also give rise to an OutOfMemoryException. See http://stackoverflow.com/questions/1108607/out-of-memory-exception-on-system-drawing-image-fromfile – ManoDestra Apr 06 '16 at 17:35
  • @Valentin no, the sOriginalPath is the file with the text and the sLogoPath is the file with the watermark. – patricia Apr 07 '16 at 09:21
  • @PrabhatSinha my image is a png and I can open it in my computer. Doesn't seem to be corrupted or something like that. – patricia Apr 07 '16 at 09:22
  • @ManoDestra I've even tried 3 different images I took from a google search and all of them gave me the out of memory exception. Thay all seem fine so I don't think thats the problem. – patricia Apr 07 '16 at 09:23
  • You need to provide minimal complete example (http://stackoverflow.com/help/mcve), then we will be able to resolve your problem MUCH faster. – Evk Apr 07 '16 at 09:30

3 Answers3

7

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;
        }
    }
}
abc123
  • 17,855
  • 7
  • 52
  • 82
  • I find out that int he previous function I was creating a file with the same name and path as the sLogoPath and so when I tried to generate the image I got the error. I solved it because of a comment above that asked for a runnable example. When I separate that function from the rest of the program (that wasn't made by me) it all worked fine so I start looking back and found the problem. Thank you anyway :D – patricia Apr 07 '16 at 14:20
  • You also helped me because then I got another error because the image was being dispose and then I was returning it. So I saved the image in a temporary file and returned that path. Thank you for your help. – patricia Apr 07 '16 at 14:21
1

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;
    }
patricia
  • 1,075
  • 1
  • 16
  • 44
0

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;

        }
Prabhat Sinha
  • 1,500
  • 20
  • 32
  • this has 2 memory leaks in it, `Bitmap` and `MemoryStream` should be disposed of when you are done with them – abc123 Apr 06 '16 at 18:10
  • My function throws an exception before that part. See in my question I put a comment where it throws the exception. – patricia Apr 07 '16 at 09:33