• ベストアンサー

C言語

座標から画像の値を読み出すプログラムを教えてください。REDHATLinuxを使用しています。

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

  • ベストアンサー
回答No.8

BMPの場合。。。BMPファイルを(windows版の情報ヘッダ,24bitカラー,無圧縮,パレットなし)と固定してしまえば、画像データはファイルの54バイト目から入っていると思います。 ただし、データ順が一般的な走査順と違って、左下からになります。画素データは青緑赤の順に24ビットで、横幅が4バイト境界になるようにダミーデータが入ります(横1024ならダミーなしですね)。 linuxということでちと気になるのは、BMP形式のデータはリトルエンディアンで格納されています。1バイトずつファイルから読んでくれば問題ないですが、マシン(またはOS)によってはビッグエンディアンに変換が必要なです。 (参考)BMPファイルのヘッダ概要 オフセット 内容とサイズ ------------------------------------------------------------------- 0     ファイルタイプ(2バイト) 'BM'固定 2     ファイルサイズ(4バイト) 6     予約(2バイト+2バイト) 常に0 10    ファイル先頭から画像データまでのオフセット(4バイト) ------------------------------------------------------------------- 14    情報ヘッダのサイズ(4バイト) たぶん40 18    画像の幅(ピクセル)(4バイト) 22    画像の高さ(ピクセル)(4バイト) 正負で方向違う 26    プレーン数(2バイト) 常に1 28    1画素あたりのデータサイズ(2バイト) 24のはず 30    圧縮形式(4バイト) 0のはず 34    画像データ部のサイズ(4バイト) 38    横方向解像度(4バイト) 42    縦方向解像度(4バイト) 46    パレット数(4バイト) たぶん0 50    重要パレットインデックスの数(4バイト) ------------------------------------------------------------------- 54    画像データ 本当の開始位置はヘッダを見ること -------------------------------------------------------------------

tadashi1111
質問者

補足

ありがとうございます。上のは構造体の宣言なのでそれを用いてやってみます。一度回答を締めてもう一度質問しますね。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (7)

回答No.7

参考まで、rawフォーマットのデータ(test.raw)をpicに格納して、ヒルベルト走査してdataに入れてファイルに書き出します。画像データは横16ドット*縦16ドット*RGB(24bit)=768バイトです。 #include <stdio.h> #define SIZE 16 /* データ用変数 */ unsigned char pic[SIZE][SIZE][3]; int data[SIZE*SIZE]; /* intが16bitの時はlongにする */ int idx; /* ヒルベルト曲線用データ */ int dx[8][4]={{0,0,1,1},{1,0,0,1},{0,1,1,0},{1,1,0,0},{0,1,1,0},{1,1,0,0},{0,0,1,1},{1,0,0,1}}; int dy[8][4]={{0,1,1,0},{0,0,1,1},{1,1,0,0},{1,0,0,1},{0,0,1,1},{0,1,1,0},{1,0,0,1},{1,1,0,0}}; /* ヒルベルトスキャン */ void hilbert(int n, int pattern, int x, int y) {  if (n>1) {   hilbert(n/2, (pattern+4)%8, x+dx[pattern][0]*(n/2), y+dy[pattern][0]*(n/2));   hilbert(n/2, pattern, x+dx[pattern][1]*(n/2), y+dy[pattern][1]*(n/2));   hilbert(n/2, pattern, x+dx[pattern][2]*(n/2), y+dy[pattern][2]*(n/2));   hilbert(n/2, 7-pattern, x+dx[pattern][3]*(n/2), y+dy[pattern][3]*(n/2));  } else {   /* XY座標から画素値(24bit)を取得 */   data[idx++] = ((int)pic[x][y][0]<<16) | ((int)pic[x][y][1]<<8) | (int)pic[x][y][2];  } } int main(void) {  FILE *fp;  if ((fp=fopen("test.raw","rb"))==NULL) { printf("infile open error\n"); return -1;}  if (fread(pic,sizeof(unsigned char),SIZE*SIZE*3,fp)!=SIZE*SIZE*3) { printf("file read error\n"); fclose(fp); return -1;}  fclose(fp);  idx=0; hilbert(SIZE,0,0,0);  if ((fp=fopen("result.dat","wb"))==NULL) { printf("outfile open error\n"); return -1;}  if (fwrite(data,sizeof(int),SIZE*SIZE,fp)!=SIZE*SIZE) { printf("file write error\n"); fclose(fp); return -1;}  fclose(fp);  return 0; } ヒルベルトのところはさっき思いついたやり方なのでバグありかもしれません。。。

tadashi1111
質問者

お礼

うまく動きませんでした。><。 bpm方式も同じ用な感じですか?

tadashi1111
質問者

補足

ありがとうございます★やってみます。私は画像データを1024*1024にしたいにでそれでやってみますね。

全文を見る
すると、全ての回答が全文表示されます。
  • kyrsche
  • ベストアンサー率41% (7/17)
回答No.6

またまたアドバイスということで。 #今回は裏付け無しなので、ちょっとあやふや(^_^;; RAW形式は、例えばビデオカードのメモリの状態そのままを ファイルに切り出したと思ってもらえればよいです。 英単語で「未処理の」「生の」という意味があります。 BMP形式は、このRAW形式にBMPヘッダが付いたフォーマットと 思ってもらえればよいです。 Binary Mapped Picture だか、そんな感じの略語です。 どちらも、24bit(32bit)フォーマットであれば、RGBの各レベルが 1ピクセル分格納されます。 (RAWとBMPではRGBの出現順番が違うかもしれません) RGBに分かれないのは、555/655といった1バイトのpacked形式や、 8bitグレースケールの場合、またインデックスカラー(パレットカラー)の場合です。 #呼び名はこれでよかったのか心配・・・(汗 RAW形式は、配列に格納した場合にインデックスがそのまま ラスター位置になりますが、BMP形式は、ラスター位置に更に BMPヘッダ分のオフセットが付きます。 また、RAW形式は左から右、上から下の順でデータを格納しますが、 BMP形式は左から右は同じですが、下から上にデータを格納します。 (WindowsのBMPは確かそうです。unixのBMPは違ったかもしれません) ですので、BMP形式はヘッダのオフセットと上下逆のアクセスが 必要になります。RAW形式だと、この操作がいりません。 ちなみにラスター位置は、ディスプレイの走査順に見た位置で、 左から右、上から下となります。 #ラスター位置だと、画像データと位置情報が同一になるので #処理がしやすく(=分かりやすく)なります。 ですので、画像を扱いたい(プログラムで画像処理をしたい)と いったときに、特に要求が無ければRAW形式の方が 余計な処理(=プログラム)を考えなくても良い利点があります。 その代わり、用意する画像を作るのに特殊な方法が必要になります。 #例えば、JaritenCatさんの例のように 画像処理は、結局は配列のデータをどういじるかですので、 どんな状態で配列に格納しているのかを押さえていると、 どんなデータ形式で格納されていても適切なアクセスができます。 いま、tadashi1111さんがプログラムにかけられる時間(BMP形式)と、 理解・データの準備にかけられる時間(RAW形式)を天秤に掛けて、 傾いた方を選択すると良いと思います。 ちなみに、tadashi1111さんはどんな答えをほしいのでしょう? 今はファイルアクセスのサンプルコードでしょうか?

tadashi1111
質問者

お礼

一度回答をしめてまた新たに質問しますね。

tadashi1111
質問者

補足

