将图像存储在缓冲区

时间:2018-02-04 13:51:06

标签: c# image winforms bitmap buffer

我正在编写我的第一个图像编辑程序(c#,winforms),我对缓冲区和有效存储数据非常不满意。 我有一个包含图片的文件夹,并通过string[]

将文件加载到FolderBrowserDialog
files = Directory.GetFiles(fbd.SelectedPath);

我总是在图片框中显示其中一张图片。我有各种适用的功能,例如:显示图像上的过滤器。我的所有函数都在Bitmaps上运行,我的所有函数基本上都是通过调用另一个函数来启动的:

Bitmap bmp = GetImage();

Image GetImage()
{
    FileStream imageStream = new FileStream(Convert.ToString(files[SelIndex]), FileMode.Open);
    Image image = Image.FromStream(imageStream);
    imageStream.Close();
    return image;
}

每当我调用我的一个函数时(例如因为我想显示不同的图像并看看滤镜是如何应用的)我在显示新图片之前会遇到痛苦的延迟。就我而言,每当我打电话给我的一个功能时,它就会进入图片所在的原始文件夹并从那里获取数据,我相信这就是滞后的原因。 第一个:那是正确的吗?其次:什么是避免这种情况的方法?我可以想象将数据保存在某种缓冲区中?

我的函数/过滤器非常基本,我不使用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文件,每个大约12 MB,绝对是问题的一部分。

1 个答案:

答案 0 :(得分:1)

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

首先,考虑一下您编写的所有FileStream内容的简单替代方法。

Bitmap input = new Bitmap(pathToFile);

此外,您的GetImage函数实际上是LoadImageFromDisk函数。因此,首先要做的是确保只执行一次并将输入的Bitmap对象保留在内存中并重用它。在输入图像上调用LockBits时,请使用ReadOnly access。

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

Bitmap output = new Bitmap(input.Width, input.Height, PixelFormat.Format32bppRgb);

当您在输出图像上使用LockBits时,请使用WriteOnly访问。

另外,考虑使用 unsafe 上下文直接访问数据而不是使用Marshal.Copy,它会为您节省缓冲区副本。

最后,无论你的过滤器是什么,看看你是否可以使用Parallel.For来一次操作它并使用你所有的处理器。