我先声明一下代码只适用于256色位图,图像大小在33K左右,程序中使用了windows自带的AVI库,所以要正确设置头文件和Lib文件( Vfw.h Vfw32.lib ),要播放大一点的图像,或者是24位真彩色图像,都需要修改程序。另一点是要播放的AVI文件被我写死了,你需要注意。这只是一个实验性质的程序,但你只要稍微对其进行修改就可以用于实际的项目。另外,我播放的这个视频文件的透明色是粉色,所以如果你发现不能透明,请你注意这一点。如果需要完全理解这段代码,可能对位图结构和位图透明的实现需要了解。
在这里我只附上Play函数的代码。如果代码中有任何错误,就拜托你自己了。
以下这个Play函数只需要你传递一个窗口的句柄就可以,当然你可以增加位置的参数,但我只是把它绘制在窗口的左上角。
INT CAnime::play(HWND hWnd)
{
PAVIFILE aviFile;
INT nAviRet;
TCHAR szFileName[MAX_PATH];
DWORD ret = -1;
m_hDC = GetDC(hWnd);
nAviRet = AVIFileOpen(&aviFile, TEXT("E:\\avi\\DelFile.avi"), OF_READ, NULL); // 要播放的AVI文件
if (nAviRet != AVIERR_OK) {
MessageBox(NULL, TEXT("AVI AVIFileOpen Err"), TEXT("Error"), MB_OK);
goto PLAY_FAIL1;
}
AVIFILEINFO aviInfo;
AVIFileInfo(aviFile, &aviInfo, sizeof(AVIFILEINFO));
DWORD dwImageWidth = aviInfo.dwWidth;
DWORD dwImageHeight = aviInfo.dwHeight;
PAVISTREAM pStream;
nAviRet = AVIFileGetStream(aviFile, &pStream, streamtypeVIDEO, 0);
if (nAviRet != AVIERR_OK) {
MessageBox(NULL, TEXT("AVI AVIFileGetStream Err"), TEXT("Error"), MB_OK);
goto PLAY_FAIL2;
}
INT iFirstFrame = AVIStreamStart(pStream);
if (iFirstFrame == -1) {
MessageBox(NULL, TEXT("AVI AVIStreamStart Err"), TEXT("Error"), MB_OK);
goto PLAY_FAIL2;
}
INT iNumFrames=AVIStreamLength(pStream);
if (iNumFrames == -1) {
MessageBox(NULL, TEXT("AVI AVIStreamLength Err"), TEXT("Error"), MB_OK);
goto PLAY_FAIL2;
}
PGETFRAME pFrame;
pFrame = AVIStreamGetFrameOpen(pStream, NULL);
HDC hImageDC = CreateCompatibleDC(m_hDC);
// 创建一个目标
HDC hDestDC = CreateCompatibleDC(m_hDC);
HBITMAP hDestBitMap = CreateCompatibleBitmap(m_hDC, dwImageWidth, dwImageHeight);
HBITMAP hOldDestBitMap = (HBITMAP)SelectObject(hDestDC, hDestBitMap);
// 保存背景
HDC hBackDC = CreateCompatibleDC(m_hDC);
HBITMAP hBackBitMap = CreateCompatibleBitmap(m_hDC, dwImageWidth, dwImageHeight);
HBITMAP hOldBackBitMap = (HBITMAP)SelectObject(hBackDC, hBackBitMap);
BitBlt(hBackDC, 0, 0, dwImageWidth, dwImageHeight, m_hDC, 0, 0, SRCCOPY);
// 创建掩码位图
HDC hMaskDC = CreateCompatibleDC(m_hDC);
HBITMAP hMaskBitMap = CreateBitmap(dwImageWidth, dwImageHeight, 1, 1, NULL);
HBITMAP hOldMaskBitMap = (HBITMAP)SelectObject(hMaskDC, hMaskBitMap);
SetBkColor(hImageDC, RGB(0,0,0)); // 设置背景色为黑色
LONG lsize;
BYTE *pBih = new BYTE[34000];// 一幅图像数据大小
for (int i = iFirstFrame;i < iNumFrames; i++) {
lsize = 34000;
AVIStreamReadFormat(pStream, i, pBih, &lsize);
BITMAPINFOHEADER *bih = (BITMAPINFOHEADER *)pBih;
DWORD biSize = bih->biSizeImage;
// 读取图像数据
AVIStreamRead(pStream, i, 1, pBih + lsize, biSize, NULL, NULL);
HBITMAP hBitmap = CreateDIBitmap(m_hDC,
(BITMAPINFOHEADER*)pBih,
CBM_INIT,
(LPBYTE)pBih + lsize,
(LPBITMAPINFO)pBih,
DIB_RGB_COLORS);
SelectObject(hImageDC, hBitmap);
if (i == 0) {
BitBlt(hDestDC, 0, 0, dwImageWidth, dwImageHeight, hImageDC, 0, 0, SRCCOPY);
} else {
// 以下处理为将当前图像与前一幅图像合成
BitBlt(hMaskDC, 0, 0, dwImageWidth, dwImageHeight, hImageDC, 0, 0, SRCCOPY); // 拷贝到hMaskDC
BitBlt(hDestDC, 0, 0, dwImageWidth, dwImageHeight, hMaskDC, 0, 0, SRCAND);
BitBlt(hDestDC, 0, 0, dwImageWidth, dwImageHeight, hImageDC, 0, 0, SRCPAINT);
}
BitBlt(m_hDC, 0, 0, dwImageWidth, dwImageHeight, hBackDC, 0, 0, SRCCOPY); // 描画背景
// 将新的位图透明绘制到背景上
TransparentBlt(m_hDC,0, 0, dwImageWidth, dwImageHeight, hDestDC, 0,0,dwImageWidth, dwImageHeight,
RGB(254,0,254));
Sleep(100);
}
delete[] pBih;
SelectObject(hDestDC, hOldDestBitMap);
SelectObject(hBackDC, hOldBackBitMap);
SelectObject(hMaskDC, hOldMaskBitMap);
DeleteObject(hDestBitMap);
DeleteObject(hBackBitMap);
DeleteObject(hMaskBitMap);
DeleteDC(hBackDC);
DeleteDC(hDestDC);
DeleteDC(hImageDC);
DeleteDC(m_hDC);
AVIStreamGetFrameClose(pFrame);
ret = 0;
PLAY_FAIL2:
if (pStream != NULL)
AVIStreamRelease(pStream);
PLAY_FAIL1:
if (aviFile != NULL)
AVIFileRelease(aviFile);
AVIFileExit();
DeleteFile(szFileName);
return ret;
}