• ベストアンサー

TIFFを開いてBITMAPで保存する方法

■開発環境 VC++6.0,Windows2000 Pro,+ libtiff(TIFFを扱うライブラリ) で以下のようなコードを書きました. ************************************************* BOOL CTiff::OpenTiffAndSaveBMP(CString path) { HDIB hDIB; hDIB = LoadTIFFinDIB(path); BITMAPFILEHEADER BMPFILEHEADER; LPBITMAPINFOHEADER BMPINFOHEADER; if(!hDIB) return FALSE; CFile file; path.Replace("tif", "bmp"); if( !file.Open( path, CFile::modeWrite|CFile::modeCreate) ) return FALSE; BMPINFOHEADER = (LPBITMAPINFOHEADER)hDIB; int nColors = 1 << BMPINFOHEADER->biBitCount; // BITMAPFILEHEADERのフィールドを初期化 BMPFILEHEADER.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM" BMPFILEHEADER.bfSize = GlobalSize (hDIB) + sizeof( BMPFILEHEADER ); BMPFILEHEADER.bfReserved1 = 0; BMPFILEHEADER.bfReserved2 = 0; BMPFILEHEADER.bfOffBits = (DWORD)(sizeof( BMPFILEHEADER ) + BMPINFOHEADER-> biSize + nColors * sizeof(RGBQUAD)); // ファイルヘッダを書き込む file.Write( &BMPFILEHEADER, sizeof(BMPFILEHEADER) ); // DIBのヘッダとビット列を書き込む DWORD nSize = GlobalSize(hDIB); file.Write( BMPINFOHEADER, nSize ); file.Close(); return TRUE; } ************************************************ しかし,OpenTiffAndSaveBMP()の下から3行目の >file.Write( BMPINFOHEADER, nSize ); でDebug Assertion Failed!なるエラーで止まってしまいます. そこで「無視」ボタンを押すと「ファイルにアクセス中に不明なエラーが発生しまし た」となります. 文字数の制限上LoadTIFFinDIB()のソースは無いのですが, 原因ならびに解決策の分かる方ご教授ください.

質問者が選んだベストアンサー

  • ベストアンサー
noname#9119
noname#9119
回答No.2

GlobalSize(hDIB)としているならグローバルメモリなんでしょう。 hDIBがポインタとは限らないので、GlobalLock() でメモリブロックへのポインタを得てからキャストする。 BMPINFOHEADER = (LPBITMAPINFOHEADER)GlobalLock(hDIB);

mkmarimo
質問者

補足

ご回答ありがとうございます. 上記のやり方でエラーで止まることなくプログラムは走りました. しかし,保存されたビットマップはペイントで開くと, 元がどんなTIFF画像であろうと真っ白になってしまいます. これの原因について分かる方ご教授お願いします.

その他の回答 (6)

  • mcWalker
  • ベストアンサー率69% (27/39)
回答No.7

LoadTIFFinDIB() の BitsPerSample, PhotometricInterpretation の定義は uint16 でないといけないのに、VC++ default では、 32bits になりますね。 tiff2dib.c の作者は自分の tiff data 向けに作ったものでしょう。 canon の tiff を処理したいのなら、スペックを把握して 範囲を限定して進めた方がよさそうです。 因みに tiff2dib.c でうまく行くのは、pics フォルダの jello.tif のみでした。

mkmarimo
質問者

お礼

わざわざそのようなことまで調べて、アドバイスしていただきありがとうございます。 16ビットのTIFFを読みたかったんですけど、難しそうですね。 もうすこしがんばってみます。

  • mcWalker
  • ベストアンサー率69% (27/39)
回答No.6

libtiff3.dll の入った libtiff で、tiff2dib.c を libtiff ソースの pics フォルダの .tif ファイルで試したのですが、 .bmp ファイルで取り出せない例が出ます。 取り出せても、真っ黒あるいは真っ白。 libtiff3.dll は、2004.2.11 付けで、 tiff2dib.c は、1995.4.12 付けです。 tiff2dib.c はフランスの方が win95 向けに作ったものですが、 何かが、整合していないようです。LoadTIFFinDIB() の中の memcpy() で落ちる例がありました。 仕様書に立ち戻った精査が必要な予感がします。

mkmarimo
質問者

お礼

mcWalkerさん、いろいろ調べていただき本当に感謝です。 お陰で大分前進した気がします。ありがとうございます。

mkmarimo
質問者

補足

今自分でもやってみたところ,PhotoShopを使って作成したTIFFなら読めますが, Canonのカメラで撮ってCanonのソフトでTIFFにしたものでは確かにmemcpy()で落ちました. 後者のCanonのものはPhotoShopでも開くことができなかったです. 「書類を開けません.これはTIFFファイルではありません,」 というエラーが出ます.けど,イメージングでは開きます. TIFFフォーマットは共通ではないのですかねぇ・・・

  • kmb01
  • ベストアンサー率45% (63/138)
回答No.5

libtiffは触ったことないのですが… No.2補足より >しかし,保存されたビットマップはペイントで開くと, >元がどんなTIFF画像であろうと真っ白になってしまいます. バイナリエディタで開いて正しいBmpファイルが書き込まれているか 確認してください。 No.1補足より、 >nSizeには値は入ってました. >640×480の画像でnSize = 921640でした. >これは多分あってますよね…?? 640*480 =307200 640*480*3=921600 このことからおそらくsizeof(BITMAPINFOHEADER)=40で 各ピクセルに3バイト(24ビット)、 カラーテーブルなしのビットマップを LoadTIFFinDIBが作成したと推測しました。 カラーテーブルなしのため、 >BMPFILEHEADER.bfOffBits = (DWORD)(sizeof( BMPFILEHEADER ) + >BMPINFOHEADER-> >biSize + nColors * sizeof(RGBQUAD)); のnColors * sizeof(RGBQUAD))は余分です。 #通常の24ビットBmpファイルのbfOffBits部分に2^24*4を 加算するとペイントでは真っ白の画面が出力されるようになります。

