如何在没有内存问题的情况下加载/操作巨大的图像?

时间:2022-02-25 02:15:41

Attempting to load a huge image (e.g. a 9000x9000 pixel image) into a Bitmap object can create out-of-memory errors, a "Parameter is not valid" error, and no doubt other related problems.

尝试将巨大的图像(例如9000x9000像素图像)加载到Bitmap对象中可能会产生内存不足错误,“参数无效”错误,并且毫无疑问会出现其他相关问题。

How can I load a 9000x9000pixel image from disk, ultimately resizing it before saving back to disk, without causing a fatal error (such as out-of-memory)?

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

Let's assume a 32-bit environment with 2gb of ram, C# 4.0, and will be working with image formats of jpg, gif, bmp, tif, png.

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

I have tried the following 3 snippets, and each fail with a memory error.

我尝试了以下3个片段,每个片段都因内存错误而失败。

Attempt 1:

尝试1:

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

Attempt 2:

尝试2:

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

Attempt 3:

尝试3:

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

My thought for a possible solution is to load the image file directly into an array (so you don't have the huge overhead of a Bitmap object), somehow resize it smaller using that array (probably need to code for different image format headers?), before finally converting to a Bitmap object of manageable size.

我想到一个可能的解决方案是将图像文件直接加载到一个数组中(这样你就没有Bitmap对象的巨大开销),不知何故使用该数组调整它的大小(可能需要为不同的图像格式标题编写代码? ),在最终转换为可管理大小的Bitmap对象之前。

Thoughts or possible solutions?

想法或可能的解决方案

2 个解决方案

#1


1  

Have a look at the AForge.Net library, which is supposedly good at processing large files.

看看AForge.Net库,据说它擅长处理大文件。

#2


0  

Here are the steps that i followed to get it working:

以下是我遵循的步骤:

1.Go to http://www.opennetcf.org/PermaLink.aspx?guid=d57ace50-2762-4b19-b07d-39421829d410 and download the Download the SDF 2.0 Beta1 Redistributables. Install.

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

2.Create a Smart Device Project in VS.NET 2005 targeting PPC 2003 SE device. I had to right-click my project and choose "Upgrade" to ensure it was targetting the .NET CF v2.0 rather than .NET CF 1.1 SP3.

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

3.I added the OpenNETCF.dll and OpenNETCF.Drawing.dll files as references from the default installation directory (C:\Program Files\OpenNETCF\Smart Device Framework 2.0)

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

4.I created a simple app with a picturebox on a form, that loads my image when the form is loaded. Here's the relevant code, some copied from Alex Feinman's web log:

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;
}

#1


1  

Have a look at the AForge.Net library, which is supposedly good at processing large files.

看看AForge.Net库,据说它擅长处理大文件。

#2


0  

Here are the steps that i followed to get it working:

以下是我遵循的步骤:

1.Go to http://www.opennetcf.org/PermaLink.aspx?guid=d57ace50-2762-4b19-b07d-39421829d410 and download the Download the SDF 2.0 Beta1 Redistributables. Install.

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

2.Create a Smart Device Project in VS.NET 2005 targeting PPC 2003 SE device. I had to right-click my project and choose "Upgrade" to ensure it was targetting the .NET CF v2.0 rather than .NET CF 1.1 SP3.

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

3.I added the OpenNETCF.dll and OpenNETCF.Drawing.dll files as references from the default installation directory (C:\Program Files\OpenNETCF\Smart Device Framework 2.0)

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

4.I created a simple app with a picturebox on a form, that loads my image when the form is loaded. Here's the relevant code, some copied from Alex Feinman's web log:

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;
}