JPEG画像を縦横に並べて結合した画像をファイル保存するには?

解決


テン  2006-11-05 06:32:27  No: 63482

4つのJPEGファイル(2048×2048)を読み取った後に
この読み取った画像を縦横に並べて4096×4096のビットマップ画像
としてファイルに保存しようとしています。
しかし、出力されてビットマップファイルは一面黒です。
何が問題なのでしょうか?ソースは下記の通りです。
何分初心者ですのでよろしくアドバイスお願いします。

テンプレート:MFCアプリケーション
アプリケーション種類:ダイアログベース
Spi_LoadImage関数はhttp://www.asahi-net.or.jp/~uk8t-ktu/wincode/graphic/0006.htmから
いただきました。

HBITMAP Spi_LoadImage(LPSTR plugin,LPSTR filename);
void saveBMP(HDC hdc,LPCTSTR lpszFn,int dwWidth,int dwHeight);
HDC hDC1;
HBITMAP hbmpOld;
char filename[4][10]={"file1.jpg","file2.jpg","file3.jpg","file4.jpg"};
int i_ima;
int start_point_x[4]={0,2048,   0,2048};
int start_point_y[4]={0,   0,2048,2048};
char spiname[] = "ifjpeg.spi";
char s_fpath1[50];

// 貼り付け準備
hDC1 = m_pict.GetDC()->GetSafeHdc();
HDC g_memdc = CreateCompatibleDC(hDC1);

  for (i_ima=0; i_ima<=3; i_ima++){
    strcpy(s_fpath1, "C:\\TEST\\");
    strcat(s_fpath1, filename[i_ima]);

    // 読み込み準備(BITMAPINFO構造体を確保)
    HBITMAP bmp =Spi_LoadImage(spiname, s_fpath1);

    HDC memdc1 = CreateCompatibleDC(hDC1);
    hbmpOld=(HBITMAP)SelectObject(memdc1,bmp);

    // 貼り付け
    BitBlt(g_memdc,start_point_x[i_ima], start_point_y[i_ima],2048,2048, memdc1,0,0,SRCCOPY);
    SelectObject(memdc1,hbmpOld);
    DeleteObject(bmp);
    DeleteObject(memdc1);
  }
saveBMP(g_memdc,"C:\\TEST\\test.bmp",4096,4096);

