- ベストアンサー
BMPファイルの輝度を配列で表す
- C++でBMPファイルの輝度を配列で表す方法を教えてください
- BMPファイルの画像を読み込み、RGB値から輝度を求めて配列に格納し、テキストファイルに書き込む方法を教えてください
- Win32プラットフォームで、BMPファイル(480×640)の輝度を配列で表す方法を教えてください
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
最初に書いたように、示された条件に限定すれば問題無いはずです。 となれば ・条件が間違っている 「24bitBGR無圧縮」「幅640x高さ480」「BMPファイル」のどれかが実際と違う 画像閲覧ソフトには、その画像の詳細なデータを調べられるものがります。それで条件が間違ってないか確認してみましょう。 ・テキストの確認方法が間違っている 1行に (1~3桁(0~255)+カンマ1桁) x 640 = 1280~2560桁です。 使用したテキストエディタやビューアによっては、途中までしか表示できなかったり、折り返して次の行になっていたりする可能性があります。 特に、最初の内は0が多いので桁数も少ないですが、円の中心に近付けば255が多くなって桁が増えます。 確実に表示できるソフトを使う、とか、csvとしてExcel(2007以降でないと列が足りない)やOpenOfficeで開いてみるとかしてはどうでしょう。
その他の回答 (5)
- Tacosan
- ベストアンサー率23% (3656/15482)
手元で 640×480 の bmp ファイルを作って試した限りでは, 想定した通りに動作します. 「画像のサイズに間違いはない」というのはどのように確かめたのでしょうか?
お礼
画像のプロパティから画像のサイズを見ました。 また、皆さんのご指摘の通りCSVファイルで書き込み、エクセル2007で開いたら問題なく動いていました。お手数かけてすみませんでした。勉強になりました。 ありがとうございました。
- yama5140
- ベストアンサー率54% (136/250)
#3 です >ここが原因でずれていってしまうのでしょうか? >>どうして、「ずれる」と判ったのでしょうか。 640×10桁として、1行6400文字となりますが、「ずれる」と判った?テキストエディタ?の「折り返し」設定は大丈夫でしょうか。 私のソースのように、1行の文字数を少なくして試されることをお勧めします。 >ご掲示して頂いたソースコードは書き込みがバイナリになってますが、テキストを開いたら文字化けしていませんか? すみません、ミスりました。正 "w" ← 誤 "wb" しかし、fwrite() でなく、fprintf() ですので、文字化けはしません。 試していただければ確認できます。 #2お礼>本プログラムは%dで計算しています。 y = (int)( 0.5 + 0.298912 * (double)R + 0.586611 * (double)G + 0.114478 * (double)B ); fprintf( fpy, "%3d,", y ); ということでしょうか。
お礼
>どうして、「ずれる」と判ったのでしょうか。 読み込んでる画像が黒地に白の円が中央にある画像なので、最初と最後が0でなければおかしいですよね?最初は0となっているんですが、最後が255となっていておかしなことになっているので、どこかでずれているのかと。 > y = (int)( 0.5 + 0.298912 * (double)R + 0.586611 * (double)G + 0.114478 * (double)B ); ということでしょうか。 y = (int)( 0.5 + 0.298912 * (int)R + 0.586611 * (int)G + 0.114478 * (int)B ); という計算です。
- yama5140
- ベストアンサー率54% (136/250)
>BMPファイル(480×640) 通常は、横480、縦640の記述ですよね、 for(h=0;h<480;h++){ for(l=0;l<640;l++){ これだと、横640、縦480のループかと思います。 下のURLの「画像データ」で、記録方式を確認して下さい。 >・・その画像の輝度を配列(480×640)でテキストファイルに書き込みたいのですが、途中から配列がずれてしまいます。 プログラムでは、配列は用いていませんが、どうして、「ずれる」と判ったのでしょうか。 >どなたかご教示お願いします。 「情報ヘッダ」を読み込み、その「横・縦」を用いればいいと思います。 http://www.kk.iij4u.or.jp/~kondo/bmp/ なお、↑の「画像データ」に、 「画像の横のラインのデータは,long (4 byte) の境界に揃えなければいけない」 とあるため、/* ◆ */の行(読み飛ばし)が必須となります。 (今回は、4の倍数なので、読み飛ばし動作無し) #include <stdio.h> #include <stdlib.h> #include <windows.h> int main( void ) { double y; // ++++++ int R, G, B, h, l; FILE *fpi, *fpy; BITMAPFILEHEADER BmpHead; BITMAPINFOHEADER BmpInfo; if( NULL == ( fpy = fopen( "Z:/test.txt", "wb" ) ) ){ fprintf( stderr, "output file open error\n" ); exit( 1 ); } if( NULL == ( fpi = fopen( "Z:/filename.bmp", "rb" ) ) ){ fprintf( stderr, "input file open error\n" ); exit( 1 ); } fread( &BmpHead, 1, sizeof( BITMAPFILEHEADER ), fpi ); fread( &BmpInfo, 1, sizeof( BITMAPINFOHEADER ), fpi ); fprintf( stderr, "BitCnt%5d\n", BmpInfo.biBitCount ); fprintf( stderr, "width %5d\n", BmpInfo.biWidth ); fprintf( stderr, "height%5d\n", BmpInfo.biHeight ); for( h = 0; h < BmpInfo.biHeight; h++ ){ for( l = 0; l < BmpInfo.biWidth; l++ ){ B = fgetc( fpi ); G = fgetc( fpi ); R = fgetc( fpi ); y = 0.298912 * R + 0.586611 * G + 0.114478 * B; fprintf( fpy, "%02X %02X %02X %f\n", B, G, R, y ); } /* ◆ */ for( l = 0; l < ( ( 4 - ( BmpInfo.biWidth % 4 ) ) % 4 ); l++ ) fgetc( fpi ); } fclose( fpy ); fclose( fpi ); return( 0 ); } 注:インデントに全角空白を用いています。コピペ後、タブに一括変換して下さい。
お礼
ご指摘の通り、サイズ表記が逆になっていました。正しくはBMPファイル(640×480)です。 また、 for(h=0;h<480;h++){ for(l=0;l<640;l++){ B = fgetc(fpi); G = fgetc(fpi); R = fgetc(fpi); y=0.298912*R+0.586611*G+0.114478*B;/*輝度の算出*/ fprintf(fpy,"%f,",y); } fprintf(fpy,"\n"); } のところでテキストには横640、縦480の形で配列されると思うのですが、ここが原因でずれていってしまうのでしょうか? また、ご掲示して頂いたソースコードは書き込みがバイナリになってますが、テキストを開いたら文字化けしていませんか?
- sygh
- ベストアンサー率76% (42/55)
多分 fprintf(fpy,"%f,",y); の箇所が間違い。 %f書式指定はfloat/doubleに対する書式で、可変個引数として渡された値はfloat/doubleと判断され、さらに内部でdouble(Win32だと64bit浮動小数点数)に格上げされて扱われるので、int型の変数y(Win32だと32bit符号付き整数)を渡すと異常な値が出力されるだけ。 C++が使えてなおかつ速度性能をあまり追求しないのならば、printf系のこういう弱点を避けて、極力ストリーム(std::ofstream)を使うことをお勧めします。
お礼
回答ありがとうございます。ご指摘の通り、こちらに載せているソースの%dを%fと書き間違えていました。すみません。本プログラムは%dで計算しています。
- kmee
- ベストアンサー率55% (1857/3366)
ヘッダを読んで画素の先頭へシーク、とやりかたは特に間違っていないと思いますが。 /* もっと正確には、BmpHead.bfTypeが正しいこと、BITMAPINFOHEADERの分も読み込んで24bitカラー圧縮無しで画素数とかが正しいことも確認した方がいいですが */ 画素データは幅方向に4バイト単位なるように、足りない分はダミーデータを入れることになっていますが、480x640なら3倍しても4の倍数なので、それは考えず連続で読むことができます。 BMPのY座標の並びは画面下が先に来ます。よくある画像データでの左上が(0,0)のものとは上下逆になります。 > BMPファイル(480×640) 念の為確認ですが、高さ480x幅640の横長でよろしいでしょうか? あと「ずれる」とはどんな状態のことを言っていますか?
お礼
御即答ありがとうございます。 画像の表記の仕方が逆になってました。すみません。ご指摘の通り幅640、高さ480です。 説明不足ですみません。「ずれる」というのは、実は扱ってる画像が黒の画像でして、中央に白の円が書かれ、の輝度の値を並べたら、0と255の値が縦480、横640で配列され、255が円を描くようになるはずです。しかし、その結果のテキストを見ると最初は0,0,0,0・・・255、255、・・・0,0,0,0ときれいに並んであるのですが、後半が0,0,0,0・・・0,0,0,0・・・255,255,255,255という風に最後の値が255になってしまいます。画像のサイズに間違いはないです。
お礼
ご指摘の通りcsvファイルとしてエクセル2007で開いたところ問題なく動いていました。 勉強になりました。ありがとうございました。