bmpの解析について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
パコネコ
記事: 139
登録日時: 9年前
住所: 大阪

bmpの解析について

#1

投稿記事 by パコネコ » 9年前

題名の通り解析をしていて。
http://coconut.sys.eng.shizuoka.ac.jp/bmp/
というサイトで調べながらやっていたのですが。

コード:

「リトル・エンディアン」式に, つまり, 下位バイトから順に書かれているので, 0x09ca76 = 641,654 [バイト] である. 
と書かれています。
途中までやったものが、

コード:

#include<stdio.h>
int main(void){
	FILE *fp;
	int a,b,c,d;
	int i;
	fp=fopen("C:\\~個人情報につき省略~\\参考資料2\\dog2.bmp","rb");
//ファイルヘッダ
	//ファイルの種類(BM)
	for(i=0;i<2;i++){
		//fscanf(fp,"%c ",&a);
		a=getc(fp);
		printf("%c",a);
	}
	printf("\n");
	//ファイルサイズ
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("0x%02x%02x%02x%02x=>%ld",d,c,b,a,わかりません);

	fclose(fp);
}
まだファイルサイズを出すところですが・・・
わかりませんの部分がなんて書けば、いいのか・・・
0x09ca76 = 641,654
となるように計算したいのですが、
a=76
b=ca
c=09
d=00
をうまく10進数に変換できません。
単体なら何とかなるのですがつながってしまうと少しきついです。
(紙の上での計算はできます。)

アドバイスいただけないでしょうか?
ニャン!!\(゜ロ\)(/ロ゜)/

アバター
パコネコ
記事: 139
登録日時: 9年前
住所: 大阪

Re: bmpの解析について

#2

投稿記事 by パコネコ » 9年前

ごめんなさい自己解決できました。

コード:

#include<stdio.h>
int main(void){
	FILE *fp;
	int a,b,c,d;
	int i;
	fp=fopen("C:\\~省略~\\参考資料2\\dog2.bmp","rb");
//ファイルヘッダ
	//ファイルの種類(BM)
	for(i=0;i<2;i++){
		//fscanf(fp,"%c ",&a);
		a=getc(fp);
		printf("%c",a);
	}
	printf("\n");
	//ファイルサイズ
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("0x%02x%02x%02x%02x=>%ld",d,c,b,a,d*256*256*256+c*256*256+b*256+a);

	fclose(fp);
}
16進数で計算しても出なかったので、256進数で計算すると出てきました。
みた方には大変ご迷惑かけてすいません。
ニャン!!\(゜ロ\)(/ロ゜)/

アバター
パコネコ
記事: 139
登録日時: 9年前
住所: 大阪

Re: bmpの解析について

#3

投稿記事 by パコネコ » 9年前

一応完成しました。

コード:

