有没有一种有效的方法来处理C#中的高分辨率照片?

时间:2015-08-07 11:40:55

标签: c# .net memory-leaks photos

我制作了一个分析图像第一个像素的程序,然后在List中记下它的值,这用于检查图像是黑白还是彩色。现在,有没有人知道读取高分辨率图像的有效方法?现在我正在使用Bitmaps,但效率非常低。图像大约是1800万像素,我想分析大约400张照片。代码如下:

Bitmap b;

foreach (FileInfo f in files) {
  // HUGE MEMORY LEAK
  System.GC.Collect();
  System.GC.WaitForPendingFinalizers();

  b = (Bitmap)Bitmap.FromFile(f.FullName);

  // reading pixel (0,0) from bitmap

当我运行我的程序时,它说:

"An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll
Additional information: There is no available memory."

我已经尝试使用System.GC.Collect()进行清理,正如您所看到的,但异常并没有消失。如果我分析一个只包含几张照片的文件夹,程序运行正常,很乐意这样做。

3 个答案:

答案 0 :(得分:2)

使用图像的第一个像素来检查它是否是颜色是错误的方法。

如果您的图像背景为黑色(RGB中的像素值为0,0,0),您如何知道图像是黑白的,而不是黑色背景的颜色?

将位图置于“正在使用”中是正确的,因为它将正确处理。

以下将有所帮助。

class Program
{
    static void Main(string[] args) {
        List<String> ImageExtensions = new List<string> { ".JPG", ".JPE", ".BMP", ".GIF", ".PNG" };

        String rootDir = "C:\\Images";
        foreach (String fileName in Directory.EnumerateFiles(rootDir)) {
            if (ImageExtensions.Contains(Path.GetExtension(fileName).ToUpper())) {
                try {
                    //Image.FromFile will work just as well here.
                    using (Image i = Bitmap.FromFile(fileName)) {
                        if (i.PixelFormat == PixelFormat.Format16bppGrayScale) {
                            //Grey scale...
                        } else if (i.PixelFormat == PixelFormat.Format1bppIndexed) {
                            //1bit colour (possibly b/w, but could be other indexed colours)
                        }
                    }
                } catch (Exception e) {
                    Console.WriteLine("Error - " + e.Message);
                }
            }
        }
    }
}

PixelFormat的参考资料可在此处找到 - https://msdn.microsoft.com/en-us/library/system.drawing.imaging.pixelformat%28v=vs.110%29.aspx

C#中的对象限制为2Gb,因此我怀疑单个图像是否会导致问题。 我也建议你不要手动调用GC来解决内存泄漏问题(虽然这在技术上不是泄漏,只是大量内存使用)。

使用语句非常适合确保对象标记为可处置,并且GC非常擅长清理。

我们在软件中执行密集的图像处理,并且使用我所显示的方法从未遇到过内存问题。

虽然简单地读取标题来查找图像数据是一个非常正确的解决方案,但它确实意味着要解码不同文件类型的大量额外工作,除非您在非常小的内存中处理大量图像,否则这是不必要的(虽然如果这是你的目标,直接C是一个更好的方式,而不是C#。马匹的课程和所有的爵士乐!)

编辑 - 我刚刚在包含超过5000个高分辨率TIFF的目录上运行它,没有内存问题。该过程中最慢的部分是控制台输出!

答案 1 :(得分:0)

我想,如果你只需要第一个像素 - 不需要读取所有文件。也许你应该从位图字节数组中取出第一个像素并使用它。你应该手动找到像素阵列并先拿。

如何找到像素阵列?嗯,这取决于文件格式。您应该找到每种可用格式的规范并使用它。以下是BMP reader

的示例

答案 2 :(得分:0)

我认为您可以通过处理位图来解决问题。

试试这个:

ng-repeat