提高setpixel()效率,即颜色值直接赋给位图显示的问题解决

原创 2014年04月24日 07:52:26

最近在做的项目是在MFC的框架下的,我主要负责图像的绘制显示部分。是在对方框架下做插件功能,对方给出的绘图DEMO是用fillsolidrect()与SetPixel(),显示效率很低。项目的主要内容是把大量数据通过计算转换,然后赋予颜色值,通过图像来表现巨幅的井文件。呃,闲话不多说了~~~~~~~

我只说绘制部分,当然也是分块显示,即只绘当前屏幕内容,通过双缓冲实现,先绘制到内存DC,然后再贴到屏幕上。

我这两天做的修改是把效率极低的setpixel()用直接给点赋值的方法代替。就是相当于把表示颜色值BYTE的数组直接赋值给位图显示,而不是再经过先绘制到位图再显示。

考虑到效率,直接调用了API函数。经过查询有两个函数可以实现的比较好,这两个函数都能将位图数据填到位图中去,SetDIBits和SetBitmapBits,前者是对于设备无关位图的,后者是对相关位图的。

int SetDIBits(HDC hdc, HBITMAP hbmp, UINT uStartScan, UINT cScanLines, CONST VOID *lpvBits,CONST BITMAPINFO *lpbmi, UINT fuColorUse);
参数:
hdc:指向设备环境中的句柄。
hbmp:指向位图的句柄。函数要使用指定DIB中的颜色数据对该位图进行更改。
uStartScan:为参数lpvBits指向的数组中的、与设备无关的颜色数据指定起始扫描线。
cScanLines:为包含与设备无关的颜色数据的数组指定扫描线数目。
lpvBits:指向DIB颜色数据的指针,这些数据存储在字节类型的数组中,位图值的格式取决于参数lpbmi指向的BITMAPINFO结构中的成员biBitCount。
lpbmi:指向BITMAPINFO数据结构的指针,该结构包含有关DIB的信息。

fuColorUse:指定是否提供了BITMAPINFO结构中的bmiColors成员,如果提供了,那么bmiColors是否包含了明确的RGB值或调色板索引。参数fuColorUse必须取下列值。

DIB_PAL_COLORS:颜色表由16bit的索引值数组组成。这些值可以对由hdc参数标识的设备环境中的逻辑调色板进行索引。
DIB_RGB_COLORS:提供了颜色表,并且表中包含了原义的RGB值。
返回值:
如果函数成功,那么返回值就是复制的扫描线数;如果函数失败,那么返回值是0。


LONG SetBitmapBits(HBITMAP hmbp, DWORDcBytes, CONST VOID (lpBits));

参数:

hbmp:指向要设置的位图的句柄。

cBytes:指定参数lpBits指向的数组的字节数。

lpBits:指向字节类型数组的指针。该数组中包含了指定位图的颜色数据。

返回值:

如果函数成功,则返回值就是在设置位图位时使用的字节数;如果失败,则返回值为0。


上面是两个函数的百度定义。下面贴我参考过的两段程序,也许以后还有一定的用处~~~

CX, CY;// 这个值你必须知道,事先给定int sz= CX* CY;
BYTE*pData=new BYTE[sz*4];// show in 32 bits
for(int i=0; i< sz; i++)
    {
        pData[i*4+0]=*ColorB++ ;
        pData[i*4+1]=*ColorG++;
        pData[i*4+2]=*ColorR++;
        pData[i*4+3]=0;
    }
    
    CDC*pdc= GetDC(); 
    CDC memdc; 
    CBitmap bmp;
    CRect rt;
    
    memdc.CreateCompatibleDC(pdc);
    bmp.CreateBitmap(CX, CY ,1,32,pData);
    CBitmap* pOldBitmap= memdc.SelectObject(&bmp); 
    
    pdc->BitBlt(0,0, CX, CY,&memdc,0,0, SRCCOPY); 
    
    memdc.SelectObject(pOldBitmap);
    memdc.DeleteDC();
ReleaseDC(pdc);

上面的是设备相关的,我这貌似显示出来是黑白的,所以不建议使用,因为兼容性问题,显示不一定正确。

void CTest:OnDraw(CDC* pDC) 
{
// TODO: Add extra validation here

CDC memDC;
memDC.CreateCompatibleDC(pDC);

CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC,500,500);
memDC.SelectObject(&bmp);

