【问题标题】:How can I load/manipulate a huge image without memory issues?如何在没有内存问题的情况下加载/操作巨大的图像?
【发布时间】:2012-11-18 21:00:39
【问题描述】:

尝试将巨大的图像(例如 9000x9000 像素的图像)加载到 Bitmap 对象中可能会产生内存不足错误、"Parameter is not valid" error 以及毫无疑问的其他相关问题。

如何从磁盘加载 9000x9000 像素的图像,最终在保存回磁盘之前调整其大小,而不会导致致命错误(例如内存不足)?

让我们假设一个 32 位环境,具有 2gb 的内存,C# 4.0,并且将使用 jpg、gif、bmp、tif、png 的图像格式。

我尝试了以下 3 个 sn-ps,每个都失败并出现内存错误。

尝试 1:

using (Bitmap srcImg = new Bitmap(@"C:\9000x9000.jpg"))
{
    // boom
}

尝试 2:

using (Image srcImg = Image.FromFile(@"C:\9000x9000.jpg"))
{
    // kapow
}

尝试 3:

using (FileStream fs = new FileStream(@"C:\9000x9000.jpg", FileMode.Open, FileAccess.Read))
{
    using (Image srcImg = Image.FromStream(fs))
    {
        // kelly clarkson
    }
}

我对一个可能的解决方案的想法是将图像文件直接加载到一个数组中(这样您就没有 Bitmap 对象的巨大开销),以某种方式使用该数组将其调整为更小(可能需要为不同的图像编码格式标题?),然后最终转换为可管理大小的位图对象。

想法或可能的解决方案?

【问题讨论】:

  • 错误信息是什么?首先在一个简单的控制台应用程序中尝试,然后在您的应用程序中应用该解决方案。
  • 图片的位深是多少?我很好奇该图像试图消耗多少 RAM。我的猜测是很多,因为 32 位图像意味着至少 310MB。考虑到您的其他问题,我强烈建议您升级到至少 8GB 内存的 64 位系统。可能更多。并且我会建议您使用专为处理如此大的图像而构建的工具
  • 您是否真的遇到了错误,或者您只是在猜测可能存在的问题?我认为没有任何先验理由认为 18 Mpx 的图像会引起任何悲伤,除非你真的想把它放大。它将占用几百 MB。
  • @MarceloCantos 他说他实际上尝试过这个问题并提到内存不足和“参数无效”(= ArgumentException)
  • 回答:确切的错误是,取决于环境:“参数无效。在 System.Drawing.Bitmap..ctor”(有问题的链接提供了有关错误的信息)和“OutOfMemoryException:Out of内存。在 System.Drawing.Bitmap..ctor"。位图对象是“32 位”(PixelFormat.Format32bppArgb) 以允许 alpha 透明度,例如 png。升级到 64 位系统/8gb 内存是未来可能的选择,但请记住问题指定 32 位/2gb;此外,优化代码以在 32 位/2gb 环境中运行无疑也会使其在 64 位/8gb 环境中更高效。

标签: c# asp.net c#-4.0


【解决方案1】:

看看AForge.Net library,这是supposedly good处理大文件。

【讨论】:

  • 我感觉他的系统受到了相当严重的限制,使用像这样的库可能是一种很好的方式。
  • 关于被“约束”,最大的约束是 32 位系统。在 32 位系统上,单个对象的大小非常有限,并且 Bitmap 对象有很多开销,因此在 32 位系统上出现内存不足错误并不需要太多系统,即使系统实际上可能有空闲内存。无论如何,即使在 64 位环境中,优化代码以尽可能少地占用内存仍然会很棒。
  • 关于 AForge 的初步想法:它似乎最初将图像直接加载到 Bitmap 对象中,因此它会有完全相同的内存问题(注释末尾的链接显示 AForge FromFile 方法)。我将运行一些测试来验证。 aforgenet.com/framework/docs/html/…
【解决方案2】:

以下是我为其工作所遵循的步骤:

1.转到 http://www.opennetcf.org/PermaLink.aspx?guid=d57ace50-2762-4b19-b07d-39421829d410 并下载下载 SDF 2.0 Beta1 Redistributables。安装。

2.在 VS.NET 2005 中针对 PPC 2003 SE 设备创建一个智能设备项目。我必须右键单击我的项目并选择“升级”以确保它针对的是 .NET CF v2.0 而不是 .NET CF 1.1 SP3。

3.我添加了 OpenNETCF.dll 和 OpenNETCF.Drawing.dll 文件作为默认安装目录(C:\Program Files\OpenNETCF\Smart Device Framework 2.0)的引用

4.我在表单上创建了一个带有图片框的简单应用程序,它会在加载表单时加载我的图像。以下是相关代码,其中一些是从 Alex Feinman 的网络日志中复制而来的:

#region Using directives
using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using OpenNETCF.Drawing.Imaging;
using System.IO;
#endregion

....

const string szFileName = @"\Storage Card\TEMP\2MBJPEG.JPG";



private void Form1_Load(object sender, EventArgs e)
{
IBitmapImage imageBitmap;
FileStream fsImage;
fsImage = new FileStream(
    szFileName,
    FileMode.Open);
imageBitmap = CreateThumbnail(
    fsImage,
    new Size(100, 100));

Bitmap bm = ImageUtils.IBitmapImageToBitmap(
    imageBitmap);
pictureBox1.Image = bm;
}


static public IBitmapImage CreateThumbnail(Stream stream, Size size)
{
IBitmapImage imageBitmap;
ImageInfo ii;
IImage image;
ImagingFactory factory = new ImagingFactoryClass();
    factory.CreateImageFromStream(
    new StreamOnFile(stream), 
    out image);
image.GetImageInfo(out ii);
factory.CreateBitmapFromImage(
    image, 
    (uint)size.Width, 
    (uint)size.Height,
    ii.PixelFormat, 
    InterpolationHint.InterpolationHintDefault, 
    out imageBitmap);
    return imageBitmap;
}

【讨论】:

  • 你是说这可以让你在 32 位系统上处理巨大的图像吗?
猜你喜欢
  • 2018-07-10
  • 2022-01-18
  • 2011-08-26
  • 2010-10-23
  • 2012-07-13
  • 2010-12-05
  • 2018-05-26
  • 2015-11-29
  • 2011-08-17
相关资源
最近更新 更多