且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2021-08-22 20:58:47

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

Bitmaps are read in a lazy fashion. The actual algorithm used depends a great deal on the image format, a .bmp file is easy, a .jpeg is not so easy. Under the hood, GDI+ creates a memory mapped file to map the file data into RAM, when necessary, taking advantage of the demand-paged virtual memory mapping feature of the operating system. It is this MMF that infamously creates a lock on the file and is responsible for the ratty exceptions you get when trying to save an image back to a file with the same name.

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

Bitmap.LockBits() creates a separate buffer that maps the pixel data from the MMF to an area in memory that has the requested pixel format. Now you have the data in a well defined format that's independent from the format in the file. Calling UnlockBits() writes the modified data back, if any. Exactly how the data from the file gets re-combined with the modified pixels is not specified and is likely to depend a great deal on the codec.

这种完全相同的锁定发生,看不见,当你在其他方法中使用位图时。就像用Graphics.DrawImage()绘制图像一样。当你使用Bitmap.GetPixel()时臭名昭着。正如你现在可以猜到的那样,在锁定调用中获取转换像素数据需要相当大的开销,因为GetPixel()因为你对位图中的每个像素而不是仅仅一次这样做而这么慢, DrawImage和LockBits()可以。

This exact same locking happens, unseen, when you use the bitmap in other methods. Like when you draw the image with Graphics.DrawImage(). And infamously when you use Bitmap.GetPixel(). As you can guess by now, there's a fair amount of overhead involved in getting the pixel data converted at the lock call, the reason that GetPixel() is so slow since you do it for every pixel in the bitmap rather than just once, as DrawImage and LockBits() do.

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

It should be also clear that the amount of overhead depends a great deal on the image file format, the expense of decoding the pixel data on-the-fly, the amount of caching done by the decoder, the pixel format of the file versus the pixel format you ask for in LockBits(). There's way too much going on here to make predictable perf guesses, you'll have to profile it.