如何MFC里直接把一个width×height的unsigned char数组绘制到屏幕

cxz7531 2010-02-03 09:25:49
近来做一个模拟毛笔的项目,老大要求必须用纯C来做绘制。我是这样做的:
屏幕大小为w×h,定义一个unsigned char数组m_buffer = new unsigned char[n];绘制任何图形都在这个数组中直接操作。但用鼠标在屏幕绘制的时候发觉一顿一顿的,我的代码是这样的:
CClientDC dc(this);
Graphics graphics( dc.m_hDC );
Bitmap *image1 = Bitmap::FromBITMAPINFO(br,m_buffer);
graphics.DrawImage(image1,PointF(0,0));
delete image1;
ReleaseDC(&dc);
鼠标每次OnMouseMove都需要把这个m_buffer 转化成一个Bitmap ,然后绘制到屏幕,开销是在太大。
有没有办法直接把m_buffer绘制到屏幕(不转化Bitmap ),或者每次只绘制m_buffer的一小部分内容,因为每次鼠标采样实际上只影响顶多4、5个像素的范围。


...全文
180 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
lambochan 2010-02-04
  • 打赏
  • 举报
回复
简单,用CreateDIBScetion()来create一个HBITMAP,它的ppvbits就当做是你的无符号数组.
然后就可以直接在上面写写画画,画完后可直接显示,而且所画的已在那ppvbits位数据指针上....
不需要如你楼顶的create完又del掉那样麻烦.

btw..或许,去偶那look look吧,hohoho~~
red-fly 2010-02-04
  • 打赏
  • 举报
回复
步骤如下:
1. 从最后一次的位置开始绘制到当前鼠标的位置
2. 记录本次的位置为最后一次位置

中间如果鼠标被抬起,则表示新一个笔画,则在第2步中复位最后一次位置的变量
swenfang 2010-02-04
  • 打赏
  • 举报
回复
你既然把每个点的信息都放在数组里了,并且知道哪些点的颜色值改变了,那就直接创建一个小的位图,直接用贴图函数贴在屏幕的某个合适的位置不就行了吗
lambochan 2010-02-04
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 cxz7531 的回复:]
我用StretchDIBits已经实现了,加上个Invalidate(False)就可以了。
用CreateDIBScetion的优势在哪里?在ppvbits数组中写画完毕后,还需要把HBITMAP在屏幕上绘制,还是可以直接把HBITMAP跟屏幕预先关联起来?如果还要绘制的话,效率估计不会比StretchDIBits高
[/Quote]

不是这个问题,是偶看漏了,你不是用GDI画而已,自己软处理的话,确实不需要create一个HBITMAP.
如果是用GDI的话,那就完全不同了~~~

当然了,用HBITMAP和直接用StretchDibBits()来显示的话,效率估计一样的,而且还可以直接解决闪烁问题.
不过,不create有不create的好处,不用浪费多点内存.随便~~
cxz7531 2010-02-04
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 lambochan 的回复:]
简单,用CreateDIBScetion()来create一个HBITMAP,它的ppvbits就当做是你的无符号数组.
然后就可以直接在上面写写画画,画完后可直接显示,而且所画的已在那ppvbits位数据指针上....
不需要如你楼顶的create完又del掉那样麻烦.

btw..或许,去偶那look look吧,hohoho~~
[/Quote]
我用StretchDIBits已经实现了,加上个Invalidate(False)就可以了。
用CreateDIBScetion的优势在哪里?在ppvbits数组中写画完毕后,还需要把HBITMAP在屏幕上绘制,还是可以直接把HBITMAP跟屏幕预先关联起来?如果还要绘制的话,效率估计不会比StretchDIBits高
sjdev 2010-02-03
  • 打赏
  • 举报
回复
不知道StretchDIBits行不行?
cxz7531 2010-02-03
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 happyparrot 的回复:]
关键是你要知道哪部分变化了啊

[/Quote]
这个容易知道,鼠标本次采样点和上次采样点之间,形成一个矩形区域,每次绘制都是在这个范围内。
只要在这个矩形区域中绘制就行了。现在没找到直接把这个矩形区域会知道屏幕上去的办法,转化Bitmap比较低效
快乐鹦鹉 2010-02-03
  • 打赏
  • 举报
回复
关键是你要知道哪部分变化了啊
cxz7531 2010-02-03
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 happyparrot 的回复:]
那你就记录哪些格点信息发生变化。只需绘制哪些发生变化的格点即可,不用整个屏幕绘制。
[/Quote]
m_buffer = new unsigned char[w×h]记录一个点阵信息,比如,我每次只想把这个点阵中取出一个子矩形(x0,y0,w0,h0)来绘制,有没有高效的办法,最好不要转化BitMap,直接拿数组的一部分去绘制
快乐鹦鹉 2010-02-03
  • 打赏
  • 举报
回复
那你就记录哪些格点信息发生变化。只需绘制哪些发生变化的格点即可,不用整个屏幕绘制。
cxz7531 2010-02-03
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 happyparrot 的回复:]
既然是图形绘制,为什么要用图像来处理呢?直接用CDC画线来处理啊。
[/Quote]
有些嵌入式设备不提供CDC画线功能,只提供直接设置每个像素点的功能。所以采用这个蹩脚办法,如果用CDC画线就不好移植了
cxz7531 2010-02-03
  • 打赏
  • 举报
回复
用Graphics 的DrawXXX或者fillXXX等等效果好得多,但这个是打算移植到嵌入式设备,所以不用这些方法,一切绘制都在m_buffer = new unsigned char[w×h]中自己操作
快乐鹦鹉 2010-02-03
  • 打赏
  • 举报
回复
既然是图形绘制,为什么要用图像来处理呢?直接用CDC画线来处理啊。
zhou1xp 2010-02-03
  • 打赏
  • 举报
回复
mark
cxz7531 2010-02-03
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 sjdev 的回复:]
不知道StretchDIBits行不行?
[/Quote]
我该用StretchDIBits后,反而什么画不出了
int w=pDoc->brush->width;
int h=pDoc->brush->height;
UNIT8 *m_buffer=pDoc->brush->m_buffer;
PAINTSTRUCT ps ;
HDC hdc = hdc = ::BeginPaint (this->GetSafeHwnd(), &ps) ;
StretchDIBits(hdc,//
0,0,w, h,//
0,0,w, h,//
pDoc->brush->m_buffer,//
br, DIB_RGB_COLORS, SRCCOPY
);
::EndPaint (this->GetSafeHwnd(), &ps) ;
我的m_buffer是无符号char数组,8位,不知道是不是最后两个参数的设置有误
DIB_RGB_COLORS, SRCCOPY
yjs_ideal 2010-02-03
  • 打赏
  • 举报
回复
我也遇到这个问题了 尤其是当width 和 height很大的时候 刷新很慢

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