Windowsコード集 上のページ

#0004 DIBSectionクラスでのセーブロード

#0003のDIBSectionクラスに、セーブロード機能を拡張するコードです。
非デバイス依存BITMAPではデバイスの状態に関係無く様々な色数でBITMAPを持つことができます。
// CDIBSectionの派生クラスとして、CDIBSectionExを作ります。
class CDIBSectionEx:public CDIBSection{
public:
    LONG m_bpp;             // 1ピクセル当たりのビット数
    RGBQUAD m_rgb[256];     // カラーテーブル

    CDIBSectionEx():m_bpp(0){;}
    BOOL LoadBitmap(LPSTR filename);
    BOOL SaveBitmap(LPSTR filename);
};


// BITMAPロードメンバ関数
BOOL CDIBSectionEx::LoadBitmap(LPSTR filename)
{
    // ファイルオープン
    HFILE fp = _lopen(filename,OF_READ);
    if(fp == HFILE_ERROR)return FALSE;
    LONG filesize = _llseek(fp,0,FILE_END);     // ファイルサイズ取得
    _llseek(fp,0,FILE_BEGIN);

    // ファイルヘッダー読み込み
    BITMAPFILEHEADER fh;
    _lread(fp,&fh,sizeof(fh));
    if(memcmp(&fh.bfType,"BM",2) != 0){
        // BITMAPファイルでは無い
        _lclose(fp);
        return FALSE;
    }

    // 画像情報ヘッダー読み込み
    LPBITMAPINFO ih = (LPBITMAPINFO)malloc(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
    _lread(fp,ih,sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);

    // ヘッダーに従って、DIBSectionを生成する
    HDC dc = GetDC(0);
    if(!Create(dc,ih,DIB_RGB_COLORS)){
        ReleaseDC(0,dc);
        free(ih);
        _lclose(fp);
        return FALSE;
    }
    ReleaseDC(0,dc);
    m_bpp = ih->bmiHeader.biBitCount;

    // 必要ならカラーテーブルを読み込む
    switch(m_bpp){
    case 1:     memcpy(m_rgb,ih->bmiColors,sizeof(RGBQUAD) *   2);break;
    case 4:     memcpy(m_rgb,ih->bmiColors,sizeof(RGBQUAD) *  16);break;
    case 8:     memcpy(m_rgb,ih->bmiColors,sizeof(RGBQUAD) * 256);break;
    }

    // 画像データ読み込み
    _llseek(fp,fh.bfOffBits,FILE_BEGIN);
    _lread(fp,m_bits,GET_DIBSIZE(ih));

    _lclose(fp);
    free(ih);
    return TRUE;
}

// BITMAPセーブメンバ関数
BOOL CDIBSectionEx::SaveBitmap(LPSTR filename)
{
    // BITMAP情報生成
    BITMAPFILEHEADER fh;    ZeroMemory(&fh,sizeof(fh));
    BITMAPINFOHEADER ih;    ZeroMemory(&ih,sizeof(ih));
    LONG rgb_count = 0;
    memcpy(&fh.bfType,"BM",2);
    fh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    ih.biSize = sizeof(ih);
    ih.biWidth = m_width;
    ih.biHeight = m_height;
    ih.biPlanes = 1;
    ih.biBitCount  = (WORD)m_bpp;
    ih.biCompression = BI_RGB;
    switch(m_bpp){
    case 1:
        rgb_count = 2;
        ih.biSizeImage = (((ih.biWidth / 4) + 3) & 0xfffffffc) * ih.biHeight;
        fh.bfOffBits += (sizeof(RGBQUAD) * 2);
        break;
    case 4:
        rgb_count = 16;
        ih.biSizeImage = (((ih.biWidth / 2) + 3) & 0xfffffffc) * ih.biHeight;
        fh.bfOffBits += (sizeof(RGBQUAD) * 16);
        break;
    case 8:
        rgb_count = 256;
        ih.biSizeImage = ((ih.biWidth + 3) & 0xfffffffc) * ih.biHeight;
        fh.bfOffBits += (sizeof(RGBQUAD) * 256);
        break;
    case 24:
        rgb_count = 0;
        ih.biSizeImage = ((ih.biWidth * 3 + 3) & 0xfffffffc) * ih.biHeight;
        break;
    default:
        return FALSE;
    }
    fh.bfSize = fh.bfOffBits + ih.biSizeImage;

    // ファイル出力オープン
    HFILE fp = _lcreat(filename,0);
    if(fp == HFILE_ERROR)return FALSE;

    // ファイルヘッダー出力
    _lwrite(fp,(LPSTR)&fh,sizeof(fh));

    // BITMAP情報出力
    _lwrite(fp,(LPSTR)&ih,sizeof(ih));
    if(rgb_count > 0)_lwrite(fp,(LPSTR)m_rgb,sizeof(RGBQUAD) * rgb_count);

    // 画像データ出力
    _lwrite(fp,(LPSTR)m_bits,ih.biSizeImage);

    _lclose(fp);
    return TRUE;
}



// CDIBSectionExの使用例です。
// ファイルからBITMAPをロードし、加工した後にファイル出力を行います。

CDIBSectionEx dib;

if(dib.LoadBitmap("input.bmp")){

    // dibをGDIで加工できるようにデバイスコンテキストを用意する
    HDC dc = GetDC(0);
    HDC mdc = CreateCompatibleDC(dc);
    ReleaseDC(dc);
    HBITMAP ob = SelectObject(mdc,dib);

    // テキストを書きこむ
    SetBkMode(mdc,TRANSPARENT);
    TextOut(mdc,32,64,"あいうえおかきくけこ",10);

    // デバイスコンテキストを開放する
    SelectObject(mdc,ob);
    DeleteDC(mdc);

    // ファイル出力
    dib.SaveBitmap("output.bmp");
}


上のページ