今回は32ビットDIBの使用例をいくつか示すので、自分でも色々やってみて下さい。
■DIBの概念の復習
原点は左下のボトムアップ座標系。
確保するのはただのバッファ。
幅と高さとビット数は必要な時にプログラムに教えてあげる。
それぞれの画素は数値で表現され、直接アクセスする事ができる。
おまけにDIBは裏画面なので各画素の色はいつまでの保存されているんでしたね
(表画面の色は一度表示するとリセット)。
■複数のDIB
二つのDIBを作成して一方を描画用、もう一方を表示用にするとしましょう。
描画用には適当な色をつけ、赤っぽい色だけ表示用にコピーします。
つまり透過処理を行います。
二つのDIBの大きさとビット数は等しいとすれば BITMAPINFO は共用することができます。
#include<windows.h> #include<time.h> #define WIDTH 200 #define HEIGHT 100 LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; static LPDWORD lpPixel,lpPixel2; static BITMAPINFO bmpInfo; int x,y,r,g,b; switch(uMsg) { case WM_CREATE: //二つ分確保する lpPixel=(LPDWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,WIDTH*HEIGHT*4*2); lpPixel2=lpPixel+WIDTH*HEIGHT; //DIBの情報を設定する bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bmpInfo.bmiHeader.biWidth=WIDTH; bmpInfo.bmiHeader.biHeight=HEIGHT; bmpInfo.bmiHeader.biPlanes=1; bmpInfo.bmiHeader.biBitCount=32; bmpInfo.bmiHeader.biCompression=BI_RGB; srand((unsigned)time(NULL)); //砂嵐 for(y=0;y<HEIGHT;y++){ for(x=0;x<WIDTH;x++){ r=rand()%256; g=rand()%256; b=rand()%256; lpPixel2[x+y*WIDTH]=(r<<16)+(g<<8)+b; } } //赤っぽい色だけコピー for(y=0;y<HEIGHT;y++){ for(x=0;x<WIDTH;x++){ r=(BYTE)(lpPixel2[x+y*WIDTH]>>16); g=(BYTE)(lpPixel2[x+y*WIDTH]>>8); b=(BYTE) lpPixel2[x+y*WIDTH]; if(r>=0x80 && g<0x80 && b<0x80){ lpPixel[x+y*WIDTH]=lpPixel2[x+y*WIDTH]; } } } return 0; case WM_DESTROY: HeapFree(GetProcessHeap(),0,lpPixel); PostQuitMessage(0); return 0; case WM_PAINT: hdc=BeginPaint(hWnd,&ps); //表画面へ転送 StretchDIBits(hdc,0,0,WIDTH,HEIGHT, 0,0,WIDTH,HEIGHT,lpPixel,&bmpInfo,DIB_RGB_COLORS,SRCCOPY); StretchDIBits(hdc,250,0,WIDTH,HEIGHT, 0,0,WIDTH,HEIGHT,lpPixel2,&bmpInfo,DIB_RGB_COLORS,SRCCOPY); EndPaint(hWnd,&ps); return 0; } return DefWindowProc(hWnd,uMsg,wParam,lParam); }
バッファの確保は同時に行うことができます。
参照するバッファの範囲にさえ気を付ければよいのです。
同時に確保すれば解放も簡単です。
★☆ ソースファイル表示 ☆★
■トップダウンなDIB
あくまでもDIBは左下が原点なボトムアップですが、
左上が原点なボトムアップにする事もできます。
でも他人様に公開するならあまり好ましくないかもしれません。
トップダウンにする方法は簡単です。
BITMAPINFOHEADER 構造体の biHeight メンバーに高さの負数を設定すればいいだけです。
#include<windows.h> #define WIDTH 200 #define HEIGHT 100 LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; static LPDWORD lpPixel; static BITMAPINFO bmpInfo; int x,y; switch(uMsg) { case WM_CREATE: lpPixel=(LPDWORD)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,WIDTH*HEIGHT*4); //DIBの情報を設定する bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bmpInfo.bmiHeader.biWidth=WIDTH; bmpInfo.bmiHeader.biHeight=-HEIGHT; //注目! bmpInfo.bmiHeader.biPlanes=1; bmpInfo.bmiHeader.biBitCount=32; bmpInfo.bmiHeader.biCompression=BI_RGB; //描画 for(y=25;y<=50;y++){ for(x=25;x<=50;x++){ lpPixel[x+y*WIDTH]=0x00ff0000; //赤 } } return 0; case WM_DESTROY: HeapFree(GetProcessHeap(),0,lpPixel); PostQuitMessage(0); return 0; case WM_PAINT: hdc=BeginPaint(hWnd,&ps); //表画面へ転送 StretchDIBits(hdc,0,0,WIDTH,HEIGHT, 0,0,WIDTH,HEIGHT,lpPixel,&bmpInfo,DIB_RGB_COLORS,SRCCOPY); EndPaint(hWnd,&ps); return 0; } return DefWindowProc(hWnd,uMsg,wParam,lParam); }
★☆ ソースファイル表示 ☆★