BITMAPINFO bmpInfo;
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = 487;
bmpInfo.bmiHeader.biHeight = -500;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 24;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biSizeImage = 0;
bmpInfo.bmiHeader.biXPelsPerMeter = 3000;
bmpInfo.bmiHeader.biYPelsPerMeter = 3000;
bmpInfo.bmiHeader.biClrUsed = 0;
bmpInfo.bmiHeader.biClrImportant = 0;

//每行字节数,4字节对齐
long nLnBytes = (487*3+3)/4*4;

BYTE *pData = new BYTE[nLnBytes*500];
memset(pData,0,nLnBytes*500);
for(int i=10; i<90; i++)
{
pData[50*nLnBytes+i*3]=255;
pData[i*nLnBytes+50*3+2]=255;
}

SetDIBits(pDC->m_hDC,bmp,0,500,pData,&bmpInfo,DIB_RGB_COLORS);
delete []pData;
pDC ->BitBlt(0,0,500,500,&memDC,0,0,SRCCOPY);
}

最后我是使用上面这段,修改过后解决了问题。

        当然也有好多其他方法,如先定义BITMAPINFO变量,然后对这个变量进行初始化,定义好图片的文件头,接着使用CreateDIBSection,根据BITMAPINFO创建一个空的位图,然后用memcpy把BYTE中的像素数据拷贝到这个空位图中,最后用CBitmap::FromHandle把得到的HBITMAP类型变量转换为CBitmap类型。

        提高绘制的效率,也有很多人提到了OPENGL与DIRECRX。当然这些都是用来绘制很复杂的场景使用的,如游戏场景。还有大幅图像也可以考虑多线程建立后台临时文件,滚动显示的时候可以直接调用,不需要再计算绘制或赋值的过程了~~~~~~




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

解决 C# GetPixel 和 SetPixel 效率问题

在对Bitmap图片操作的时候,有时需要用到获取或设置像素颜色方法:GetPixel 和 SetPixel, 如果直接对这两个方法进行操作的话速度很慢,这里我们可以通过把数据提取出来操作,然后操...

用画点的函数SetPixel实现画线的功能

void CDlgMain::UpdateDraw(CDC* pDC, CRect rect) { //如果位图不够大,则重新申请 if( m_bitmap.m_hObject ) { BI...

将rgb图像数据保存为BMP格式图片的方法

extern "C" { #include #include #include } typedef long LONG; typedef unsigned long D...
  • chyxwzn
  • chyxwzn
  • 2012年12月27日 15:38
  • 14200

读取BMP图像每一像素点RGB数据

对于24位bmp图片,每一个像素点存放着此点的RGB值。首先定义一个结构体,包含红(red)、绿(green)、蓝(blue)这三个字段,如下: //像素颜色值 typedef struct t...

灰度图像用SetPixel可以正常显示,StretchDIBits画出的图像倾斜

目前已经正确获得指向所要绘制的指针 m_lpBits,(存有相应的像素值),此灰度图像用SetPixel可以正常显示,StretchDIBits画出的图像倾斜????详细情况如下: 当用Se...

mpChart如何根据y值的范围赋给bar需要的颜色值

这篇转载自http://stackoverflow.com/questions/29791086/how-to-set-colors-in-mpandroidchart我们需要继承BarDataSet...

63.windbg-r?(使得伪寄存器获得任意类型信息)

r?命令可以让伪寄存器自动获取所赋参数的类型 (仅在指派伪寄存器时) 使得伪寄存器获得类型信息。可以使用任何类型 如,我们知道@$peb的类型是_PEB: 0:000> dt ntdll!*PE...
  • hgy413
  • hgy413
  • 2013年10月21日 13:10
  • 1019

62.windbg-p、t、pa、ta(单步步过、单步步入)

p|t =startAddr count 可以让目标程序从指定的startAddr开始指行,注意,如果指定地址跳过了调整栈的代码,栈就会失去平衡 count指定要单步执行的次数,如t 2就是两次运...
  • hgy413
  • hgy413
  • 2013年10月10日 14:47
  • 2328
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:提高setpixel()效率,即颜色值直接赋给位图显示的问题解决
举报原因:
原因补充:

(最多只允许输入30个字)