简体   繁体   English

处理大量图像时出现内存不足异常

[英]Out of Memory Exception when Processing Large Number of Images

Im using the following code to fix the Orientation of Images depending on EXIF Data 我使用以下代码根据EXIF数据修复图像的方向

 Image FixImageOrientation(Image srce)
        {
            const int ExifOrientationId = 0x112;
            // Read orientation tag
            if (!srce.PropertyIdList.Contains(ExifOrientationId)) return srce;
            var prop = srce.GetPropertyItem(ExifOrientationId);
            var orient = BitConverter.ToInt16(prop.Value, 0);
            // Force value to 1
            prop.Value = BitConverter.GetBytes((short)1);
            srce.SetPropertyItem(prop);
          //  MessageBox.Show(orient.ToString());
            // Rotate/flip image according to <orient>
            switch (orient)
            {

                case 1:
                    srce.RotateFlip(RotateFlipType.RotateNoneFlipNone);
                    return srce;


                case 2:
                    srce.RotateFlip(RotateFlipType.RotateNoneFlipX);
                    return srce;

                case 3:
                    srce.RotateFlip(RotateFlipType.Rotate180FlipNone);
                    return srce;

                case 4:
                    srce.RotateFlip(RotateFlipType.Rotate180FlipX);
                    return srce;

                case 5:
                    srce.RotateFlip(RotateFlipType.Rotate90FlipX);
                    return srce;

                case 6:
                    srce.RotateFlip(RotateFlipType.Rotate90FlipNone);
                    return srce;

                case 7:
                    srce.RotateFlip(RotateFlipType.Rotate270FlipX);
                    return srce;

                case 8:
                    srce.RotateFlip(RotateFlipType.Rotate270FlipNone);
                    return srce;

                default:
                    srce.RotateFlip(RotateFlipType.RotateNoneFlipNone);
                    return srce;
            }
        }

I process a large batch of Images like this 我像这样处理大量图像

for (x= 0; x<list.Count; x++)
{
filepath= list.ElementAt(x);
Bitmap image = new Bitmap(FixImageOrientation(Bitmap.FromFile(filepath)));
//Do long processing and at the end i do image.dispose();
image.dispose();
}

But when processing a large batch of images i get Out of Memory exception at 但是当处理大量图像时,我在

Bitmap image = new Bitmap(FixImageOrientation(Bitmap.FromFile(filepath)));

Why do i get this.. I dispose this image at the end of the loop i guess. 我为什么得到这个..我把这个图像放在循环的末尾。

In your code you create two bitmaps but dispose only one. 在您的代码中,您创建了两个位图,但只放置了一个。 Change your code: 更改您的代码:

using(var source = Bitmap.FromFile(filepath)) {
    using(var image = new Bitmap(FixImageOrientation(source))) {
       // ... do long processing
    }
}

This should solve your problems. 这应该可以解决您的问题。

As you can find in this answer https://stackoverflow.com/a/7520919/6439999 the call to dispose does not necessarily free memory. 正如您在此答案中可以找到的https://stackoverflow.com/a/7520919/6439999调用处置不一定释放内存。 This is the task of the Garbage Collector. 这是垃圾收集器的任务。 I assume, that you are loading the images quite fast into the memory. 我假设您正在将图像快速加载到内存中。 The problem is, that the Garbage collection is only done every now and then. 问题是,垃圾收集不时进行。 If you are using a huge amount of memory by creating new objects, the garbage collection might be to slow with releasing the memory again. 如果通过创建新对象使用大量内存,则垃圾回收可能会减慢再次释放内存的速度。

You could try calling it directly from within you loop with GC.Collect(). 您可以尝试使用GC.Collect()从循环内部直接调用它。 If this is not enough, you can also try the blocking parameter, which will pause your thread until the GC run has completed. 如果这还不够,您还可以尝试使用阻塞参数,该参数将暂停线程,直到GC运行完成。

As a different approach you can set you project to compile as x64, this will give your program access to more than 1GB of memory. 作为另一种方法,您可以将项目设置为x64编译,这将使程序可以访问超过1GB的内存。 But with this solution you only push the problem further down the road. 但是,使用此解决方案,您只会将问题进一步推向前进。

Thomas 汤玛士

OUT OF MEMORY EXCEPTION IN FOR LOOP OF THOUSAND OF RECORD , a possible solution: 超出存储记录范围 ,可能的解决方案是:

  1. use using statement in your Program for restricting scope of data base object 在程序中使用using语句限制数据库对象的范围

  2. assign null value to the list after use 使用后将空值分配给列表

  3. dispose connection object 放置连接对象

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM