X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=images%2Fcolor.c;h=80f48294c86c0db14d7d5fe925a365c6469208ef;hb=9c00dfe809b9ac03c1cbe8a233812f486f64ddcb;hp=e6846605681d45a4c955f30192113370445a542c;hpb=35d602a8f8676b8988eca13086c63f2026c1b952;p=libucw.git diff --git a/images/color.c b/images/color.c index e6846605..80f48294 100644 --- a/images/color.c +++ b/images/color.c @@ -11,8 +11,61 @@ #include "sherlock/sherlock.h" #include "lib/math.h" +#include "images/images.h" #include "images/color.h" +struct color color_black = { .color_space = COLOR_SPACE_GRAYSCALE }; +struct color color_white = { .c = { 255 }, .color_space = COLOR_SPACE_GRAYSCALE }; + +inline void +color_put_grayscale(byte *dest, struct color *color) +{ + switch (color->color_space) + { + case COLOR_SPACE_GRAYSCALE: + dest[0] = color->c[0]; + break; + case COLOR_SPACE_RGB: + dest[0] = rgb_to_gray_func(color->c[0], color->c[1], color->c[2]); + break; + default: + ASSERT(0); + } +} + +inline void +color_put_rgb(byte *dest, struct color *color) +{ + switch (color->color_space) + { + case COLOR_SPACE_GRAYSCALE: + dest[0] = dest[1] = dest[2] = color->c[0]; + break; + case COLOR_SPACE_RGB: + dest[0] = color->c[0]; + dest[1] = color->c[1]; + dest[2] = color->c[2]; + break; + default: + ASSERT(0); + } +} + +void +color_put_color_space(byte *dest, struct color *color, enum color_space color_space) +{ + switch (color_space) + { + case COLOR_SPACE_GRAYSCALE: + color_put_grayscale(dest, color); + break; + case COLOR_SPACE_RGB: + color_put_rgb(dest, color); + break; + default: + ASSERT(0); + } +} /********************* EXACT CONVERSION ROUTINES **********************/ @@ -31,6 +84,21 @@ srgb_to_xyz_slow(double xyz[3], double srgb[3]) xyz[2] = SRGB_XYZ_ZR * a[0] + SRGB_XYZ_ZG * a[1] + SRGB_XYZ_ZB * a[2]; } +/* XYZ to sRGB */ +void +xyz_to_srgb_slow(double srgb[3], double xyz[3]) +{ + double a[3]; + a[0] = 3.2406 * xyz[0] + -1.5372 * xyz[1] + -0.4986 * xyz[2]; + a[1] = -0.9689 * xyz[0] + 1.8758 * xyz[1] + 0.0415 * xyz[2]; + a[2] = 0.0557 * xyz[0] + -0.2040 * xyz[1] + 1.0570 * xyz[2]; + for (uns i = 0; i < 3; i++) + if (a[i] > 0.0031308) + srgb[i] = 1.055 * pow(a[i], 1 / 2.4) - 0.055; + else + srgb[i] = 12.92 * a[i]; +} + /* XYZ to CIE-Luv */ void xyz_to_luv_slow(double luv[3], double xyz[3]) @@ -52,6 +120,23 @@ xyz_to_luv_slow(double luv[3], double xyz[3]) } } +/* CIE-Luv to XYZ */ +void +luv_to_xyz_slow(double xyz[3], double luv[3]) +{ + double var_u = luv[1] / (13 * luv[0]) + (4 * REF_WHITE_X / (REF_WHITE_X + 15 * REF_WHITE_Y + 3 * REF_WHITE_Z)); + double var_v = luv[2] / (13 * luv[0]) + (9 * REF_WHITE_Y / (REF_WHITE_X + 15 * REF_WHITE_Y + 3 * REF_WHITE_Z)); + double var_y = (luv[0] + 16) / 116; + double pow_y = var_y * var_y * var_y; + if (pow_y > 0.008856) + var_y = pow_y; + else + var_y = (var_y - 16 / 116) / 7.787; + xyz[1] = var_y; + xyz[0] = -(9 * xyz[1] * var_u) / ((var_u - 4) * var_v - var_u * var_v); + xyz[2] = (9 * xyz[1] - 15 * var_v * xyz[1] - var_v * xyz[0]) / (3 * var_v); +} + /***************** OPTIMIZED SRGB -> LUV CONVERSION *********************/