我正在编写我的第一个图像编辑程序(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,绝对是问题的一部分。
答案 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来一次操作它并使用你所有的处理器。