ページ 11

L*a*b変換について

Posted: 2009年5月16日(土) 22:10
by packls
こんにちはpacklsと申します。
今回XYZ値をL*a*b変換するプログラムを作っているのですが、L*a*b変換する際にうまく処理できず苦戦しています。
アドバイスよろしくお願いします。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>

//画像データを保存する構造体
typedef struct tagImageData{
	unsigned char *data;			//各画素の濃度値
	unsigned char header[54];		//画像のヘッダ
	int width;						//画像の横幅
	int height;						//画像の縦幅
}
ImageData;

//readImage:データの読み込み関数
//第一引数:読み出しファイルのファイルポインタ
//第二引数:読み出しデータの保存変数(ImageData型)

void readImage(FILE *fp, ImageData *img){
	//ヘッダ情報を読み込む
	fread(img->header, sizeof(unsigned char),54,fp);
	//ヘッダから画像の横幅を読み込む
	memcpy(&img->width,&img->header[18],4);
	//ヘッダから画像の縦幅を読み込む
	memcpy(&img->height,&img->header[22],4);
	
	//各画素の濃度値を保存する領域を確保
	img->data = (unsigned char *)malloc(sizeof(unsigned char) * img->width * img->height * 3);
	
	//画像データお読み込む
	fread(img->data,sizeof(unsigned char),img->width * img->height * 3,fp);
}

//writeImage:データの書き出し関数
//第一引数:書き出しファイルのファイルポインタ
//第二引数:書き出しデータの保存変数(ImageData型)

void writeImage(FILE *fp,ImageData *img){
	//ヘッダデータの書き出し
	fwrite(img->header, sizeof(unsigned char),54,fp);
	//画像データの書き出し
	fwrite(img->data,sizeof(unsigned char),img->width*img->height*3,fp);
}

void labImage(ImageData *img,ImageData *limg,ImageData *aimg,ImageData *bimg){
  int i,j;
  double l,a,b;
  unsigned char R,G,B;
  double X,Y,Z;
  long p;
  
  //X,Y,Zそれぞれの各画素の濃度値を保存する領域を確保

  limg->data=(unsigned char *)malloc(sizeof(unsigned char)*img->width*img->height*3);
  aimg->data=(unsigned char *)malloc(sizeof(unsigned char)*img->width*img->height*3);
  bimg->data=(unsigned char *)malloc(sizeof(unsigned char)*img->width*img->height*3);
  
  //X,Y,Z画像へヘッダ情報、横幅、縦幅の情報をコピーする
  limg->width=img->width;
  aimg->width=img->width;
  bimg->width=img->width;
  limg->height=img->height;
  aimg->height=img->height;
  bimg->height=img->height;
  
  for(i=0;i<54;i++){
    limg->header=img->header;
    aimg->header=img->header;
    bimg->header=img->header;
  }
  
  //各画素の濃度値を順番にコピーする
  for(j=0;j<img->height;j++){
    	for(i=0;i<img->width;i++){
    		p=j*img->width*3+i*3;     //元の位置
    		
    		B=img->data[p];    //青
    		G=img->data[p+1];  //緑
    		R=img->data[p+2];  //赤
    		
   			//XYZ表色系への変換       
   		 	X=2.7689*R+1.7517*G+1.1302*B;
  			Y=1.0000*R+4.5907*G+0.0601*B;
  			Z=0.0000*R+0.0565*G+5.5943*B;
  			
  			//L*a*b表色系への変換
  			if((X/99.09>0.008856) && (Y/100.00>0.008856) && (Z/85.32>0.008856)){
  				l=116*(pow(Y/100.00,1/3))-16;
  				a=500*(pow(X/99.09,1/3)-pow(Y/100.00,1/3));
  				b=200*(pow(Y/100.00,1/3)-pow(Z/85.32,1/3));
  			}
  			else{
  				l=116*(7.787*Y/100.00+16/116)-16;
  				a=500*(7.787*(X/99.09)+16/116-(7.787*Y/100.00+16/116));
  				b=200*(7.787*(Y/100.00)+16/116-(7.787*Z/85.32+16/116));
  			}
  			limg->data[p]=limg->data[p+1]=limg->data[p+2]=l;
			aimg->data[p]=aimg->data[p+1]=aimg->data[p+2]=a;
  			bimg->data[p]=bimg->data[p+1]=bimg->data[p+2]=b;		
    	}
  }
}

int main(void){
	FILE	        *fp;
	ImageData       inImg;
	ImageData		lImg,  aImg,  bImg;
	int                 i,j;
	
	//画像データを開く
	if((fp=fopen("lenna.bmp","rb"))==NULL){
		printf("file not found!!\n");
		exit(1);
	}

	readImage(fp,&inImg);
	
	fclose(fp);
	
    labImage(&inImg,&lImg,&aImg,&bImg);
    //出力画像ファイル(X)を開く
	if((fp=fopen("L*-result.bmp","wb"))==NULL){
		printf("file not found!!\n");
	exit(1);
	}
	
	writeImage(fp,&lImg);
	
    //出力画像ファイル(Y)を開く    
    if((fp=fopen("a*-result.bmp","wb"))==NULL){
        printf("file not found!!\n");
        exit(1);
    }
    writeImage(fp,&aImg);
    
    //出力画像ファイル(Z)を開く    
    if((fp=fopen("b*-result.bmp","wb"))==NULL){
        printf("file not found!!\n");
        exit(1);
    }
    writeImage(fp,&bImg);
	
	fclose(fp);

	free(inImg.data);
	free(lImg.data);
    free(aImg.data);
    free(bImg.data);
	return 0;
}

Re:L*a*b変換について

Posted: 2009年5月16日(土) 22:52
by box
> 今回XYZ値をL*a*b変換するプログラムを作っているのですが、L*a*b変換する際にうまく処理できず苦戦しています。

うまく処理できずに苦戦されている、というのは、

>   //各画素の濃度値を順番にコピーする
>   for(j=0;jheight;j++){
>     	for(i=0;iwidth;i++){

ここの2行で出るコンパイルエラーのことですか?

Re:L*a*b変換について

Posted: 2009年5月16日(土) 23:18
by packls
boxさん回答ありがとうございます。
ソースをペーストする際に->が抜けてしまいました。
正しくは
//各画素の濃度値を順番にコピーする
for(j=0;j<img->height;j++){
  for(i=0;i<img->width;i++){
です。

Re:L*a*b変換について

Posted: 2009年5月16日(土) 23:48
by box
で、肝心の

>L*a*b変換する際にうまく処理できず苦戦しています。

この内容は、どうなりましたか?
また、テスト用の入力ファイルはありますか?

Re:L*a*b変換について

Posted: 2009年5月17日(日) 00:15
by box
>	if((fp=fopen("L*-result.bmp","wb"))==NULL){

Windowsで開発しているとすると、ファイル名そのものに'*'は使えません。

Re:L*a*b変換について

Posted: 2009年5月17日(日) 01:11
by pcckls
ubuntuで開発しています。
コンパイルはうまくいき、出力ファイルもちゃんとできるのですが、正しく出力ファイルの画像が表示されない状態です。
自分が思うにLab変換の部分がひっかかってると思うのですが、どなたか分かりますか?
かなり人任せな感じになってしまったのですが、よろしくお願いします。