BMP方式でやりたいと思います。 C言語の場合、bmpファイルの構造は1画素ごとにRGBがワード単位で多重されているのではなく、1画素ごとに(RGB)の3次元ベクトルを配置する構造をとっているいるようです。よって、たとえば画像imgの(i,j)画素は img[i][j][k]と記述されるようです。ここで、k=1がR、k=2がG、k=3がBの値を表すことになるそうです。と聞きました。 圧縮するまでのBMP方式画像をヒルベルトスキャンし、その座標ごとの画素値を配列にし適当なファイル名をつけディスクに書き出したいんです。圧縮するプログラムはあるのですが><。

全文を見る
すると、全ての回答が全文表示されます。
  • kyrsche
  • ベストアンサー率41% (7/17)
回答No.5

取得した画像を圧縮したい(圧縮率を出したい)、ということと、 JaritenCat さんのフォローから、私もなんとなく(^_^; 二次元画像を扱う場合、普通は一次元のデータに変換して加工処理を 行いますが、通常の画像の格納方法はラスター形式なのでX軸が回帰する 部分で連続しない無関係のデータになってしまう。 この部分を効率よく処理(圧縮)するために二次元の情報を持ちつつ 一次元にする変換方法として、ヒルベルトスキャンがある。 この変換を事前に行うことで、圧縮効率の向上が見られるかどうか、 そしてどの程度の向上があるかを判断したい、ということですね(^_^;; #かなり説明チックですね・・・。 やり方としては、JaritenCat さんがだいたい書かれてますのでそちらを(^_^;;; ファイルアクセス(read/write)と、配列からヒルベルトスキャンを行う 関数を組み合わせればよいと思います。ファイルアクセス処理は、C言語の 参考書であれば、だいたい載っていますので、そちらを参考に。 ヒルベルトスキャンは・・・自作だとちょっと面倒かもしれませんので、 出来合いのライブラリを借用(フリー公開のものを(^_^;;)して作るほうが 良いでしょうね。 #C Magazine2000年10月号にそういう特集があるみたいですね。 #ソースコードも公開されているようです。 #googleで「ヒルベルト」「ソース」「C」で検索して最初の方に出てくるようです。 #ただ、C++ for VC++なので、ちょっとクセがあるかなーと思いますが。 ##「クセ」は、Linuxでそのままでは使用できなさそうという意味で。 私は、ここ数年来Java屋さんなので C/C++ はちょっとつらいですね(^_^;; #心はC屋さんのつもりなのですが・・・(>△<

tadashi1111
質問者

補足

ありがとうございます。ヒルベルトスキャンのプログラムはいちおうできました。結果は(0,0)(0,1)(1,1)・・・・ という感じで。それからできなくて困ってます><。

全文を見る
すると、全ての回答が全文表示されます。
回答No.4

なんとなくやりたい事は分かりました。 画像はBMP形式ではなくRAW形式ならヘッダなしにできるのでプログラムが簡単になります。 プログラムは、 (1)画像データを読みながら内部メモリ(2次元配列)に格納 (2)ヒルベルトスキャンの座標を計算して内部メモリ(1次元配列2個)に格納 (3)上で求めた座標から該当する画素の値を別のメモリ領域(1次元配列)に代入 (4)圧縮 (5)ファイルに書き出し という手順ですね。 RAWフォーマットのデータは、photoshopで作ることができます。ヒルベルトスキャンするので2^n*2^nサイズの画像ですね。RGB各8ビットの画像だとすると、photoshopで保存するときに汎用フォーマット(*.RAW)を選んで、ヘッダサイズを0にして、インターレースにチェックして保存します。 データは左上から順に、RGBRGBRGB・・・の順に並びます。 純粋に画像データだけでヘッダがないのでプログラムは簡単になります。 ファイルの読み込みは、fopenしてfgetcで1バイトずつ読んで配列に格納し、読み終わったらfclose。 いろいろ計算して、ファイルに書き出すのは、fopenしてfputcで1バイトずつ書き出せばいいでしょう。 そういえば、15年ぐらい前にヒルベルトスキャン+ランレングスで画像圧縮しようとしていました。。。懐かしい

tadashi1111
質問者

補足

RAW方式とBMP方式の違いはなんでしょうか?私はBMP方式でやりたいです。他の人に聞いたらRGBにわけなくてもよいと聞きましたが分けなくてもできますか?

全文を見る
すると、全ての回答が全文表示されます。
  • kyrsche
  • ベストアンサー率41% (7/17)
回答No.3

レヨナという画像フォーマットがあるのですね。 勉強不足でした。 しかし、文章で説明できるということは、後はそのままプログラムに 落とせばよいのですが、難しいのでしょうか。 > JPEGだといけないんでBMP方式でないと画素値の値が取れないないのでBMPの画像にします。 > 画像をfil(file?)として読み込みヒルベルトスキャンして座標の(x、y)を出します。 > XYの長さを16としたとき(0,0)(0,1)(1,0)・・・・(0,14)(0,15)と256個の座標がでてきます。 > その値を画像に照らしあわせてその座標のとこの画素値を取り出したいんですけすど。 > そしてそれを(0,0)→file[0][0](0,1)→file[0][1]・・・みたいに2次元配列にし、次に1次元配列に直し > file[0][0]→g[0],file[0][1])→g[1]・・・と表したいんです。 いまいちやりたいことがストレートに読み取れません。 もっと前後というか、何がやりたいからコレが知りたいというのが 見えないので、明快に回答しにくいのです。 a「レヨナ→画像として閲覧したい」でしょうか、 b「画像→レヨナへの変換」でしょうか。 そして、矢印の間のドコが知りたいのでしょうか。 補足の内容から後者だとして、私なりの手順を考えると、こんな感じです。 1. 読み込ませたい画像ファイル(jpeg)を用意 2. 画像フォーマットを変換(jpeg→bmp) 3. bmpファイルを読み込み、画像データとしてメモリに格納 4. メモリの任意位置の画素値をヒルベルトスキャンにて取得 5. 取得した画素値を加工(ファイルに出力?) プログラムが出てくるのは3,4,5ですが、どこが分からないのでしょう?

tadashi1111
質問者

補足

説明下手ですみません。kyrscheさんのが要領がいいかもしれません。取得した画素値のファイルを圧縮したいんです。それでどれだけ圧縮できたかを調べたいんです。プログラムは3,4,5わかりません><。初心者で締め切り近くて困っています。

全文を見る
すると、全ての回答が全文表示されます。
  • kyrsche
  • ベストアンサー率41% (7/17)
回答No.2

もうこし整理しましょう。 レヨナというのは画像フォーマットでしょうか。それともアーティスト? アーティストだとしたら、アーティストのどんな画像でしょうか。 CDジャケット?それとも、Web公開のサムネイル画像ですか? 次にその画像をどうしたいのでしょう? この辺りが分からないと、アドバイス使用にもできません。 もう少し補足をお願いします。

tadashi1111
質問者

補足

画像フォーマットです。でしたがJPEGだといけないんでBMP方式でないと画素値の値が取れないないのでBMPの画像にします。画像をfilとして読み込みヒルベルトスキャンして座標の(x、y)を出します。XYの長さを16としたとき (0,0)(0,1)(1,0)・・・・(0,14)(0,15)と256個の座標がでてきます。その値を画像に照らしあわせてその座標のとこの画素値を取り出したいんですけすど。そしてそれを(0,0)→file[0][0](0,1)→file[0][1]・・・みたいに2次元配列にし、次に1次元配列に直しfile[0][0]→g[0],file[0][1])→g[1]・・・と表したいんです。長くなりすみません。