mkmarimo
質問者

お礼

ご回答ありがとうございます. ご指摘のとおりやってみたらうまくいきました. ありがとうございました.

noname#9119
noname#9119
回答No.4

sizeof(BMPFILEHEADER)は4になるような。

  • mcWalker
  • ベストアンサー率69% (27/39)
回答No.3

様子が分からないので、探してやっと tiff2dib.c を落としてきました。 #2さんがご指摘の BMPINFOHEADER へ入れるところで、 GlobalLock() がないと、hDIB が示す場所が不定です。 tiff2dib.c の CreateDIB() をご覧になると、hDIB の 内容が分かると思います。ヘッダを格納するところで、 GlobalLock() やってますよね。 尚、この関数の最後に hDIB を解放しないといけません。

mkmarimo
質問者

お礼

>様子が分からないので、探してやっと tiff2dib.c を落としてきました。 わざわざありがとうございます. hDIBは最後にちゃんと解放します. 今はまた下の補足のように別件で悩んでます. なかなかゴールまでたどり着けません・・・

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

nSizeの値はちゃんと入ってますか? GlobalSize()で取れるのかなぁ? 不精しないでsizeof(BITMAPINFOHEADER) + ビット列のバイト長にしないといけないのでは? #変数名を大文字だけで書くのはやめたほうが。 非常に見づらいです。 特にBMPINFOHEADERがポインタなのに・・・

mkmarimo
質問者

補足

ご回答ありがとうございます. nSizeには値は入ってました. 640×480の画像でnSize = 921640でした. これは多分あってますよね…?? デバッグしてみると,どうやらhDIBがBITMAPINFOHEADERの先頭を指してないみたいなのですが, 原因はそれですよねぇ… hDIBがいったいなにを指しているのかわかりません. LoadTIFFinDIB()が返すものは何なのでしょう…?? 分かる方ご教授ください. >#変数名を大文字だけで書くのはやめたほうが。 >非常に見づらいです。 >特にBMPINFOHEADERがポインタなのに・・・ 気をつけます.

関連するQ&A