大图片的平滑拖动

Perfy_Yang 2010-03-30 04:12:23
前段时间问了这个问题,可是问题还没有解决...

我从一个大文件中读取一块数据,存在byte数组中,大小480 * 600,显示为灰度图像。

当我拖动鼠标之后,就要从文件中读取另外一块数据,并且显示。

我用SetPixels逐点显示,很慢,有一个明显的从上到下绘制的过程!

用什么方法能快速的更新图片呢?
...全文
171 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
Perfy_Yang 2010-04-01
  • 打赏
  • 举报
回复
下面的实现有什么问题么?
运行时,窗口变的没有背景了,也不能显示图像。
CRect rect;
GetClientRect(&rect);
//
CDC memDC;//用于缓存作图的内存DC
HBITMAP hBitmap = NULL;//内存中承载临时对象的位图
memDC.CreateCompatibleDC(NULL);//依附窗口DC,创建内存兼容DC
hBitmap = CreateCompatibleBitmap(memDC,rect.Width(),rect.Height());
//在内存DC中绘图

LPBYTE p = pDoc->GetPixels();//数据集
hBitmap = CreateDIBSection(memDC
,bitmapInfo,DIB_RGB_COLORS
,(void**)&p,NULL,0);

memDC.SelectObject(&hBitmap);//将位图选择进内存DC
memDC.FillSolidRect(0,0,rect.right,rect.bottom,RGB(255,255,255));//填充窗口
pDC->BitBlt(0,0,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);

if(hBitmap)DeleteObject(hBitmap);//删除位图
memDC.DeleteDC();//删除内存DC
xinfeng2005 2010-04-01
  • 打赏
  • 举报
回复
利用内存DC
还有VC2005 CImage类不错
辰岡墨竹 2010-03-31
  • 打赏
  • 举报
回复
如果要更快一些,可以用一个比较老的系统组件Video For Windows里的DrawDib系列函数,这个速度是为视频显示设计的绘制要快一些。而且支持褪色运算(就是在256位上显示真彩色)。
http://msdn.microsoft.com/zh-cn/library/dd797892(v=VS.85).aspx
当然更快的就是用DirectX了。DirectDraw已经不推荐用了,最好直接在Direct3D里画一张占满屏幕的矩形,然后把位图作为纹理绘制上去。但是这个需要有DirectX SDK,而且要复杂多了。
aa3000 2010-03-31
  • 打赏
  • 举报
回复
我承认,我是来接分的。
aa3000 2010-03-31
  • 打赏
  • 举报
回复
我承认,我是来接分的。
辰岡墨竹 2010-03-31
  • 打赏
  • 举报
回复
既然你都有数组了,为什么还要用SetPixels?你直接填写一个BITMAPINFO结构,然后创建一个调色板,CreateDIBSection()把这个数组当成位图就行了。

//8位位图调色板个数为256,每个RGBQUAD有4个元素,所以调色板所占内存空间为256×4
unsigned full_size = sizeof(BITMAPINFOHEADER) + 1024;
//为BITMAPINFO结构分配内存
BITMAPINFO *bmp = (BITMAPINFO *) new unsigned char[full_size];

bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmp->bmiHeader.biWidth = width;
bmp->bmiHeader.biHeight = height;
bmp->bmiHeader.biPlanes = 1;
bmp->bmiHeader.biBitCount = 8; //8位位图
bmp->bmiHeader.biCompression = 0;
bmp->bmiHeader.biSizeImage = 0;
bmp->bmiHeader.biXPelsPerMeter = 0;
bmp->bmiHeader.biYPelsPerMeter = 0;
bmp->bmiHeader.biClrUsed = 0;
bmp->bmiHeader.biClrImportant = 0;

//建立256级灰度调色板
for(int i = 0; i < 256; i++)
{
bmp->bmiColors[i].rgbBlue = i;
bmp-> bmiColors[ i ].rgbGreen = i;
bmp-> bmiColors[ i ].rgbRed = i;
bmp-> bmiColors[ i ].rgbReserved = 0;
}

void* img_ptr = 0;
//用RGB色与自定义调色板配对
HBITMAP h_bitmap = ::CreateDIBSection(pdc->m_hDC, bmp, DIB_RGB_COLORS, &img_ptr, NULL, 0);

你把这个位图选入你的后台缓冲DC,然后用Bitblt写入前台DC就可以了。注意最后要释放掉资源,*bmp之类的delete了,选入后台DC的位图和后台DC自身也要DeleteObject()。
Perfy_Yang 2010-03-31
  • 打赏
  • 举报
回复
每次鼠标移动,更新这800*600的数据,然后显示更新的数据。
bobob 2010-03-31
  • 打赏
  • 举报
回复
SetPixel()不慢才怪,为什么非要用它?
计算需要更新的部分,每次只画这一块,再配合一定的预测缓冲,效果应该会好很多


Perfy_Yang 2010-03-31
  • 打赏
  • 举报
回复
整个图像在文件中存储的形式是5900 * 1400 个浮点数。
我现在是从其中读出800 * 600显示。
Perfy_Yang 2010-03-31
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 fandh 的回复:]

图片移动,如果图片太大,即使是双缓冲,也会不流畅的!一般建议这样,你在移动过程,以一个虚影代替图片贴图!
当然,双缓冲是必须的!一次画好,一直受益!
[/Quote]

我用了双缓冲,在鼠标移动的过程中就更新图像。效果还是不够好,一钝一钝的,我希望图像能够完全跟随鼠标。
“移动过程,以一个虚影代替图片”是什么意思?

还有,我用双缓冲的时候,用了SetPixel(),逐个像素点的,画到内存中,然后BitBlt。有什么方法可以不用SetPixel么?直接把一个数据集画到内存。
我是苦力 2010-03-31
  • 打赏
  • 举报
回复
如果不是很大,先把图片load到内存,每次拖拉就显示图片的部分。
如果实在很大,那就构建个你的客户区大小的bmp,然后不断的更换这个bmp的buffer data,然后绘制。
sciencstf 2010-03-31
  • 打赏
  • 举报
回复
同上,如果你是按照鼠标的坐标改变就绘制,这个频率是太快。这个问题很不好解决
我是苦力 2010-03-31
  • 打赏
  • 举报
回复
你的图片究竟有多少M?有100M吗? 会不会把简单的问题做复杂了。
fandh 2010-03-31
  • 打赏
  • 举报
回复
图片移动,如果图片太大,即使是双缓冲,也会不流畅的!一般建议这样,你在移动过程,以一个虚影代替图片贴图!
当然,双缓冲是必须的!一次画好,一直受益!
rambo_ghaip 2010-03-30
  • 打赏
  • 举报
回复
先建一个内存DC,把大位图选入。
这样就可以仅通过bitblt来实现图像移动。

当然,这只是猜测,你试一下,看行不。
yschenwei 2010-03-30
  • 打赏
  • 举报
回复
网上关于图片放大,缩小,平移的例子很多。LZ下个下来看看就知道了。
Eleven 2010-03-30
  • 打赏
  • 举报
回复
用双缓冲贴图。。。

19,468

社区成员

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

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