- ベストアンサー
3次元配列でのポインタ
唐突ですみません。 サイズが640*480の画像を180枚読み込むプログラムをポインタを使って作成しようと考えています。 以下で示すプログラムは画像を読み込むための作成したものですが、エラーが出てしまい実行することができません。 間違えている箇所があればご指摘お願いします。 また、そのほかに効率の良いやり方などがありましたらご教授願います。 #include <stdio.h> #include <stdlib.h> #include <math.h> #define xsize 640 #define ysize 480 #define round 180 #include "Input.h" void Input_task(unsigned char ***In); void main() { static unsigned char ***In; int i,j; In=(unsigned char***)malloc(sizeof(unsigned char)*round); for(i=0;i<round;i++) { In[i]=(unsigned char**)malloc(sizeof(unsigned char)*ysize); for(j=0;j<ysize;j++) { In[i][j]=(unsigned char*)malloc(sizeof(unsigned char)*xsize); } } Input_task(In); } Input.hの中身 void Input_task(unsigned char ***In) { char filename[30]; int i,j,k; FILE *fp; for(i=0;i<round;i++) { sprintf(filename,"b20_%04d.raw",i); fp=fopen(filename,"rb"); for(j=0;j<ysize;j++) { for(k=0;k<xsize;k++) { *(*(*(In+i)+j)+k)=(unsigned char)getc(fp); } } fclose(fp); } }
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
★3次元配列のポインタ宣言が間違っています。 ・3次元配列のポインタは『static unsigned char (*In)[ysize][xsize];』と宣言しますよ。 ・ちなみに、3次元配列は『static unsigned char ln[round][ysize][xsize];』と同じになります。 ・分かりますか?→多次元配列のポインタはなれないと難しいですよ。考え方が。宣言方法がね。 ・『Input.h』内の『Input_task』の引数宣言も『unsigned char (*In)[ysize][xsize]』とします。 ★その他 ・640×480の画像を180枚ということは 55,296,000 バイト(約53Mバイト)ですよ。メモリ容量は大丈夫? ・『効率』良くというのならば、『getc』ではなく『fread』で一度に『640×480=307,200』バイトを 読み込みます。→メモリを確保しているので出来ますよ。あとは、180枚分をループして読み込みます。 ・サンプルを載せておきます。解説しませんので読み取って下さい。 /* main関数のサンプル */ void main() { static unsigned char (*In)[ysize][xsize]; if ( (In = (unsigned char (*)[ysize][xsize])malloc(round * ysize * xsize)) == NULL ){ printf( "メモリが足りません。\n" ); exit( 255 ); } Input_task( In ); free( In ); ←忘れずに! } /* Input.hの中身 */ void Input_task( unsigned char (*In)[ysize][xsize] ) { char filename[30]; int i; FILE *fp; for ( i = 0 ; i < round ; i++ ){ sprintf( filename, "b20_%04d.raw", i ); if ( (fp = fopen(filename,"rb")) != NULL ){ fread( In[i], xsize, ysize, fp ); fclose( fp ); } } } 最後に: ・回答者 No.1 さんと同じくヘッダにはソースは記述してはいけません。→トラブルの原因になるから。 ・また、単純に1次元配列を確保して自分で掛け算してアクセスするのも方法の1つですよ。 ・以上。
その他の回答 (1)
- venzou
- ベストアンサー率71% (311/435)
>In=(unsigned char***)malloc(sizeof(unsigned char)*round); In=(unsigned char***)malloc(sizeof(unsigned char **)*round); >In[i]=(unsigned char**)malloc(sizeof(unsigned char)*ysize); In[i]=(unsigned char**)malloc(sizeof(unsigned char *)*ysize); InとIn[i]はポインタの配列ですよ。 私なら・・・ 単純に一次元配列で確保して unsigned char *In; In = (unsigned char*)malloc(sizeof(unsigned char)*round*ysize*xsize); Input_taskの代入部分 *In++ = (unsigned char)getc(fp); 後から参照する時は In[i*ysize*xsize + j*xsize + k] あと、ヘッダファイルにはプログラムは書かないですね。
お礼
的確な回答ありがとうございました。 確かに、一次元配列で確保したほうがいいですね。 まだ慣れていないせいもあり、苦労しているところですTT
補足
回答ありがとうございました。 実際まだポインタに慣れていないので、自分の理想とするものを作ることガで木津にいたのですが、この返答は理想に近いもので驚きました。 本当にありがとうございました。