画像(bmp)を読み込み、そのRGBデータを配列に入れる処理を以下のように作りました。
xとyにはint型で数字が入っています。
unsigned char header[54],rgb[x][y][3];
fr=fopen("gazou.bmp","rb");
fread(header,1,54,fr);
fread(rgb,1,x*y*3,fr);
rgb[0][0][1]などでRGBの取得が成功したので、rgbを動的な三次元配列として確保したあとにfreadしたいと思っています。
そこで以下のように作ってみたところ、メイクは成功するのですが※の部分で止まってしまいます。
unsigned char header[54];
unsigned char*** rgb;
rgb=(unsigned char***)malloc(sizeof(unsigned char**)*x);
for(i=0;i<x;++i){
rgb=(unsigned char**)malloc(sizeof(unsigned char*)*y);
for(j=0;j<y;++j){
rgb[j]=(unsigned char*)malloc(sizeof(unsigned char)*3);
}
}
fr=fopen("gazou.bmp","rb");
fread(header,1,54,fr);
fread(rgb,1,x*y*3,fr);
for (i=0;i<x;i++) {
for (j=0;j<y;j++) {
free(rgb[j]);※
}
free(rgb);
}
free(rgb);
本やHPにあった二次元配列の作り方を参考にして作ってみたのですが何か根本的な勘違いをしているのでしょうか?
お教えいただけると幸いです。
動的な三次元配列で画像のRGBを取得
Re: 動的な三次元配列で画像のRGBを取得
この動的確保の方法ですと、三次元配列のメモリ上の位置が1次元的に連続していないので
fread(rgb,1,x*y*3,fr);
をした時点でデータが壊れています。
rgb=(unsigned char*)malloc(sizeof(unsigned char)*x*y*3);
のように確保するべきだと思います。
fread(rgb,1,x*y*3,fr);
をした時点でデータが壊れています。
rgb=(unsigned char*)malloc(sizeof(unsigned char)*x*y*3);
のように確保するべきだと思います。
- bitter_fox
- 記事: 607
- 登録日時: 14年前
- 住所: 大阪府
Re: 動的な三次元配列で画像のRGBを取得
本当にfreeで止まってしまっていますか?
個人的にはfreadの方が問題がありそうな気がするのですが・・・
[hr][追記]
それからコードを載せる際にはcodeタグで囲っていただきますようにお願いします。
Re: 動的な三次元配列で画像のRGBを取得
>>h2so5さん
rgb=(unsigned char*)malloc(sizeof(unsigned char)*x*y*3);
だとx*y*3に相当する一次元の配列が出来るということだと思うのですが、取得したいものは[0,255,0],[255,0,0],[0,0,255]のようになっているので・・・
>>bitter_fox
間違いなく最初のfreeまでは処理が進んでいます。
freadをコメントアウトすると止まららないので、freadでデータが壊れても無視して進み、freeで解放するときに壊れたデータで止まっているのだと思います。
codeタグのご指摘ありがとうございます。次回から必ず使うようにします。
rgb=(unsigned char*)malloc(sizeof(unsigned char)*x*y*3);
だとx*y*3に相当する一次元の配列が出来るということだと思うのですが、取得したいものは[0,255,0],[255,0,0],[0,0,255]のようになっているので・・・
>>bitter_fox
間違いなく最初のfreeまでは処理が進んでいます。
freadをコメントアウトすると止まららないので、freadでデータが壊れても無視して進み、freeで解放するときに壊れたデータで止まっているのだと思います。
codeタグのご指摘ありがとうございます。次回から必ず使うようにします。
Re: 動的な三次元配列で画像のRGBを取得
unsigned char header[54];
unsigned char* rgb;
rgb=(unsigned char*)calloc(x*y,sizeof(unsigned char*)*3);
fr=fopen("gazou.bmp","rb");
fread(header,1,54,fr);
for(i=0;i<x*y;++i){
fread(rgb,1,3,fr);
rgb++;
}
free(rgb);
上のサンプルは、取得したいものは[0,255,0],[255,0,0],[0,0,255]のようになっているので・・・
callocを使って3バイトのメモリを「x*y」個確保してファイルから3バイトずつ読み込ませています。
これでうまくいきそうですが・・・いかがでしょう?
- bitter_fox
- 記事: 607
- 登録日時: 14年前
- 住所: 大阪府
Re: 動的な三次元配列で画像のRGBを取得
確かにh2so5さんが仰られた六氏 さんが書きました: 間違いなく最初のfreeまでは処理が進んでいます。
freadをコメントアウトすると止まららないので、freadでデータが壊れても無視して進み、freeで解放するときに壊れたデータで止まっているのだと思います。
が原因のようですね。h2so5 さんが書きました: この動的確保の方法ですと、三次元配列のメモリ上の位置が1次元的に連続していないので
fread(rgb,1,x*y*3,fr);
をした時点でデータが壊れています。
細かく見ると を実行したときのrgb[0]の値を0x00004000として。(注:以下の値はすべて仮定の値です)
その次の で、
rgb[0]の時に0x00005000が入ったとします。
そこで とした場合は、
rgb[0]の0x00004000を先頭にしてファイルの内容をx*y*3バイト分書き込んでしまいます。(この時にx*y*3バイトは最初に確保した範囲を当然超えているのでヒープ領域を破壊する恐れもあります。)
で、書き込んだ結果
*(0x00004000) = 0xff (←ここは画像データの値
...
となり、次のfreeのところはどうなるかというと
free(*(0x00004000))がfree(0xff)となって解放してはいけない領域を解放しようとしてエラーになってしまったのだと思います。
ですので、freadのところを各ピクセルごとに読み込むように変えて実行してみてください。
Re: 動的な三次元配列で画像のRGBを取得
kimuchiさんとbitter_foxさんのコードを見ながら考えてみたところ、上手く出来ました。
止まってしまう原因も理解でき、何を勘違いしていたのかもわかったのでとても勉強になりました。
ありがとうございました。
止まってしまう原因も理解でき、何を勘違いしていたのかもわかったのでとても勉強になりました。
ありがとうございました。
- Dixq (管理人)
- 管理人
- 記事: 1662
- 登録日時: 15年前
- 住所: 北海道札幌市
- 連絡を取る:
Re: 動的な三次元配列で画像のRGBを取得
> rgb=(unsigned char*)malloc(sizeof(unsigned char)*x*y*3);
> だとx*y*3に相当する一次元の配列が出来るということだと思うのですが、取得したいものは[0,255,0],[255,0,0],[0,0,255]のようになっているので・・・
解決されたようですが、補足です。
二次元配列も結局は一次元配列と同じことですよ。
例えば
int arr[2][3];
と確保すると
* * * * * *
このように横6つの連続した領域が確保され、例えばarr[1][0]と示せば4つめの要素を示せるだけです。
逆に言えば配列要素が連続していない二次元配列において、arr[1][0]を示すと要素ではないものを指してしまいます。
今回、
このように要素が全て別々に作られているので、アドレスが連続しているとは限りません。
よって、期待しない要素を示してしまっていたのだと思います。
> だとx*y*3に相当する一次元の配列が出来るということだと思うのですが、取得したいものは[0,255,0],[255,0,0],[0,0,255]のようになっているので・・・
解決されたようですが、補足です。
二次元配列も結局は一次元配列と同じことですよ。
例えば
int arr[2][3];
と確保すると
* * * * * *
このように横6つの連続した領域が確保され、例えばarr[1][0]と示せば4つめの要素を示せるだけです。
逆に言えば配列要素が連続していない二次元配列において、arr[1][0]を示すと要素ではないものを指してしまいます。
今回、
rgb=(unsigned char***)malloc(sizeof(unsigned char**)*x);
for(i=0;i<x;++i){
rgb[i]=(unsigned char**)malloc(sizeof(unsigned char*)*y);
for(j=0;j<y;++j){
rgb[i][j]=(unsigned char*)malloc(sizeof(unsigned char)*3);
}
}
よって、期待しない要素を示してしまっていたのだと思います。