ビットマップを読み込むには

解決


yuu  2004-03-24 08:50:15  No: 53387

現在24BitのBitmapをディスク(リソースではない)より取得し、
それに編集(描画や回転)等を行ったあと、
24bitのBitmap形式で出力するプログラムの開発を行っています。

当プログラムにおいて、読み込み処理に不具合があります。

読み込む元のBitmapが40MB程度のものであれば、
取得→出力の動作が問題なく流れるのですが、
340MBのファイルを読み込んだ際、Bitmapのハンドルの取得に失敗します。

メモリは2GB積んであり、常に1.5GB程度の空き容量が存在するマシンですので、
メモリ不足は考えずらいです(PG内で340MBのメモリ確保に成功している)

もしかしたらVCの限界なのでしょうか。

一応ソースを以下に示します。

CBitmap*  LoadBitmapFile( char* filename, LPBITMAPINFO bmpinfo )
{
    // ファイル読み込み
    HFILE fp = _lopen(filename,OF_READ);
    if(fp == HFILE_ERROR)return NULL;
    LONG size = _llseek(fp,0,FILE_END);
    LPBYTE buf = (LPBYTE)malloc(size);
    if(buf == NULL){
        _lclose(fp);
        return NULL;
    }
    _llseek(fp,0,FILE_BEGIN);
    _lread(fp,buf,size);
    _lclose(fp);

    // BMPヘッダーかどうかチェック
    if(memcmp(buf,"BM",2) != 0){
        free(buf);
        return NULL;
    }

    // BITMAP情報を格納する
    if(bmpinfo != NULL)memcpy(bmpinfo,buf + sizeof(BITMAPFILEHEADER),sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256);

    // BITMAP作成
    LPBITMAPFILEHEADER fh = (LPBITMAPFILEHEADER)buf;
    LPBITMAPINFOHEADER ih = (LPBITMAPINFOHEADER)(buf + sizeof(BITMAPFILEHEADER));
    LPBITMAPINFO bi = (LPBITMAPINFO)(buf + sizeof(BITMAPFILEHEADER));
    LPBYTE img = buf + fh->bfOffBits;
    HDC dc = ::GetDC(0);
    HBITMAP hb = CreateDIBitmap(dc,ih,CBM_INIT,img,bi,DIB_RGB_COLORS);  // ※ ここでhbがNULLで返って来ます。
    ::ReleaseDC(0,dc);
    free(buf);

//  return hb;

    // CBitmapで返す
    CBitmap *map;
    map = new CBitmap;
    map->Attach(hb);

    return map;
}

インターネットでいろいろ調べてみたのですが、
限界についての記事は見あたりませんでした・・・。
ご教授よろしくお願いいたします。

開発環境:VC++ 6(MFC)  WindowsXP Pro


YuO  2004-03-24 09:18:03  No: 53388

とりあえず,GetLastErrorを調べてみてはどうですか?


yuu  2004-03-24 19:49:34  No: 53389

ご意見ありがとうございます。

GetLastErrorを使ってCreateDIBitmap発行直後にシステムメッセージを表示させてみたところ、
「このコマンドを実行するのに十分な記憶域がありません」
と表示されました。

システム上のメモリには余裕があるので、もしかしたら  ですが、
CreateDIBitmapの読み込みの限界を超えているのかもしれません。

引き続き  CreateDIBitmap  の限界について調べてみたいと思います。


yuu  2004-03-26 04:21:48  No: 53390

自己レスです。

CreateDIBitmapを用いたBITMAPの読み込みには、
GDIリソースの制限が絡むようです(2000/XP共に
故に巨大なBITMAPの読み込みに失敗していました。

レジストリの編集等で回避を試みましたがうまく行かず、
最終的にはGDIリソースを用いずにBITMAPを扱うことにしました。

具体的には
CreateDIBitmap  を用いてGDIリソース上で領域確保していた部分を、
CreateDIBSection  を用いてメモリ上に領域確保することにしました。

また、内部で作業領域として使用していたBITMAP領域の確保を、
CreateCompatibleBitmap(CreateBitmap)を用いずに、上記と同様に
CreateDIBSection  を用いることにしました。

結果エラーは無くなりましたが、使用するメモリが半端無くなりました(1GBを越えたり
メモリにはまだ余裕があるので今のところは問題ありませんが・・・。

以上です。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加