2010年01月22日

デバイス非依存ビットマップ(DIB)を扱うクラス-(Windows, C/C++)

CA3A0024

OS:windows xp
言語:C/C++

ビットマップ(DDB)ファイルを読み込むプログラム-(Windows, C/C++)」ではデバイス依存のビットマップを読み込むプログラムを取り上げました。

デバイスに依存しないビットマップ(DIB)を扱う方法も覚えたので、書き留めます。
以下のCDibクラスが、DIBを扱うクラスです。
※1 DIBは、1行のバイト数(横1列の画素を格納するのに必要なバイト数)が4の倍数でなければならないので、ファイルの読み書きに注意が必要です。
※2 DDBは画像の左上が原点ですが、DIBは左下が原点です。
※3 HDCに転送するにはStretchDIBits関数を使います。
int StretchDIBits(
    HDC hdc, // 転送先のHDC
    int XDest, // 転送先矩形の左上隅の x 座標
    int YDest, // 転送先矩形の左上隅の y 座標
    int nDestWidth, // 転送先矩形の幅
    int nDestHeight, // 転送先矩形の高さ
    int XSrc, // 転送元矩形の左上隅の x 座標
    int YSrc, // 転送元矩形の左上隅の x 座標
    int nSrcWidth, // 転送元矩形の幅
    int nSrcHeight, // 転送元矩形の高さ
    CONST VOID *lpBits, // ビット列(CDibのメンバ変数pixel)
    CONST BITMAPINFO *lpBitsInfo, // ビットマップのデータ(CDibのメンバ変数bmpInfoへのポインタ)
    UINT iUsage, // データの種類(ここではDIB_RGB_COLORSを指定)
    DWORD dwRop // ラスタオペレーションコード(普通に転送するだけならSRCCOPYを指定)
);


/* 宣言 */
#include <windows.h>

class CDib
{
public:
    CDib(const char* filename);
    CDib(const int w, const int h);
    ~CDib();
    int getWidth() {
        return this->bmpInfo.bmiHeader.biWidth;
    }
    int getHeight() {
        return this->bmpInfo.bmiHeader.biHeight;
    }
    unsigned char* getPixel() {
        return this->pixel;
    }

private:
    BITMAPFILEHEADER bfh;
    BITMAPINFO bmpInfo;
    unsigned char* pixel;
    int len;
};

/* 定義 */
#define BMP_TYPE (('M' << 8) + 'B')

static int getBytePerLine(const int width)
{
    const int r = (width * 3) % 4;
    return ((r == 0) ? width * 3 : width * 3 + (4 - r));
}

CDib::CDib(const char* filename)
: pixel(NULL), len(0)
{
    // ファイル読み込み
    FILE* fp = NULL;
    fp = fopen(filename, "rb");

    // ヘッダーの読み込み
    fread(&(this->bfh), sizeof(BITMAPFILEHEADER), 1, fp);
    fread(&(this->bmpInfo.bmiHeader), sizeof(BITMAPINFOHEADER), 1, fp);

    // ピクセル列の読み込み
    const int width = this->bmpInfo.bmiHeader.biWidth;
    const int height = this->bmpInfo.bmiHeader.biHeight;
    this->len = getBytePerLine(width);
    this->pixel = new unsigned char[ this->len * height ];
    fread(this->pixel, sizeof(unsigned char), this->len * height, fp);
   
    fclose(fp);
}

CDib::CDib(const int w, const int h)
: pixel(NULL), len(0)
{
    // BITMAPINFOHEADERの設定
    this->bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    this->bmpInfo.bmiHeader.biPlanes = 1;
    this->bmpInfo.bmiHeader.biCompression = BI_RGB;
    this->bmpInfo.bmiHeader.biWidth = w;
    this->bmpInfo.bmiHeader.biHeight = h;
    this->bmpInfo.bmiHeader.biBitCount = 24;
    this->bmpInfo.bmiHeader.biSizeImage = 0;
    this->len = getBytePerLine(w);
    this->pixel = new unsigned char[ this->len * h ];
    memset(this->pixel, 0xff, this->len * h);

    this->bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + this->len * h;
    this->bfh.bfType = BMP_TYPE;
    this->bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
}

CDib::~CDib()
{
    if ( this->pixel != NULL ) {
        delete [] this->pixel;
    }
}


    • 0 Comment |
    • 0 Trackback |
    • このエントリーをはてなブックマークに追加
2010年01月21日

Windows APIを使ったビットマップ(DDB)ファイルを読み込むプログラム-(Windows, C/C++)

os:windows xp
言語:C/C++

デバイス依存ビットマップ(DDB)を読み込むクラスです。
コンストラクタにファイル名を指定します。
描画するときは、メンバ変数のhMemDCを使います(getDC()で取得)。


/* 宣言 */
#include <windows.h>

class CDdb
{
public:
    CDdb(const char* _fileName);
    ~CDdb();
    int getWidth() {
        return this->bmp.bmWidth;
    }
    int getHeight() {
        return this->bmp.bmHeight;
    }

    HDC getDC() {
        return this->hMemDC;
    }

private:
    HBITMAP hBmp;
    BITMAP bmp;
    HDC hMemDC;
};

/* 定義 */
CDdb::CDdb(const char *_fileName)
: hBmp(NULL), hMemDC(NULL)
{
    this->hBmp = (HBITMAP)LoadImage(
        NULL,
        _fileName,
        IMAGE_BITMAP,
        0,
        0,
        LR_LOADFROMFILE
        );

    this->hMemDC = CreateCompatibleDC(NULL);
    SelectObject(this->hMemDC, this->hBmp);
    GetObject(this->hBmp, sizeof(this->bmp), &(this->bmp));
}

CDdb::~CDdb()
{
    if ( NULL != this->hBmp ) {
        DeleteObject(this->hBmp);
    }

    if ( NULL != this->hMemDC ) {
        DeleteDC(this->hMemDC);
    }
}

    • 0 Comment |
    • 0 Trackback |
    • このエントリーをはてなブックマークに追加
2010年01月20日

Windows API でウィンドウを表示するだけのプログラム-(Windows, C/C++)

OS:windows xp
言語:C/C++

WindowsAPIとC言語(C++)を使って、ウィンドウを表示するプログラム。ウィンドウを表示するだけで、何もしない。

#include <windows.h>

#define WNDCLASSNAME TEXT("SampleClass")

LRESULT CALLBACK WindowProc( HWND hWnd, UINT msg, WPARAM wp, LPARAM lp )
{
    switch (msg) {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }
    return DefWindowProc( hWnd, msg, wp, lp );
}

int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, PSTR lpCmdLine, int nCmdShow )
{
    HWND hWnd;
    WNDCLASS wc;
    MSG msg;

    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = WindowProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInst;
    wc.hIcon         = LoadIcon( NULL, IDI_APPLICATION );
    wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = WNDCLASSNAME;

    if ( !RegisterClass(&wc) ) {
        return 0;
    }

    hWnd = CreateWindow(
        WNDCLASSNAME,
        TEXT("SampleWindow"),
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL,
        NULL,
        hInst,
        NULL
        );

    if ( hWnd == NULL ) {
        return 0;
    }

    while ( GetMessage( &msg, NULL, 0, 0 ) > 0 ) {
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}


    • 0 Comment |
    • 0 Trackback |
    • このエントリーをはてなブックマークに追加