| 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..8d49e5ce6dd96fbdd3ad01d591ad38e61c0edffa 100644
|
| --- a/third_party/qcms/src/transform.c
|
| +++ b/third_party/qcms/src/transform.c
|
| @@ -411,6 +411,41 @@ static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform,
|
| }
|
| }
|
|
|
| +static void qcms_transform_data_bgra_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +{
|
| + unsigned int i;
|
| + float (*mat)[4] = transform->matrix;
|
| + for (i = 0; i < length; i++) {
|
| + unsigned char device_b = *src++;
|
| + unsigned char device_g = *src++;
|
| + unsigned char device_r = *src++;
|
| + unsigned char alpha = *src++;
|
| + uint16_t r, g, b;
|
| +
|
| + float linear_r = transform->input_gamma_table_r[device_r];
|
| + float linear_g = transform->input_gamma_table_g[device_g];
|
| + float linear_b = transform->input_gamma_table_b[device_b];
|
| +
|
| + float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + mat[2][0]*linear_b;
|
| + 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;
|
| +
|
| + out_linear_r = clamp_float(out_linear_r);
|
| + out_linear_g = clamp_float(out_linear_g);
|
| + out_linear_b = clamp_float(out_linear_b);
|
| +
|
| + /* we could round here... */
|
| + r = out_linear_r * PRECACHE_OUTPUT_MAX;
|
| + g = out_linear_g * PRECACHE_OUTPUT_MAX;
|
| + b = out_linear_b * PRECACHE_OUTPUT_MAX;
|
| +
|
| + *dest++ = transform->output_table_b->data[b];
|
| + *dest++ = transform->output_table_g->data[g];
|
| + *dest++ = transform->output_table_r->data[r];
|
| + *dest++ = alpha;
|
| + }
|
| +}
|
| +
|
| // Not used
|
| /*
|
| static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
|
| @@ -584,6 +619,121 @@ static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsig
|
| }
|
| }
|
|
|
| +// Using lcms' tetra interpolation algorithm.
|
| +static void qcms_transform_data_tetra_clut_bgra(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
|
| + unsigned int i;
|
| + int xy_len = 1;
|
| + int x_len = transform->grid_size;
|
| + int len = x_len * x_len;
|
| + float* r_table = transform->r_clut;
|
| + float* g_table = transform->g_clut;
|
| + float* b_table = transform->b_clut;
|
| + float c0_r, c1_r, c2_r, c3_r;
|
| + float c0_g, c1_g, c2_g, c3_g;
|
| + float c0_b, c1_b, c2_b, c3_b;
|
| + float clut_r, clut_g, clut_b;
|
| + for (i = 0; i < length; i++) {
|
| + unsigned char in_b = *src++;
|
| + unsigned char in_g = *src++;
|
| + unsigned char in_r = *src++;
|
| + unsigned char in_a = *src++;
|
| + float linear_r = in_r/255.0f, linear_g=in_g/255.0f, linear_b = in_b/255.0f;
|
| +
|
| + int x = floor(linear_r * (transform->grid_size-1));
|
| + int y = floor(linear_g * (transform->grid_size-1));
|
| + int z = floor(linear_b * (transform->grid_size-1));
|
| + int x_n = ceil(linear_r * (transform->grid_size-1));
|
| + int y_n = ceil(linear_g * (transform->grid_size-1));
|
| + int z_n = ceil(linear_b * (transform->grid_size-1));
|
| + float rx = linear_r * (transform->grid_size-1) - x;
|
| + float ry = linear_g * (transform->grid_size-1) - y;
|
| + float rz = linear_b * (transform->grid_size-1) - z;
|
| +
|
| + c0_r = CLU(r_table, x, y, z);
|
| + c0_g = CLU(g_table, x, y, z);
|
| + c0_b = CLU(b_table, x, y, z);
|
| +
|
| + if( rx >= ry ) {
|
| + if (ry >= rz) { //rx >= ry && ry >= rz
|
| + c1_r = CLU(r_table, x_n, y, z) - c0_r;
|
| + c2_r = CLU(r_table, x_n, y_n, z) - CLU(r_table, x_n, y, z);
|
| + c3_r = CLU(r_table, x_n, y_n, z_n) - CLU(r_table, x_n, y_n, z);
|
| + c1_g = CLU(g_table, x_n, y, z) - c0_g;
|
| + c2_g = CLU(g_table, x_n, y_n, z) - CLU(g_table, x_n, y, z);
|
| + c3_g = CLU(g_table, x_n, y_n, z_n) - CLU(g_table, x_n, y_n, z);
|
| + c1_b = CLU(b_table, x_n, y, z) - c0_b;
|
| + c2_b = CLU(b_table, x_n, y_n, z) - CLU(b_table, x_n, y, z);
|
| + c3_b = CLU(b_table, x_n, y_n, z_n) - CLU(b_table, x_n, y_n, z);
|
| + } else {
|
| + if (rx >= rz) { //rx >= rz && rz >= ry
|
| + c1_r = CLU(r_table, x_n, y, z) - c0_r;
|
| + c2_r = CLU(r_table, x_n, y_n, z_n) - CLU(r_table, x_n, y, z_n);
|
| + c3_r = CLU(r_table, x_n, y, z_n) - CLU(r_table, x_n, y, z);
|
| + c1_g = CLU(g_table, x_n, y, z) - c0_g;
|
| + c2_g = CLU(g_table, x_n, y_n, z_n) - CLU(g_table, x_n, y, z_n);
|
| + c3_g = CLU(g_table, x_n, y, z_n) - CLU(g_table, x_n, y, z);
|
| + c1_b = CLU(b_table, x_n, y, z) - c0_b;
|
| + c2_b = CLU(b_table, x_n, y_n, z_n) - CLU(b_table, x_n, y, z_n);
|
| + c3_b = CLU(b_table, x_n, y, z_n) - CLU(b_table, x_n, y, z);
|
| + } else { //rz > rx && rx >= ry
|
| + c1_r = CLU(r_table, x_n, y, z_n) - CLU(r_table, x, y, z_n);
|
| + c2_r = CLU(r_table, x_n, y_n, z_n) - CLU(r_table, x_n, y, z_n);
|
| + c3_r = CLU(r_table, x, y, z_n) - c0_r;
|
| + c1_g = CLU(g_table, x_n, y, z_n) - CLU(g_table, x, y, z_n);
|
| + c2_g = CLU(g_table, x_n, y_n, z_n) - CLU(g_table, x_n, y, z_n);
|
| + c3_g = CLU(g_table, x, y, z_n) - c0_g;
|
| + c1_b = CLU(b_table, x_n, y, z_n) - CLU(b_table, x, y, z_n);
|
| + c2_b = CLU(b_table, x_n, y_n, z_n) - CLU(b_table, x_n, y, z_n);
|
| + c3_b = CLU(b_table, x, y, z_n) - c0_b;
|
| + }
|
| + }
|
| + } else {
|
| + if (rx >= rz) { //ry > rx && rx >= rz
|
| + c1_r = CLU(r_table, x_n, y_n, z) - CLU(r_table, x, y_n, z);
|
| + c2_r = CLU(r_table, x, y_n, z) - c0_r;
|
| + c3_r = CLU(r_table, x_n, y_n, z_n) - CLU(r_table, x_n, y_n, z);
|
| + c1_g = CLU(g_table, x_n, y_n, z) - CLU(g_table, x, y_n, z);
|
| + c2_g = CLU(g_table, x, y_n, z) - c0_g;
|
| + c3_g = CLU(g_table, x_n, y_n, z_n) - CLU(g_table, x_n, y_n, z);
|
| + c1_b = CLU(b_table, x_n, y_n, z) - CLU(b_table, x, y_n, z);
|
| + c2_b = CLU(b_table, x, y_n, z) - c0_b;
|
| + c3_b = CLU(b_table, x_n, y_n, z_n) - CLU(b_table, x_n, y_n, z);
|
| + } else {
|
| + if (ry >= rz) { //ry >= rz && rz > rx
|
| + c1_r = CLU(r_table, x_n, y_n, z_n) - CLU(r_table, x, y_n, z_n);
|
| + c2_r = CLU(r_table, x, y_n, z) - c0_r;
|
| + c3_r = CLU(r_table, x, y_n, z_n) - CLU(r_table, x, y_n, z);
|
| + c1_g = CLU(g_table, x_n, y_n, z_n) - CLU(g_table, x, y_n, z_n);
|
| + c2_g = CLU(g_table, x, y_n, z) - c0_g;
|
| + c3_g = CLU(g_table, x, y_n, z_n) - CLU(g_table, x, y_n, z);
|
| + c1_b = CLU(b_table, x_n, y_n, z_n) - CLU(b_table, x, y_n, z_n);
|
| + c2_b = CLU(b_table, x, y_n, z) - c0_b;
|
| + c3_b = CLU(b_table, x, y_n, z_n) - CLU(b_table, x, y_n, z);
|
| + } else { //rz > ry && ry > rx
|
| + c1_r = CLU(r_table, x_n, y_n, z_n) - CLU(r_table, x, y_n, z_n);
|
| + c2_r = CLU(r_table, x, y_n, z_n) - CLU(r_table, x, y, z_n);
|
| + c3_r = CLU(r_table, x, y, z_n) - c0_r;
|
| + c1_g = CLU(g_table, x_n, y_n, z_n) - CLU(g_table, x, y_n, z_n);
|
| + c2_g = CLU(g_table, x, y_n, z_n) - CLU(g_table, x, y, z_n);
|
| + c3_g = CLU(g_table, x, y, z_n) - c0_g;
|
| + c1_b = CLU(b_table, x_n, y_n, z_n) - CLU(b_table, x, y_n, z_n);
|
| + c2_b = CLU(b_table, x, y_n, z_n) - CLU(b_table, x, y, z_n);
|
| + c3_b = CLU(b_table, x, y, z_n) - c0_b;
|
| + }
|
| + }
|
| + }
|
| +
|
| + clut_r = c0_r + c1_r*rx + c2_r*ry + c3_r*rz;
|
| + 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_b*255.0f);
|
| + *dest++ = clamp_u8(clut_g*255.0f);
|
| + *dest++ = clamp_u8(clut_r*255.0f);
|
| + *dest++ = in_a;
|
| + }
|
| +}
|
| +
|
| // Using lcms' tetra interpolation code.
|
| static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
|
| unsigned int i;
|
| @@ -769,6 +919,43 @@ static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned
|
| }
|
| }
|
|
|
| +static void qcms_transform_data_bgra_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| +{
|
| + unsigned int i;
|
| + float (*mat)[4] = transform->matrix;
|
| + for (i = 0; i < length; i++) {
|
| + unsigned char device_b = *src++;
|
| + unsigned char device_g = *src++;
|
| + unsigned char device_r = *src++;
|
| + unsigned char alpha = *src++;
|
| + float out_device_r, out_device_g, out_device_b;
|
| +
|
| + float linear_r = transform->input_gamma_table_r[device_r];
|
| + float linear_g = transform->input_gamma_table_g[device_g];
|
| + float linear_b = transform->input_gamma_table_b[device_b];
|
| +
|
| + float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + mat[2][0]*linear_b;
|
| + 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;
|
| +
|
| + out_linear_r = clamp_float(out_linear_r);
|
| + out_linear_g = clamp_float(out_linear_g);
|
| + out_linear_b = clamp_float(out_linear_b);
|
| +
|
| + out_device_r = lut_interp_linear(out_linear_r,
|
| + transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
|
| + out_device_g = lut_interp_linear(out_linear_g,
|
| + transform->output_gamma_lut_g, transform->output_gamma_lut_g_length);
|
| + 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_b*255);
|
| + *dest++ = clamp_u8(out_device_g*255);
|
| + *dest++ = clamp_u8(out_device_r*255);
|
| + *dest++ = alpha;
|
| + }
|
| +}
|
| +
|
| #if 0
|
| static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
|
| {
|
| @@ -1068,6 +1255,8 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms
|
| transform->grid_size = samples;
|
| if (in_type == QCMS_DATA_RGBA_8) {
|
| transform->transform_fn = qcms_transform_data_tetra_clut_rgba;
|
| + } else if (in_type == QCMS_DATA_BGRA_8) {
|
| + transform->transform_fn = qcms_transform_data_tetra_clut_bgra;
|
| } else {
|
| transform->transform_fn = qcms_transform_data_tetra_clut;
|
| }
|
| @@ -1102,7 +1291,8 @@ qcms_transform* qcms_transform_create(
|
| return NULL;
|
| }
|
| if (out_type != QCMS_DATA_RGB_8 &&
|
| - out_type != QCMS_DATA_RGBA_8) {
|
| + out_type != QCMS_DATA_RGBA_8 &&
|
| + out_type != QCMS_DATA_BGRA_8) {
|
| assert(0 && "output type");
|
| transform_free(transform);
|
| return NULL;
|
| @@ -1151,7 +1341,8 @@ qcms_transform* qcms_transform_create(
|
| struct matrix in_matrix, out_matrix, result;
|
|
|
| if (in_type != QCMS_DATA_RGB_8 &&
|
| - in_type != QCMS_DATA_RGBA_8){
|
| + in_type != QCMS_DATA_RGBA_8 &&
|
| + in_type != QCMS_DATA_BGRA_8){
|
| assert(0 && "input type");
|
| transform_free(transform);
|
| return NULL;
|
| @@ -1161,6 +1352,8 @@ qcms_transform* qcms_transform_create(
|
| if (sse_version_available() >= 2) {
|
| if (in_type == QCMS_DATA_RGB_8)
|
| transform->transform_fn = qcms_transform_data_rgb_out_lut_sse2;
|
| + else if (in_type == QCMS_DATA_BGRA_8)
|
| + transform->transform_fn = qcms_transform_data_bgra_out_lut_sse2;
|
| else
|
| transform->transform_fn = qcms_transform_data_rgba_out_lut_sse2;
|
|
|
| @@ -1171,6 +1364,8 @@ qcms_transform* qcms_transform_create(
|
| if (sse_version_available() >= 1) {
|
| if (in_type == QCMS_DATA_RGB_8)
|
| transform->transform_fn = qcms_transform_data_rgb_out_lut_sse1;
|
| + else if (in_type == QCMS_DATA_BGRA_8)
|
| + transform->transform_fn = qcms_transform_data_bgra_out_lut_sse1;
|
| else
|
| transform->transform_fn = qcms_transform_data_rgba_out_lut_sse1;
|
| #endif
|
| @@ -1179,12 +1374,16 @@ qcms_transform* qcms_transform_create(
|
| {
|
| if (in_type == QCMS_DATA_RGB_8)
|
| transform->transform_fn = qcms_transform_data_rgb_out_lut_precache;
|
| + else if (in_type == QCMS_DATA_BGRA_8)
|
| + transform->transform_fn = qcms_transform_data_bgra_out_lut_precache;
|
| else
|
| transform->transform_fn = qcms_transform_data_rgba_out_lut_precache;
|
| }
|
| } else {
|
| if (in_type == QCMS_DATA_RGB_8)
|
| transform->transform_fn = qcms_transform_data_rgb_out_lut;
|
| + else if (in_type == QCMS_DATA_BGRA_8)
|
| + transform->transform_fn = qcms_transform_data_bgra_out_lut;
|
| else
|
| transform->transform_fn = qcms_transform_data_rgba_out_lut;
|
| }
|
|
|