C# 在缓冲区中存储图像

C# 在缓冲区中存储图像,c#,image,winforms,bitmap,buffer,C#,Image,Winforms,Bitmap,Buffer,我正在编写我的第一个图像编辑程序(c#,winforms),我对缓冲区和有效存储数据的能力非常差。 我有一个包含图片的文件夹,并通过FolderBrowserDialog将文件加载到字符串[]: files = Directory.GetFiles(fbd.SelectedPath); 我总是在图片框中显示其中一个图像。我有各种应用的功能,例如在显示的图像上应用过滤器。我的所有函数都在位图上工作,我的所有函数基本上都是从调用另一个函数开始的: Bitmap bmp = GetImage();

我正在编写我的第一个图像编辑程序(c#,winforms),我对缓冲区和有效存储数据的能力非常差。 我有一个包含图片的文件夹,并通过
FolderBrowserDialog
将文件加载到
字符串[]

files = Directory.GetFiles(fbd.SelectedPath);
我总是在图片框中显示其中一个图像。我有各种应用的功能,例如在显示的图像上应用过滤器。我的所有函数都在位图上工作,我的所有函数基本上都是从调用另一个函数开始的:

Bitmap bmp = GetImage();
以及:

每当我调用一个函数时(例如,因为我想显示不同的图像并查看过滤器在那里的应用情况),我都会在显示新图片之前经历痛苦的延迟。就我而言,每次我调用一个函数时,它都会进入图片所在的原始文件夹,并从那里获取数据,我相信这就是延迟的原因。 第一个:对吗?第二:有什么办法可以避免这种情况?我可以想象将数据保存在某种缓冲区中

我的函数/过滤器非常基本,我不使用
SetPixel
方法,但:

BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);

byte[] bytes = new byte[data.Height * data.Stride];

Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);

//whatever my filter is

Marshal.Copy(bytes, 0, data.Scan0, bytes.Length);

bmp.UnlockBits(data);
因为它要快得多,所以滞后不应该来自于它


编辑:另外,我使用的是.tif文件,每个文件大约有12MB,这肯定是问题的一部分。

你说得对,文件操作很昂贵。它们涉及两个相对较慢的操作:从磁盘读取数据和解压缩数据

首先,考虑一下你写的所有文件的简单选择。

Bitmap input = new Bitmap(pathToFile);
另外,您的
GetImage
函数实际上是一个
LoadImageFromDisk
函数。因此,要做的第一件事是确保只执行一次,并将输入位图对象保留在内存中并重用它。在输入映像上调用锁位时,请使用只读访问

如果要进行修改(如应用图像过滤器),请将此过滤器操作的结果存储在新的输出图像中,而不是在内存中覆盖原始图像。然后,如果您想更改过滤器的详细信息,您仍然可以使用原始过滤器

Bitmap output = new Bitmap(input.Width, input.Height, PixelFormat.Format32bppRgb);
当您在输出图像上锁定位时,请使用WriteOnly访问

也可以考虑使用一个不安全的上下文来直接访问数据,而不是使用MalSal.Read,它会为您节省一个缓冲区拷贝。


最后,不管你的过滤器是什么,看看你是否能利用Parallel.For一次在线操作,并利用你所有的处理器。

已经尝试实施了你的一些建议,到目前为止效果很好,非常感谢。访问数据的不安全上下文是什么意思?允许您从BitmapData.Scan0的IntPtr创建
字节*
指针,并直接访问数据。你必须在你的项目设置中;默认情况下,它处于禁用状态。
Bitmap output = new Bitmap(input.Width, input.Height, PixelFormat.Format32bppRgb);