• ベストアンサー

より高速な画像の表示法

医療画像(DICOM)のバイナリデータを読み込んで表示させるプログラムを作っているのですが、非常に遅い(約4秒)ので改善したいのです。 おそらく、ループ中での、エンディアンの変換とPixelへの張付けが原因と思うのですが、改善方法が判りません。宜しくお願いします。 BolandC++Builder6,Pentiam4,1Gメモリ,XPの環境です。 DICOMO画像のファイルサイズは約2053kB 画像データは1024*1024の16ビットです。 __________________________________ Byte bb[2097152]; int iImage[512][512]; word c,wData; fp=fopen("filename","rb"); setvbuf(fp,NULL,_IOFBF,4096*1024*1024); while(gData!=0xE07F) //グループタグの検索// fread(& gData,2,1,fp); while(eData!=0x1000) //エレメントタグの検索// freadd(& eData,2,1,fp); fread(&wData,2,4,fp); //空読み// fread(bb,1,2097152,fp); //画像データ// fclose(fp); for(y=0;y<=512;y++){ for(x=0;x<=512;x++){ wData=256*bb[4*x+4096*y]+bb[4*x+4096*y+1]; c=wData*256/4096; iImage[x][y]=c; Image->Canvas->Pixels[x][y]=(TColor)((c<<16)|(c<<8)|c); c=0; } }

  • t0103
  • お礼率65% (17/26)

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

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.8

原因は幾つか推測できるだろうと思います。 が、ここでやるべきは闇雲にここが怪しいからいじってみよう という場当たり的な対処ではなく、 きちんとプロファイリングをして、どこがホットスポットなのかを 見極めることだと思います。 もっともC++ Builderだとまともに使えるプロファイラがあるのかどうか わかりません(無責任ですみません)。 少なくとも無料で使えるものはないかも知れません。

t0103
質問者

お礼

その後、ダブルバッファの様な処理をさせたところ、0.4sと約7倍速くなりました。貴重なご意見ありがとうございました。

t0103
質問者

補足

遅くなりましたがご意見を参考にしてclockで処理時間を計測しました default 3.00s 配列を[y][x] 2.47s #16#17 2.49s Canvas->Pixel[x][y]を外し、新たな配列に入れた場合 0.062s となりました。 Canvas->Pixel[x][y]の処理が遅い原因のようですが、ループ内ではBitmapの画素値の計算だけにして、ループ外でBItmapの配列を直接imageに貼付ける処理を試してようと思いますが、方法が判りません。 

その他の回答 (17)

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.18

┌色々検索していたら,面白いものを見つけました. │DICOM ファイルフォーマットのわかりやすい説明があります. ↓ DR研究会誌 pp.189~222 よくわかるDICOM画像の取得方法 ‐自作プログラムによる方法‐ http://www.kit.hi-ho.ne.jp/dr-study-group/naiyou/105.pdf これを読んで,いくつか疑問点が出てきました. (1) #5,#14 のお礼欄に「うまくいかない」と書かれていますが,   どう「うまくいかない」んでしょうか?   ・画像の形はそれらしいが,階調がおかしい.   ・似ても似つかない画像が表示される. (2) ご質問は高速化方法となっていますが,元のプログラムでは   ちゃんと画像が表示されていたのでしょうか?   #14 のお礼欄に「表示だけなら … OK」とありますが,   これは画像ファイルを読んで表示させたということでしょうか? (3) #14 のお礼欄に「リトルエンディアンのはず」とあるので,   ファイルのフォーマットはおそらく "Implicit VR Little Endian"   とやらになるのだと思いますが,その場合グループタグや   エレメントタグもリトルエンディアンなのでしょうか?   もしそうだとしたら,グループタグとエレメントタグの検索部分   には間違いがあります.グループタグは PIXEL_GROUP=0x7FE0,   エレメントタグは PIXEL_DATA_ELEMENT=0x0010 となっているので,   これをそのまま (エンディアン反転させずに) 検索すべきです.   つまり 0xE07F → 0x7FE0,0x1000 → 0x0010 に訂正が必要.   (#9 のお礼欄の URL の Fig.8 参照.) (4) 上記 URL (DR研究会誌の方) の204~205ページによると,   Implicit VR のヘッダは,次の4つの繰り返しだそうです.   (a) Group Tag (2バイト)   (b) Element Tag (2バイト)   (c) Value Length (4バイト)   (d) Data (Value Length バイト)   ところで,ご質問のプログラムでは,エレメントヘッダを読んだ   直後に8バイトの空読みをしています.wData が2バイトなのに   8バイト読み込んでいるのでアクセス違反になるという問題も   ありますが,それは置いといて….   Implicit VR の Value Length は4バイトですが,8バイト読んで   いるのは単なる4バイトの間違い? それとも8バイトが正しいと   すると,Explicit VR フォーマットの "OB,OW,SQ,US の場合"   というのに相当しているんでしょうか? (5) 画像データより前の Data 部にバイナリデータが入ることは   ないんでしょうか? もしあるとすると,その中にたまたま   グループタグやエレメントタグと同じ2バイトがあった場合に   「偽物」をつかまされてしまいます. (6) Value Length の値は奇数になることはないんでしょうか?   グループタグとエレメントタグの検索は2バイト単位で読んで   いるので,奇数バイトの Data があると検索に失敗する可能性   があります. 画像ファイル内にある,画像データの本体の開始位置前後数十バイト の16進ダンプを見せていただけると,色々わかるかもしれません.