#include<stdio.h>
#include<graph.h>
int main(void){
	FILE *fp;
	int a,b,c,d;
	int i;
	int mapx,mapy;
	int x,y;
	fp=fopen("C:\\~省略~\\参考資料2\\dog2.bmp","rb");
//ファイルヘッダ
	//ファイルの種類(BM)
	for(i=0;i<2;i++){
		//fscanf(fp,"%c ",&a);
		a=getc(fp);
		printf("%c",a);
	}
	printf("\n");
	//ファイルサイズ
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("ファイルサイズ\t0x%02x%02x%02x%02x\t%ldバイト\n",d,c,b,a,d*256*256*256+c*256*256+b*256+a);

	//予約領域(0らしい・・・)
	for(i=1;i<=2;i++){
		a=getc(fp);
		b=getc(fp);
		printf("予約領域%d\t0x%x%x\n",i,b,a);
	}

	//画像データまでのオフセット(意味不明)
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("画像データまでのオフセット\t%ld\n",d*256*256*256+c*256*256+b*256+a);

//情報ヘッダ
	//情報ヘッダのサイズ
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("情報ヘッダのサイズ\t%ld\n",d*256*256*256+c*256*256+b*256+a);

	//画像の高さ
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("画像の縦幅\t%ldピクセル\n",mapx=d*256*256*256+c*256*256+b*256+a);

	//画像の幅
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("画像の横幅\t%ldピクセル\n",mapy=d*256*256*256+c*256*256+b*256+a);

	//プレーン数(常に1)<-不明
	a=getc(fp);
	b=getc(fp);
	printf("プレーン数\t%d\n",b*256+a);

	//1画素当たりの色数
	a=getc(fp);
	b=getc(fp);
	printf("1画素当たりの色数\t%dビット\n",b*256+a);

	//圧縮形式
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("圧縮形式?\t%ld\n",d*256*256*256+c*256*256+b*256+a);

	//画像データのサイズ
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("画像データのサイズ\t%ldバイト\n",d*256*256*256+c*256*256+b*256+a);

	//水平解像度
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("水平解像度\t%ldppg\n",d*256*256*256+c*256*256+b*256+a);

	//垂直解像度
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("垂直解像度\t%ldppg\n",d*256*256*256+c*256*256+b*256+a);

	//パレットの色数
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("パレットの色数\t\t\t%ld\n",d*256*256*256+c*256*256+b*256+a);

	//重要パレットのインデックス
	a=getc(fp);
	b=getc(fp);
	c=getc(fp);
	d=getc(fp);
	printf("重要パレットのインデックス\t%ld\n",d*256*256*256+c*256*256+b*256+a);

//データ部
	//ウィンドウの作成
	gl_openwin(-1,-1,mapx,mapy,1);
	for(y=mapy;0<y;y--){
		for(x=0;x<mapx;x++){
			//色
			a=getc(fp);
			b=getc(fp);
			c=getc(fp);
			//点の描写
			gl_setpixel(x,y,RGB(c,b,a));
			//ずれの修正
			if(x==mapx-1)
				for(i=0;i<mapx%4;i++)
					getc(fp);
		}
	}

	fclose(fp);
}
ついに完成しました。
これからが本番ですが・・・
一応出来上がったものを張っておきます。
(スタディcようなので起動はできないと思います。ウィンドウの作成と点の描写を書き換えてください)

予想以上に描写が遅かったです・・・
ニャン!!\(゜ロ\)(/ロ゜)/

アバター
Dixq (管理人)
管理人
記事: 1661
登録日時: 9年前
住所: 北海道札幌市
連絡を取る:

Re: bmpの解析について

#4

投稿記事 by Dixq (管理人) » 9年前

バイトオーダーを変換する関数を作ってはどうですか?

後、ビットシフトやバイトオーダーを計算する時は10進数ではなく、16進数で計算する方が簡単ですよ。
(10進数だろうと16進数だろうと変数の中に入っているデータは同じです)

例えば4バイトあるうちの1バイト目のみを取り出したい時は

変数 & 0x000000FF

で取れます。2バイト目を取り出したい時は

(変数 & 0x0000FF00 ) >> 8

となります。
変換する時は、くっつけたい位置にビットシフトして論理和でくっつけてやればOKです。

コード:

#include <stdio.h>

unsigned short ChangeByteOrder2( unsigned short a ){
	return	((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8);
}

unsigned long  ChangeByteOrder4( unsigned long  a ){
	return	((a & 0x000000FF) << 24) | 
			((a & 0x0000FF00) << 8 ) | 
			((a & 0x00FF0000) >> 8 ) | 
			((a & 0xFF000000) >> 24) ;
}

int main(){
	unsigned short a = 0x0102;
	unsigned long  b = 0x01020304;

	printf("0x%04x\n"  , a);
	printf("0x%04x\n\n", ChangeByteOrder2(a));

	printf("0x%08x\n"  , b);
	printf("0x%08x\n\n", ChangeByteOrder4(b));
	return 0;
}

実行結果
0x0102
0x0201

0x01020304
0x04030201
しかしこれなら関数じゃなくマクロの方がいいかもしれませんね。

閉鎖

“C言語何でも質問掲示板” へ戻る