请教CreateDIBSection怎么用? 谢谢各位了. 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 刚在原贴回复,转过来吧:一个用CreateDIBSection创建32*32的32位位图的代码段DWORD nWidth = 32;DWORD nHeight = 32;PVOIL pBits = NULL;BITMAPINFO bi;bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);bi.bmiHeader.biWidth = nWidth;bi.bmiHeader.biHeight = nHeight;bi.bmiHeader.biPlanes = 1;bi.bmiHeader.biBitCount = 32;bi.bmiHeader.biCompression = BI_RGB;bi.bmiHeader.biSizeImage = nHeight * nWidth * 4;CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &pBits, NULL, NULL);每行是4字节对齐的,32位的比较简单,对于其它色深,通用公式(设置biSizeImage):BytesPerScanLine = 4 * ((nWidth * nBitCount + 31) / 32) 呵呵,粗心了,这句PVOIL pBits = NULL;应该改成PVOID pBits = NULL; // Step 1:创建DIBSection BITMAPINFO info; memset(&info.bmiHeader, 0, sizeof(BITMAPINFOHEADER)); info.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); info.bmiHeader.biWidth = DeviceInfo.width; info.bmiHeader.biHeight = DeviceInfo.height; info.bmiHeader.biPlanes = 1; info.bmiHeader.biBitCount = 32; info.bmiHeader.biCompression = BI_RGB; DeviceInfo.hBitmap = CreateDIBSection( NULL, (BITMAPINFO*) &info, DIB_RGB_COLORS, (void**) &DeviceInfo.framebuf, 0, 0); DeviceInfo.displaybuf = (ARGB8*)malloc(DeviceInfo.width * DeviceInfo.height * sizeof(ARGB8)); // Step 2:绘制程序 // 直接在您自己的DeviceInfo.displaybuf上执行绘制 for(y = 0 ; ....) for(x= 0; ....) // Step 3:将绘制好的图形直接显示到设备上去 HDC hdc = GetDC(DeviceInfo.m_hWnd); HDC mdc = CreateCompatibleDC( hdc ); HBITMAP hbmOld = (HBITMAP)::SelectObject(mdc, DeviceInfo.hBitmap); BitBlt( hdc, 0, 0, DeviceInfo.width, DeviceInfo.height, mdc, 0, 0, SRCCOPY); ::SelectObject(mdc, hbmOld); DeleteDC(mdc); ReleaseDC(DeviceInfo.m_hWnd, hdc);说明:1)以上程序仅仅是示意程序; 2)不擅长MFC(从Windows 3.0开始编程的),所以全部程序用的是API 3)过程没有问题,我的gingkoVG的Windows版本就是这样输出的 CreateDIBSection 很好的一个函数,创建后,可以得到创建的图像在内存中的首地址,在VB中就可以利用模拟指针了,在VC中也就可以直接访问图像内存地址了。 调用完后,pBits是Windows已经分配好的像素内存块指针,直接用内存拷贝函数把已经读取好的像素阵列拷过去就行了。CreateDIBSection返回一个位图句柄,可以选入DC场景进行GDI绘图操作,像素数据做相应改变。 更正一下:1)DeviceInfo.displaybuf = (ARGB8*)malloc(DeviceInfo.width * DeviceInfo.height * sizeof(ARGB8));并不必须,因为我使用的是双Buffer2)// 直接在您自己的DeviceInfo.displaybuf上执行绘制同理:可以直接绘制在Step1建立的framebuf;更正一下,以免误导楼主 根据你的上个帖子,这样处理更简便一些:if (loadimage(_T("ClockBackchain.png"), &lpData, &nSize, &nHeight, &nWidth, &nPitch)){ BITMAPINFOHEADER bih; memset(&bih, 0, sizeof(bih)); bih.biSize = sizeof(bih); bih.biWidth = nWidth; bih.biHeight = nHeight; bih.biPlanes = 1; bih.biBitCount = 24; bih.biSizeImage = nSize; SetDIBitsToDevice(pDC->m_hDC, 0, 0, nWidth, nHeight, 0, 0, 0, nHeight, lpData, (BITMAPINFO*)&bih, DIB_RGB_COLORS); free(lpData);} 这里面有相关介绍http://www.vczx.com/article/show.php?id=218 函数功能:该函数使用DIB位图和颜色数据对与目标设备环境相关的设备上的指定矩形中的像素进行设置。对于Windows 98和Windows NT 5.0,函数SetDIBitsToDevice已经得到扩展,它允许JPEG图像作为源图像。 函数原型:int SetDIBitsToDevice(HDC hdc, int xDest, int Ydest, DWORD dwWidth, DWORD dwHeight, intXSrc, int Ysrc, UINT uStartScan, UINT cScanLines, CONST VOID *lpvBits, CONST BITMAPINFO *lpbmi, UINT fuColorUse); 参数: hdc:设备环境句柄。 XDest:指定目标矩形左上角的X轴坐标,按逻辑单位表示坐标。 YDest:指字目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。 dwWidth:指定DIB的宽度,按逻辑单位表示宽度。 dwHeight:指定DIB的高度,按逻辑单位表示高度。 XSrc:指定DIB位图左下角的X轴坐标,按逻辑单位表示坐标。 YSrc:指定DIB位图左下角的Y轴坐标,按逻辑单位表示坐标。 uScanLines:指定DIB中的起始扫描线。 cScanLInes:指定参数lpvBits指向的数组中包含的DIB扫描线数目。 lpvBits:指向存储DIB颜色数据的字节类型数组的指针。关于更多的信息,请参考下面的备注一节。 lpbmi:指向BITMAPINFO结构的指针,该结构包含有关DIB的信息。 fuColorUse:指向BITMAPINFO结构中的成员bmiColors是否包含明确的RGB值或对调色板进行索引的值。有关更多的信息,请参考下面的备注部分。 参数fuColorUse必须是下列值之一,这些值的含义如下: DIB_PAL_COLORS:表示颜色表由16位的索引值数组组成,利用这些值可对当前选中的逻辑调色板进行索引。 DIB_RGB_COLORS:表示颜色表包含原义的RGB值。 返回值:如果函数执行成功,那么返回值是设置的扫描线数目;如果函数失败,那么返回值为0。 Windows NT:若想获得更多错误信息,请调用GetLastError函数。 Windows 98、NT 5.0及以后版本:如果驱动程序不支持传给SetDIBitsToDevice函数的JPEG文件图像,那么函数将失败,并返回GDI_ERROR。 备注:当位图的位是对系统调色板进行索引时,可获得最佳的位图绘制速度。应用程序可以通过调用GetSystemPaletteEntries函数来检索系统调色板的颜色和索引值。在检索到颜色和索引值之后,应用程序可以创建DIB。有关系统调色板方面更多的信息,请参考颜色方面的内容。 自底向上的DIB位图的起始点是在该位图的左下角,而自顶向下的DIB的起始点是在左上角。 为了减少对大型DIB位图的位进行设置所需的内存量,应用程序可以通过重复调用SetDIBitsToBevice。每次将位图的不同部分放入到lpvBits数组来将输出捆绑在一起。参数uStartScan和cScanLines的值标明了lpvBits数组中包含的位图部分。在有一个全屏幕MS DOS会话在前台运行时,如果正在后台运行的一个进程调用了SetDIBitsToDevice函数,那么该函数会返回一个错误。 对于Windows 98、Windows NT 5.0及以后版本;如果BITMAPINFOHEADER中的成员biCompression为BI_JPEG,那么lpvBits指向一个包含JPEG图像的缓冲区。BITMAPINFOHEADER结构中的成员biSizeimage指定了该缓冲区的大小。参数fuColorUse必须设置为DIB_RGB_COLORS。如果BITMAPV4HEADER中的成员bV4SizeImage指定了该缓冲区的大小。参数fuColorUse必须设为DIB_RGB-COLORS。如果BITMAPV5HEADER结构中的成员bV5Compression为BI_JPEG,那么参数lpbBits指向一个包含JPEG图像的缓冲区。DITMAPV5HEADER结构中的成员bV5SizeImage指定了该缓冲区的大小,参数fuColorUse必须设为DIB_RGB_COLORS。 ICM:进行颜色管理操作。如果指定的BITMAPINFO结构不是BITMAPV4HEADER或BITMAPV5HEADER,那么当前设备环境的颜色配置(profile)就当作源颜色配置使用。如果BITMAPINFO结构不是BITMAPV4HEADER或BITMAPV5HEADER,那么使用RGB颜色。如果指定的BITMAPINFO结构为BITMAPV4HEADER或BITMAPV5HEADER,那么与该位图有关的颜色配置(profile)就用作源颜色。 主线程进行运算,子线程显示对话框负责进度的显示,这样是可以的吗? 如何弹出一个基类为CRecordView的对话框 如何实现split函数对字符串分割 如何将 HBITMAP保存成jpg类型的图片文件 如何移植对话框等资源??? 为什么总是少加一条记录 为什么用 recv() 读数据会有丢失??? 当鼠标点击一个窗口的标题栏时,产生的消息是什么呢? 三维虚拟软件vega的问题 图像抓取与识别问题 如何获取窗口内控件的句柄 基于D3D Shader的YUV视频渲染源代码
DWORD nHeight = 32;
PVOIL pBits = NULL;
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = nWidth;
bi.bmiHeader.biHeight = nHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = nHeight * nWidth * 4;
CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &pBits, NULL, NULL);
每行是4字节对齐的,32位的比较简单,对于其它色深,通用公式(设置biSizeImage):
BytesPerScanLine = 4 * ((nWidth * nBitCount + 31) / 32)
PVOIL pBits = NULL;
应该改成
PVOID pBits = NULL;
BITMAPINFO info;
memset(&info.bmiHeader, 0, sizeof(BITMAPINFOHEADER));
info.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
info.bmiHeader.biWidth = DeviceInfo.width;
info.bmiHeader.biHeight = DeviceInfo.height;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 32;
info.bmiHeader.biCompression = BI_RGB; DeviceInfo.hBitmap = CreateDIBSection( NULL, (BITMAPINFO*) &info, DIB_RGB_COLORS, (void**) &DeviceInfo.framebuf, 0, 0);
DeviceInfo.displaybuf = (ARGB8*)malloc(DeviceInfo.width * DeviceInfo.height * sizeof(ARGB8)); // Step 2:绘制程序
// 直接在您自己的DeviceInfo.displaybuf上执行绘制
for(y = 0 ; ....)
for(x= 0; ....) // Step 3:将绘制好的图形直接显示到设备上去
HDC hdc = GetDC(DeviceInfo.m_hWnd); HDC mdc = CreateCompatibleDC( hdc ); HBITMAP hbmOld = (HBITMAP)::SelectObject(mdc, DeviceInfo.hBitmap); BitBlt( hdc, 0, 0, DeviceInfo.width, DeviceInfo.height,
mdc, 0, 0, SRCCOPY); ::SelectObject(mdc, hbmOld);
DeleteDC(mdc); ReleaseDC(DeviceInfo.m_hWnd, hdc);
说明:1)以上程序仅仅是示意程序;
2)不擅长MFC(从Windows 3.0开始编程的),所以全部程序用的是API
3)过程没有问题,我的gingkoVG的Windows版本就是这样输出的
CreateDIBSection返回一个位图句柄,可以选入DC场景进行GDI绘图操作,像素数据做相应改变。
1)DeviceInfo.displaybuf = (ARGB8*)malloc(DeviceInfo.width * DeviceInfo.height * sizeof(ARGB8));
并不必须,因为我使用的是双Buffer
2)// 直接在您自己的DeviceInfo.displaybuf上执行绘制
同理:可以直接绘制在Step1建立的framebuf;更正一下,以免误导楼主
if (loadimage(_T("ClockBackchain.png"), &lpData, &nSize, &nHeight, &nWidth, &nPitch))
{
BITMAPINFOHEADER bih;
memset(&bih, 0, sizeof(bih));
bih.biSize = sizeof(bih);
bih.biWidth = nWidth;
bih.biHeight = nHeight;
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biSizeImage = nSize;
SetDIBitsToDevice(pDC->m_hDC, 0, 0, nWidth, nHeight, 0, 0, 0, nHeight, lpData, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
free(lpData);
}
http://www.vczx.com/article/show.php?id=218
函数功能:该函数使用DIB位图和颜色数据对与目标设备环境相关的设备上的指定矩形中的像素进行设置。对于Windows 98和Windows NT 5.0,函数SetDIBitsToDevice已经得到扩展,它允许JPEG图像作为源图像。
函数原型:int SetDIBitsToDevice(HDC hdc, int xDest, int Ydest, DWORD dwWidth, DWORD dwHeight, intXSrc, int Ysrc, UINT uStartScan, UINT cScanLines, CONST VOID *lpvBits, CONST BITMAPINFO *lpbmi, UINT fuColorUse);
参数:
hdc:设备环境句柄。
XDest:指定目标矩形左上角的X轴坐标,按逻辑单位表示坐标。
YDest:指字目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。
dwWidth:指定DIB的宽度,按逻辑单位表示宽度。
dwHeight:指定DIB的高度,按逻辑单位表示高度。
XSrc:指定DIB位图左下角的X轴坐标,按逻辑单位表示坐标。
YSrc:指定DIB位图左下角的Y轴坐标,按逻辑单位表示坐标。
uScanLines:指定DIB中的起始扫描线。
cScanLInes:指定参数lpvBits指向的数组中包含的DIB扫描线数目。
lpvBits:指向存储DIB颜色数据的字节类型数组的指针。关于更多的信息,请参考下面的备注一节。
lpbmi:指向BITMAPINFO结构的指针,该结构包含有关DIB的信息。
fuColorUse:指向BITMAPINFO结构中的成员bmiColors是否包含明确的RGB值或对调色板进行索引的值。有关更多的信息,请参考下面的备注部分。
参数fuColorUse必须是下列值之一,这些值的含义如下:
DIB_PAL_COLORS:表示颜色表由16位的索引值数组组成,利用这些值可对当前选中的逻辑调色板进行索引。
DIB_RGB_COLORS:表示颜色表包含原义的RGB值。
返回值:如果函数执行成功,那么返回值是设置的扫描线数目;如果函数失败,那么返回值为0。
Windows NT:若想获得更多错误信息,请调用GetLastError函数。
Windows 98、NT 5.0及以后版本:如果驱动程序不支持传给SetDIBitsToDevice函数的JPEG文件图像,那么函数将失败,并返回GDI_ERROR。
备注:当位图的位是对系统调色板进行索引时,可获得最佳的位图绘制速度。应用程序可以通过调用GetSystemPaletteEntries函数来检索系统调色板的颜色和索引值。在检索到颜色和索引值之后,应用程序可以创建DIB。有关系统调色板方面更多的信息,请参考颜色方面的内容。
自底向上的DIB位图的起始点是在该位图的左下角,而自顶向下的DIB的起始点是在左上角。
为了减少对大型DIB位图的位进行设置所需的内存量,应用程序可以通过重复调用SetDIBitsToBevice。每次将位图的不同部分放入到lpvBits数组来将输出捆绑在一起。参数uStartScan和cScanLines的值标明了lpvBits数组中包含的位图部分。在有一个全屏幕MS DOS会话在前台运行时,如果正在后台运行的一个进程调用了SetDIBitsToDevice函数,那么该函数会返回一个错误。
对于Windows 98、Windows NT 5.0及以后版本;如果BITMAPINFOHEADER中的成员biCompression为BI_JPEG,那么lpvBits指向一个包含JPEG图像的缓冲区。BITMAPINFOHEADER结构中的成员biSizeimage指定了该缓冲区的大小。参数fuColorUse必须设置为DIB_RGB_COLORS。如果BITMAPV4HEADER中的成员bV4SizeImage指定了该缓冲区的大小。参数fuColorUse必须设为DIB_RGB-COLORS。如果BITMAPV5HEADER结构中的成员bV5Compression为BI_JPEG,那么参数lpbBits指向一个包含JPEG图像的缓冲区。DITMAPV5HEADER结构中的成员bV5SizeImage指定了该缓冲区的大小,参数fuColorUse必须设为DIB_RGB_COLORS。
ICM:进行颜色管理操作。如果指定的BITMAPINFO结构不是BITMAPV4HEADER或BITMAPV5HEADER,那么当前设备环境的颜色配置(profile)就当作源颜色配置使用。如果BITMAPINFO结构不是BITMAPV4HEADER或BITMAPV5HEADER,那么使用RGB颜色。如果指定的BITMAPINFO结构为BITMAPV4HEADER或BITMAPV5HEADER,那么与该位图有关的颜色配置(profile)就用作源颜色。