VSC++学习3BMP图像文件的特效显示.docx
《VSC++学习3BMP图像文件的特效显示.docx》由会员分享,可在线阅读,更多相关《VSC++学习3BMP图像文件的特效显示.docx(12页珍藏版)》请在冰点文库上搜索。
VSC++学习3BMP图像文件的特效显示
VS2010C++学习(3):
BMP图像文件的特效显示
学习VC++编制的BMP图像文件的特效显示程序.。
一、主要内容:
1.面向对象的DIB的读写及访问,ImgCenterDib类;
2.特效显示类,SpecialEffectShow类;
3.图像的扫描显示;
4.图像的滑动显示;
5.图像的渐进显示;
6.图像的马赛克显示;
7.垂直对接;VerticalButt
8.压缩反转;CompressInvert
9.中心闭幕;CenterFallCurtain
10.中心放大;CenterEnlarge
11.交叉竖条;CrossBars
12.水平拉幕;PullCurtain
13.随机拉丝;RandomDraw
14.对角闭幕;DiagonalClose
15.垂直百叶;VerticalBlinds
16.水平拉入;PullScroll
二、设计实现:
1.面向对象的DIB的读写及访问,ImgCenterDib类;
面向对象的方式实现图像的可视化编程,声明的类叫ImgCenterDib;里面封装了DIB位图处理所需要的基本的成员变量和成员函数。
1).ImgCenterDib类的定义
ImgCenterDib类的定义在头文件“ImageCenterDib.h”中。
classImgCenterDib
{
public:
//图像数据指针
unsignedchar*m_pImgData
//图像颜色表指针
LPRGBQUADm_lpColorTable;
//每像素占的位数
intm_nBitCount;
private:
//指向DIB的指针(包含BITMAPFILEHEADER、BITMAPINFOHEADER和颜色表)
LPBYTEm_lpDib;
//图像信息头指针
LPBITMAPINFOHEADERm_lpBmpInfoHead;
//调色板句柄
HPALETTEm_hPalette;
//颜色表长度
intm_nColorTableLength;
public:
//不带参数的构造函数
ImgCenterDib();
//带参数的构造函数
ImgCenterDib(CSizesize,intnBitCount,LPRGBQUADlpColorTable,
unsignedchar*pImgData);
//析构函数
~ImgCenterDib();
//DIB读函数
BOOLRead(LPCTSTRlpszPathName);
//DIB写函数
BOOLWrite(LPCTSTRlpszPathName);
//DIB显示函数
BOOLDraw(CDC*pDC,CPointorigin,CSizesize);
//逻辑调色板生成函数
voidMakePalette();
//获取DIB的尺寸(宽、高)
CSizeGetDimensions();
//清理空间
voidEmpty();
//用新的数据替换当前DIB
voidReplaceDib(CSizesize,intnBitCount,LPRGBQUADlpColorTable,unsignedchar*pImgData);
//计算颜色表的长度
intComputeColorTabalLength(intnBitCount);
protected:
//图像的宽,像素为单位
intm_imgWidth;
//图像的高,像素为单位
intm_imgHeight;
};
2.特效显示类,SpecialEffectShow类;
图像的特效显示就是利用人眼的视觉特性,通过先对图像分块,然后以不同的次序显示出来。
其中的要点是:
如何划分图像块;确定图像块的操作次序,以及两个图像块的操作之间的延时。
SpecialEffectShow类继承了ImgCenterDib类。
3.图像的扫描显示;
扫描是最基本的特效显示方式,它没有划分图像块,只是顺序地一行一行或一列一列地显示图像。
单重循环,最基本的。
4.图像的滑动显示;
滑动是将图像看做一个整体,显示时不能像扫描那样,扫描方式有些像打开一幅画,例如显示上部分的时候,下部分可以不显示。
而移动则可以看成一块木板画,显示时候必须按照物理顺序进行,例如从上向下平移时,必须先显示下面的图像,后显示上面的图像。
因此平移的算法比扫描要难一些,平移是以复制的方法显示图像的,每次显示一次,复制的行数就增加一行,直至显示完成。
双重循环,最基本的。
5.图像的渐进显示;
图像渐进显示的思路是先记录下图像的每个像素点的灰度值,显示的时候先将屏幕置黑,将循环显示图像n次,这里设n为0,1,2,…,256。
每一次显示像素灰度值的n/256倍,图像的像素点计算一遍后,显示一次,重复执行上述过程,直至每一个屏幕上的像素点的灰度值恢复到原始图像灰度值的水平。
渐进显示特效虽然不需要对图像进行分块,但是需要开辟两块内存空间,一块用来存储图像的原始灰度值,另一块用来存储每次计算后的像素灰度值。
逐渐增强亮度,从0到256。
6.图像的马赛克显示;
马赛克显示是图像被分成许多小区域,显示时候小区域以杂乱无章的顺序显示在屏幕上。
马赛克显示是比较难的特效,它的图像分块和显示都比较复杂。
其编程思想是:
先将图像分成大小相同的小区域,计算出每一块区域的首地址,并记录下来。
设置一个随机数,用来产生随机显示区域的次序,每获得一个随机区域,就根据首地址显示这块区域的图像,直至所有的区域都至少显示一次。
把每个小方块都显示出来,即使每个小方块的标记都为真。
7.图像的垂直对接显示;VerticalButt
垂直对接显示是将图像分为上下部分,然后同时向中心移动;
需要注意的是,BMP文件是倒着存放的,即屏幕显示位置(0,j)对应数据块的(0,bitmapHeight–j);屏幕显示位置(0,bitmapHeight–j)对应数据块的(0,j)。
8.图像的压缩反转显示;CompressInvert
计算图像位置和高度,以高度的一半为轴进行对换上下半边的图像。
目标矩形区域在循环的前半段为垂直反向。
//压缩反转特效显示的具体算法
intblockSize=4;//每次显示的高度增量,应能被高度整除
for(intj=-bitmapHeight/blockSize;j<=bitmapHeight/blockSize;j++)
{
//目标矩形区域在循环的前半段为垂直反向
:
:
StretchDIBits(pDC->GetSafeHdc(),
0,bitmapHeight/2-j*blockSize/2,bitmapWidth,j*blockSize,
0,0,bitmapWidth,bitmapHeight,
m_pImgData,pBitmapInfo,
DIB_RGB_COLORS,SRCCOPY);
Sleep(3);//设置延时时间
}
9.中心闭幕;CenterFallCurtain
由大到小生成图像中心区域,然后用总区域减去该中心区域,并用材质画刷填充。
//中心闭幕特效显示的具体算法
for(intj=0;j<=bitmapWidth/2;j+=stepCount)
{
CRgnrgn1,rgn2;
rgn1.CreateRectRgn(0,0,bitmapWidth,bitmapHeight);
//以源图象的尺寸创建一个矩形
rgn2.CreateRectRgn(j,j*bitmapHeight/bitmapWidth,bitmapWidth-2*j,bitmapHeight-j*2*bitmapHeight/bitmapWidth);
//不在rgn1中的部分
rgn1.CombineRgn(&rgn1,&rgn2,RGN_DIFF);
:
:
StretchDIBits(pDC->GetSafeHdc(),j,j*bitmapHeight/bitmapWidth,
bitmapWidth-2*j,bitmapHeight-j*2*bitmapHeight/bitmapWidth,
0,0,bitmapWidth,bitmapHeight,
m_pImgData,pBitmapInfo,
DIB_RGB_COLORS,SRCCOPY);
pDC->FillRgn(&rgn1,&brush1);
rgn1.DeleteObject();
rgn2.DeleteObject();
Sleep(3);//设置延时时间
}
10.中心放大;CenterEnlarge
由中心向边缘按高度和宽度的比例循环输出所有像素,直到高度和宽度为原始大小。
//中心放大特效显示的具体算法
intstepCount=2;//每次收缩的步长像素
for(intj=0;j<=bitmapWidth/2;j+=stepCount)
{
:
:
StretchDIBits(pDC->GetSafeHdc(),bitmapWidth/2-j,
bitmapHeight/2-j*bitmapHeight/bitmapWidth,2*j,2*j*bitmapHeight/bitmapWidth,
0,0,bitmapWidth,bitmapHeight,
m_pImgData,pBitmapInfo,
DIB_RGB_COLORS,SRCCOPY);
Sleep(30);//设置延时时间
}
11.交叉竖条;CrossBars
将图像分成宽度相等的列,然后计算从上下两个方向交叉前进的区域,并使用材质画刷填充。
//交叉竖条特效显示的具体算法
intlineWidth=8;//竖条宽度
intlineStep=6;//竖条每次前进的步长
for(intj=0;j<=bitmapHeight/lineStep;j++){
for(inti=0;i<=bitmapWidth/lineWidth;i++)
{if(i%2==0)//从上到下
{
:
:
StretchDIBits(pDC->GetSafeHdc(),
i*lineWidth,j*lineStep,lineWidth,lineStep,
i*lineWidth,bitmapHeight-(j+1)*lineStep,lineWidth,lineStep,
m_pImgData,pBitmapInfo,
DIB_RGB_COLORS,SRCCOPY);
}
else//从下到上
{
:
:
StretchDIBits(pDC->GetSafeHdc(),
bitmapWidth-(i+0)*lineWidth,bitmapHeight-(j+1)*lineStep,
lineWidth,lineStep,
bitmapWidth-(i+0)*lineWidth,j*lineStep,lineWidth,lineStep,
m_pImgData,pBitmapInfo,
DIB_RGB_COLORS,SRCCOPY);
}
}
Sleep(30);//设置延时时间
}
12.水平拉幕;PullCurtain
由中心向开始逐渐输出中心两侧的像素,直到宽度为原始大小。
//水平拉幕特效显示的具体算法
for(inti=0;i<=bitmapWidth/2;i+=lineStep)
{
:
:
StretchDIBits(pDC->GetSafeHdc(),
bitmapWidth/2-i,0,2*i,bitmapHeight,
bitmapWidth/2-i,0,2*i,bitmapHeight,
m_pImgData,pBitmapInfo,
DIB_RGB_COLORS,SRCCOPY);
Sleep(30);//设置延时时间
}
13.随机拉丝;RandomDraw
每次随机显示图像的一个像素行。
//13.随机拉丝特效显示的具体算法
int*rowIndex=newint[bitmapHeight];
for(inti=0;irowIndex[i]=0;
intindex=1;//数组索引
longRandNum;//随机变量
srand((unsigned)time(NULL));//生成随机种子
do
{
RandNum=(long)(((double)bitmapHeight)*rand()/RAND_MAX);
//随机变量在0到bitmapHeight-1之间取值
if(rowIndex[RandNum]==0)
{
rowIndex[RandNum]=index++;
}
}while(index//按照上面随机生成的次序逐一显示每个像素行
for(inti=0;i{
:
:
StretchDIBits(pDC->GetSafeHdc(),
0,rowIndex[i]-1,bitmapWidth,1,
0,bitmapHeight-rowIndex[i],bitmapWidth,1,
m_pImgData,pBitmapInfo,
DIB_RGB_COLORS,SRCCOPY);
Sleep(3);//设置延时时间
}
14.对角闭幕;DiagonalClose
用背景色填充左上、右下角。
//对角闭幕特效显示的具体算法
intstepCount=4;//每次收缩的步长像素
CBrushbrush1(RGB(0,128,128));//设置画刷为lan色
CPointptVertex[3];
for(intj=0;j<=bitmapHeight;j+=stepCount)
{
CRgnrgn1,rgn2;
//左上角区域
ptVertex[0].x=0;
ptVertex[0].y=0;
ptVertex[1].x=0;
ptVertex[1].y=j;
ptVertex[2].x=j*bitmapWidth/bitmapHeight;
ptVertex[2].y=0;
rgn1.CreatePolygonRgn(ptVertex,3,ALTERNATE);
//右下角区域
ptVertex[0].x=bitmapWidth;
ptVertex[0].y=bitmapHeight;
ptVertex[1].x=bitmapWidth;
ptVertex[1].y=bitmapHeight-j;
ptVertex[2].x=bitmapWidth-j*bitmapWidth/bitmapHeight;
ptVertex[2].y=bitmapHeight;
rgn2.CreatePolygonRgn(ptVertex,3,ALTERNATE);
pDC->FillRgn(&rgn1,&brush1);
pDC->FillRgn(&rgn2,&brush1);
rgn1.DeleteObject();
rgn2.DeleteObject();
Sleep(30);//设置延时时间
}
15.垂直百叶;VerticalBlinds
//百叶特效显示的具体算法
for(inti=0;i{
for(intj=0;j<=bitmapHeight/lineHeight;j++)
{
CRgnrgn1;
inty=lineHeight*j+i;
if(y>=(bitmapHeight-1))y=bitmapHeight-1;
rgn1.CreateRectRgn(0,y,bitmapWidth,y+1);
pDC->FillRgn(&rgn1,&brush1);
rgn1.DeleteObject();
Sleep(10);//设置延时时间
}
}
16.水平拉入;PullScroll
由于内存位图与设备无关,故不能使用在水平方向逐渐改变图像分辨率(每英寸点数)的办法而改为使用在水平方向拉伸显示,并逐步缩小。
CBrushbrush1(RGB(255,255,255));//设置画刷为白色
for(inti=1;i<=96;i++)
{
CRgnrgn1;
rgn1.CreateRectRgn(bitmapWidth,0,bitmapWidth*96/i,bitmapHeight);
:
:
StretchDIBits(pDC->GetSafeHdc(),
0,0,bitmapWidth*96/i,bitmapHeight,
0,0,bitmapWidth,bitmapHeight,
m_pImgData,pBitmapInfo,
DIB_RGB_COLORS,SRCCOPY);
pDC->FillRgn(&rgn1,&brush1);
rgn1.DeleteObject();
Sleep(30);//设置延时时间
}
三、源码下载