diff options
author | Mattias Andrée <maandree@kth.se> | 2017-06-12 18:03:48 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2017-06-12 18:03:48 +0200 |
commit | 7871f5f946ce19c22c1b69a1019dee9cfa665731 (patch) | |
tree | d28f677ab6e4a4c4c5a194c66e1ba4ef53f3ee80 /en_masse-template.c | |
parent | Make conversion macros not require restrict (diff) | |
download | libcolour-7871f5f946ce19c22c1b69a1019dee9cfa665731.tar.gz libcolour-7871f5f946ce19c22c1b69a1019dee9cfa665731.tar.bz2 libcolour-7871f5f946ce19c22c1b69a1019dee9cfa665731.tar.xz |
libcolour_convert uses libcolour_convert_en_masse instead of the other way around
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'en_masse-template.c')
-rw-r--r-- | en_masse-template.c | 693 |
1 files changed, 647 insertions, 46 deletions
diff --git a/en_masse-template.c b/en_masse-template.c index 9a9f17f..b539328 100644 --- a/en_masse-template.c +++ b/en_masse-template.c @@ -1,5 +1,620 @@ /* See LICENSE file for copyright and license details. */ +#define XPARAMETERS\ + size_t n, size_t width, TYPE *ch1, TYPE *ch2, TYPE *ch3 + +#define XARGUMENTS\ + (n), (width), (ch1), (ch2), (ch3) + +#define PARAMETERS(FROM_SPACE, TO_SPACE)\ + const libcolour_##FROM_SPACE##_t *from, const libcolour_##TO_SPACE##_t *to, XPARAMETERS + +#define ARGUMENTS(FROM, TO)\ + (FROM), (TO), XARGUMENTS + + +#define SIMPLE_LOOP(CH, INSTRUCTIONS)\ + do {\ + TYPE *ch = (CH);\ + size_t i__;\ + for (i__ = 0; i__ < n; i__++) {\ + INSTRUCTIONS;\ + (CH) += width;\ + }\ + (CH) = ch;\ + } while (0) + +#define LOOP(INSTRUCTIONS)\ + do {\ + TYPE *c1 = ch1, *c2 = ch2, *c3 = ch3;\ + size_t i__;\ + for (i__ = 0; i__ < n; i__++) {\ + INSTRUCTIONS;\ + ch1 += width;\ + ch2 += width;\ + ch3 += width;\ + }\ + ch1 = c1;\ + ch2 = c2;\ + ch3 = c3;\ + } while (0) + +#define CONV_0(MACRO)\ + LOOP(MACRO(*ch1, *ch2, *ch3, *ch1, *ch2, *ch3)) + +#define CONV_N(MACRO, ...)\ + LOOP(MACRO(*ch1, *ch2, *ch3, *ch1, *ch2, *ch3, __VA_ARGS__)) + + +#define LINEAR_SRGB\ + do {\ + if (from->srgb.with_transfer) {\ + libcolour_srgb_t srgb__ = from->srgb;\ + srgb__.with_transfer = 0;\ + to_srgb(ARGUMENTS(from, &srgb__));\ + }\ + } while (0) + + + +#define X(C, T, N) static void to_##N(const libcolour_colour_t *from, const T *to, XPARAMETERS); +LIST_MODELS(X) +#undef X + + + +static void +conversion_by_matrix(XPARAMETERS, TYPE m11, TYPE m12, TYPE m13, TYPE m21, TYPE m22, TYPE m23, TYPE m31, TYPE m32, TYPE m33) +{ + TYPE c1, c2, c3; + while (n--) { + c1 = *ch1; + c2 = *ch2; + c3 = *ch3; + *ch1 = m11 * c1 + m12 * c2 + m13 * c3; + *ch2 = m21 * c1 + m22 * c2 + m23 * c3; + *ch3 = m31 * c1 + m32 * c2 + m33 * c3; + ch1 += width; + ch2 += width; + ch3 += width; + } +} + + +static void +rgb_encode(XPARAMETERS, const libcolour_rgb_t *restrict space) +{ + TYPE r_sign, g_sign, b_sign; + switch (space->encoding_type) { + case LIBCOLOUR_ENCODING_TYPE_LINEAR: + break; + case LIBCOLOUR_ENCODING_TYPE_SIMPLE: + case LIBCOLOUR_ENCODING_TYPE_REGULAR: + LOOP(do { + (r_sign = 1, g_sign = 1, b_sign = 1); + if (*ch1 < 0) (r_sign = -1, *ch1 = -*ch1); + if (*ch2 < 0) (g_sign = -1, *ch2 = -*ch2); + if (*ch3 < 0) (b_sign = -1, *ch3 = -*ch3); + if (space->encoding_type == LIBCOLOUR_ENCODING_TYPE_SIMPLE) { + *ch1 = xpow(*ch1, 1 / space->GAMMA); + *ch2 = xpow(*ch2, 1 / space->GAMMA); + *ch3 = xpow(*ch3, 1 / space->GAMMA); + } else { + *ch1 = REGULAR(space, *ch1); + *ch2 = REGULAR(space, *ch2); + *ch3 = REGULAR(space, *ch3); + } + *ch1 *= r_sign; + *ch2 *= g_sign; + *ch3 *= b_sign; + } while (0)); + break; + case LIBCOLOUR_ENCODING_TYPE_CUSTOM: + LOOP((*ch1 = (space->TO_ENCODED_RED)(*ch1), + *ch2 = (space->TO_ENCODED_GREEN)(*ch2), + *ch3 = (space->TO_ENCODED_BLUE)(*ch3))); + break; + default: + fprintf(stderr, "libcolour: invalid encoding type\n"); + abort(); + } +} + +static void +rgb_decode(XPARAMETERS, const libcolour_rgb_t *restrict space) +{ + TYPE r_sign, g_sign, b_sign; + switch (space->encoding_type) { + case LIBCOLOUR_ENCODING_TYPE_LINEAR: + break; + case LIBCOLOUR_ENCODING_TYPE_SIMPLE: + case LIBCOLOUR_ENCODING_TYPE_REGULAR: + LOOP(do { + (r_sign = 1, g_sign = 1, b_sign = 1); + if (*ch1 < 0) (r_sign = -1, *ch1 = -*ch1); + if (*ch2 < 0) (g_sign = -1, *ch2 = -*ch2); + if (*ch3 < 0) (b_sign = -1, *ch3 = -*ch3); + if (space->encoding_type == LIBCOLOUR_ENCODING_TYPE_SIMPLE) { + *ch1 = xpow(*ch1, space->GAMMA); + *ch2 = xpow(*ch2, space->GAMMA); + *ch3 = xpow(*ch3, space->GAMMA); + } else { + *ch1 = INVREGULAR(space, *ch1); + *ch2 = INVREGULAR(space, *ch2); + *ch3 = INVREGULAR(space, *ch3); + } + *ch1 *= r_sign; + *ch2 *= g_sign; + *ch3 *= b_sign; + } while (0)); + break; + case LIBCOLOUR_ENCODING_TYPE_CUSTOM: + LOOP((*ch1 = (space->TO_DECODED_RED)(*ch1), + *ch2 = (space->TO_DECODED_GREEN)(*ch2), + *ch3 = (space->TO_DECODED_BLUE)(*ch3))); + break; + default: + fprintf(stderr, "libcolour: invalid encoding type\n"); + abort(); + } +} + +static int +rgb_same_transfer(const libcolour_rgb_t *a, const libcolour_rgb_t *b) +{ + if (a->encoding_type != b->encoding_type) + return 0; + switch (a->encoding_type) { + case LIBCOLOUR_ENCODING_TYPE_SIMPLE: + return a->GAMMA == b->GAMMA; + case LIBCOLOUR_ENCODING_TYPE_REGULAR: + return a->GAMMA == b->GAMMA && + a->OFFSET == b->OFFSET && + a->SLOPE == b->SLOPE && + a->TRANSITION == b->TRANSITION; + case LIBCOLOUR_ENCODING_TYPE_CUSTOM: + return a->TO_ENCODED_RED == b->TO_ENCODED_RED && + a->TO_ENCODED_GREEN == b->TO_ENCODED_GREEN && + a->TO_ENCODED_BLUE == b->TO_ENCODED_BLUE && + a->TO_DECODED_RED == b->TO_DECODED_RED && + a->TO_DECODED_GREEN == b->TO_DECODED_GREEN && + a->TO_DECODED_BLUE == b->TO_DECODED_BLUE; + default: + return 1; + } +} + +static void +to_rgb(PARAMETERS(colour, rgb)) +{ + int have_transfer = 0, with_transfer = to->with_transfer; + switch (from->model) { + case LIBCOLOUR_RGB: + if (!memcmp(from->rgb.M, to->M, sizeof(TYPE[3][3]))) { + have_transfer = from->rgb.with_transfer; + if (have_transfer && with_transfer && !rgb_same_transfer(&from->rgb, to)) { + rgb_decode(XARGUMENTS, &from->rgb); + have_transfer = 0; + } + break; + } + /* fall through */ + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_RGB(to->Minv)); + break; + } + + if (have_transfer != with_transfer) { + if (with_transfer) + rgb_encode(XARGUMENTS, to); + else + rgb_decode(XARGUMENTS, &from->rgb); + } +} + + +static void +to_srgb(PARAMETERS(colour, srgb)) +{ + libcolour_srgb_t tmp; + switch (from->model) { + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_SRGB); + break; + case LIBCOLOUR_SRGB: + srgb_to_srgb: + if (from->srgb.with_transfer != to->with_transfer) { + if (to->with_transfer) { + LOOP((*ch1 = srgb_encode(*ch1), + *ch2 = srgb_encode(*ch2), + *ch3 = srgb_encode(*ch3))); + } else { + LOOP((*ch1 = srgb_decode(*ch1), + *ch2 = srgb_decode(*ch2), + *ch3 = srgb_decode(*ch3))); + } + } + return; + case LIBCOLOUR_YIQ: + conversion_by_matrix(XARGUMENTS, YIQ_TO_SRGB); + break; + case LIBCOLOUR_YDBDR: + conversion_by_matrix(XARGUMENTS, YDBDR_TO_SRGB); + break; + case LIBCOLOUR_YPBPR: + CONV_0(YPBPR_TO_SRGB); + break; + case LIBCOLOUR_YUV: + conversion_by_matrix(XARGUMENTS, YUV_TO_SRGB); + break; + case LIBCOLOUR_YCGCO: + conversion_by_matrix(XARGUMENTS, YCGCO_TO_SRGB); + break; + } + if (to->with_transfer) { + tmp = *to; + tmp.with_transfer = 0; + from = (const void *)&tmp; + goto srgb_to_srgb; + } +} + + +static void +to_ciexyy(PARAMETERS(colour, ciexyy)) +{ + libcolour_srgb_t tmp; + size_t m, old_n; +beginning: + m = old_n = n; + switch (from->model) { + case LIBCOLOUR_CIEXYY: + break; + case LIBCOLOUR_SRGB: + tmp.model = LIBCOLOUR_SRGB; + tmp.with_transfer = 0; + if (from->srgb.with_transfer) + to_srgb(ARGUMENTS((const libcolour_colour_t *)from, &tmp)); + if (!*ch1 && !*ch2 && !*ch3) { + for (m = 1; m < n && !ch1[m * width] && !ch2[m * width] && !ch3[m * width]; m++); + n = m; + LOOP((*ch1 = D(0.31272660439158), + *ch2 = D(0.32902315240275), + *ch3 = 0)); + n = old_n; + break; + } else { + for (m = 1; m < n && (ch1[m * width] || ch2[m * width] || ch3[m * width]); m++); + n = m; + from = (const void *)&tmp; + } + /* fall through */ + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + CONV_0(CIEXYZ_TO_CIEXYY); + break; + } + if (m != old_n) { + n = old_n - m; + ch1 += m * width; + ch2 += m * width; + ch3 += m * width; + goto beginning; + } +} + + +static void +to_ciexyz(PARAMETERS(colour, ciexyz)) +{ + libcolour_colour_t tmp; + switch (from->model) { + case LIBCOLOUR_RGB: + if (from->rgb.with_transfer) { + tmp.rgb = from->rgb; + tmp.rgb.with_transfer = 0; + to_rgb(ARGUMENTS(from, &tmp.rgb)); + } + conversion_by_matrix(XARGUMENTS, RGB_TO_CIEXYZ(from->rgb.M)); + break; + default: + tmp.srgb.model = LIBCOLOUR_SRGB; + tmp.srgb.with_transfer = 0; + to_srgb(ARGUMENTS(from, &tmp.srgb)); + from = (const void *)&tmp.srgb; + /* fall through */ + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + conversion_by_matrix(XARGUMENTS, SRGB_TO_CIEXYZ); + break; + case LIBCOLOUR_CIEXYY: + CONV_0(CIEXYY_TO_CIEXYZ); + break; + case LIBCOLOUR_CIEXYZ: + break; + case LIBCOLOUR_CIELAB: + CONV_0(CIELAB_TO_CIEXYZ); + break; + case LIBCOLOUR_CIELCHUV: + tmp.cieluv.model = LIBCOLOUR_CIELUV; + tmp.cieluv.white = from->cielchuv.white; + to_cieluv(ARGUMENTS(from, &tmp.cieluv)); + from = (const void *)&tmp.cieluv; + /* fall through */ + case LIBCOLOUR_CIELUV: + CONV_N(CIELUV_TO_CIEXYZ, from->cieluv.white.X, from->cieluv.white.Y, from->cieluv.white.Z); + break; + case LIBCOLOUR_YIQ: + conversion_by_matrix(XARGUMENTS, YIQ_TO_CIEXYZ); + break; + case LIBCOLOUR_YDBDR: + conversion_by_matrix(XARGUMENTS, YDBDR_TO_CIEXYZ); + break; + case LIBCOLOUR_YUV: + conversion_by_matrix(XARGUMENTS, YUV_TO_CIEXYZ); + break; + case LIBCOLOUR_YPBPR: + conversion_by_matrix(XARGUMENTS, YPBPR_TO_CIEXYZ); + break; + case LIBCOLOUR_YCGCO: + conversion_by_matrix(XARGUMENTS, YCGCO_TO_CIEXYZ); + break; + case LIBCOLOUR_CIEUVW: + tmp.cie1960ucs.model = LIBCOLOUR_CIE1960UCS; + to_cie1960ucs(ARGUMENTS(from, &tmp.cie1960ucs)); + from = (const void *)&tmp.cie1960ucs; + /* fall through */ + case LIBCOLOUR_CIE1960UCS: + CONV_0(CIE1960UCS_TO_CIEXYZ); + break; + } +} + + +static void +to_cielab(PARAMETERS(colour, cielab)) +{ + switch (from->model) { + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + CONV_0(CIEXYZ_TO_CIELAB); + break; + case LIBCOLOUR_CIELAB: + break; + } +} + + +static void +to_cieluv(PARAMETERS(colour, cieluv)) +{ + libcolour_ciexyz_t tmp; + libcolour_cielchuv_t tmp2; + TYPE m; + switch (from->model) { + case LIBCOLOUR_CIELCHUV: + if (to->white.X != from->cielchuv.white.X || + to->white.Y != from->cielchuv.white.Y || + to->white.Z != from->cielchuv.white.Z) { + tmp.model = LIBCOLOUR_CIEXYZ; + tmp2.model = LIBCOLOUR_CIELCHUV; + tmp2.white = to->white; + tmp2.one_revolution = PI2; + to_ciexyz(ARGUMENTS(from, &tmp)); + to_cielchuv(ARGUMENTS((const libcolour_colour_t *)&tmp, &tmp2)); + } else if (from->cielchuv.one_revolution != PI2) { + m = PI2 / from->cielchuv.one_revolution; + SIMPLE_LOOP(ch3, *ch3 *= m); + } + CONV_0(CIELCHUV_TO_CIELUV); + break; + case LIBCOLOUR_CIELUV: + if (to->white.X == from->cieluv.white.X && + to->white.Y == from->cieluv.white.Y && + to->white.Z == from->cieluv.white.Z) + break; + /* fall through */ + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + CONV_N(CIEXYZ_TO_CIELUV, to->white.X, to->white.Y, to->white.Z); + break; + } +} + + +static void +to_cielchuv(PARAMETERS(colour, cielchuv)) +{ + libcolour_cieluv_t tmp1, tmp2; + TYPE m; + switch (from->model) { + case LIBCOLOUR_CIELCHUV: + if (to->white.X == from->cielchuv.white.X && + to->white.Y == from->cielchuv.white.Y && + to->white.Z == from->cielchuv.white.Z) { + if (to->one_revolution != from->cielchuv.one_revolution) { + m = to->one_revolution; + m /= from->cielchuv.one_revolution; + SIMPLE_LOOP(ch3, *ch3 *= m); + } + break; + } + /* fall through */ + default: + tmp1.model = LIBCOLOUR_CIELUV; + tmp1.white = to->white; + to_cieluv(ARGUMENTS(from, &tmp1)); + from = (const void *)&tmp1; + /* fall through */ + case LIBCOLOUR_CIELUV: + if (to->white.X != from->cieluv.white.X || + to->white.Y != from->cieluv.white.Y || + to->white.Z != from->cieluv.white.Z) { + tmp2.model = LIBCOLOUR_CIELUV; + tmp2.white = to->white; + to_cieluv(ARGUMENTS(from, &tmp2)); + from = (const void *)&tmp2; + } + CONV_N(CIELUV_TO_CIELCHUV, to->one_revolution); + break; + } +} + + +static void +to_yiq(PARAMETERS(colour, yiq)) +{ + switch (from->model) { + case LIBCOLOUR_YIQ: + break; + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + conversion_by_matrix(XARGUMENTS, SRGB_TO_YIQ); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_YIQ); + break; + } +} + + +static void +to_ydbdr(PARAMETERS(colour, ydbdr)) +{ + switch (from->model) { + case LIBCOLOUR_YDBDR: + break; + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + conversion_by_matrix(XARGUMENTS, SRGB_TO_YDBDR); + break; + case LIBCOLOUR_YUV: + CONV_0(YUV_TO_YDBDR); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_YDBDR); + break; + } +} + + +static void +to_yuv(PARAMETERS(colour, yuv)) +{ + switch (from->model) { + case LIBCOLOUR_YUV: + break; + case LIBCOLOUR_YDBDR: + CONV_0(YDBDR_TO_YUV); + break; + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + conversion_by_matrix(XARGUMENTS, SRGB_TO_YUV); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_YUV); + break; + } +} + + +static void +to_ypbpr(PARAMETERS(colour, ypbpr)) +{ + switch (from->model) { + case LIBCOLOUR_YPBPR: + break; + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + CONV_0(SRGB_TO_YPBPR); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_YPBPR); + break; + } +} + + +static void +to_ycgco(PARAMETERS(colour, ycgco)) +{ + switch (from->model) { + case LIBCOLOUR_YCGCO: + break; + case LIBCOLOUR_SRGB: + LINEAR_SRGB; + conversion_by_matrix(XARGUMENTS, SRGB_TO_YCGCO); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + conversion_by_matrix(XARGUMENTS, CIEXYZ_TO_YCGCO); + break; + } +} + + +static void +to_cie1960ucs(PARAMETERS(colour, cie1960ucs)) +{ + switch (from->model) { + case LIBCOLOUR_CIE1960UCS: + break; + case LIBCOLOUR_CIEUVW: + CONV_N(CIEUVW_TO_CIE1960UCS, from->cieuvw.u0, from->cieuvw.v0); + break; + default: + to_ciexyz(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIEXYZ: + CONV_0(CIEXYZ_TO_CIE1960UCS); + break; + } +} + + +static void +to_cieuvw(PARAMETERS(colour, cieuvw)) +{ + switch (from->model) { + case LIBCOLOUR_CIEUVW: + CONV_N(CIEUVW_TO_CIEUVW, from->cieuvw.u0, from->cieuvw.v0, to->u0, to->v0); + break; + default: + to_cie1960ucs(ARGUMENTS(from, NULL)); + /* fall through */ + case LIBCOLOUR_CIE1960UCS: + CONV_N(CIE1960UCS_TO_CIEUVW, to->u0, to->v0); + break; + } +} + + int libcolour_convert_en_masse(const libcolour_colour_t *from, const libcolour_colour_t *to, libcolour_convert_en_masse_mode_t mode, size_t n, ...) @@ -10,8 +625,8 @@ libcolour_convert_en_masse(const libcolour_colour_t *from, const libcolour_colou int no_override = mode & LIBCOLOUR_CONVERT_EN_MASSE_NO_OVERRIDE; va_list args; TYPE *in1, *in2, *in3, *in_alpha = NULL; - TYPE *out1, *out2, *out3, *out_alpha = NULL; - size_t width, i; + TYPE *ch1, *ch2, *ch3, *ch_alpha = NULL; + size_t width; if ((unsigned int)mode > 15U) { errno = EINVAL; @@ -49,28 +664,34 @@ libcolour_convert_en_masse(const libcolour_colour_t *from, const libcolour_colou } if (!no_override) { - out1 = in1; - out2 = in2; - out3 = in3; - out_alpha = in_alpha; + ch1 = in1; + ch2 = in2; + ch3 = in3; + ch_alpha = in_alpha; } else if (alpha_mode == LIBCOLOUR_CONVERT_EN_MASSE_NO_ALPHA) { - out1 = va_arg(args, TYPE *); - out2 = out1 + 1; - out3 = out1 + 2; + ch1 = va_arg(args, TYPE *); + ch2 = ch1 + 1; + ch3 = ch1 + 2; + memcpy(ch1, in1, n * 3 * sizeof(TYPE)); } else if (alpha_mode == LIBCOLOUR_CONVERT_EN_MASSE_ALPHA_FIRST) { - out_alpha = va_arg(args, TYPE *); - out1 = out_alpha + 1; - out2 = out_alpha + 2; - out3 = out_alpha + 3; + ch_alpha = va_arg(args, TYPE *); + ch1 = ch_alpha + 1; + ch2 = ch_alpha + 2; + ch3 = ch_alpha + 3; + memcpy(ch_alpha, in_alpha, n * 4 * sizeof(TYPE)); } else if (alpha_mode == LIBCOLOUR_CONVERT_EN_MASSE_ALPHA_LAST) { - out1 = va_arg(args, TYPE *); - out2 = out1 + 1; - out3 = out1 + 2; - out_alpha = out1 + 3; + ch1 = va_arg(args, TYPE *); + ch2 = ch1 + 1; + ch3 = ch1 + 2; + ch_alpha = ch1 + 3; + memcpy(ch1, in1, n * 4 * sizeof(TYPE)); } else { - out1 = va_arg(args, TYPE *); - out2 = va_arg(args, TYPE *); - out3 = va_arg(args, TYPE *); + ch1 = va_arg(args, TYPE *); + ch2 = va_arg(args, TYPE *); + ch3 = va_arg(args, TYPE *); + memcpy(ch1, in1, n * sizeof(TYPE)); + memcpy(ch2, in2, n * sizeof(TYPE)); + memcpy(ch3, in3, n * sizeof(TYPE)); } va_end(args); @@ -85,38 +706,18 @@ libcolour_convert_en_masse(const libcolour_colour_t *from, const libcolour_colou } switch (to->model) { -#define X(C, T, N) case C: memcpy(&tto, to, sizeof(T)); break; - LIST_MODELS(X) +#define X(C, T, N)\ + case C:\ + memcpy(&tto, to, sizeof(T));\ + to_##N(ARGUMENTS(&tfrom, &tto.N));\ + break; + LIST_MODELS(X) #undef X default: errno = EINVAL; return -1; } - if (in_alpha != out_alpha) { - for (i = 0; i < n; i++) { - *out_alpha = *in_alpha; - in_alpha += width; - out_alpha += width; - } - } - - while (n--) { - tfrom.rgb.R = *in1; - tfrom.rgb.G = *in2; - tfrom.rgb.B = *in3; - libcolour_convert(&tfrom, &tto); - *out1 = tto.rgb.R; - *out2 = tto.rgb.G; - *out3 = tto.rgb.B; - in1 += width; - in2 += width; - in3 += width; - out1 += width; - out2 += width; - out3 += width; - } - (void) on_cpu; return 0; } |