[ create a new paste ] login | about

Link: http://codepad.org/om8Y3MiX    [ raw code | fork ]

C, pasted on Dec 15:
#include <stdio.h>

#pragma pack(1) //##### コンパイラ依存 ##### 少なくともgccとVC++は使える

//BMPファイルヘッダ構造体
typedef struct {
	unsigned short type;
	unsigned long size;
	unsigned short reserved1;
	unsigned short reserved2;
	unsigned long offset;
}bmpfileheader_t;

//BMP情報ヘッダ構造体
typedef struct {
	unsigned long size;
	long width;
	long height;
	unsigned short plane;
	unsigned short bit;
	unsigned long copmress;
	unsigned long sizeimage;
	long x_permeter;
	long y_permeter;
	unsigned long color;
	unsigned long index;
}bmpinfoheader_t;

typedef struct {
	//24bitBMPファイルはB,G,Rの順で並んでいる
	unsigned char b;
	unsigned char g;
	unsigned char r;
}rgb_t;

typedef struct {
	long h;
	unsigned char s;
	unsigned char v;
}hsv_t;

void rgb2hsv(rgb_t*, hsv_t*); //RGB->HSV変換

#pragma pack()

void main(int argc, char *argv[])
{
	FILE *fp;
	bmpfileheader_t bf;
	bmpinfoheader_t ih;
	rgb_t rgb;
	hsv_t hsv;;
	int padding;
	int x, y;

	//引数が無い場合
	if(argc < 2)
		return;

	//ファイルオープン
	if((fp = fopen(argv[1], "rb")) == NULL) {
		printf("Can't open %s", argv[1]);
		fclose(fp);
		return;
	}

	//ファイルヘッダを読む
	if(fread((void *)&bf, sizeof(bmpfileheader_t), 1, fp) !=1) {
		puts("Failed to get BMPHEADER.");
		fclose(fp);
		return;
	}

	//情報ヘッダを読む
	if(fread((void *)&ih, sizeof(bmpinfoheader_t), 1, fp) !=1) {
		puts("Failed to get INFOHEADER.");
		fclose(fp);
		return;
	}

	//BMP形式ではない場合
	if(bf.type != 0x4d42) { //0x4d42 = BM(リトルエンディアン)
		puts("Not BMP file.");
		fclose(fp);
		return;
	}

	//OS/2形式のBMPは対応しない
	if(ih.size != sizeof(bmpinfoheader_t)) {
		printf("Unsupported format.");
		fclose(fp);
		return;
	}

	//24ビット以外は対応しない(手抜き)
	if(ih.bit != 24) {
		puts("Unsupported Colorbit.");
		fclose(fp);
		return;
	}

	padding = ih.width % 4; //パディングを計算
	x = 1; y = ih.height; //左下から右上へ
	if(fseek(fp, bf.offset, SEEK_SET) != 0) { //ピクセルのデータまで移動
		printf("Failed to seek");
		fclose(fp);
		return;
	}

while((fread((void *)&rgb, sizeof(rgb_t), 1, fp)) == 1) { //EOFまで1ピクセル分のデータを繰り返し読み込み
		printf("X:%5d: Y:%5d R:G:B|%3d:%3d:%3d ->", x, y, rgb.r, rgb.g, rgb.b);
		rgb2hsv(&rgb, &hsv);
		printf("H:S:V|%3d:%3d:%3d\n", hsv.h, hsv.s, hsv.v);
		x++;
		if(x > ih.width) { //右端に達したら
			x = 1; y--;
			fseek(fp, padding, SEEK_CUR); //パディングを飛ばす
		}
	}

	fclose(fp);
}

void rgb2hsv(rgb_t *rgb, hsv_t *hsv)
{
	unsigned char max, min;

	if(rgb->r >= rgb->g && rgb->r >= rgb->b)
		max = rgb->r;
	if(rgb->g >= rgb->r && rgb->g >= rgb->b)
		max = rgb->g;
	if(rgb->b >= rgb->r && rgb->b >= rgb->g)
		max = rgb->b;

	if(rgb->r <= rgb->g && rgb->r <= rgb->b)
		min = rgb->r;
	if(rgb->g <= rgb->r && rgb->g <= rgb->b)
		min = rgb->g;
	if(rgb->b <= rgb->r && rgb->b <= rgb->g)
		min = rgb->b;

	hsv->v = max; //vを計算
	if(hsv->v == 0){ //v=0の時、sは未定義で完全な黒色
		hsv->h = 0; hsv->s = 0; hsv->v = 0;
		return;
	}

	hsv->s = 255 * (max - min) / max; //sを計算
	if(hsv->s == 0) { //s=0の時hは未定義
		hsv->h = 0;
		return;
	}

	//hを計算
	if(max == rgb->r)
		hsv->h = 60 * (rgb->b - rgb->g) / (max - min);
	if(max == rgb->g)
		hsv->h = 60 * (2 + (rgb->r - rgb->b) / (max - min));
	if(max == rgb->b)
		hsv->h = 60 * (4 + (rgb->g - rgb->r) / (max - min));
	if(hsv->h < 0)
		hsv += 360;

	return;
}


Create a new paste based on this one


Comments: