如何用软件切分一幅位图?

cameo888 2003-10-16 09:37:05
如果要将一幅位图从上到下平均切分成3张位图,切分以后最好能将原图删除掉
如何实现?谁有相关代码?
...全文
33 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
w5meng 2003-10-17
  • 打赏
  • 举报
回复
以下是一个位图缩放的程序,在DIB方式下操作的。
原理差不多,你改一下就可以啦。


/*************************************************************************
*
* 函数名称:
* ZoomDIB()
*
* 参数:
* HDIB hDIB - 待处理的DIB
* float fZoomRatioW - 宽缩放比率
* float fZoomRatioH - 高缩放比率
*
* 返回值:
* HDIB - 缩放后的DIB
*
* 说明:
* 该函数用来缩放DIB图像,返回处理后的DIB
*
************************************************************************/

HDIB CGeoTrans::ZoomDIB(HDIB hDIB,float fZoomRatioW,float fZoomRatioH)
{
// 源图像的宽度和高度
LONG lWidth;
LONG lHeight;

// 缩放后图像的宽度和高度
LONG lNewWidth;
LONG lNewHeight;

// 指向源图像的指针
LPBYTE lpDIBBits;

// 指向DIB的指针
LPBYTE lpDIB;

// 缩放后新DIB句柄
HDIB hNewDIB;

// 指向缩放图像对应象素的指针
LPBYTE lpDst = NULL;

// 指向缩放图像的指针
LPBYTE lpNewDIB;
LPBYTE lpNewDIBBits;

// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFOHEADER lpbmi;

// 指向BITMAPCOREINFO结构的指针
LPBITMAPCOREHEADER lpbmc;

// 循环变量(象素在新DIB中的坐标)
LONG i;
LONG j;

// 象素在源DIB中的坐标
LONG i0;
LONG j0;

// 锁定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);

// 找到源DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);

// 判断是否是24-bpp位图
if (m_clsDIB.DIBBitCount(lpDIB) != 24)
{
// 提示用户
//MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);

// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);

// 返回
return NULL;
}

// 更改光标形状
//BeginWaitCursor();

// 获取图像的宽度
lWidth = m_clsDIB.DIBWidth(lpDIB);

// 获取图像的高度
lHeight = m_clsDIB.DIBHeight(lpDIB);

// 计算图像每行的字节数
LONG lLineBytes = WIDTHBYTES(lWidth * 24);

// 计算缩放后的图像实际宽度
// 此处直接加0.5是由于强制类型转换时不四舍五入,而是直接截去小数部分
lNewWidth = (LONG) (lWidth * fZoomRatioW + 0.5);

// 计算缩放后的图像高度
lNewHeight = (LONG) (lHeight * fZoomRatioH + 0.5);

// 计算图像每行的字节数
LONG lNewLineBytes = WIDTHBYTES(lNewWidth * 24);

// 分配内存,以保存新DIB
hNewDIB = (HDIB) ::GlobalAlloc(GHND, lNewHeight * lNewLineBytes
+ *(LPDWORD)lpDIB + m_clsDIB.PaletteSize(lpDIB));

// 判断是否内存分配失败
if (hNewDIB == NULL)
{
// 分配内存失败
return NULL;
}

// 锁定内存
lpNewDIB = (LPBYTE)::GlobalLock((HGLOBAL) hNewDIB);

// 复制DIB信息头和调色板
memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + m_clsDIB.PaletteSize(lpDIB));

// 找到新DIB象素起始位置
lpNewDIBBits = m_clsDIB.FindDIBBits(lpNewDIB);

// 获取指针
lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;
lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;

// 更新DIB中图像的高度和宽度
if (IS_WIN30_DIB(lpNewDIB))
{
// 对于Windows 3.0 DIB
lpbmi->biWidth = lNewWidth;
lpbmi->biHeight = lNewHeight;
}
else
{
// 对于其它格式的DIB
lpbmc->bcWidth = (unsigned short) lNewWidth;
lpbmc->bcHeight = (unsigned short) lNewHeight;
}

// 针对图像每行进行操作
for(i = 0; i < lNewHeight; i++)
{
// 针对图像每列进行操作
for(j = 0; j < lNewLineBytes; j++)
{
// 计算该象素在源DIB中的坐标
i0 = (LONG) (i / fZoomRatioH);
j0 = (LONG) (j / (fZoomRatioW * 3));

// 对应缩放前象素的红色分量
unsigned char R = *((unsigned char *)lpDIBBits + lLineBytes * i0 + 3 * j0);
// 复制象素
*((unsigned char *)lpNewDIBBits + lNewLineBytes * i + j) = R;

// 源、目的图像移到G分量
lpDst++; j++;

// 对应缩放前象素的绿色分量
unsigned char G = *((unsigned char *)lpDIBBits + lLineBytes * i0 + 3 * j0 +1);
// 复制象素
*((unsigned char *)lpNewDIBBits + lNewLineBytes * i + j) = G;

// 源、目的图像移到B分量
lpDst++; j++;

// 对应缩放前象素的蓝色分量
unsigned char B = *((unsigned char *)lpDIBBits + lLineBytes * i0 + 3 * j0 +2);
// 复制象素
*((unsigned char *)lpNewDIBBits + lNewLineBytes * i + j) = B;
}
}

// 解除锁定
::GlobalUnlock((HGLOBAL) hDIB);

// 恢复光标
//EndWaitCursor();

// 返回
return hNewDIB;
}

w5meng 2003-10-17
  • 打赏
  • 举报
回复
这个应该不难,你应该先了解一下位图结构。
只需要先获得位图象素行数,除3。
然后一行行读取原位图并存储到新的位图中即可。
cameo888 2003-10-17
  • 打赏
  • 举报
回复
没人回帖?

19,468

社区成员

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

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