t0103
質問者

お礼

お世話になっております。 私の勘違いが判りました。各装置のデータはリトルエンディアンなのですが、画像サーバがビックエンディアンに変換してました。 (1)(3)(4)上記理由によりお騒がせいたしました。 ちなみに画像データ前の16進並びは E0 7F 10 00 57(W) 4F(O) 00 00 20 00 00 00 画像が22 00 20 00............です。 (2)正常に表示できました。 (5)(6)そういう場合もあるかもしれませんが、CT,MRI,透視,カラー画像のDICOM変換の4つでは2byte区切りです。これらの画像に対応できれば当面は問題ありません。

t0103
質問者

補足

お礼の書き込み訂正します。Wordで持ってきて E07F,1000,574F,0000,2000,0000,......................です。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.17

★あぁ、済みませんでした。 ・訂正前⇒Word (*lpBuff)[ 1024 ] = (Word*)bb; ←これを宣言  訂正後⇒Word (*lpBuff)[ 1024 ] = (Word(*)[1024])bb; ←これを宣言  でした。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.16

★回答者 No.1 です。 ・補足要求、有り難うございます。  ようやく質問ソースを把握できましたので、繰り返し部分を中心にサンプルを載せます。 サンプル: int iImage[ 512 ][ 512 ]; Byte bb[ 2 * 1024 * 1024 ]; Word (*lpBuff)[ 1024 ] = (Word*)bb; ←これを宣言 Word wData; if ( (fp = fopen("filename","rb")) != NULL ){  /*  画像データを読み込む  */  fclose( fp ); } for ( y = 0 ; y < 512 ; y++ ){  for ( x = 0 ; x < 512 ; x++ ){   wData = lpBuff[ y * 2 ][ x * 2 ] >> 4; ←2ピクセル毎に12Bit→8Bit(4096→256階調)   iImage[ x ][ y ] = wData;   Image->Canvas->Pixels[ x ][ y ] = (TColor)(wData * 0x010101); ←グレイスケール変換  } } 最後に: ・本当は iImage[x][y] は iImage[y][x] にすべきです。  一般に C 言語で2次元配列は横方向を次元の低い方で表し、縦方向を高い次元で表します。  多分、もうすべてを [x][y] と操作するように設計していると思うので今度、プログラムを  行うときには気をつけて下さい。本当は [y][x] 操作に直すべきだと思っていますが…。 ・以上。一通り動作するか、確認をお願いします。

t0103
質問者

お礼

Word (*lpBuff)[ 1024 ] = (Word*)bb; ←これを宣言 の部分で以下のエラーがでました。 [C++ エラー] E2034 'unsigned short *' 型は 'unsigned short ( *)[1024]' 型に変換できない

  • don_go
  • ベストアンサー率31% (336/1059)
回答No.15

>もし「1画素16ビットの1024×1024を、間引きして、 >8ビット256階調の512×512にする」んで正しければ、 >以下のようになる。 間引処理     wData=*p++;      ↓     wData=*p;     p+=2;

  • don_go
  • ベストアンサー率31% (336/1059)
回答No.14