全文を見る
すると、全ての回答が全文表示されます。
  • kyrsche
  • ベストアンサー率41% (7/17)
回答No.1

まず扱いたい画像を決めてください。 次に扱う画像が、どういうフォーマットになっているかを調べてください。 そうすれば、おのずとどうすればよいかが分かります。 Unixはかなり離れてしまったので、良く覚えていませんが、 Xで扱える簡単な画像フォーマットがあったはずです。 一般的な画像(jpeg/gif/bmpなど)を扱いたいのであれば、 その画像フォーマットを読み込めるライブラリを探して利用するほうが 手っ取り早いと思います。 (bmpは何とかなると思いますが、gifやjpegは自分で解析するには大変です) じゃあ、どういうところを探せばそのライブラリが見つかるか というと、そこは私もよく分かりませんので(^_^; #googleなんかの検索サイトで頑張ってください(無責任ですが(^_^;;;)

tadashi1111
質問者

補足

画像はレヨナというのを使います。後はプログラムだけなんですが苦手でわかりません。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • c言語、パチンコリール

    c言語とDirectXを使用して、パチンコのリールを作っています。 質問なんですが、図柄の画像が0~9まであったとします。 現在、スプライトを使って左上と右下座標のY座標に値を与えて、画面の上から下まで画像を動かしています。 しかし、9まで行ってもまた画面の上から0を出すことができません。 これをループさせたいのですがどうすればよいでしょうか? 説明内容不足を承知していますので、随時補足していきたいと思いますので、よろしくお願い致します。

  • C言語の質問です。

    C言語の質問です。 以前質問した、C言語初心者のものです。 以前回答してくださった方、ありがとうございました! 前回の質問とかぶるんですが、質問は、 正方形の画像を円形にひきのばす(歪ませる)というプログラムがなかなか書けません。 どなたか教えてください! 円形にひきのばしたときに、正方形のどの座標がどにに移動してるのかってのを考えてつくりたいのですが。 画像を添付しました。 この画像の意味は、たとえば、正方形の中にある緑の四角(座標)が円のほうの緑の四角(座標)に移動したと考えたときに、添付画像に書いてある公式をつかって処理していくってことなんですが・・・。 それを同じようにすべての座標で処理していって円形に歪ませた画像をつくりあげたいんです。

  • c言語によるアルゴリズム

    やりたいことは、たくさんの画像をいくつかのグループ(1グループに画像が数十種類)用意し、入力画像とそれらを比較します。そして、最も入力画像に似ている画像があるグループを選び出します。画像自体はx-y座標に点がある程度です。似た画像かどうかは、openCVのcvMatchShapesを使おうかと考えています。 参考 http://opencv.jp/sample/matching.html 画像を呼び出そうと思うと、一つ一つ画像名から呼び出すと思うのですが、大量の画像を呼び出すことを考えると、画像名を全て書いていたのではプログラムが長くなると思います。何かいい方法はないでしょうか。 また、座標値がわかっていますので、数値でグループを特定できる方法があれば、そちらの方法を教えてもらいたいです。 こちらはプログラミング、画像処理ともに初心者です。他にいい方法があれば,それも教えてもらえるとうれしいです。よろしくお願いします。

  • ヒルベルト曲線のプログラムについて(C言語)

    私は今画像の圧縮の勉強でヒルベルト曲線を勉強していますが、その曲線の座標を示すプログラムが書けません。教えて欲しいです。またその復元させるプログラムも教えて欲しいです。

  • c言語にてプログラミング

    四角じゃないいびつな形の画像があります その画像の中心の座標を得るためのプログラミングを作らなければなりません 全ピクセルのx座標をピクセルの数で割ったりして求めなければなりません これをどうやってプログラミングするかわかりません! 教えてください!!

  • C言語のプログラムに関することで質問です。

    C言語のライブラリを利用したプログラムのことで質問なのですが、座標xとyの成分から、ベクトルの角度(t)と大きさ(r)を求めるプログラムを作りました。しかし、このままのプログラムだと、ある場合のときに限り、正しい値が返されなくなるらしいのですが、それはどのような場合で正しい値が返されなくなってしまうのかを教えてください。また、正しい値がでるようにするにはどこをどう直したらよいのでしょうか? 自分でも考えてみたのですが、分からず困っています。分かる方どうかよろしくお願いいたします。 #include <stdio.h> #include <stdlib.h> #include <math.h> #define square(x) ((x) * (x)) //ベクトルの角度θを返す関数 double theta(double x, double y) { return atan(y / x); } //ベクトルの大きさを返す関数 double radius(double x, double y) { return sqrt(square(x) + square(y)); } int main(int argc, char **argv) { double x, y; //x, yは座標 double t, r; //t, rは極座標 if(argc == 3 && (x = atof(argv[1])) && (y = atof(argv[2]))) { t = theta(x, y);  //極座標tを計算 r = radius(x, y); //極座標rを計算   //ベクトルの角度と大きさを表示 printf("t = %f, r = %f\n", t, r); } return 0; }

  • C言語について

    倍精度の浮動小数点で与えられる4点の座標(x1,y1),(x2,y2),(x3,y3),(x4,y4)を入力して、その4点が頂点になる四角形の面積を算出して表示するプログラムをC言語を用いて書くとどういうプログラムをつくればいいのでしょうかm(__)m

  • 座標

    私は今座標から画像の値を読み出す勉強しています。プログラムを用いて座標を出すことはできました。今度はその実行結果ででた座標の値から画像の画素値を取り出すプログラムを書けたいのですが書けません。いろいろ参考書を見たりCマガジンという雑誌を読んだりしましたが理解できなくて投稿しました。

  • Cで回転プログラムの高速化を

    Cで、90枚の画像を、それぞれ0度から90度まで回転させるプログラムを作りました。 回転の処理は重く時間がかかるため、 それぞれの角度の回転後の位置を配列に格納して、 その値を参照して画像を回転させていこうと思ったのですが、 例えば、画像が300*300としたら回転座標を入れる配列は2次元で2つとりますよね? kaitenX[90][300] kaitenY[90][300] これで、例えば元画像を50度回転させる時のx,y座標が10,50の所の回転後の座標は kaitenX[50][10]の値(回転後のx座標の値) と kaitenY[50][50]の値(回転後のY座標の値)を 参照さしてやればいいと思うのですが、 このとき、回転後の画像をtemp[300][300]という回転後の出力用配列に 代入していくとき、 どうやって代入していけばよいでしょうか? まさか、 for(r=0;r<90;r++) //rは角度情報 for(i=0;i<300;i++) for(j=0;j<300;j++) { temp[i][j] = Gengazo[r][kaitenx[r][j]][kaiteny[r][i]] } なんて風には書けませんよね^^;(自分で一応試したけどダメでした) 回転後の座標を格納するまでは出来ると思うのですが、 格納後、どうやってその値を参照させて、格納させていけばいいか わかりません。 教えていただけませんでしょうか? また、もっと高速化できる効率の良い方法があれば教えて下さい。

  • C言語→MATLABへの変換で、困っています。

    学生研究でMATLABを使用しています。 光学測定系で画像を取り込み、それを解析する実験を行っています。 MATLABはプログラム内の値の変更や処理の追加できることから 大変助かっています。 そこで、もともとはC言語でやっていた3種類の処理を 一つのMファイルで行いたいと思い。 只今、C→MATLAB変換するプログラムの書き直しを行っています。 そのうち2種のプログラムは行列の計算がメインだったため何とか Mファイルに書き直すことができたのですが、 最後のひとつが難しい関数らしきものが多く、 MATLABに書き直すことができるプログラムなのかもわからない状態です。 そこで、 ・C→MATLAB変換可能なプログラムか? ・書き直すにあたってどこを部分を直せばよいのか? をアドバイスいただけないでしょうか? ↓MATLAB化したいC言語ファイル http://karispace.web.fc2.com/cmat2.c 一枚のbmp画像から4枚のdatデータを出力するプログラムです。 C言語とMATLABの三ヶ月前に勉強して、使用しており、基礎がわかる程度です。 よろしくお願いします。