【C言語】XYZ表色系をL*a*b*表色系に変換するプログラム 【C言語】XYZ表色系をL*a*b*表色系に変換するプログラム – みなためラボ

【C言語】XYZ表色系をL*a*b*表色系に変換するプログラム


文字サイズ:?? (px)

はじめに

みなため

どうも! みなため(@MinatameT)です。

この記事は、「XYZ表色系やL*a*b*表色系については大体知っている」という方を対象にしています。そのため、これらの表色系については簡単に説明しておきます。

まず、XYZ表色系には次のような特徴があります。

  • Xは赤色の強さ。数値が大きいほど、赤色が強くなる。
  • Yは緑色の強さと明るさ(輝度)。数値が大きいほど、緑色が強くなり、明るくなる。値の範囲は、0.0から1.0とする場合と、それを100倍にして0から100とする場合がある。
  • Zは青色の強さ。数値が大きいほど、青色が強くなる。
  • RGB表色系と違って、すべての色を表現できる。

また、L*a*b*表色系には次のような特徴があります。

  • L*は明るさ。0から100までの範囲で、数値が大きいほど明るい。
  • a*は赤色の強さ。a*が大きくなるほど赤色が強くなり、a*が小さくなるほど緑色が強くなる。
  • b*は黄色の強さ。b*が大きくなるほど黄色が強くなり、b*が小さくなるほど青色が強くなる。

なお、関連記事に「RGB表色系をXYZ表色系に変換するプログラム」があります。必要であればご覧ください。

キャラクター

それでは、ソースコードと実行結果を確認していきます。

XYZ表色系からL*a*b*表色系に変換するプログラム

まず、Yの範囲が0.0から1.0の場合のソースコードと実行結果です。

ソースコード(Yの範囲が0.0から1.0の場合)

#include<stdio.h>
#include<math.h>

int main(void)
{
  double X,Y,Z;
  double Xp,Yp,Zp;
  double L,a,b;

  printf("Yの値の範囲は0.0から1.0です。\n");
  printf("Xの値を入力してください。>");
  scanf("%lf",&X);
  printf("Yの値を入力してください。>");
  scanf("%lf",&Y);
  printf("Zの値を入力してください。>");
  scanf("%lf",&Z);

  Xp = X*(100.0/95.047);
  Yp = Y*(100.0/100.0);
  Zp = Z*(100.0/108.883);

  if(Xp>0.008856)
  {
    Xp = pow(Xp,(double)1/3);
  }
  else
  {
    Xp = (7.787*Xp) + ((double)16/116);
  }
  if(Yp>0.008856)
  {
    Yp = pow(Yp,(double)1/3);
  }
  else
  {
    Yp = (7.787*Yp) + ((double)16/116);
  }
  if(Zp>0.008856)
  {
    Zp = pow(Zp,(double)1/3);
  }
  else
  {
    Zp = (7.787*Zp) + ((double)16/116);
  }

  L = (116*Yp) - 16;
  a = 500*(Xp - Yp);
  b = 200*(Yp - Zp);

  printf("・XYZ表色系   :(%0.4f,%0.4f,%0.4f)\n",X,Y,Z);
  printf("・L*a*b*表色系:(%0.4f,%0.4f,%0.4f)\n",L,a,b);
	
  return(0);
}

pow関数は、累乗計算をするためのものです。pow関数を使うためには、「#include<math.h>」を記述しておく必要があります。

pow関数の文法や使用例については、次の記事をご覧ください。

それでは、実行結果の例を確認していきます。

実行結果の例(Yの範囲が0.0から1.0の場合)

Yの値の範囲は0.0から1.0です。
Xの値を入力してください。>0.5703
Yの値を入力してください。>0.7693
Zの値を入力してください。>0.2320
・XYZ表色系   :(0.5703,0.7693,0.2320)
・L*a*b*表色系:(90.2894,-36.4231,63.8021)

色は以下の円のとおりです。

L*a*b* = (90.2894,-36.4231,63.8021)

もう1つだけ例を示します。

