LockBits in GDI+

发布时间:March 31, 2011 分类:技术

什么东西一旦追求起效率来最终还是要归到比较底层的操作,比如 GDI 中直接操作位图数据就要用 GetDIBits / SetDIBits(或者已经废弃的 GetBitmapBits / SetBitmapBits)。因为最近要处理的都是 GDI 处理不了的 PNG 格式图片,所以还是用上了 GDI+。GDI+ 中直接操作 Bitmap 的数据就要用 LockBits / UnlockBits 了。

第一眼看见 Bitmap::LockBits 的声明我就比较晕:

Status LockBits(const Rect *rect,UINT flags,PixelFormat format,BitmapData *lockedBitmapData
);

不过说实话,整个 GDI+ 库的风格相对于 M$ 的其它库来说已经是很清新脱俗了 :)

rect
要锁定的矩形区域,一般都是锁定整个图像大小。(吐槽:为神马不能传 NULL 进去表示全图啊~)
flags
锁定区域要进行读操作还是写操作,以及是否自己分配缓冲区。(看着比较不顺眼的 UINT 类型可取的值其实是 enum
format
锁定区域所需的像素格式,如果和图片本身的格式不符,GDI+ 会自动进行转换。
lockedBitmapData
输出锁定区域信息,成员变量 Scan0 会指向被锁定的像素区域(如果 flags 里指定自己分配缓冲区的话,系统只是往 Scan0 所指缓冲区写数据)。

那么锁定全图进行读操作就是:

int w = bmp->GetWidth();
int h = bmp->GetHeight();
BitmapData bmpData;
bmp->LockBits(Rect(0, 0, w, h), ImageLockModeRead, PixelFormat32bppARGB, &bmpData);

锁定完图像区域,就可以对得到的 BitmapData 进行操作了。BitmapData 包含了被锁定区域的长、宽、格式、指针信息。取坐标 (x, y) 的像素颜色可以用:

unsigned int *pData = reinterpret_cast<unsigned int *>(bmpData.Scan0);
int stride = bmpData.Stride;
unsigned int color = pData[y * stride / 4 + x]; // color= 0xAARRGGBB

有一个比较特别的 Stride 成员,它表示「一行」图像对应的缓冲区所实际占用的字节数(因为位图文件有一条变态的规则:图片数据在存储时每一行字节数必须是 4 的倍数,如果真实图片数据宽度不是 4 的倍数则需要用垃圾数据补齐不足的字节数,于是就造成了 Stride ≠ Width 的现象,即所谓的字节对齐)。

对于图片数据操作完以后要记得对锁定区域进行解锁:

bmp->UnlockBits(&bmpData);

这样一来就功德圆满了。

嗯~这段笔记就是这样,这真是有意义的一天啊~

自己提供缓冲区

咳咳~距刚刚写这篇东西已经有大半年了,在仔细看 GDI+ 的文档时又发现了些有用的东东。

正如你所看到的,上边所说的「LockBits → 读写 bmpData.San0 → UnlockBits」的三部曲其实并不与 GDI 中的 GetDIBits / SetDIBits 完全对应。至少后者是直接从位图中读取数据到我们自己提供的颜色缓冲区、直接从自己的颜色缓冲区写到位图中去,而前者却需要在 Lock 后一行一行、甚至一个像素一个像素地手动交换。

好消息是 Bitmap::LockBits 的 flags 参数除了可以传入 ImageLockModeRead 和 ImageLockModeWrite 外还可以同时或上一个 ImageLockModeUserInputBuf。这个标志位表示让 LockBits 使用我们传入的 BitmapData 中的缓冲区信息来进行读写,而不是由它来分配、我们来读写。

举个栗子 :)

int w = bmp->GetWidth();
int h = bmp->GetHeight();
unsigned int *buffer = new unsigned int[w * h * 4]; // 缓冲区,以 32 位色 ARGB 模式读取
BitmapData bmpData;
bmpData.Width  = w;
bmpData.Height = h;
bmpData.Stride = w * 4; // 缓冲区每行大小,自行分配,每行就没有多余字节了
bmpData.Scan0  = buffer;
bmpData.PixelFormat = PixelFormat32bppARGB;
bmpData.Reserved = NULL;
bmp->LockBits(Rect(0, 0, w, h),ImageLockModeRead | ImageLockModeUserInputBuf,PixelFormat32bppARGB,&bmpData);
bmp->UnlockBits(&bmpData);

转载于:https://www.cnblogs.com/songtzu/archive/2013/01/25/2876805.html

LockBits in GDI+【转】http://timothyqiu.com/archives/lockbits-in-gdiplus/相关推荐

  1. GDI+编程说明及小结

    原文地址:http://blog.csdn.net/byxdaz/article/details/5972759 GDI+(Graphics Device Interface Plus图形设备接口加) ...

  2. vs2008中使用gdi+的设置

    vs2008中使用gdi+ 1.新建一个mfc工程 2.在stdafx.h文件中加入以下几行语句: #include <gdiplus.h>                // #prag ...

  3. NX二次开发-GDI+绘制button图片(模仿燕秀)

    目录 前言 二.使用步骤 1.头文件cpp 2.hpp 总结 前言 1.本人非专业人士,第一次写,请各位大佬指正: 2.如有侵权问题,请私信. 一.样式 如图:燕秀工具的颜色按钮,两类,第一类只显示颜 ...

  4. 【转】c#数字图像处理(一)Bitmap类、 Bitmapdata类和 Graphics类

    转自:https://www.cnblogs.com/dearzhoubi/p/8553763.html Bitmap类. Bitmapdata类和 Graphics类是C#图像处理中最重要的3个类, ...

  5. windows配置gvim高效率编程(cc++)带自动补全代码

    对vim的配置足以处理一般的比赛获其他编程项目要求,如自动缩进,自动补全等等.先上几张截图,看看效果:  可以看见vim简洁高效的界面和不错的缩进功能. debug功能  一.安装gvim  下载资源 ...

  6. 视频直播:Windows中各类画面源的截取和合成方法总结

    当今,视频直播技术和实时音视频技术已经是很多行业必备,典型的应用场景有教育直播.远程视频会议.互联网娱乐等.在移动端发起直播,其画面源的种类是十分有限的,无非是取摄像头.截屏等.PC端由于其系统资源充 ...

  7. Windows中各类画面源的截取和合成方法总结

    曹伟 2015年毕业于华中科技大学后入职网易,先后参与过易信PC版.云信PC demo以及教育直播产品的研发,目前在云信音视频组PC端组从事开发. 作者简介 ●●● 概要 当今,视频直播和实时音视频技 ...

  8. vb不能插入png图片_VB6.0载入PNG格式图片

    展开全部 给你一个示例吧,显示PNG到e69da5e6ba903231313335323631343130323136353331333335313739FORM上,用GDI的:Private Dec ...

  9. 图形图像平面几何变换类(C++版)

    来源:http://www.cnblogs.com/maozefa/archive/2010/10/27/1862698.html 本文用C++实现一个图形图像平面几何变换类TransformMatr ...

最新文章

  1. 旋转矩阵、欧拉角、四元数比较
  2. 没装Sql Server 2005 Express就不能使用webpart控件?
  3. php url 筛选,PHP获取当前URL路径的处理方法(适用于多条件筛选列表)
  4. 关于WebRTC发展的担忧和思考
  5. 使用Java 8.0进行类型安全的依赖项注入
  6. 卡巴绿杀6 By Moshow魔手
  7. 第三方框架-纯代码布局:Masonry的简单使用
  8. 【译】 WebSocket 协议第十章——安全性考虑(Security Considerations)
  9. EF BB BF的问题
  10. 创建图片mat_Python骚操作,让图片人物动起来!
  11. java dht 爬虫_P2P中DHT网络爬虫
  12. OC中链式编程和函数式编程
  13. SPSSPRO杯第十五届数学中国数学建模网络挑战赛赛题浅评
  14. 计算几何之求圆与直线的交点
  15. 手机罗盘(指南针)校准方法
  16. ampserv mysql升级_APMServ5.2.6升级PHP
  17. 如何强制修改电脑密码
  18. 一个开源的网易云音乐api项目
  19. 树莓派CM4烧录Ubuntu20镜像与ROS2的安装(无屏)
  20. 【小程序源码】检讨书生成微信小程序工具源码-安装搭建简单

热门文章

  1. VB 实现大文件的分割与恢复,引用 ADODB.Stream 提供一个过程代码
  2. 中外教育专家“支招”中国学生如何接轨国际教育
  3. 小撸 array map 源码
  4. shiro系列一、认识shiro
  5. Javascript Symbol 隐匿的未来之星
  6. 为什么多线程可以利用到多核?
  7. 私有网盘nextcloud 12的问题处理及优化
  8. Lintcode18 Subsets II solution 题解
  9. 百度地图infowindow
  10. Cobbler 2.4.4 安装