C++でアルファチャンネル付きのAVIを出力する方法

 とりあえず、1ピクセル32ビットのアルファチャンネルを出力できるC++のコードを作成できました。コンパイルして実行すればAVIファイルができるので、それを動画編集ソフトに取り込めば背景が透過します。

バグなどの問題もあるので、手持ちの数値データを動画にしたいなどの個人的なツールとして利用するための参考にしてみてください。

  1. #include <windows.h>
  2. #include <vfw.h>
  3. #pragma comment (lib, "vfw32.lib")
  4. //実行すると100までカウントアップするアルファチャンネル付きAVI動画を作成します。。
  5. //g++ .\outCntAviA.cpp -mwindows -lvfw32
  6. void paintAlpha(LPDWORD lpPixel,const unsigned int alpha,const RECT *fill,const RECT *canbas){
  7.     
  8.         unsigned char *pTest;
  9.         
  10.         for(int y=fill->top;y<fill->bottom;y++){
  11.     for(int x=fill->left;x<fill->right;x++){
  12.     
  13.     int memadr = x+(canbas->bottom - y)*canbas->right;
  14.   
  15.     
  16.    
  17.    pTest=(unsigned char *)&lpPixel[memadr];
  18.    pTest++; //B
  19.    pTest++; //G
  20.    pTest++; //R
  21.     *pTest = alpha; //A
  22.     
  23.     }
  24.         }
  25.     
  26.     
  27. }
  28. int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
  29. {
  30.     PAVIFILE pfile;
  31.     PAVISTREAM pavi;
  32.     AVISTREAMINFO si;
  33.     LPAVISTREAMINFO lpsi = &si;
  34.     HDC hdcMem;
  35.     HBITMAP hbmpMem, hbmpMemPrev;
  36.     DWORD i;
  37.     TCHAR szBuf[32];
  38.     LPVOID lpBits;
  39.     BITMAPV5HEADER bmiHeader;    
  40.     
  41.     AVIFileInit();
  42.     if (AVIFileOpen(&pfile, TEXT("video.avi"), OF_CREATE | OF_WRITE, NULL) != 0) {
  43.         MessageBox(NULL, TEXT("Fail file open."), TEXT("OK"), MB_OK);
  44.         AVIFileExit();
  45.         return 0;
  46.     }
  47.     ZeroMemory(&si, sizeof(AVISTREAMINFO));
  48.     si.fccType = streamtypeVIDEO;
  49.     si.fccHandler = comptypeDIB;
  50.     si.dwScale = 1;
  51.     si.dwRate = 2;
  52.     si.dwLength = 0;
  53.     si.dwQuality = (DWORD)-1;
  54.     SetRect(&si.rcFrame, 0, 0, 300,200);
  55.     if (AVIFileCreateStream(pfile, &pavi, &si) != 0) {
  56.         MessageBox(NULL, TEXT("Fail open stream."), TEXT("OK"), MB_OK);
  57.         AVIFileRelease(pfile);
  58.         AVIFileExit();
  59.         return 0;
  60.     }
  61.     ZeroMemory(&bmiHeader, sizeof(BITMAPINFOHEADER));
  62.     bmiHeader.bV5Size = sizeof(BITMAPINFOHEADER);
  63.     bmiHeader.bV5Width = lpsi->rcFrame.right;
  64.     bmiHeader.bV5Height = lpsi->rcFrame.bottom;
  65.     bmiHeader.bV5Planes = 1;
  66.     bmiHeader.bV5BitCount = 32;
  67.     bmiHeader.bV5Compression = BI_RGB;
  68.     bmiHeader.bV5SizeImage = bmiHeader.bV5Height * bmiHeader.bV5Width * 4;
  69.     if (AVIStreamSetFormat(pavi, 0, &bmiHeader, sizeof(BITMAPINFOHEADER)) != 0){
  70.         MessageBox(NULL, TEXT("Fail Init BMI Header."), TEXT("OK"), MB_OK);
  71.     }
  72.     hdcMem = CreateCompatibleDC(NULL);
  73.     hbmpMem = CreateDIBSection(NULL, (LPBITMAPINFO)&bmiHeader, DIB_RGB_COLORS, &lpBits, NULL, 0);
  74.     hbmpMemPrev = (HBITMAP)SelectObject(hdcMem, hbmpMem);
  75.     SetBkMode(hdcMem, TRANSPARENT);
  76.     SetTextColor(hdcMem, RGB(255, 255, 255));
  77.     HGDIOBJ hFont = CreateFontW(100, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS,
  78.         CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"UI Gothic");
  79.     HGDIOBJ hFontOld = SelectObject(hdcMem, hFont);    
  80.     
  81.     HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));
  82.     for (int fCnt = 0; fCnt < 1000; fCnt++) {
  83.         wsprintf(szBuf, TEXT("%d"), fCnt);
  84.         FillRect(hdcMem, &lpsi->rcFrame, hBrush);
  85.         //アルファチャンネル塗りつぶし
  86.         paintAlpha((LPDWORD)lpBits,0x90,&si.rcFrame,&si.rcFrame);
  87.         
  88.         DrawText(hdcMem, szBuf, -1, &lpsi->rcFrame, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  89.         AVIStreamWrite(pavi, fCnt, 1, lpBits, bmiHeader.bV5SizeImage, AVIIF_KEYFRAME, NULL, NULL);
  90.     }
  91.     
  92.     SelectObject(hdcMem, hFontOld);
  93.     DeleteObject(hFont);
  94.     
  95.     DeleteObject(hBrush);
  96.     
  97.     SelectObject(hdcMem, hbmpMemPrev);
  98.     DeleteObject(hbmpMem);
  99.     DeleteDC(hdcMem);
  100.     
  101.     MessageBox(NULL, TEXT("Done."), TEXT("OK"), MB_OK);
  102.     AVIStreamRelease(pavi);
  103.     AVIFileRelease(pfile);
  104.     AVIFileExit();
  105.     return 0;
  106. }

簡単に手持ちのC,C++の処理に進捗バーを実装する方法

 C言語やC++で何か処理を書ける人は多いですが、Windowプログラムとなると実装方法が難しいです。VisualStudioのプロジェクトの雛形にボタンを配置し、そこから手持ちのコードを起動すれば動きそうです。 しかし、その方法では「未応答」状態になったり、ウィンドウの操作すら...