Bitmaps如何在.NET中存储在内存中? [英] How are Bitmaps stored in memory in .NET?

查看:138
本文介绍了Bitmaps如何在.NET中存储在内存中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In .NET you usually use the Bitmap class to store images. To access it quickly, you need to call lock() and unlock() to copy the contents of the bitmap into memory. So, does it mean that the bitmap was not stored in a packed memory array before locking?

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

Exactly what is the need for locking?, i.e. why couldn't the platform simply return a pointer to the first pixel of the bitmap and let you access the pixels directly? (apart from the "unsafe" memory access considerations)

一些可能的原因:


  • 位图以原始压缩形式存储以节省内存(PNG,JPEG等)

  • 位图以24-bpp格式存储,因此其访问速度比32-更低bpp image

  • 位图不存储在打包存储器阵列中并且是碎片化的,因此无法快速读/写

  • 存储位图以一种未公开的方式,平台不希望您访问实际的位图数据内存 - 强制您使用lock()

  • The bitmap is stored in its original compressed form to save memory (PNG, JPEG, etc)
  • The bitmap is stored in 24-bpp format so its slower to access than a 32-bpp image
  • The bitmap is not stored in a packed memory array and is fragmented so can't be read/written fast
  • The bitmap is stored in an undisclosed manner, and the platform does not want you to access the actual bitmap data memory - forcing you to create a copy of it in memory using lock()

推荐答案

以懒惰的方式读取位图。使用的实际算法在很大程度上取决于图像格式,.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.

这篇关于Bitmaps如何在.NET中存储在内存中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