作者:chunjhyy6668787 | 来源:互联网 | 2023-02-09 12:22
我最近在一个答案中偶然发现了一个问题,该问题是关于在C#中将位图格式转换为24位RGB:更快地复制图像以更改其PixelFormat,其中选定的答案指出以下内容:
另一种方法是在没有alpha通道的情况下锁定位,然后将内存复制到新的位图
并提供以下代码作为示例(为简便起见,已简化):
public static Bitmap RemoveAlphaChannel(Bitmap bitmap) {
Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
Bitmap bitmapDest = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format24bppRgb);
BitmapData data = bitmap.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData dataDest = bitmapDest.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
int bitmapSize = data.Stride * data.Height;
Buffer.MemoryCopy(dataDest.Scan0, data.Scan0, bitmapSize, bitmapSize);
bitmap.UnlockBits(data);
bitmapDest.UnlockBits(dataDest);
return bitmapDest;
}
让我们使用此功能将32位ARGB图像转换为24位RGB。我有以下问题:
如何将32位位图锁定为24位,为什么允许?
现在,原始位图中每个像素的RGB分量如何邻接?Alpha组件去哪儿了?步幅怎么了?
将位图的位锁定为其他格式是否会导致在后台创建位图的副本?
Hans Passant..
5
这只是GDI +提供的便利。重要的是,使用一种与您要应用的特定算法配合得很好的格式来访问像素通常更方便,更快捷。
32bppPArgb格式最好是使位图尽可能快地呈现到屏幕上,它与视频帧缓冲区格式兼容,因此不需要转换。典型渲染速度比任何其他像素格式快10倍。但是PArgb很难在代码中进行操作。R,G和B通道值已由alpha值校正,您必须再次将其除以恢复原始RGB值。要求使用Argb格式可以一举解决。
同样,24bppRgb格式很尴尬,您必须使用a byte*
来访问像素通道。这要求每个像素3次内存访问,从而大大降低了代码速度。要求使用32bppArgb可以int*
更快地使用,并允许您忽略步幅。
这些转换没有什么特别复杂的。但是它们不是免费的,GDI +必须完成分配临时存储并来回转换像素值的工作。我使用1000 x 1000位图和ImageLockMode.ReadWrite在pokey笔记本电脑上对其进行了分析:
32bppArgb => 32bppArgb : 0.002 msec
32bppPArgb => 32bppArgb : 5.6 msec
32bppArgb => 24bppRgb : 5.6 msec
32bppPArgb => 24bppRgb : 5.6 msec
我使用memcpy()在相同的32bppArgb 1000 x 1000位图上进行复制时,在RemoveAlphaChannel()方法上测量了perf。对于所需的单个ImageLockMode.ReadOnly像素转换,我得到2.8毫秒,对于副本,我得到了2.8毫秒。GDI +提供的Graphics.DrawImage()速度约为完成速度的两倍,耗时9.3毫秒。
1> Hans Passant..:
这只是GDI +提供的便利。重要的是,使用一种与您要应用的特定算法配合得很好的格式来访问像素通常更方便,更快捷。
32bppPArgb格式最好是使位图尽可能快地呈现到屏幕上,它与视频帧缓冲区格式兼容,因此不需要转换。典型渲染速度比任何其他像素格式快10倍。但是PArgb很难在代码中进行操作。R,G和B通道值已由alpha值校正,您必须再次将其除以恢复原始RGB值。要求使用Argb格式可以一举解决。
同样,24bppRgb格式很尴尬,您必须使用a byte*
来访问像素通道。这要求每个像素3次内存访问,从而大大降低了代码速度。要求使用32bppArgb可以int*
更快地使用,并允许您忽略步幅。
这些转换没有什么特别复杂的。但是它们不是免费的,GDI +必须完成分配临时存储并来回转换像素值的工作。我使用1000 x 1000位图和ImageLockMode.ReadWrite在pokey笔记本电脑上对其进行了分析:
32bppArgb => 32bppArgb : 0.002 msec
32bppPArgb => 32bppArgb : 5.6 msec
32bppArgb => 24bppRgb : 5.6 msec
32bppPArgb => 24bppRgb : 5.6 msec
我使用memcpy()在相同的32bppArgb 1000 x 1000位图上进行复制时,在RemoveAlphaChannel()方法上测量了perf。对于所需的单个ImageLockMode.ReadOnly像素转换,我得到2.8毫秒,对于副本,我得到了2.8毫秒。GDI +提供的Graphics.DrawImage()速度约为完成速度的两倍,耗时9.3毫秒。