//DeleteObject(memdc1);
//ReleaseDC(hDC1);
}
HBITMAP Spi_LoadImage(LPSTR plugin,LPSTR filename)
{

  // プラグインのロード
    HMODULE module = NULL;
  if((module = LoadLibrary(plugin)) == NULL){
    AfxMessageBox("プラグインのロードに失敗しました。");
    return NULL;
  }
    // プラグイン関数の取得
    SPI_ISSUPPORTED spi_issupported = (SPI_ISSUPPORTED)GetProcAddress(module,SPIPROC_ISSUPPORTED);
    SPI_GETPICTURE  spi_getpicture  = (SPI_GETPICTURE )GetProcAddress(module,SPIPROC_GETPICTURE);
    if(spi_issupported == NULL || spi_getpicture == NULL){
        FreeLibrary(module);
    AfxMessageBox("プラグイン関数の取得に失敗しました。");
        return NULL;
    }

    // ファイル内容をロードする
    HANDLE handle = NULL;
    if((handle = CreateFile_Read(filename)) == INVALID_HANDLE_VALUE){
        FreeLibrary(module);
    AfxMessageBox("ファイル内容のロードに失敗しました。");
        return NULL;
    }
    DWORD filesize = GetFileSize(handle,NULL),readsize;
    LPSTR data = (LPSTR)Heap_Malloc(filesize);
    SetFilePointer(handle,0,NULL,FILE_BEGIN);
    if(!ReadFile(handle,data,filesize,&readsize,NULL)){
        CloseHandle(handle);
        FreeLibrary(module);
    }
    CloseHandle(handle);

    // ロードできる形式かどうかをチェックする
    if(spi_issupported(filename,(DWORD)data) == 0){
        Heap_Free(data);
        FreeLibrary(module);
    AfxMessageBox("Susieプラグインに対応してません。");
        return NULL;
    }

    // 画像を展開する
  HLOCAL info,bm;
    if(spi_getpicture(data,filesize,1,&info,&bm,NULL,0) != 0){
        Heap_Free(data);
        FreeLibrary(module);
    AfxMessageBox("画像のロードできません。");
        return NULL;
    }
    LPBITMAPINFO bmpinfo = (LPBITMAPINFO)LocalLock(info);   // BITMAPINFO構造体
    LPBYTE bmbits = (LPBYTE)LocalLock(bm);     // 画像データ

    // 取得した情報からBITMAPハンドルを生成する
    HDC dc = GetDC(0);
    HBITMAP bitmap = CreateDIBitmap(dc,&bmpinfo->bmiHeader,CBM_INIT,bmbits,bmpinfo,DIB_RGB_COLORS);
    ReleaseDC(0,dc);

  // いろいろと開放
    LocalUnlock(info);
    LocalFree(info);
    LocalUnlock(bm);
    LocalFree(bm);
    Heap_Free(data);
    FreeLibrary(module);

    return bitmap;
}
void saveBMP(HDC hdc,LPCTSTR lpszFn,int dwWidth,int dwHeight) {

  DWORD dwSize,dwFSize,dwLength;
  HANDLE fh;
  LPBITMAPFILEHEADER lpHead;
  LPBITMAPINFOHEADER lpInfo;
  LPBYTE lpBuf,lpPixel;
  HDC hdcMem;
  HBITMAP hBMP,hOld;

  if ((dwWidth*3) % 4==0) /* バッファの1ラインの長さを計算 */
    dwLength=dwWidth*3;
  else
    dwLength=dwWidth*3+(4-(dwWidth*3) % 4);

  /* 書き込み用バッファのサイズ計算 */
  dwFSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwLength*dwHeight;

  /* バッファ確保とポインタ設定 */
  lpBuf=(LPBYTE)GlobalAlloc(GPTR,dwFSize);
  lpHead=(LPBITMAPFILEHEADER)lpBuf;
  lpInfo=(LPBITMAPINFOHEADER)(lpBuf+sizeof(BITMAPFILEHEADER));
  lpPixel=lpBuf+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);

  /* 24ビットBMPファイルのヘッダ作成 */
  lpHead->bfType='M'*256+'B';
  lpHead->bfSize=dwFSize;
  lpHead->bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
  lpInfo->biSize=sizeof(BITMAPINFOHEADER);
  lpInfo->biWidth=dwWidth;
  lpInfo->biHeight=dwHeight;
  lpInfo->biPlanes=1;
  lpInfo->biBitCount=24;

  /* ウインドウのデバイスコンテキスト互換のBITMAP作成 */
  hBMP=CreateCompatibleBitmap(hdc,dwWidth,dwHeight);
  /* BITMAPにウインドウのクライアント領域をコピー */
  hdcMem=CreateCompatibleDC(hdc);
//  hBMP    = CreateDIBSection( hdcMem, (LPBITMAPINFO)&lpInfo, DIB_RGB_COLORS, (void**)&lpPixel, NULL, NULL );  // 指定したパラメータでDIBを確保  
  hOld=(HBITMAP)SelectObject(hdcMem,hBMP);
  BitBlt(hdcMem,0,0,dwWidth,dwHeight,hdc,0,0,SRCCOPY);
  SelectObject(hdcMem,hOld);
  GetDIBits(hdc,hBMP,0,dwHeight,lpPixel,(LPBITMAPINFO)lpInfo,DIB_RGB_COLORS);

  DeleteObject(hBMP);
  DeleteObject(hdcMem);

  /* バッファをファイルに書き出す */
  fh=CreateFile(lpszFn,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  WriteFile(fh,lpBuf,dwFSize,&dwSize,NULL);
  CloseHandle(fh);

  GlobalFree(lpBuf);

}


とおりすがり  2006-11-07 10:33:26  No: 63483

>何分初心者ですのでよろしくアドバイスお願いします。
こんな無茶な質問はしない。しても回答を得られる可能性は低い。

