c# System.Drawing.Image 内存不足异常
c# Out of Memory Exception with System.Drawing.Image
我想创建一个包含 2 张图片的 pdf。其中一个图像是文本,另一个是在第一个图像之上绘制的水印。好吧,当我加载第一张图片时一切正常,但随后我尝试加载水印图片并获得 "Out of Memory" 异常。我有内存(打印内存使用量大约 20MB)并且可以在我的计算机中打开图像(我正在使用我从 google 中获取的图像只是为了测试,直到我没有得到真正的图像)。
我得到异常的代码是这个:
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))
然后您要返回它...但它已经被处理掉...您不需要通过使用 using 展开它来处理该对象...无论使用什么,都需要处理该对象。
其他问题
bitmap
也是内存泄漏,需要用隐式调用的using
或dispose
包装。
最终函数示例
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;
}
示例控制台应用程序演示
我已经测试了下面的内容,它按预期工作。
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[] 格式,再转换 base64 格式试试下面的代码可能会解决你的问题,
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;
}
我想创建一个包含 2 张图片的 pdf。其中一个图像是文本,另一个是在第一个图像之上绘制的水印。好吧,当我加载第一张图片时一切正常,但随后我尝试加载水印图片并获得 "Out of Memory" 异常。我有内存(打印内存使用量大约 20MB)并且可以在我的计算机中打开图像(我正在使用我从 google 中获取的图像只是为了测试,直到我没有得到真正的图像)。
我得到异常的代码是这个:
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))
然后您要返回它...但它已经被处理掉...您不需要通过使用 using 展开它来处理该对象...无论使用什么,都需要处理该对象。
其他问题
bitmap
也是内存泄漏,需要用隐式调用的using
或dispose
包装。
最终函数示例
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;
}
示例控制台应用程序演示
我已经测试了下面的内容,它按预期工作。
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[] 格式,再转换 base64 格式试试下面的代码可能会解决你的问题,
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;
}