tools
読み取り中…
検索中…
一致する文字列を見つけられません
colorConverter.h
[詳解]
1#pragma once
2#include <iostream>
3#include <cmath>
4#include <stdexcept>
5#include <algorithm>
6
7/**
8 * @file colorConverter.h
9 * @brief 色空間変換ユーティリティ
10 *
11 * RGB・CMYK・HSL・HSB(HSV)・CIE Lab の各色空間間で相互変換する
12 * 関数と構造体を提供します。
13 */
14
15/**
16 * @namespace ccv
17 * @brief 色変換ユーティリティ用名前空間
18 */
19namespace ccv {
20
21/**
22 * @struct RGB
23 * @brief RGB 色空間を表す構造体(各成分 0〜255 の整数)
24 */
25struct RGB {
26 int r; ///< 赤成分 (0〜255)
27 int g; ///< 緑成分 (0〜255)
28 int b; ///< 青成分 (0〜255)
29 /** @brief コンストラクタ @param ir 赤 @param ig 緑 @param ib 青 */
30 RGB(int ir, int ig, int ib): r(ir), g(ig), b(ib) {}
31 RGB() {}
32};
33
34/**
35 * @struct CMYK
36 * @brief CMYK 色空間を表す構造体(各成分 0.0〜1.0 の浮動小数点数)
37 */
38struct CMYK {
39 float c; ///< シアン (0.0〜1.0)
40 float m; ///< マゼンタ (0.0〜1.0)
41 float y; ///< イエロー (0.0〜1.0)
42 float k; ///< キー(黒)(0.0〜1.0)
43 /** @brief コンストラクタ @param ic シアン @param im マゼンタ @param iy イエロー @param ik キー */
44 CMYK(float ic, float im, float iy, float ik): c(ic), m(im), y(iy), k(ik) {}
45 CMYK() {}
46};
47
48/**
49 * @struct HSL
50 * @brief HSL 色空間を表す構造体
51 */
52struct HSL {
53 float h; ///< 色相 (0〜360)
54 float s; ///< 彩度 (0.0〜1.0)
55 float l; ///< 輝度 (0.0〜1.0)
56 /** @brief コンストラクタ @param ih 色相 @param is 彩度 @param il 輝度 */
57 HSL(float ih, float is, float il): h(ih), s(is), l(il) {}
58 HSL() {}
59};
60
61/**
62 * @struct HSB
63 * @brief HSB (HSV) 色空間を表す構造体
64 */
65struct HSB {
66 float h; ///< 色相 (0〜360)
67 float s; ///< 彩度 (0.0〜1.0)
68 float b; ///< 明度 (0.0〜1.0)
69 /** @brief コンストラクタ @param ih 色相 @param is 彩度 @param ib 明度 */
70 HSB(float ih, float is, float ib): h(ih), s(is), b(ib) {}
71 HSB() {}
72};
73
74/**
75 * @struct Lab
76 * @brief CIE L*a*b* 色空間を表す構造体
77 */
78struct Lab {
79 float l; ///< 明度 L* (0〜100)
80 float a; ///< 色度軸 a* (負:緑〜正:赤)
81 float b; ///< 色度軸 b* (負:青〜正:黄)
82 /** @brief コンストラクタ @param il L* @param ia a* @param ib b* */
83 Lab(float il, float ia, float ib): l(il), a(ia), b(ib) {}
84 Lab() {}
85};
86
87/**
88 * @brief HEX 値(整数)を RGB 構造体に変換する
89 * @param hex 0xRRGGBB 形式の色値
90 * @return 変換後の RGB 構造体
91 */
92RGB hexToRgb(int hex) {
93 RGB rgb;
94 rgb.r = (hex >> 16) & 0xFF; // 上位8ビットを取得
95 rgb.g = (hex >> 8) & 0xFF; // 中間8ビットを取得
96 rgb.b = hex & 0xFF; // 下位8ビットを取得
97 return rgb;
98}
99
100/**
101 * @brief RGB 構造体を HEX 値(整数)に変換する
102 * @param rgb 変換元の RGB 構造体
103 * @return 0xRRGGBB 形式の整数値
104 */
105int rgbToHex(RGB rgb) {
106 return (rgb.r << 16) | (rgb.g << 8) | rgb.b;
107}
108
109/**
110 * @brief RGB を CMYK に変換する
111 * @param rgb 変換元の RGB 構造体
112 * @return 変換後の CMYK 構造体
113 */
115 CMYK cmyk;
116 float r = rgb.r / 255.0;
117 float g = rgb.g / 255.0;
118 float b = rgb.b / 255.0;
119
120 cmyk.k = 1 - std::max({r, g, b});
121 if (cmyk.k < 1) {
122 cmyk.c = (1 - r - cmyk.k) / (1 - cmyk.k);
123 cmyk.m = (1 - g - cmyk.k) / (1 - cmyk.k);
124 cmyk.y = (1 - b - cmyk.k) / (1 - cmyk.k);
125 } else {
126 cmyk.c = cmyk.m = cmyk.y = 0;
127 }
128 return cmyk;
129}
130
131/**
132 * @brief CMYK を RGB に変換する
133 * @param cmyk 変換元の CMYK 構造体
134 * @return 変換後の RGB 構造体
135 */
137 RGB rgb;
138 rgb.r = static_cast<int>((1 - cmyk.c) * (1 - cmyk.k) * 255);
139 rgb.g = static_cast<int>((1 - cmyk.m) * (1 - cmyk.k) * 255);
140 rgb.b = static_cast<int>((1 - cmyk.y) * (1 - cmyk.k) * 255);
141 return rgb;
142}
143
144/**
145 * @brief RGB を HSL に変換する
146 * @param rgb 変換元の RGB 構造体
147 * @return 変換後の HSL 構造体(色相 0〜360°)
148 */
150 HSL hsl;
151 float r = rgb.r / 255.0;
152 float g = rgb.g / 255.0;
153 float b = rgb.b / 255.0;
154
155 float max = std::max({r, g, b});
156 float min = std::min({r, g, b});
157 hsl.l = (max + min) / 2;
158
159 if (max == min) {
160 hsl.h = hsl.s = 0; // achromatic
161 } else {
162 float d = max - min;
163 hsl.s = (hsl.l > 0.5) ? d / (2 - max - min) : d / (max + min);
164 if (max == r) {
165 hsl.h = fmod((g - b) / d + (g < b ? 6 : 0), 6);
166 } else if (max == g) {
167 hsl.h = (b - r) / d + 2;
168 } else {
169 hsl.h = (r - g) / d + 4;
170 }
171 hsl.h *= 60;
172 }
173 return hsl;
174}
175
176/**
177 * @brief HSL を RGB に変換する
178 * @param hsl 変換元の HSL 構造体(色相 0〜360°)
179 * @return 変換後の RGB 構造体
180 */
182 RGB rgb;
183 float c = (1 - std::abs(2 * hsl.l - 1)) * hsl.s;
184 float x = c * (1 - std::abs(fmod(hsl.h / 60.0, 2) - 1));
185 float m = hsl.l - c / 2;
186
187 float r, g, b;
188 if (hsl.h < 60) {
189 r = c; g = x; b = 0;
190 } else if (hsl.h < 120) {
191 r = x; g = c; b = 0;
192 } else if (hsl.h < 180) {
193 r = 0; g = c; b = x;
194 } else if (hsl.h < 240) {
195 r = 0; g = x; b = c;
196 } else if (hsl.h < 300) {
197 r = x; g = 0; b = c;
198 } else {
199 r = c; g = 0; b = x;
200 }
201
202 rgb.r = static_cast<int>((r + m) * 255);
203 rgb.g = static_cast<int>((g + m) * 255);
204 rgb.b = static_cast<int>((b + m) * 255);
205 return rgb;
206}
207
208/**
209 * @brief RGB を HSB (HSV) に変換する
210 * @param rgb 変換元の RGB 構造体
211 * @return 変換後の HSB 構造体(色相 0〜360°)
212 */
214 HSB hsb;
215 float r = rgb.r / 255.0;
216 float g = rgb.g / 255.0;
217 float b = rgb.b / 255.0;
218
219 float max = std::max({r, g, b});
220 float min = std::min({r, g, b});
221 hsb.b = max;
222
223 float d = max - min;
224 hsb.s = (max == 0) ? 0 : d / max;
225
226 if (max == min) {
227 hsb.h = 0; // achromatic
228 } else {
229 if (max == r) {
230 hsb.h = fmod((g - b) / d, 6);
231 } else if (max == g) {
232 hsb.h = (b - r) / d + 2;
233 } else {
234 hsb.h = (r - g) / d + 4;
235 }
236 hsb.h *= 60;
237 if (hsb.h < 0) hsb.h += 360;
238 }
239 return hsb;
240}
241
242/**
243 * @brief HSB (HSV) を RGB に変換する
244 * @param hsb 変換元の HSB 構造体(色相 0〜360°)
245 * @return 変換後の RGB 構造体
246 */
248 RGB rgb;
249 float c = hsb.b * hsb.s;
250 float x = c * (1 - std::abs(fmod(hsb.h / 60.0, 2) - 1));
251 float m = hsb.b - c;
252
253 float r, g, b;
254 if (hsb.h < 60) {
255 r = c; g = x; b = 0;
256 } else if (hsb.h < 120) {
257 r = x; g = c; b = 0;
258 } else if (hsb.h < 180) {
259 r = 0; g = c; b = x;
260 } else if (hsb.h < 240) {
261 r = 0; g = x; b = c;
262 } else if (hsb.h < 300) {
263 r = x; g = 0; b = c;
264 } else {
265 r = c; g = 0; b = x;
266 }
267
268 rgb.r = static_cast<int>((r + m) * 255);
269 rgb.g = static_cast<int>((g + m) * 255);
270 rgb.b = static_cast<int>((b + m) * 255);
271 return rgb;
272}
273
274/**
275 * @brief RGB を CIE L*a*b* に変換する
276 *
277 * sRGB → XYZ (D65) → Lab の2段階変換を行います。
278 *
279 * @param rgb 変換元の RGB 構造体
280 * @return 変換後の Lab 構造体
281 */
283 Lab lab;
284 float r = rgb.r / 255.0;
285 float g = rgb.g / 255.0;
286 float b = rgb.b / 255.0;
287
288 // sRGBをXYZに変換
289 r = (r > 0.04045) ? std::pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
290 g = (g > 0.04045) ? std::pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
291 b = (b > 0.04045) ? std::pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
292
293 float x = r * 0.4124564 + g * 0.3575761 + b * 0.1804375;
294 float y = r * 0.2126729 + g * 0.7151522 + b * 0.0721750;
295 float z = r * 0.0193339 + g * 0.1191920 + b * 0.9503041;
296
297 // XYZをLabに変換
298 x /= 0.95047; // reference white
299 y /= 1.00000;
300 z /= 1.08883;
301
302 x = (x > 0.008856) ? std::pow(x, 1.0 / 3.0) : (x * 7.787 + 16 / 116.0);
303 y = (y > 0.008856) ? std::pow(y, 1.0 / 3.0) : (y * 7.787 + 16 / 116.0);
304 z = (z > 0.008856) ? std::pow(z, 1.0 / 3.0) : (z * 7.787 + 16 / 116.0);
305
306 lab.l = (116 * y) - 16;
307 lab.a = 500 * (x - y);
308 lab.b = 200 * (y - z);
309
310 return lab;
311}
312
313/**
314 * @brief CIE L*a*b* を RGB に変換する
315 *
316 * Lab → XYZ (D65) → sRGB の2段階変換を行います。
317 * 変換後の RGB 値は 0〜255 にクランプされます。
318 *
319 * @param lab 変換元の Lab 構造体
320 * @return 変換後の RGB 構造体
321 */
323 RGB rgb;
324 float y = (lab.l + 16) / 116;
325 float x = lab.a / 500 + y;
326 float z = y - lab.b / 200;
327
328 // Inverse transformation
329 y = std::pow(y, 3) > 0.008856 ? std::pow(y, 3) : (y - 16 / 116) / 7.787;
330 x = std::pow(x, 3) > 0.008856 ? std::pow(x, 3) : (x - 16 / 116) / 7.787;
331 z = std::pow(z, 3) > 0.008856 ? std::pow(z, 3) : (z - 16 / 116) / 7.787;
332
333 x *= 0.95047; // reference white
334 y *= 1.00000;
335 z *= 1.08883;
336
337 rgb.r = static_cast<int>(std::clamp((x * 3.2404542 - y * 1.5371385 - z * 0.4985314) * 255, 0.0, 255.0));
338 rgb.g = static_cast<int>(std::clamp((-x * 0.9692660 + y * 1.8760108 + z * 0.0415560) * 255, 0.0, 255.0));
339 rgb.b = static_cast<int>(std::clamp((x * 0.0556434 - y * 0.2040259 + z * 1.0572252) * 255, 0.0, 255.0));
340
341 return rgb;
342}
343}
色変換ユーティリティ用名前空間
HSB rgbToHsb(RGB rgb)
RGB を HSB (HSV) に変換する
RGB hexToRgb(int hex)
HEX 値(整数)を RGB 構造体に変換する
RGB labToRgb(Lab lab)
CIE L*a*b* を RGB に変換する
RGB hslToRgb(HSL hsl)
HSL を RGB に変換する
HSL rgbToHsl(RGB rgb)
RGB を HSL に変換する
int rgbToHex(RGB rgb)
RGB 構造体を HEX 値(整数)に変換する
RGB hsbToRgb(HSB hsb)
HSB (HSV) を RGB に変換する
RGB cmykToRgb(CMYK cmyk)
CMYK を RGB に変換する
CMYK rgbToCmyk(RGB rgb)
RGB を CMYK に変換する
Lab rgbToLab(RGB rgb)
RGB を CIE L*a*b* に変換する
CMYK 色空間を表す構造体(各成分 0.0〜1.0 の浮動小数点数)
float k
キー(黒)(0.0〜1.0)
CMYK(float ic, float im, float iy, float ik)
コンストラクタ
float y
イエロー (0.0〜1.0)
float c
シアン (0.0〜1.0)
float m
マゼンタ (0.0〜1.0)
HSB (HSV) 色空間を表す構造体
HSB(float ih, float is, float ib)
コンストラクタ
float b
明度 (0.0〜1.0)
float s
彩度 (0.0〜1.0)
float h
色相 (0〜360)
HSL 色空間を表す構造体
float l
輝度 (0.0〜1.0)
float h
色相 (0〜360)
HSL(float ih, float is, float il)
コンストラクタ
float s
彩度 (0.0〜1.0)
CIE L*a*b* 色空間を表す構造体
Lab(float il, float ia, float ib)
コンストラクタ
float b
色度軸 b* (負:青〜正:黄)
float l
明度 L* (0〜100)
float a
色度軸 a* (負:緑〜正:赤)
RGB 色空間を表す構造体(各成分 0〜255 の整数)
int r
赤成分 (0〜255)
int b
青成分 (0〜255)
RGB(int ir, int ig, int ib)
コンストラクタ
int g
緑成分 (0〜255)
@ y
Definition time.h:33
@ c
マイクロ秒
Definition time.h:26
@ m
Definition time.h:29
@ d
Definition time.h:31