| Index: third_party/qcms/src/transform.c
|
| diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c
|
| index 9a6562bf2712db51bfdef01a6b3f751c31e54d39..ae3f628cdfaca274b6b232e6a79b3283d289d209 100644
|
| --- a/third_party/qcms/src/transform.c
|
| +++ b/third_party/qcms/src/transform.c
|
| @@ -181,11 +181,20 @@ compute_chromatic_adaption(struct CIE_XYZ source_white_point,
|
| static struct matrix
|
| adaption_matrix(struct CIE_XYZ source_illumination, struct CIE_XYZ target_illumination)
|
| {
|
| +#if defined (_MSC_VER)
|
| +#pragma warning(push)
|
| +/* Disable double to float truncation warning 4305 */
|
| +#pragma warning(disable:4305)
|
| +#endif
|
| struct matrix lam_rigg = {{ // Bradford matrix
|
| { 0.8951, 0.2664, -0.1614 },
|
| { -0.7502, 1.7135, 0.0367 },
|
| { 0.0389, -0.0685, 1.0296 }
|
| }};
|
| +#if defined (_MSC_VER)
|
| +/* Restore warnings */
|
| +#pragma warning(pop)
|
| +#endif
|
| return compute_chromatic_adaption(source_illumination, target_illumination, lam_rigg);
|
| }
|
|
|
| @@ -230,8 +239,11 @@ qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcm
|
| }
|
|
|
| #if 0
|
| -static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| {
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| int i;
|
| float (*mat)[4] = transform->matrix;
|
| for (i=0; i<length; i++) {
|
| @@ -251,15 +263,19 @@ static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned
|
| float out_device_g = pow(out_linear_g, transform->out_gamma_g);
|
| float out_device_b = pow(out_linear_b, transform->out_gamma_b);
|
|
|
| - *dest++ = clamp_u8(255*out_device_r);
|
| - *dest++ = clamp_u8(255*out_device_g);
|
| - *dest++ = clamp_u8(255*out_device_b);
|
| + dest[r_out] = clamp_u8(out_device_r*255);
|
| + dest[1] = clamp_u8(out_device_g*255);
|
| + dest[b_out] = clamp_u8(out_device_b*255);
|
| + dest += 3;
|
| }
|
| }
|
| #endif
|
|
|
| -static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| {
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| unsigned int i;
|
| for (i = 0; i < length; i++) {
|
| float out_device_r, out_device_g, out_device_b;
|
| @@ -267,13 +283,14 @@ static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned
|
|
|
| float linear = transform->input_gamma_table_gray[device];
|
|
|
| - out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
|
| + out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
|
| out_device_g = lut_interp_linear(linear, transform->output_gamma_lut_g, transform->output_gamma_lut_g_length);
|
| out_device_b = lut_interp_linear(linear, transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
|
|
|
| - *dest++ = clamp_u8(out_device_r*255);
|
| - *dest++ = clamp_u8(out_device_g*255);
|
| - *dest++ = clamp_u8(out_device_b*255);
|
| + dest[r_out] = clamp_u8(out_device_r*255);
|
| + dest[1] = clamp_u8(out_device_g*255);
|
| + dest[b_out] = clamp_u8(out_device_b*255);
|
| + dest += 3;
|
| }
|
| }
|
|
|
| @@ -283,8 +300,11 @@ static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned
|
| See: ftp://ftp.alvyray.com/Acrobat/17_Nonln.pdf
|
| */
|
|
|
| -static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| {
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| unsigned int i;
|
| for (i = 0; i < length; i++) {
|
| float out_device_r, out_device_g, out_device_b;
|
| @@ -293,20 +313,24 @@ static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigne
|
|
|
| float linear = transform->input_gamma_table_gray[device];
|
|
|
| - out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
|
| + out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
|
| out_device_g = lut_interp_linear(linear, transform->output_gamma_lut_g, transform->output_gamma_lut_g_length);
|
| out_device_b = lut_interp_linear(linear, transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
|
|
|
| - *dest++ = clamp_u8(out_device_r*255);
|
| - *dest++ = clamp_u8(out_device_g*255);
|
| - *dest++ = clamp_u8(out_device_b*255);
|
| - *dest++ = alpha;
|
| + dest[r_out] = clamp_u8(out_device_r*255);
|
| + dest[1] = clamp_u8(out_device_g*255);
|
| + dest[b_out] = clamp_u8(out_device_b*255);
|
| + dest[3] = alpha;
|
| + dest += 4;
|
| }
|
| }
|
|
|
|
|
| -static void qcms_transform_data_gray_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +static void qcms_transform_data_gray_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| {
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| unsigned int i;
|
| for (i = 0; i < length; i++) {
|
| unsigned char device = *src++;
|
| @@ -317,14 +341,19 @@ static void qcms_transform_data_gray_out_precache(qcms_transform *transform, uns
|
| /* we could round here... */
|
| gray = linear * PRECACHE_OUTPUT_MAX;
|
|
|
| - *dest++ = transform->output_table_r->data[gray];
|
| - *dest++ = transform->output_table_g->data[gray];
|
| - *dest++ = transform->output_table_b->data[gray];
|
| + dest[r_out] = transform->output_table_r->data[gray];
|
| + dest[1] = transform->output_table_g->data[gray];
|
| + dest[b_out] = transform->output_table_b->data[gray];
|
| + dest += 3;
|
| }
|
| }
|
|
|
| -static void qcms_transform_data_graya_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +
|
| +static void qcms_transform_data_graya_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| {
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| unsigned int i;
|
| for (i = 0; i < length; i++) {
|
| unsigned char device = *src++;
|
| @@ -336,15 +365,19 @@ static void qcms_transform_data_graya_out_precache(qcms_transform *transform, un
|
| /* we could round here... */
|
| gray = linear * PRECACHE_OUTPUT_MAX;
|
|
|
| - *dest++ = transform->output_table_r->data[gray];
|
| - *dest++ = transform->output_table_g->data[gray];
|
| - *dest++ = transform->output_table_b->data[gray];
|
| - *dest++ = alpha;
|
| + dest[r_out] = transform->output_table_r->data[gray];
|
| + dest[1] = transform->output_table_g->data[gray];
|
| + dest[b_out] = transform->output_table_b->data[gray];
|
| + dest[3] = alpha;
|
| + dest += 4;
|
| }
|
| }
|
|
|
| -static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| {
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| unsigned int i;
|
| float (*mat)[4] = transform->matrix;
|
| for (i = 0; i < length; i++) {
|
| @@ -370,14 +403,18 @@ static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform,
|
| g = out_linear_g * PRECACHE_OUTPUT_MAX;
|
| b = out_linear_b * PRECACHE_OUTPUT_MAX;
|
|
|
| - *dest++ = transform->output_table_r->data[r];
|
| - *dest++ = transform->output_table_g->data[g];
|
| - *dest++ = transform->output_table_b->data[b];
|
| + dest[r_out] = transform->output_table_r->data[r];
|
| + dest[1] = transform->output_table_g->data[g];
|
| + dest[b_out] = transform->output_table_b->data[b];
|
| + dest += 3;
|
| }
|
| }
|
|
|
| -static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| {
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| unsigned int i;
|
| float (*mat)[4] = transform->matrix;
|
| for (i = 0; i < length; i++) {
|
| @@ -404,16 +441,21 @@ static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform,
|
| g = out_linear_g * PRECACHE_OUTPUT_MAX;
|
| b = out_linear_b * PRECACHE_OUTPUT_MAX;
|
|
|
| - *dest++ = transform->output_table_r->data[r];
|
| - *dest++ = transform->output_table_g->data[g];
|
| - *dest++ = transform->output_table_b->data[b];
|
| - *dest++ = alpha;
|
| + dest[r_out] = transform->output_table_r->data[r];
|
| + dest[1] = transform->output_table_g->data[g];
|
| + dest[b_out] = transform->output_table_b->data[b];
|
| + dest[3] = alpha;
|
| + dest += 4;
|
| }
|
| }
|
|
|
| // Not used
|
| /*
|
| -static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
|
| +static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| +{
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| unsigned int i;
|
| int xy_len = 1;
|
| int x_len = transform->grid_size;
|
| @@ -462,15 +504,20 @@ static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *s
|
| float b_y2 = lerp(b_x3, b_x4, y_d);
|
| float clut_b = lerp(b_y1, b_y2, z_d);
|
|
|
| - *dest++ = clamp_u8(clut_r*255.0f);
|
| - *dest++ = clamp_u8(clut_g*255.0f);
|
| - *dest++ = clamp_u8(clut_b*255.0f);
|
| - }
|
| + dest[r_out] = clamp_u8(clut_r*255.0f);
|
| + dest[1] = clamp_u8(clut_g*255.0f);
|
| + dest[b_out] = clamp_u8(clut_b*255.0f);
|
| + dest += 3;
|
| + }
|
| }
|
| */
|
|
|
| // Using lcms' tetra interpolation algorithm.
|
| -static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
|
| +static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| +{
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| unsigned int i;
|
| int xy_len = 1;
|
| int x_len = transform->grid_size;
|
| @@ -577,15 +624,20 @@ static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsig
|
| clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz;
|
| clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz;
|
|
|
| - *dest++ = clamp_u8(clut_r*255.0f);
|
| - *dest++ = clamp_u8(clut_g*255.0f);
|
| - *dest++ = clamp_u8(clut_b*255.0f);
|
| - *dest++ = in_a;
|
| - }
|
| + dest[r_out] = clamp_u8(clut_r*255.0f);
|
| + dest[1] = clamp_u8(clut_g*255.0f);
|
| + dest[b_out] = clamp_u8(clut_b*255.0f);
|
| + dest[3] = in_a;
|
| + dest += 4;
|
| + }
|
| }
|
|
|
| // Using lcms' tetra interpolation code.
|
| -static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
|
| +static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| +{
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| unsigned int i;
|
| int xy_len = 1;
|
| int x_len = transform->grid_size;
|
| @@ -691,14 +743,18 @@ static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned c
|
| clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz;
|
| clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz;
|
|
|
| - *dest++ = clamp_u8(clut_r*255.0f);
|
| - *dest++ = clamp_u8(clut_g*255.0f);
|
| - *dest++ = clamp_u8(clut_b*255.0f);
|
| - }
|
| + dest[r_out] = clamp_u8(clut_r*255.0f);
|
| + dest[1] = clamp_u8(clut_g*255.0f);
|
| + dest[b_out] = clamp_u8(clut_b*255.0f);
|
| + dest += 3;
|
| + }
|
| }
|
|
|
| -static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| {
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| unsigned int i;
|
| float (*mat)[4] = transform->matrix;
|
| for (i = 0; i < length; i++) {
|
| @@ -726,14 +782,18 @@ static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned
|
| out_device_b = lut_interp_linear(out_linear_b,
|
| transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
|
|
|
| - *dest++ = clamp_u8(out_device_r*255);
|
| - *dest++ = clamp_u8(out_device_g*255);
|
| - *dest++ = clamp_u8(out_device_b*255);
|
| + dest[r_out] = clamp_u8(out_device_r*255);
|
| + dest[1] = clamp_u8(out_device_g*255);
|
| + dest[b_out] = clamp_u8(out_device_b*255);
|
| + dest += 3;
|
| }
|
| }
|
|
|
| -static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| {
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| unsigned int i;
|
| float (*mat)[4] = transform->matrix;
|
| for (i = 0; i < length; i++) {
|
| @@ -762,16 +822,20 @@ static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned
|
| out_device_b = lut_interp_linear(out_linear_b,
|
| transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
|
|
|
| - *dest++ = clamp_u8(out_device_r*255);
|
| - *dest++ = clamp_u8(out_device_g*255);
|
| - *dest++ = clamp_u8(out_device_b*255);
|
| - *dest++ = alpha;
|
| + dest[r_out] = clamp_u8(out_device_r*255);
|
| + dest[1] = clamp_u8(out_device_g*255);
|
| + dest[b_out] = clamp_u8(out_device_b*255);
|
| + dest[3] = alpha;
|
| + dest += 4;
|
| }
|
| }
|
|
|
| #if 0
|
| -static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_format)
|
| {
|
| + const int r_out = output_format.r;
|
| + const int b_out = output_format.b;
|
| +
|
| int i;
|
| float (*mat)[4] = transform->matrix;
|
| for (i = 0; i < length; i++) {
|
| @@ -787,9 +851,10 @@ static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsign
|
| float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + mat[2][1]*linear_b;
|
| float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + mat[2][2]*linear_b;
|
|
|
| - *dest++ = clamp_u8(out_linear_r*255);
|
| - *dest++ = clamp_u8(out_linear_g*255);
|
| - *dest++ = clamp_u8(out_linear_b*255);
|
| + dest[r_out] = clamp_u8(out_linear_r*255);
|
| + dest[1] = clamp_u8(out_linear_g*255);
|
| + dest[b_out] = clamp_u8(out_linear_b*255);
|
| + dest += 3;
|
| }
|
| }
|
| #endif
|
| @@ -1262,7 +1327,17 @@ __attribute__((__force_align_arg_pointer__))
|
| #endif
|
| void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length)
|
| {
|
| - transform->transform_fn(transform, src, dest, length);
|
| + static const struct _qcms_format_type output_rgbx = { 0, 2 };
|
| +
|
| + transform->transform_fn(transform, src, dest, length, output_rgbx);
|
| +}
|
| +
|
| +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type)
|
| +{
|
| + static const struct _qcms_format_type output_rgbx = { 0, 2 };
|
| + static const struct _qcms_format_type output_bgrx = { 2, 0 };
|
| +
|
| + transform->transform_fn(transform, src, dest, length, type == QCMS_OUTPUT_BGRX ? output_bgrx : output_rgbx);
|
| }
|
|
|
| qcms_bool qcms_supports_iccv4;
|
|
|