Bitmaps如何在.NET中存储在内存中?

Rob*_*cks 6 .net architecture performance image bitmap

在.NET中,您通常使用Bitmap类来存储图像.要快速访问它,您需要调用lock()和unlock()将位图的内容复制到内存中.那么,这是否意味着位图在锁定之前没有存储在打包内存数组中?

究竟是什么需要锁定?,即为什么平台不能简单地返回指向位图的第一个像素的指针,让你直接访问像素?(除了"不安全"的内存访问注意事项)

一些可能的原因:

  • 位图以其原始压缩格式存储,以节省内存(PNG,JPEG等)
  • 位图以24-bpp格式存储,因此其访问速度比32-bpp图像慢
  • 位图不存储在压缩存储器阵列中,并且是分段的,因此无法快速读/写
  • 位图以未公开的方式存储,平台不希望您访问实际的位图数据存储器 - 强制您使用lock()在内存中创建它的副本

Han*_*ant 12

位图以懒惰的方式读取.使用的实际算法在很大程度上取决于图像格式,.bmp文件很容易,.jpeg并不那么容易.在引擎盖下,GDI +创建了一个内存映射文件,以便在必要时将文件数据映射到RAM中,从而利用操作系统的按需分页虚拟内存映射功能.正是这个MMF臭名昭着地创建了对文件的锁定,并且负责在尝试将图像保存回具有相同名称的文件时获得的稀有异常.

Bitmap.LockBits()创建一个单独的缓冲区,将MMF中的像素数据映射到具有请求像素格式的内存区域.现在,您可以使用定义良好的格式的数据,该格式与文件中的格式无关.调用UnlockBits()会将修改后的数据写回(如果有).确切地说,如何将文件中的数据与修改后的像素重新组合,并且可能在很大程度上取决于编解码器.

当您在其他方法中使用位图时,看不到这种完全相同的锁定.就像用Graphics.DrawImage()绘制图像一样.当你使用Bitmap.GetPixel()时臭名昭着.正如您现在可以猜到的那样,在锁定调用中获取像素数据所涉及的开销相当大,因为GetPixel()因为您对位图中的每个像素而不是仅仅执行一次,因此速度非常慢,因为DrawImage和LockBits()可以.

还应该清楚的是,开销量在很大程度上取决于图像文件格式,即时解码像素数据的费用,解码器完成的缓存量,文件的像素格式与你在LockBits()中要求的像素格式.这里有太多的东西可以做出可预测的猜测,你必须对它进行分析.