Intel系のCPUを使用していて、画像データが16bitの数値なら 下位8bit, 上位8bitの順に格納されるので、 wData=256*bb[n]+bb[n+1];ではなく wData=bb[n]+256*bb[n+1];となるのですが? また bb[4*x+4096*y]、bb[4*x+4096*y+1]としている所からすると 4バイト毎に頭2byteを取得するという事でしょうか? 4×8bit=32bit ≠ 16bit(?) Intel系のCPUで画像データが2byte(16bit)の場合であれば 下記の様なコーディングも可能です。 short *p, c, wData; p=(short *)bb; for(y=0;y<512;y++){   for(x=0;x<512;x++){     wData=*p++;     c=wData/16; // 256/4096 => 1/16     iImage[y][x]=c; //?? [x][y]     Image->Canvas->Pixels[y][x]=(TColor)((c<<16)|(c<<8)|c);//??     c=0;   } }

t0103
質問者

お礼

回答ありがとうございます。 ご指摘の通り、リトルエンディアンのはずなのですが、それだとうまくいかないのです。どこか2重に処理しつじつまが合っているのでしょうか?表示だけならCT装置と透視装置のDICOMデータで確認してOKなのです。 bb[4*x+4096*y]以下は元画像サイズ1024*1024を512*512にリサイズしています。

noname#39970
noname#39970
回答No.13

>(2)『c = wData * 256 / 4096;』の部分は下位バイトの上位4ビットを >  取り出して c に4ビットを代入するのですか。→c = ((wData << 8) >> 12); と考えた。 No9の考え通りに下位バイトの上位4bitを出すなら良く考えたらこうかも c= (bb[4*x+4096*y]>>4) & 0xf; ---------------以下ただのメモ wData=256*bb[4*x+4096*y]+bb[4*x+4096*y+1]; c=wData*256/4096; ↓ c = (256*bb[4*x+4096*y]+bb[4*x+4096*y+1]) *256/4096; c = (256*bb[4*x+4096*y] + bb[4*x+4096*y+1]) /16; c = 16*bb[4*x+4096*y] + bb[4*x+4096*y+1]/16 あれ?合わないぞ?(゜∀。)

t0103
質問者

お礼

私の質問に付き合っていただきましてありがとうございます。 *256/4096の部分はデータの数値0から4096をRGB256階調に変換している部分です。 手元の本でRGBは256階調でとあったので。

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.12

#3 です. 可能ならば,iImage[x][y] のxとyを入れ替えて iImage[y][x] のように した方が,いくらか速くなる可能性はあると思います. なぜならば,ご質問のプログラムの二重ループ部分がアクセスしている順番 どおりに iImage[][] の要素がメモリ上に並ぶことになり,キャッシュの効きが 良くなると考えられるからです.(bb[] の方は既にそうなっています.) 現在のままでは iImage[][] のあるメモリ領域はランダムアクセスされているので, キャッシュはあまり効いていない (むしろキャッシュライン単位で読み書きするので 逆効果になっている) のではないかと思われます. もっとも,iImage[][] のxとyを入れ替える場合には,#10 のコードも改造が必要です. (もっと簡単になります.)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.11

★回答者 No.1、No.9 です。 ・繰り返し文の最適化は、他の回答者さんのを参考にして下さい。  私はヘッダ部についてアドバイスします。  そう思いましたが質問のソースから考えると gData=0xE07F、eData=0x1000 が常に  入ってしまいませんか? ・検索となっていますが、fp で続けて fread() 関数で読み込んでいますよね。  検索後にデータを読み飛ばしているようでもないので、ここの部分が良く理解できません。  アドバイスするにあたり、医療画像(DICOM)のバイナリデータの詳細を教えてくれませんか?  また補足要求です。何度もすみません。

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.10

#3 です. #5 さんのコードを元に,iImage[x][y] の2次元アクセスをしないようにしたバージョンです. でも,どれほど効果があるかはわかりません.やはり実行時間を測定しないと…. (Image->Canvas->Pixels[x][y] の2次元アクセスは残したままだし.)  const Byte *src = bb;  int *destLine = &iImage[0][0]; // iImage の走査線の左端 iImage[0][y] を指す.  int *dest;  int x, y;  for(y = 0; y < 512; y++) {   dest = destLine; // == &iImage[0][y]   for(x = 0; x < 512; x++) {    wData = (src[0] << 8) | src[1]; #if 1    // こっちでいいのかな?    c = wData >> 4; #else /* 0/1 */    // ダメなら元のまま.    c = wData * 256 / 4096; #endif /* 0/1 */    *dest = c;    Image->Canvas->Pixels[x][y] = (TColor)(c * 0x010101);    src += 4;     // 1画素読み飛ばす.    dest += 512;   // == &iImage[x + 1][y]   }   src += 2048;    // 1行読み飛ばす.   destLine++;     // == &iImage[0][y + 1]  } > (fread() についても.)はどういう意味でしょうか? fread(),fopen() などはディスク I/O を行うので,途中でエラーが起きる 可能性もあります.それにファイルが壊れていたり,間違ったファイルを 指定したりすると,途中で読み込むべきデータがなくなることもあります. 例えばご質問のプログラムでは,ファイル内にグループタグかエレメントタグの どちらかがない場合,無限ループします.

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.9

★回答者 No.1 です。幾つかお尋ねします。 ・いろいろとソースを解読して不明な点、気になった点が出てきたので。  (1)for 文の x <= 512、y <= 512 は x < 512、y < 512 ですよね?  (2)『c = wData * 256 / 4096;』の部分は下位バイトの上位4ビットを   取り出して c に4ビットを代入するのですか。→c = ((wData << 8) >> 12); と考えた。  (3)1ピクセルは 8 バイトで記録されているのですか?  (4)画像フォーマットの DICOM を描画するとき、モノクロのグレースケールですか?  (5)bb[] 配列の画像データの構造をもう少し解説してくれませんか?お願いします。  以上。補足要求します。→やはりループ内を最適化すべきですね。

t0103
質問者

お礼

回答ありがとうございます。 1)失礼しました。x<512 or x<=511 2)最小値0最大値4096を256階調でという意味です。 3)2Byte/pixelですDICOMのBitAllocateは16bit 4)その通りです。 5)http://www.nv-med.com/jsrt/pdf/2001/57_11/1316.pdf を参照してください。

