我编写了一个C#程序,它接受一个目录名,以100个批量遍历其中的文件,并输出gif。
class Program
{
static void Main(string[] args)
{
GifBitmapEncoder encoder = new GifBitmapEncoder();
int i = 0;
int filei = 0;
foreach (string fileName in Directory.GetFiles(args[0]).OrderBy(s => s))
{
i++;
AddFileToBitmap(encoder, fileName);
Console.WriteLine("Added file {0:000}: {1}", i, fileName);
if (i % 100 == 0)
{
string outFile = string.Format("output{0}.gif", filei);
Console.WriteLine("Saving to file: {0}", outFile);
SaveGif(encoder, outFile);
filei++;
encoder.Frames.Clear();
encoder = new GifBitmapEncoder();
GC.Collect();
Console.WriteLine();
}
}
}
static void AddFileToBitmap(GifBitmapEncoder encoder, string fileName)
{
using (Bitmap img = (Bitmap)Bitmap.FromFile(fileName))
{
BitmapSource bitmap = Imaging.CreateBitmapSourceFromHBitmap(
img.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
encoder.Frames.Add(BitmapFrame.Create(bitmap));
}
}
static void SaveGif(GifBitmapEncoder encoder, string fileName)
{
using (FileStream stream = new FileStream(fileName, FileMode.Create))
{
encoder.Save(stream);
}
}
}
当我运行它时,内存使用量从~1MB开始,前100张图像增长到~800MB;对于第二批100张图像,下降到~400MB并增长到~1.2GB;对于剩余的30张图像,下降到~800MB并因内存不足而崩溃。
我认为某处存在内存泄漏,但我无法找到它。 GifBitmapEncoder
,BitmapSource
和BitmapFrame
不是IDisposable
所以我无法处置其中的任何内容,而且我也看不到我使用的任何其他变量那可能是。也许img.GetHbitmap()
会返回IntPtr
?
有什么想法吗?
我从how to create an animated gif in .net得到了我的代码。
答案 0 :(得分:2)
试试这个:
using (Bitmap img = (Bitmap)Bitmap.FromFile(fileName))
{
IntPtr hBitmap = img.GetHbitmap();
BitmapSource bitmap = Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
encoder.Frames.Add(BitmapFrame.Create(bitmap));
DeleteObject(hBitmap);
}
文档:https://msdn.microsoft.com/en-us/library/1dz311e4(v=vs.110).aspx
您负责调用GDI DeleteObject方法来释放 GDI位图对象使用的内存。有关的更多信息 GDI位图,请参阅Windows GDI文档中的位图。
答案 1 :(得分:0)
试试这个:
encoder.Frames.Clear();
encoder = null;
GC.Collect();
//GifBitmapEncoder derives from DispatcherObject which has finalizer
GC.WaitForPendingFinalizers();
//then create a new instance
encoder = new GifBitmapEncoder();