• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:BMPファイルの輝度を配列で表す)

BMPファイルの輝度を配列で表す

このQ&Aのポイント
  • C++でBMPファイルの輝度を配列で表す方法を教えてください
  • BMPファイルの画像を読み込み、RGB値から輝度を求めて配列に格納し、テキストファイルに書き込む方法を教えてください
  • Win32プラットフォームで、BMPファイル(480×640)の輝度を配列で表す方法を教えてください

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

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.6

最初に書いたように、示された条件に限定すれば問題無いはずです。 となれば ・条件が間違っている 「24bitBGR無圧縮」「幅640x高さ480」「BMPファイル」のどれかが実際と違う 画像閲覧ソフトには、その画像の詳細なデータを調べられるものがります。それで条件が間違ってないか確認してみましょう。 ・テキストの確認方法が間違っている 1行に (1~3桁(0~255)+カンマ1桁) x 640 = 1280~2560桁です。 使用したテキストエディタやビューアによっては、途中までしか表示できなかったり、折り返して次の行になっていたりする可能性があります。 特に、最初の内は0が多いので桁数も少ないですが、円の中心に近付けば255が多くなって桁が増えます。 確実に表示できるソフトを使う、とか、csvとしてExcel(2007以降でないと列が足りない)やOpenOfficeで開いてみるとかしてはどうでしょう。

evsy
質問者

お礼

ご指摘の通りcsvファイルとしてエクセル2007で開いたところ問題なく動いていました。 勉強になりました。ありがとうございました。

その他の回答 (5)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

手元で 640×480 の bmp ファイルを作って試した限りでは, 想定した通りに動作します. 「画像のサイズに間違いはない」というのはどのように確かめたのでしょうか?

evsy
質問者

お礼

画像のプロパティから画像のサイズを見ました。 また、皆さんのご指摘の通りCSVファイルで書き込み、エクセル2007で開いたら問題なく動いていました。お手数かけてすみませんでした。勉強になりました。 ありがとうございました。

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.4

#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 );  ということでしょうか。

evsy
質問者

お礼

>どうして、「ずれる」と判ったのでしょうか。 読み込んでる画像が黒地に白の円が中央にある画像なので、最初と最後が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)
回答No.3

>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 ); } 注:インデントに全角空白を用いています。コピペ後、タブに一括変換して下さい。

evsy
質問者

お礼

ご指摘の通り、サイズ表記が逆になっていました。正しくは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)
回答No.2

多分 fprintf(fpy,"%f,",y); の箇所が間違い。 %f書式指定はfloat/doubleに対する書式で、可変個引数として渡された値はfloat/doubleと判断され、さらに内部でdouble(Win32だと64bit浮動小数点数)に格上げされて扱われるので、int型の変数y(Win32だと32bit符号付き整数)を渡すと異常な値が出力されるだけ。 C++が使えてなおかつ速度性能をあまり追求しないのならば、printf系のこういう弱点を避けて、極力ストリーム(std::ofstream)を使うことをお勧めします。

evsy
質問者

お礼

回答ありがとうございます。ご指摘の通り、こちらに載せているソースの%dを%fと書き間違えていました。すみません。本プログラムは%dで計算しています。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

ヘッダを読んで画素の先頭へシーク、とやりかたは特に間違っていないと思いますが。 /* もっと正確には、BmpHead.bfTypeが正しいこと、BITMAPINFOHEADERの分も読み込んで24bitカラー圧縮無しで画素数とかが正しいことも確認した方がいいですが */ 画素データは幅方向に4バイト単位なるように、足りない分はダミーデータを入れることになっていますが、480x640なら3倍しても4の倍数なので、それは考えず連続で読むことができます。 BMPのY座標の並びは画面下が先に来ます。よくある画像データでの左上が(0,0)のものとは上下逆になります。 > BMPファイル(480×640) 念の為確認ですが、高さ480x幅640の横長でよろしいでしょうか? あと「ずれる」とはどんな状態のことを言っていますか?

evsy
質問者

お礼

御即答ありがとうございます。 画像の表記の仕方が逆になってました。すみません。ご指摘の通り幅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になってしまいます。画像のサイズに間違いはないです。

関連するQ&A

専門家に質問してみよう