MFC之使用数组读入并显示位图

1.笔记

1.1使用动态一维数组存储位图数据。

2.使用练习

2.1将一张位图的数据存储于一维数组中,读取一维数组数据,使用SetPixelV函数将图像绘制到客户区。

既然是逐个像素点绘制,那必然是按照原样绘制,没有拉伸效果。

void CExample1View::OnDraw(CDC* pDC)
{
	CExample1Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: 在此处为本机数据添加绘制代码
	CBitmap newBitmap;
	newBitmap.LoadBitmapW(IDB_BITMAP1);//加载位图
	BITMAP bmp;
	newBitmap.GetBitmap(&bmp);//获得位图信息
	int nBiteSize = bmp.bmWidthBytes * bmp.bmHeight;//每条扫描线所占字节数乘以高度
	BYTE* im = new BYTE[nBiteSize];
	newBitmap.GetBitmapBits(nBiteSize, (LPVOID)im);//将位图数据拷贝到数组中

	for(int i=0;i<bmp.bmHeight;++i)//逐行绘制,上往下,从高度-1到0为下往上
		for (int j = 0; j < bmp.bmWidth; ++j) {//左往右,从宽度-1到0为右往左
			int pos = i * bmp.bmWidthBytes + 4 * j;//一个RGB占4个字节
                        //行号和列号刚好是像素点相对于位图的坐标,可以用来做绘制设备坐标
                        //red分量存在最低8位,可以看出数组从高位字节开始存储
			pDC->SetPixelV(j, i, RGB(im[pos + 2], im[pos + 1], im[pos]));
		}
	delete[] im;
	im = NULL;
}

实现效果为位图从上往下、从左往右被绘制出来,以肉眼可见的速度,是动态的效果。想要不同的动态绘制效果,可以改变双层循环的循环变量的初值和循环条件。

2.2在自定义坐标系中居中显示一张位图,要求先显示偶数行,再显示奇数行。

void CExample1View::OnDraw(CDC* pDC)
{
	CExample1Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: 在此处为本机数据添加绘制代码
	CRect rect;
	GetClientRect(rect);
	pDC->SetMapMode(MM_ANISOTROPIC);
	pDC->SetWindowExt(rect.Width(), rect.Height());
	pDC->SetViewportExt(rect.Width(), -rect.Height());
	pDC->SetViewportOrg(rect.Width() / 2, rect.Height() / 2);
	rect.OffsetRect(-rect.Width() / 2, -rect.Height() / 2);

	CBitmap newBitmap;
	newBitmap.LoadBitmapW(IDB_BITMAP1);//加载位图
	BITMAP bmp;
	newBitmap.GetBitmap(&bmp);//获得位图信息
	int nBiteSize = bmp.bmWidthBytes * bmp.bmHeight;//每条扫描线所占字节数乘以高度
	BYTE* im = new BYTE[nBiteSize];
	newBitmap.GetBitmapBits(nBiteSize, (LPVOID)im);//将位图数据拷贝到数组中

	for(int i=0;i<bmp.bmHeight;i+=2)//绘制偶数行
		for (int j = 0; j < bmp.bmWidth; ++j) {
			//因为坐标系y轴方向改变,如果通过i和j为像素点坐标平移绘制图像
			//按照原先的行访问顺序,将会把图像画颠倒
			int k = bmp.bmHeight - 1 - i;//所以要改变行访问顺序
			int pos = k * bmp.bmWidthBytes + 4 * j;//一个RGB占4个字节
			int nx = bmp.bmWidth / 2;
			int ny = bmp.bmHeight / 2;
			pDC->SetPixelV(j - nx, i - ny, //图像数据的行号列号对应坐标系右上角
				RGB(im[pos + 2], im[pos + 1], im[pos]));//移到中心需要下移左移
		}

	Sleep(1000);//暂停一秒,增强效果

	for (int i = 1; i < bmp.bmHeight; i += 2)//绘制奇数行
		for (int j = 0; j < bmp.bmWidth; ++j) {
			//因为坐标系y轴方向改变,如果通过i和j为像素点坐标平移绘制图像
			//按照原先的行访问顺序,将会把图像画颠倒
			int k = bmp.bmHeight - 1 - i;//所以要改变行访问顺序
			int pos = k * bmp.bmWidthBytes + 4 * j;//一个RGB占4个字节
			int nx = bmp.bmWidth / 2;
			int ny = bmp.bmHeight / 2;
			pDC->SetPixelV(j - nx, i - ny, //图像数据的行号列号对应坐标系右上角
				RGB(im[pos + 2], im[pos + 1], im[pos]));//移到中心需要下移左移
		}

	delete[] im;
	im = NULL;
}

实现效果是一个还不错的动效,奇数行和偶数行均从下往上绘制,偶数行绘制得到的图像不太清晰,奇数行绘制完图像清晰展示。

此例中的坐标关系(为了清晰显示,没有将图像的0行与0列的位置对齐到坐标系的正半轴上,实际是对齐在正半轴上的):

 显然将图像沿x轴向下翻转即可获得正确图像,即读取行顺序变为倒序即可将图像方向恢复正常。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赴星辰大海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值