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轴向下翻转即可获得正确图像,即读取行顺序变为倒序即可将图像方向恢复正常。