関連するQ&A

  • 画像処理について・・・・・・・・・・・

    #include<stdio.h> #include<stdlib.h> #define X_SIZE 512 #define Y_SIZE 512 unsigned char DATA[Y_SIZE][X_SIZE]; unsigned char O_DATA[Y_SIZE][X_SIZE]; char input_file_name[256]=”Lenna.raw”; char output_file_name[256]=”Lenna_out.raw”; void heikin(){ int x,u; int temp; for(y=1;y<Y_SIZE-1;y++){ for(x=1;x<X_SIZE-1;x++){ temp=・・・・・・・・・・・・・・・・・・・・・・・・; O_DATA[x][y]=(unsigned char)temp; } } } Int main (){ FILE*fp; If((fp=fopen(input_file_name,”rb”))==NULL){ Printf(“ファイルオ-プンエラ-\n”); Return 1; } Fread(DATA,sizeof(DATA),1,fp); fclose(fp); heikin(); if((fp=fopen(output_file_name,”wb”))==NULL{ printf(“ファイルオ-プンエラ-\n”); return 1; } Fwrite(O_DATA,sizeof(O_DATA),1,fp); Fclose(fp); Return 0; } ソースコードをやっているのですが、後、・・・・・・・・・の所を入力して完成なんですが、苦戦してます。 処理の内容としましては、 1、入力画像Lenna.rawを読み込んで、 2、平均値フィルタをかけ、 3、Lenna_out.rawに書き出す(保存する)したいんですが、公式みたいなのを入れればいいのでしょうか? すみませんが、お願いします。

  • 行毎の黒のドット(ピクセル)数を教えていただけませんか?

    開発環境Microsoft Visual Studio .NET 2003 2値画像を読み込んだ時、各行毎の黒のピクセル(ドット)数を表示する プログラムを組もうとしているのですがわかりません。 画像読み込みまではできたのですがその後のプログラムがわかりません 誰か組んでいただけないでしょうか? #include <stdio.h> #include <process.h> #define Y_SIZE 3648 // 処理できる最大画像 #define X_SIZE 3648 #define HIGH 255 // 画像の最大強度値 #define LOW 0 // 画像の最小強度値 #define LEVEL 256 // 画像の強度レベル値 // BMPファイルのフォーマットに従って用意した変数 typedef unsigned short WORD; typedef unsigned long DWORD; WORD bfType; DWORD bfSize; WORD bfReserved1, bfReserved2; DWORD bfOffBits; DWORD biSize, biWidth, biHeight; WORD biPlanes, biBitCount; DWORD biCompression, biSizeImage, biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant; unsigned char image_in[Y_SIZE][X_SIZE][3]; // 入力カラー画像配列 unsigned char image_out[Y_SIZE][X_SIZE][3]; //出力カラー画像配列 unsigned char image_bw[Y_SIZE][X_SIZE]; //濃淡画像配列 unsigned char data_rgb[Y_SIZE][X_SIZE][3]; // RGB画像配列 //******************************************** // 24Bitビットマップファイル読み込み * //******************************************** void readBMP( char *filename, // BMPファイル名 unsigned char image[Y_SIZE][X_SIZE][3] // 24ビットRGB画像配列 ) { FILE *fp; int i, j, k; // ファイルオープン if ((fp = fopen(filename, "rb"))==NULL) { printf("readBmp: Open error!\n"); exit(1); } printf("input file : %s\n", filename); // ヘッダー情報読み込む fread(&bfType, sizeof(bfType), 1, fp); fread(&bfSize, sizeof(bfSize), 1, fp); fread(&bfReserved1, sizeof(bfReserved1), 1, fp); fread(&bfReserved2, sizeof(bfReserved2), 1, fp); fread(&bfOffBits, sizeof(bfOffBits), 1, fp); fread(&biSize, sizeof(biSize), 1, fp); fread(&biWidth, sizeof(biWidth), 1, fp); fread(&biHeight, sizeof(biHeight), 1, fp); fread(&biPlanes, sizeof(biPlanes), 1, fp); fread(&biBitCount, sizeof(biBitCount), 1, fp); fread(&biCompression, sizeof(biCompression), 1, fp); fread(&biSizeImage, sizeof(biSizeImage), 1, fp); fread(&biXPelsPerMeter, sizeof(biXPelsPerMeter), 1, fp); fread(&biYPelsPerMeter, sizeof(biYPelsPerMeter), 1, fp); fread(&biClrUsed, sizeof(biClrUsed), 1, fp); fread(&biClrImportant, sizeof(biClrImportant), 1, fp); // RGB画像データ読み込む for (i=0; i<(int)biHeight; i++) for (j=0; j<(int)biWidth; j++) { for (k=0; k<3; k++) { //fread(&image[i][j][2-k], 1, 1, fp); fread(&image[biHeight-i][j][2-k], 1, 1, fp); } } fclose(fp); } //********************************************** // RGBカラー画像を256諧調白黒濃淡画像へ変換 * //********************************************** void BMPto256BW( unsigned char image[Y_SIZE][X_SIZE][3], unsigned char image_bw[Y_SIZE][X_SIZE] ) { int y, x, a; for (y=0; y<(int)biHeight; y++) for (x=0; x<(int)biWidth; x++) { a = (int)(0.3*image[y][x][0] + 0.59*image[y][x][1] + 0.11*image[y][x][2]); if (a<LOW) a = LOW; if (a>HIGH) a = HIGH; image_bw[y][x] = a; } } //***************************************** //各行の黒色判定 //***************************************** //**************************************** // 白黒濃淡画像配列のコピー * //**************************************** void imageCopyBW( unsigned char image1[Y_SIZE][X_SIZE], unsigned char image2[Y_SIZE][X_SIZE] ) { int x, y; for (y=0; y<(int)biHeight; y++) for (x=0; x<(int)biWidth; x++) image2[y][x] = image1[y][x]; } void main(void) { char input[100], output[100]; int intensity; printf("入力画像ファイル名(*.bmp):"); scanf("%s", input); readBMP(input, image_in); // 画像の入力,RGB24ビットカラーBMP画像を配列に格納 //一列各行の黒色の数出力 }

  • ビットマップ画像を読み込むプログラムがうまく行きません。困ってます…。

    こんにちは。大学4年のyu-tinと申します。 現在、大学の研究で使用するためのプログラムとして、以下の機能を持ったプログラム作りに取り込んでいます。 1)ビットマップ画像(グレースケール、縦480×横640pixel)を読み込み、  その画像の1つ1つの画素の輝度値を表示させる 2)読み込んだビットマップ画像を出力させる しかし、作成したプログラムがうまく行きません。以下の3つの問題が発生しています。 a)0行0列~1行383列までの画素値がおかしい。  (0,0,0,0,1,1,1,0,2,2,2,0,3,3,3,0,…,254,0,255,255,255,0 となっている) b)出力した画像の最上部2行程度に、細くて黒い線が表示される。  (読み込んだ画像と全く同じ画像を出力させたい) c)出力した画像が、”ディスクエラー”によりPhotoshopで開けない。  (ペイントでは開ける) その問題のプログラムは、以下の通りです。 しかし、このプログラムは、他人のプログラムに改良を加えて作成したものです。なので、このプログラム自体、私自身が完璧に理解できていない状況です。 私は、プログラミングに関しては初心者に近いので、丁寧に教えて頂けると大変助かります。 研究が先に進まず、大変困っています…。みなさま、本当に、本当によろしくお願い致します。 //ビットマップ画像に関するプログラム。 //画像の表示と輝度値の表示を行う。 #include<stdio.h> #include<windows.h> #include<stdlib.h> #define X_SIZE 640  //画像の横幅(ピクセル数) #define Y_SIZE 480  //画像の縦幅(ピクセル数) #define Z_SIZE 1    //1つの画素に含まれる色の数 void *malloc(size_t size); void main(void) {  int i, j, k;   //ループ用変数 i…縦の画素用, j…横の画素用, k…色数用  int x=0;    //画像の横幅(ピクセル数)*/  int y=0;     //画像の縦幅(ピクセル数)  FILE *fp; /***********元画像データのメモリ確保*********/  BYTE ***mae;  mae=(BYTE ***)malloc(sizeof(BYTE **)*Y_SIZE);  for(i = 0; i < Y_SIZE; i++){   mae[i]=(BYTE **)malloc(sizeof(BYTE *)*X_SIZE);  }  for(i = 0; i < Y_SIZE; i++){   for(j = 0; j < X_SIZE; j++){    mae[i][j]=(BYTE *)malloc(sizeof(BYTE)*Z_SIZE);   }  } /*******画像の読み込み・輝度値の表示*******/  fp=fopen("sample1.bmp","rb");   //画像”sample1”を開く  BITMAPFILEHEADER bmfh;  BITMAPINFOHEADER bmih;  fread(&bmfh,sizeof(bmfh),1,fp);  fread(&bmih,sizeof(bmih),1,fp);  x=bmih.biWidth;  //インフォヘッダに含まれる画像の幅情報をxに代入  y=bmih.biHeight;  //インフォヘッダに含まれる画像の高さ情報をyに代入  for(i = 0; i < y ;i++){   for(j = 0; j < x; j++){    fread(&mae[i][j][0],sizeof(BYTE),1,fp);    if(i<640 && j<480)printf("%d, %d, %d\n",i, j, mae[i][j][0]);   //輝度値を表示   }  }  fclose(fp); /**************画像の表示*************/  //画像”sample1”を”sample2”という名前で出力する  fp = fopen("sample2.bmp" ,"wb");  //ヘッダの書き込み  fwrite(&bmfh,sizeof(bmfh),1,fp);  fwrite(&bmih,sizeof(bmih),1,fp);  for(i = 0; i < bmih.biHeight; i++){   for(j = 0; j < bmih.biWidth; j++){    fwrite(&mae[i][j][0],sizeof(BYTE),1,fp);   }  }  fclose(fp);  //ファイルをクローズ }

  • fread()エラー

    お世話になります。 今、バイナリファイルを操作しているのですが、 fread()でエラーになってしまいます。 char buf1[256]; FILE *fp; vector<string> f1; int num; fp = fopen("hoge.txt","r"); while( fgets( buf1, sizeof(buf1),fp ){ f1.push_back( buf1 ); num ++; } fclose(fp); FILE *cfp; unsigned char data[1024]; for(int i=0; i<num; i++ ){ cfp = fopen(f1[i].c_str(), "rb"); fread( data, sizeof(char), 1024, cfp ); } hoge.txtには、コンテンツ場所(パス)が複数記載されており、 その1つずつをfread()で読み込み解析したいのですが、 fread()でセグメンテーション違反になります。 f1の中味をprintf("%s",f1[0].c_str()); で見てみると正常にコンテンツの場所が格納されています。 また、 string pp = "/home/hoge/hoge.txt"; cfp = fopen(pp.c_str(), "rb"); fread(bb,sizeof(char),1024,cfp); とすると正常に動作します。 どうぞよろしくお願い致します。

  • c言語による画像処理について

    いつもお世話になってます。 c言語を使った画像処理を学び始めました。 入力画像の白(RGB値255,255,255)以外の画像を黒(RGB値0,0,0) に変換するプログラムを作成したいと思っているのですが、 入力画像の大きさによっては正常に命令を実行してくれないことがあるので、 改善点をご教示いただきたいと考え投稿させていただきました。ソースプログラムは #include<stdio.h> #define nx 100 //画像の幅 #define ny 100 //画像の高さ int main(void) { FILE *fp,*fp2; int i,j; unsigned char header[54]; unsigned char screen[nx][ny][3]; /* ファイルから読む */ fp=fopen("input.bmp","rb"); //ビットマップ形式 ,24ビットカラー fread(header,1,54,fp); // ヘッダ(54バイト)を飛ばす */ fread(screen,1,nx*ny*3,fp); // 残りはデータ(最下行から順に入る) //(255,255,255)以外なら黒(0,0,0)に for(j=0;j<ny;j++) for(i=0;i<nx;i++) if(screen[j][i][0]!=255||screen[j][i][1]!=255||screen[j][i][2]!=255){ screen[j][i][0]=0; screen[j][i][1]=0; screen[j][i][2]=0; } fclose(fp); /* ファイルに書く */ fp=fopen("output.bmp","wb"); fwrite(header,1,54,fp); /* ヘッダ */ fwrite(screen,1,nx*ny*3,fp); /* データ */ fclose(fp); return 0; } となっています。ここで、画像の高さ、幅を100以下にすると正常に変換できなくなります。 どなたか原因がお分かりでしたらお知らせ願えないでしょうか?

  • 平均値フィルタについて・・・・・・・・

    #include<stdio.h> #include<stdlib.h> #define X_SIZE 512 #define Y_SIZE 512 unsigned char DATA[Y_SIZE][X_SIZE]; unsigned char O_DATA[Y_SIZE][X_SIZE]; char input_file_name[256]=”Lenna.raw”; char output_file_name[256]=”Lenna_out.raw”; void heikin(){ int x,u; int temp; for(y=1;y<Y_SIZE-1;y++){ for(x=1;x<X_SIZE-1;x++){ temp=・・・・・・・・・・・・・・・・・ ; O_DATA[x][y]=(unsigned char)temp; } } } Int main (){ FILE*fp; If((fp=fopen(input_file_name,”rb”))==NULL){ Printf(“ファイルオ-プンエラ-\n”); Return 1; } Fread(DATA,sizeof(DATA),1,fp); fclose(fp); heikin(); if((fp=fopen(output_file_name,”wb”))==NULL{ printf(“ファイルオ-プンエラ-\n”); return 1; } Fwrite(O_DATA,sizeof(O_DATA),1,fp); Fclose(fp); Return 0; } 自分でプログラムを作って練習しているのですが、このソースコードで入力画像を読み込んで、平均値フィルタをかけ、Lenna_out.rawに書き出そうとしているのですが、・・・・・・の箇所には公式を当てはめていけばいいんでしょうか?? すみませんがよろしくお願いします。。。。。。

  • C言語でクロマキー合成をする方法

    input.bmpとbackground.bmpとoutput.bmpを作りで好きな絵を用意して、input.bmpというビットマップファイル(色数は24ビット)とbackground.bmpというファイルを開き,クロマキー合成をし,ビットマップファイルoutput.bmpに出力させる。 上記の物をC言語でするにはどうすればいいのでしょうか? 下記のものは自分でやったのですがやり方が分かりません。どなたか知恵を貸してください。 (ほとんど間違っていると思いますが・・・) #include<stdio.h> int main() { FILE *fp; int i; char data[2]; short s; fp1=fopen("input.bmp","rb"); fp2=fopen("background.bmp","rb"); fp3=fopen("output.bmp","wb") int k; for(k=0;k<10000;k++){ fputc(0,fp); fputc(0,fp); fputc(0,fp); } fclose(fp); fread(&data[0],1,2,fp1); fread(&data[0],1,2,fp2); fwrite(&data[0],1,2,fp3); int fs; fread(&fs,f1); fread(&fs,f2); fwrite(&fs,f3); fp=fopen("aka.bmp","wb"); fread(moji,1,2,fp); i=30054; fread(&i,4,1,fp); i=0; fread(&i,4,1,fp); i=54; fread(&i,4,1,fp); i=40; fread(&i,4,1,fp); i=100; fread(&i,4,1,fp); i=100; fread(&i,4,1,fp); s=1; fread(&s,2,1,fp); s=24; fread(&s,2,1,fp); i=0; fread(&i,4,1,fp); i=30000; fread(&i,4,1,fp); i=120; fread(&i,4,1,fp); i=120; fread(&i,4,1,fp); i=0; fread(&i,4,1,fp); i=0; fread(&i,4,1,fp); for(k=0;k<10000;k++){ fputc(0,fp); fputc(0,fp); fputc(70,fp); } fclose(fp); fp=fopen("midori.bmp","wb"); fread(moji,1,2,fp); i=30054; fread(&i,4,1,fp); i=0; fread(&i,4,1,fp); i=54; fread(&i,4,1,fp); i=40; fread(&i,4,1,fp); i=100; fread(&i,4,1,fp); i=100; fread(&i,4,1,fp); s=1; fread(&s,2,1,fp); s=24; fread(&s,2,1,fp); i=0; fread(&i,4,1,fp); i=30000; fread(&i,4,1,fp); i=120; fread(&i,4,1,fp); i=120; fread(&i,4,1,fp); i=0; fread(&i,4,1,fp); i=0; fread(&i,4,1,fp); for(k=0;k<10000;k++){ fputc(0,fp); fputc(150,fp); fputc(0,fp); } fclose(fp); fp=fopen("ao.bmp","wb"); fread(moji,1,2,fp); i=30054; fread(&i,4,1,fp); i=0; fread(&i,4,1,fp); i=54; fread(&i,4,1,fp); i=40; fread(&i,4,1,fp); i=100; fread(&i,4,1,fp); i=100; fread(&i,4,1,fp); s=1; fread(&s,2,1,fp); s=24; fread(&s,2,1,fp); i=0; fread(&i,4,1,fp); i=30000; fread(&i,4,1,fp); i=120; fread(&i,4,1,fp); i=120; fread(&i,4,1,fp); i=0; fread(&i,4,1,fp); i=0; fread(&i,4,1,fp); for(k=0;k<10000;k++){ fputc(255,fp); fputc(0,fp); fputc(0,fp); } fclose(fp); return(0); }

  • 2次元配列への代入

    入力画像ファイルの画素を取り込むところで input[x][y] = c(画素) を代入しているのですが、printfで結果を出力すると全て0になってしまい代入されません。なぜか教えてください #define X_wid 512 #define Y_wid 512 main(int argc,char *argv[]) { int x=0,y=0,X=0,Y=0,c; long input[X_wid+1][Y_wid+1],Input1[(X_wid)*(Y_wid)+1]; FILE *fp,*fp_w; if((fp = fopen(argv[1],"r")) != NULL){ while((c = getc(fp)) != EOF){ input[x][y] = c; Input1[x] = c; if(y==Y_wid){ y=0; x++; } else y++; printf("%d %d %d %d\n",x,y,input[x][y],c); } } }

  • 画像変換の高速化

    DOS/VマシンでMicrosoft C Ver6.0でCの勉強をしています。 初心者の入り口レベルなので、質問の内容が拙いかもしれませんが、よろしくお願いします。 BMPの8ビット形式の画像を任意のデータに変換するプログラムを作ったのですが、処理速度がとても遅く(1.7M位で5分30秒かかりました)何とか高速化をしたいと思います。 今やっているやり方はX方向分(ファイルサイズをYサイズで割ったもの)のバッファを取り、書込む時に実際のX方向分のみ書き込ませる。 をY方向分繰返すという処理です。 絶対もっと早くなる方法があるはずだと思うのですが、いくら考えても全く分かりません。 アドバイスをよろしくお願いします。

  • 画像を読み込んでヒストグラムを作るプログラム

    2値化画像を読み込んで、ヒストグラムを表示させるプログラムを作りたいのですが、 以下のソースを作成したのですが実行中にエラーが発生して困っています。 よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> #define width 640 #define height 480 int main(int argc, char* argv[]) { unsigned char image[640*480]; unsigned char header32[1078];//ビットマップ情報 int i; int *histogram; FILE *fp1; unsigned char buffer1[640*480]; for(i=0; i<640*480; i++) { image[i]=0; buffer1[i]=0; } fp1=fopen("koshimizu1.bmp","rb"); // fread(image,1,640*480,fp1); fread(header32,1,1078,fp1); fread(buffer1,width,height,fp1); fclose(fp1); for(i=0;i<256;i++){ histogram[i]=0; } for(i=0;i<640*480;i++){ histogram[image[i]]++; } for(i=0;i<256;i++){ printf("%d %d \n",i,histogram[i]); } return 0; }