ページ 1 / 1
bmpの解析について
Posted: 2010年12月12日(日) 04:11
by パコネコ
題名の通り解析をしていて。
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進数に変換できません。
単体なら何とかなるのですがつながってしまうと少しきついです。
(紙の上での計算はできます。)
アドバイスいただけないでしょうか?
Re: bmpの解析について
Posted: 2010年12月12日(日) 04:22
by パコネコ
ごめんなさい自己解決できました。
コード:
#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進数で計算すると出てきました。
みた方には大変ご迷惑かけてすいません。
Re: bmpの解析について
Posted: 2010年12月12日(日) 06:01
by パコネコ
一応完成しました。
コード:
#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ようなので起動はできないと思います。ウィンドウの作成と点の描写を書き換えてください)
予想以上に描写が遅かったです・・・
Re: bmpの解析について
Posted: 2010年12月12日(日) 16:29
by Dixq (管理人)
バイトオーダーを変換する関数を作ってはどうですか?
後、ビットシフトやバイトオーダーを計算する時は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
しかしこれなら関数じゃなくマクロの方がいいかもしれませんね。