C# 创建Bitmap位图中的PixelFormat如何影响stride步幅的计算

创建位图的方法

cs 复制代码
//
// 摘要:
//     用指定的大小、像素格式和像素数据初始化 System.Drawing.Bitmap 类的新实例。
//
// 参数:
//   width:
//     新 System.Drawing.Bitmap 的宽度(以像素为单位)。
//
//   height:
//     新 System.Drawing.Bitmap 的高度(以像素为单位)。
//
//   stride:
//     指定相邻扫描行开始处之间字节偏移量的整数。 这通常(但不一定)是以像素格式表示的字节数(例如,2 表示每像素 16 位)乘以位图的宽度。 传递给此参数的值必须为
//     4 的倍数。
//
//   format:
//     新 System.Drawing.Bitmap 的像素格式。 这必须指定以 Format 开头的值。
//
//   scan0:
//     指向包含像素数据的字节数组的指针。
//
// 异常:
//   T:System.ArgumentException:
//     指定了名称不以 Format 开头的 System.Drawing.Imaging.PixelFormat 值。 例如,指定 System.Drawing.Imaging.PixelFormat.Gdi
//     将导致一个 System.ArgumentException,但 System.Drawing.Imaging.PixelFormat.Format48bppRgb
//     不会出现这种情况。
public Bitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0);

PixelFormat如何影响stride步幅的计算

  1. PixelFormat.Format8bppIndexed:

    • 每像素使用 1 个字节(8 位)表示颜色,通常用于索引颜色表的灰度或调色板图像。
    • stride = (width * 1) + (对齐补足),对齐至 4 字节边界。
  2. PixelFormat.Format16bppRgb555PixelFormat.Format16bppRgb565:

    • 每像素使用 2 个字节(16 位)表示 RGB 颜色。
    • stride = (width * 2) + (对齐补足),对齐至 4 字节边界。
  3. PixelFormat.Format24bppRgbPixelFormat.Format32bppRgb:

    • 每像素分别使用 3 个字节(24 位)或 4 个字节(32 位,额外字节通常为 0 或填充)表示 RGB 颜色。
    • stride = (width * 3) 或 (width * 4) + (对齐补足),分别对齐至 4 字节边界。
  4. PixelFormat.Format32bppArgbPixelFormat.Format32bppPArgb:

    • 每像素使用 4 个字节(32 位)表示 ARGB 颜色,其中 A 代表 Alpha 透明通道。
    • stride = (width * 4) + (对齐补足),对齐至 4 字节边界。
  5. PixelFormat.Format48bppRgbPixelFormat.Format64bppArgb:

    • 每像素分别使用 6 个字节(48 位)或 8 个字节(64 位)表示高精度 RGB 或 ARGB 颜色。
    • stride = (width * 6) 或 (width * 8) + (对齐补足),分别对齐至 4 字节边界。

注意点

  • 确保 stride 符合要求: 如前所述,stride 必须是 4 字节的倍数。在计算时,如果直接按像素字节数乘以宽度得到的值不是 4 的倍数,则需要添加额外的填充字节,使其对齐至 4 字节边界。

  • **内存对齐:**stride 可能不是简单地 width * bytes_per_pixel,因为某些硬件和操作系统可能要求内存按特定边界对齐。例如,它可能是 4 的倍数,以确保内存访问效率。

  • 正确计算 scan0 指针: scan0 参数是指向包含像素数据的字节数组的指针。当创建或操作位图时,需要确保该指针指向正确的位置,即首行像素数据的起始地址。这通常需要根据 strideheight 计算得出。

  • 内存管理: 使用指针传递像素数据时,需要确保内存的有效性和生命周期。确保分配了足够的内存来存储整个位图数据,并在不再需要时正确释放内存,以避免内存泄漏。

  • 兼容性与性能: 不同的 PixelFormat 可能会影响图像的兼容性和处理性能。例如,带有 Alpha 通道的格式(如 Format32bppArgb)提供了透明度信息,但可能不被所有软件或硬件完全支持;而某些特定格式(如 16 位 RGB)可能更适合某些图形硬件加速。

  • 跨平台注意事项: 如果涉及跨平台操作,不同的操作系统或图形库可能对位图格式的支持有所差异。在设计和实现时,应考虑目标平台的兼容性需求。

  • 数据访问一致性: 当直接操作底层像素数据时,要注意多线程环境下的数据同步问题,以防止数据竞争导致的图像损坏。

  • 性能考虑 :对于大型位图或频繁操作的位图,不恰当的 stride 设置可能会导致性能问题。尽量使 stride 与硬件和操作系统的内存访问模式相匹配。

总结

在使用 Bitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0) 构造函数时,应仔细考虑 stridePixelFormat 的关系,确保正确的内存布局和数据访问,同时注意相关的内存管理和性能因素。

举例

如果是PixelFormat.Format24bppRgb,如何计算stride步幅,代码如下:

cs 复制代码
//如果是PixelFormat.Format24bppRgb
int bytesPerPixel = 3; // 对于 Format24bppRgb
int width = ...; // 图像的实际宽度
int padding = (4 - (width * bytesPerPixel) % 4) % 4;
int stride = width * bytesPerPixel + padding;
stride = ((stride + 3) / 4) * 4;
相关推荐
IT技术分享社区6 小时前
C#实战:使用腾讯云识别服务轻松提取火车票信息
开发语言·c#·云计算·腾讯云·共识算法
△曉風殘月〆13 小时前
WPF MVVM入门系列教程(二、依赖属性)
c#·wpf·mvvm
逐·風15 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
m0_6569747418 小时前
C#中的集合类及其使用
开发语言·c#
九鼎科技-Leo18 小时前
了解 .NET 运行时与 .NET 框架:基础概念与相互关系
windows·c#·.net
九鼎科技-Leo20 小时前
什么是 ASP.NET Core?与 ASP.NET MVC 有什么区别?
windows·后端·c#·asp.net·mvc·.net
.net开发20 小时前
WPF怎么通过RestSharp向后端发请求
前端·c#·.net·wpf
小乖兽技术20 小时前
C#与C++交互开发系列(二十):跨进程通信之共享内存(Shared Memory)
c++·c#·交互·ipc
幼儿园园霸柒柒21 小时前
第七章: 7.3求一个3*3的整型矩阵对角线元素之和
c语言·c++·算法·矩阵·c#·1024程序员节
平凡シンプル1 天前
C# EF 使用
c#