1. 原理
核心是将图像分成不同的块,然后以不同的顺序显示
2. 特效
要实现图片的特效,首先加载一副位图
//
//加载位图
CDC memDC;
memDC.CreateCompatibleDC(pDC); //创建兼容DC
HBITMAP hBmp; //加载位图
hBmp = (HBITMAP)LoadImageW(NULL,L"1.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
BITMAP bm; //获取位图信息
GetObject(hBmp,sizeof(bm),&bm);
SelectObject(memDC,hBmp); //位图选入内存DC
要显示特效,还需获得显示屏幕的DC
可以在MFC 单文档程序的OnDraw 中实现特效的绘制,其屏幕DC 为 pDC
2.1 逐行显示特效
方法:循环,每次显示一行
//逐行显示特效
int offset_x = 10;
int offset_y = 10;
for(int i=0;i<bm.bmHeight;++i)
{
//pDC->BitBlt(x,y,width,height,pSrcDC,xSrc,ySrc,dwRop);
//(x,y) : 屏幕左上角的坐标
//(width,height): 要绘制的宽度和高度
//pSrcDC : 源图像(的DC)
//(xSrc,ySrc) : 图像上的左上角
//dwRop : 操作方式
pDC->BitBlt(offset_x,offset_y+i,bm.bmWidth,1,&memDC,0,i,SRCCOPY);//一行一行显示
Sleep(10);
}
说明:上面程序实现了自上而下的逐行显示,自下而上、自左向右等特效实现方法类似。
2.2 向右移动进入特效
方法:从右向左显示图像,每次显示的图像宽度增加
//向右移动进入特效
offset_x = 10;
offset_y = bm.bmHeight+20;
for(int w=1;w<=bm.bmWidth;++w) //w是显示的宽度
{
pDC->BitBlt(offset_x,offset_y,w,bm.bmHeight,&memDC,bm.bmWidth-w,0,SRCCOPY);
Sleep(10);
}
2.3 马赛克特效
方法:将图像划分成小块,然后按照随机的顺序显示出每一小块
//将0到count-1 随机顺序形成一个数组
void rand_seq(int count,int seq_array[])
{
for(int i=0;i<count;++i)
{
seq_array[i] = i;
}
//打乱 做1000次随机交换
int swap_count=0;
while(swap_count<1000)
{
//生成一个随机数
LARGE_INTEGER seed;
QueryPerformanceCounter(&seed);
srand((int)seed.QuadPart);
int seq = rand()%count-1; //0到count-1
//交换seq_array[seq] 和 seq_array[count-seq-1]
int tmp = seq_array[seq];
seq_array[seq] = seq_array[count-seq-1];
seq_array[count-seq-1] = tmp;
swap_count ++;
}
}
//马赛克效果:分成不同的块,随机显示
offset_x = bm.bmWidth+20;
offset_y = 10;
int block_size = 10; //10*10的小块,按行编号 0,1,2,3,4,5...block_count-1
int bpr = bm.bmWidth/block_size; //一行的方块数目,block_per_row
int bpc = bm.bmHeight/block_size;
int block_count = bpr*bpc; //总共的方块数目
int seq=-1;
int* seq_array = new int[block_count];
rand_seq(block_count,seq_array); //获得随机顺序
for(int i=0;i<block_count;++i)
{
seq = seq_array[i]; //要显示的块号
int row = seq/bpr; //所在行
int col = seq%bpr; //所在列
pDC->BitBlt(offset_x+col*block_size,
offset_y+row*block_size,
block_size,
block_size,
&memDC,
col*block_size,
row*block_size,
SRCCOPY);
Sleep(1);
}
delete[] seq_array;
说明:由于写的随机顺序算法rand_seq不是很好,所以马赛克效果也不是很好。读者如果能否实现更好的随机排列算法,势必会得到更好的马赛克效果
2.4 雨滴特效
方法:从图像的最后一行开始,每次显示一行,并将该行上面的每一行都与该行显示相同
//雨滴特效
offset_x = bm.bmWidth+20;
offset_y = bm.bmHeight+20;
for(int i=0;i<bm.bmHeight;++i)//外循环控制每次显示的图像行,循环一次,表示显示了一行
{
for(int j=0;j<bm.bmHeight-i;++j)//内循环控制绘制出雨滴轨迹
{
pDC->BitBlt(offset_x,offset_y+j,bm.bmWidth,1,&memDC,0,bm.bmHeight-i,SRCCOPY);
}
Sleep(10);
}