そもそも質問じゃなく、
「めんどくせーから誰か俺の代わりにデバッグして」
という内容だし。


できることはや朗  2006-11-07 18:48:34  No: 63484

ブレイクポイントを使って確実に動いてるところを見つけていけば、
最終的にどこが問題なのか絞れるのではないかと。

アドバイスとしてはまず問題が起きる箇所の絞込みを行ってください。
最終的に「ここ!」と確認することができればより詳しくアドバイスできるかと思います。

今のままではとおりすがりさんと同意見です。


PATIO  2006-11-07 22:53:14  No: 63485

参考にしたところからソースを持ってきただけでは
単なるコピペと変わりません。
(たとえ変数名を変更するくらいはしていても)
単なるコピペでは全く応用が利かないのでやってもあまり意味が無いです。
参考にしたソースの一つ一つのステップが何をやっていて
どういう意味があるのかを掘り下げないと参考にした意味がありません。
ここに書き込まれている内容からではそこまでやったという部分が
全く感じられないです。
ソースを貼るのは良いのですが、せめてどの辺りが怪しいくらいは自分で
解析しましょう。
「できることはや朗」さんが書かれている通り、デバッガを使えば全く
わからないということも無いはずです。
もし全く検討もつかないのであれば、Windowsで画像を描画する方法を
もう一度勉強しなおしてください。


テン  2006-11-12 06:42:29  No: 63486

丸々ソースを出したことで、投げやりと受け取られてしまったのかもしれませんが
実は、これまでには私なりにいろいろと試行錯誤していまして
FOR文内の動作を確認しています。
「JPEG→ビットマップハンドル→メモリDCへ貼り付け」はメモリDCをピクチャボックスに関連付けられたDC
に置き換えて、4枚の絵が縦横に貼り付けられているのを確認しています。
(その際には画像を縮小する必要があったのでDCへの貼り付けはBitBlt関数でなくStretchBlt関数を使いました)
それでsaveBMP関数内でメモリDCの内容をファイルに落とすことになるのですが
まず最初に試したのがメモリDCをGetCurrentObject関数を使ってビットマップハンドルを得て
GetDIBits関数でメモリDCとビットマップハンドルからビットマップのビット列を取得して、それをファイルに書く
方法ですが、やはり一面黒になります。
それでネットを検索していてBITMAP-DIB変換のサンプルソース(http://www.sm.rim.or.jp/~shishido/wincap.html)をみつけたので
その中のウインドウのデバイスコンテキストをメモリDCに置き換えたつもりですが、やはり一面黒になります。
(CreateDIBSection関数を使うことも考えましたが、挫折しましたのでCreateDIBSectionはコメントアウトしてます。)
この元のサンプルソースではウインドウのデバイスコンテキストだったのをメモリDCにした点がまずいのでしょうか?
もし、そうならどうしたらいいのでしょうか?


kure  2006-11-12 07:31:18  No: 63487

g_memdcがCreateCompatibleDCしただけなんだけど、
それだけだと1bitのモノクロビットマップにしかなりません。

こんなのはGetDIBitsとかの結果をみればわかるはずだし、
ファイルに出力された中身を見てもわかると思うんだけど。

試行錯誤する前にMSDNとか読みましょう。


テン  2006-11-13 05:15:54  No: 63488

CreateCompatibleBitmapで作ったビットマップを
g_memdcにSelectObjectで割り当てたら、結合した
画像がファイルに保存されました。
kure様、本当にありがとうございました。


できることはや朗  2006-11-13 22:31:09  No: 63489

>丸々ソースを出したことで、投げやりと受け取られてしまったのかもしれませんが

それだけではないです。テンさんが試行錯誤した内容が記されていないから、
できることはやろうよと言うことでデバッグするようレスしたのです。

>実は、これまでには私なりにいろいろと試行錯誤していまして

最初の投稿を読んでもいろいろ試行錯誤したかどうか読み取るのは難しいのではないかと。
やってみたことは出来るだけ最初に併記しておきましょう。
私はエスパーじゃないので書いていないことは分かりません。

ともあれ解決してよかったですね。


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

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






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