Yの値の範囲は0.0から1.0です。
Xの値を入力してください。>0.2121
Yの値を入力してください。>0.1337
Zの値を入力してください。>0.0932
・XYZ表色系   :(0.2121,0.1337,0.0932)
・L*a*b*表色系:(43.3155,47.6052,14.1264)

色は以下の円のとおりです。

L*a*b* = (43.3155,47.6052,14.1264)

このように、XYZ表色系をL*a*b*表色系に変換することができました!

次は、Yの範囲が0から100の場合のソースコードと実行結果です。上記の場合と異なり、X、Y、Zそれぞれの値を100倍にして入力します。

ソースコード(Yの範囲が0から100の場合)

#include<stdio.h>
#include<math.h>

int main(void)
{
  double X,Y,Z;
  double Xp,Yp,Zp;
  double L,a,b;

  printf("Yの値の範囲は0から100です。\n");
  printf("Xの値を入力してください。>");
  scanf("%lf",&X);
  printf("Yの値を入力してください。>");
  scanf("%lf",&Y);
  printf("Zの値を入力してください。>");
  scanf("%lf",&Z);

  Xp = X/95.047;
  Yp = Y/100.0;
  Zp = Z/108.883;

  if(Xp>0.008856)
  {
    Xp = pow(Xp,(double)1/3);
  }
  else
  {
    Xp = (7.787*Xp) + ((double)16/116);
  }
  if(Yp>0.008856)
  {
    Yp = pow(Yp,(double)1/3);
  }
  else
  {
    Yp = (7.787*Yp) + ((double)16/116);
  }
  if(Zp>0.008856)
  {
    Zp = pow(Zp,(double)1/3);
  }
  else
  {
    Zp = (7.787*Zp) + ((double)16/116);
  }

  L = (116*Yp) - 16;
  a = 500*(Xp - Yp);
  b = 200*(Yp - Zp);

  printf("・XYZ表色系   :(%0.4f,%0.4f,%0.4f)\n",X,Y,Z);
  printf("・L*a*b*表色系:(%0.4f,%0.4f,%0.4f)\n",L,a,b);
	
  return(0);
}

それでは、実行結果の例を確認していきます。

実行結果の例(Yの範囲が0から100の場合)

Yの値の範囲は0から100です。
Xの値を入力してください。>50.95
Yの値を入力してください。>68.94
Zの値を入力してください。>105.23
・XYZ表色系   :(50.9500,68.9400,105.2300)
・L*a*b*表色系:(86.4743,-35.5321,-21.0580)

色は以下の円のとおりです。

L*a*b* = (86.4743,-35.5321,-21.0580)

もう1つだけ例を示します。

Yの値の範囲は0から100です。
Xの値を入力してください。>80.5
Yの値を入力してください。>82.2
Zの値を入力してください。>84.1
・XYZ表色系   :(80.5000,82.2000,84.1000)
・L*a*b*表色系:(92.6631,4.6916,3.8476)

色は以下の円のとおりです。

L*a*b* = (92.6631,4.6916,3.8476)

このように、XYZ表色系をLab*表色系に変換することができました!

キャラクター

今回はここまでです。かなりマニアックな内容の記事だったと思います。皆さん、お疲れさまでした。

追記:反省とお礼

この記事(修正前)について、ある親切な方から「実行結果の値がおかしい」とのご指摘をいただきました。

ソースコードをよく確認したところ、pow関数内の分数のdouble型への「型キャスト」を忘れており、正しいXp、Yp、Zpの値が計算できていませんでした。

私の確認不足によって一部の読者さんにご迷惑をおかけしたことを反省し、次からは内容の正確性の確認の強化に努めます。

ご指摘をしてくださった親切な方には、本当に感謝しています。ありがとうございます。

記事本文下のバナー広告

この記事をSNSでシェアする

 

プログラミングカテゴリーの最新記事(5件)

管理人のTwitter

Tweets by MinatameT

内部リンク集

広告枠のレンタルの詳細はこちら!
記事作成のご依頼の詳細はこちら!