VC++编程:调整位图尺寸技术实现
"这篇文章主要介绍了如何在VC++环境中改变位图的尺寸,以适应窗口大小。通过提供的函数和代码示例,我们可以理解调整位图大小的关键步骤,包括获取位图信息、计算新尺寸下的字节数、分配内存以及进行位图数据的重排。" 在VC++中,改变位图尺寸通常涉及到对位图信息块(BITMAPINFOHEADER)的修改以及重新排列位图数据。以下是一些关键知识点: 1. **位图信息块(BITMAPINFOHEADER)**: BITMAPINFOHEADER结构体包含了位图的一些基本信息,如宽度、高度、颜色位深度等。在调整位图尺寸时,我们需要修改这个结构体中的`biWidth`和`biHeight`字段以反映新的尺寸。 2. **位图数据的指针处理**: 函数`LPBYTE FindDIBBits(LPBYTE lpDIB)`用于找到位图的实际像素数据,它返回一个指向BITMAPINFOHEADER后的指针,这是位图的RGB像素数组开始的地方。 3. **行字节数计算**: 函数`DWORD BytesPerLine(LPBYTE lpDIB)`用于计算位图每行的字节数。它基于BITMAPINFOHEADER中的`biWidth`、`biPlanes`和`biBitCount`字段来计算。`WIDTHBYTES`宏用于确保结果是4字节对齐的,这对于内存管理至关重要。 4. **位图尺寸调整**: 在`CChangeSizeDlg::ChangeDIBSize`函数中,首先获取原位图的BITMAPINFOHEADER,然后创建一个新的BITMAPINFO结构,并将原结构的内容复制到新结构中,接着修改`biWidth`和`biHeight`以设置新的尺寸。 5. **内存分配与数据复制**: 调整位图尺寸后,需要为新的位图数据分配内存。`malloc`函数用于此目的。然后,需要计算新位图的总字节数(`dwTargetBitsSize`),并进行数据的重排。这通常涉及创建两个设备上下文(DC),一个源DC和一个目标DC,以及相应的源位图和目标位图对象。 6. **位图数据的重排**: 在创建了新的位图信息和内存后,需要将原始位图的数据复制到新位置。这一步骤通常涉及到遍历源位图的每一行,并根据新的行字节数重新组织像素数据。 7. **设备上下文(Device Context, DC)**: 在Windows编程中,设备上下文是用于图形操作的对象,它包含特定设备的图形状态信息。在这里,源DC和目标DC分别用于原始位图和新尺寸的位图,它们帮助在内存和屏幕之间进行位图操作。 8. **位图句柄的管理和释放**: 完成位图尺寸调整后,别忘了释放不再需要的资源,如位图句柄、内存以及设备上下文。 总结起来,改变位图尺寸是一个涉及多个步骤的过程,包括获取和修改位图信息,计算新的字节数,分配内存,创建设备上下文,以及处理位图数据。在VC++中,这些操作需要精确的内存管理和Windows API调用来完成。
{
return (lpDIB + *(LPDWORD)lpDIB + 0);
}
DWORD BytesPerLine(LPBYTE lpDIB)
{
return WIDTHBYTES(((LPBITMAPINFOHEADER)lpDIB)->biWidth * ((LPBITMAPINFOHEADER)lpDIB)->biPlanes * ((LPBITMAPINFOHEADER)lpDIB)->biBitCount);
}
HDIB CChangeSizeDlg::ChangeDIBSize(HDIB hDIB, int nWidth, int nHeight)
{
LPBITMAPINFO lpbmi = NULL;
LPBYTE lpSourceBits, lpTargetBits, lpResult;
HDC hDC = NULL, hSourceDC, hTargetDC;
HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap;
DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize;
HDIB hNewDIB;
DWORD dwSize;
WaitCursorBegin();
// Get DIB pointer
if (! hDIB)
{
WaitCursorEnd();
return NULL;
}
LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
if (! lpSrcDIB)
{
WaitCursorEnd();
}
// Allocate and fill out a BITMAPINFO struct for the new DIB
dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) + 0;
lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize );
memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize);
lpbmi->bmiHeader.biWidth = nWidth;
lpbmi->bmiHeader.biHeight = nHeight;
// Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
hDC = ::GetDC( NULL );
hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 );
hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 );
hSourceDC = CreateCompatibleDC( hDC );
hTargetDC = CreateCompatibleDC( hDC );
// Flip the bits on the source DIBSection to match the source DIB
dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader));
dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPBYTE)&(lpbmi->bmiHeader));
memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize );
lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize;
// Select DIBSections into DCs
hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );
hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap );
// put old bitmap in new bitmap
SetStretchBltMode( hTargetDC, COLORONCOLOR );
StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY );
剩余13页未读,继续阅读
- 粉丝: 18
- 资源: 4
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- ASP.NET数据库高级操作:SQLHelper与数据源控件
- Windows98/2000驱动程序开发指南
- FreeMarker入门到精通教程
- 1800mm冷轧机板形控制性能仿真分析
- 经验模式分解:非平稳信号处理的新突破
- Spring框架3.0官方参考文档:依赖注入与核心模块解析
- 电阻器与电位器详解:类型、命名与应用
- Office技巧大揭秘:Word、Excel、PPT高效操作
- TCS3200D: 可编程色彩光频转换器解析
- 基于TCS230的精准便携式调色仪系统设计详解
- WiMAX与LTE:谁将引领移动宽带互联网?
- SAS-2.1规范草案:串行连接SCSI技术标准
- C#编程学习:手机电子书TXT版
- SQL全效操作指南:数据、控制与程序化
- 单片机复位电路设计与电源干扰处理
- CS5460A单相功率电能芯片:原理、应用与精度分析