diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-23 01:46:02 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-23 01:46:02 +0000 |
commit | 8ca4c95564702a77d3d149e436bc7a3ae9a08df1 (patch) | |
tree | 0add621e09bc60a00bd7c7d69dacfb486ea48386 /third_party | |
parent | d5a4dd65f33e42ff766013a4f4ff3cf4a52673e5 (diff) | |
download | chromium_src-8ca4c95564702a77d3d149e436bc7a3ae9a08df1.zip chromium_src-8ca4c95564702a77d3d149e436bc7a3ae9a08df1.tar.gz chromium_src-8ca4c95564702a77d3d149e436bc7a3ae9a08df1.tar.bz2 |
Add BGRA output format support to qcms
Define QCMS_OUTPUT_BGRX and add qcms_transform_data_type() api to output
BGR or BGRA format for GRAY, GRAYA, RGB, and RGBA input data.
Update all color transform functions with an output format argument, use
that to select RGBX (the default) or BGRX output format.
Add google.patch: patch of the BGRA output changes against upstream qcms
and add README.chromium details about google.patch. TODO: send the patch
to qcms if accepted for review upstream.
Disable Visual Studio warnings when needed.
BUG=143
TEST=None
AUTHOR=noel@chromium.org
original review = http://codereview.chromium.org/10387099/
Review URL: https://chromiumcodereview.appspot.com/10407113
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@138414 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
-rw-r--r-- | third_party/qcms/README.chromium | 6 | ||||
-rw-r--r-- | third_party/qcms/google.patch | 688 | ||||
-rw-r--r-- | third_party/qcms/src/iccread.c | 9 | ||||
-rw-r--r-- | third_party/qcms/src/qcms.h | 7 | ||||
-rw-r--r-- | third_party/qcms/src/qcmsint.h | 19 | ||||
-rw-r--r-- | third_party/qcms/src/qcmstypes.h | 5 | ||||
-rw-r--r-- | third_party/qcms/src/transform-sse1.c | 34 | ||||
-rw-r--r-- | third_party/qcms/src/transform-sse2.c | 34 | ||||
-rw-r--r-- | third_party/qcms/src/transform.c | 201 |
9 files changed, 906 insertions, 97 deletions
diff --git a/third_party/qcms/README.chromium b/third_party/qcms/README.chromium index f073143..910adae 100644 --- a/third_party/qcms/README.chromium +++ b/third_party/qcms/README.chromium @@ -12,4 +12,8 @@ originally based on tinycms, re-written by Mozilla for better security and performance. This copy is a source-drop from Mozilla on March 13, 2012. Local Modifications: -Some files only have license headers in the master branch. Added the same license headers to the versions brought down from the 'v4' branch. +Some files only have license headers in the master branch. + - Added the same license headers to the versions brought down from the 'v4' + branch src URL qcms/tree/v4 +google.patch + - Add bgra output support. Apply with patch -p1 < google.patch diff --git a/third_party/qcms/google.patch b/third_party/qcms/google.patch new file mode 100644 index 0000000..84a1235 --- /dev/null +++ b/third_party/qcms/google.patch @@ -0,0 +1,688 @@ +diff --git a/src/iccread.c b/src/iccread.c +index 36b7011..2454924 100644 +--- a/src/iccread.c ++++ b/src/iccread.c +@@ -297,6 +297,11 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) + sum[1] = rY + gY + bY; + sum[2] = rZ + gZ + bZ; + ++#if defined (_MSC_VER) ++#pragma warning(push) ++/* Disable double to float truncation warning 4305 */ ++#pragma warning(disable:4305) ++#endif + // Build our target vector (see mozilla bug 460629) + target[0] = 0.96420; + target[1] = 1.00000; +@@ -310,6 +315,10 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) + tolerance[1] = 0.02; + tolerance[2] = 0.04; + ++#if defined (_MSC_VER) ++/* Restore warnings */ ++#pragma warning(pop) ++#endif + // Compare with our tolerance + for (i = 0; i < 3; ++i) { + if (!(((sum[i] - tolerance[i]) <= target[i]) && +diff --git a/src/qcms.h b/src/qcms.h +index 7d83623..1e3e125 100644 +--- a/src/qcms.h ++++ b/src/qcms.h +@@ -102,6 +102,12 @@ typedef enum { + QCMS_DATA_GRAYA_8 + } qcms_data_type; + ++/* Format of the output data for qcms_transform_data_type() */ ++typedef enum { ++ QCMS_OUTPUT_RGBX, ++ QCMS_OUTPUT_BGRX ++} qcms_output_type; ++ + /* the names for the following two types are sort of ugly */ + typedef struct + { +@@ -146,6 +152,7 @@ qcms_transform* qcms_transform_create( + void qcms_transform_release(qcms_transform *); + + void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length); ++void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type); + + void qcms_enable_iccv4(); + +diff --git a/src/qcmsint.h b/src/qcmsint.h +index 53a3420..63905de 100644 +--- a/src/qcmsint.h ++++ b/src/qcmsint.h +@@ -45,6 +45,11 @@ struct precache_output + #define ALIGN __attribute__(( aligned (16) )) + #endif + ++typedef struct _qcms_format_type { ++ int r; ++ int b; ++} qcms_format_type; ++ + struct _qcms_transform { + float ALIGN matrix[3][4]; + float *input_gamma_table_r; +@@ -88,7 +93,7 @@ struct _qcms_transform { + struct precache_output *output_table_g; + struct precache_output *output_table_b; + +- void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length); ++ void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, struct _qcms_format_type output_format); + }; + + struct matrix { +@@ -280,18 +285,22 @@ qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcm + void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, + unsigned char *src, + unsigned char *dest, +- size_t length); ++ size_t length, ++ qcms_format_type output_format); + void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, + unsigned char *src, + unsigned char *dest, +- size_t length); ++ size_t length, ++ qcms_format_type output_format); + void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, + unsigned char *src, + unsigned char *dest, +- size_t length); ++ size_t length, ++ qcms_format_type output_format); + void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, + unsigned char *src, + unsigned char *dest, +- size_t length); ++ size_t length, ++ qcms_format_type output_format); + + extern qcms_bool qcms_supports_iccv4; +diff --git a/src/qcmstypes.h b/src/qcmstypes.h +index 56d8de3..9a9b197 100644 +--- a/src/qcmstypes.h ++++ b/src/qcmstypes.h +@@ -87,7 +87,12 @@ typedef unsigned __int64 uint64_t; + #ifdef _WIN64 + typedef unsigned __int64 uintptr_t; + #else ++#pragma warning(push) ++/* Disable benign redefinition of type warning 4142 */ ++#pragma warning(disable:4142) + typedef unsigned long uintptr_t; ++/* Restore warnings */ ++#pragma warning(pop) + #endif + + #elif defined (_AIX) +diff --git a/src/transform-sse1.c b/src/transform-sse1.c +index 2f34db5..aaee1bf 100644 +--- a/src/transform-sse1.c ++++ b/src/transform-sse1.c +@@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] = + void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, + unsigned char *src, + unsigned char *dest, +- size_t length) ++ size_t length, ++ qcms_format_type output_format) + { + unsigned int i; + float (*mat)[4] = transform->matrix; +@@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, + + /* working variables */ + __m128 vec_r, vec_g, vec_b, result; ++ const int r_out = output_format.r; ++ const int b_out = output_format.b; + + /* CYA */ + if (!length) +@@ -116,9 +119,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, + src += 3; + + /* use calc'd indices to output RGB values */ +- dest[0] = otdata_r[output[0]]; +- dest[1] = otdata_g[output[1]]; +- dest[2] = otdata_b[output[2]]; ++ dest[r_out] = otdata_r[output[0]]; ++ dest[1] = otdata_g[output[1]]; ++ dest[b_out] = otdata_b[output[2]]; + dest += 3; + } + +@@ -141,9 +144,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, + result = _mm_movehl_ps(result, result); + *((__m64 *)&output[2]) = _mm_cvtps_pi32(result); + +- dest[0] = otdata_r[output[0]]; +- dest[1] = otdata_g[output[1]]; +- dest[2] = otdata_b[output[2]]; ++ dest[r_out] = otdata_r[output[0]]; ++ dest[1] = otdata_g[output[1]]; ++ dest[b_out] = otdata_b[output[2]]; + + _mm_empty(); + } +@@ -151,7 +154,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, + void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, + unsigned char *src, + unsigned char *dest, +- size_t length) ++ size_t length, ++ qcms_format_type output_format) + { + unsigned int i; + float (*mat)[4] = transform->matrix; +@@ -187,6 +191,8 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, + + /* working variables */ + __m128 vec_r, vec_g, vec_b, result; ++ const int r_out = output_format.r; ++ const int b_out = output_format.b; + unsigned char alpha; + + /* CYA */ +@@ -239,9 +245,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, + src += 4; + + /* use calc'd indices to output RGB values */ +- dest[0] = otdata_r[output[0]]; +- dest[1] = otdata_g[output[1]]; +- dest[2] = otdata_b[output[2]]; ++ dest[r_out] = otdata_r[output[0]]; ++ dest[1] = otdata_g[output[1]]; ++ dest[b_out] = otdata_b[output[2]]; + dest += 4; + } + +@@ -266,9 +272,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, + result = _mm_movehl_ps(result, result); + *((__m64 *)&output[2]) = _mm_cvtps_pi32(result); + +- dest[0] = otdata_r[output[0]]; +- dest[1] = otdata_g[output[1]]; +- dest[2] = otdata_b[output[2]]; ++ dest[r_out] = otdata_r[output[0]]; ++ dest[1] = otdata_g[output[1]]; ++ dest[b_out] = otdata_b[output[2]]; + + _mm_empty(); + } +diff --git a/src/transform-sse2.c b/src/transform-sse2.c +index 6a5faf9..fa7f2d1 100644 +--- a/src/transform-sse2.c ++++ b/src/transform-sse2.c +@@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] = + void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, + unsigned char *src, + unsigned char *dest, +- size_t length) ++ size_t length, ++ qcms_format_type output_format) + { + unsigned int i; + float (*mat)[4] = transform->matrix; +@@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, + + /* working variables */ + __m128 vec_r, vec_g, vec_b, result; ++ const int r_out = output_format.r; ++ const int b_out = output_format.b; + + /* CYA */ + if (!length) +@@ -114,9 +117,9 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, + src += 3; + + /* use calc'd indices to output RGB values */ +- dest[0] = otdata_r[output[0]]; +- dest[1] = otdata_g[output[1]]; +- dest[2] = otdata_b[output[2]]; ++ dest[r_out] = otdata_r[output[0]]; ++ dest[1] = otdata_g[output[1]]; ++ dest[b_out] = otdata_b[output[2]]; + dest += 3; + } + +@@ -137,15 +140,16 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, + + _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result)); + +- dest[0] = otdata_r[output[0]]; +- dest[1] = otdata_g[output[1]]; +- dest[2] = otdata_b[output[2]]; ++ dest[r_out] = otdata_r[output[0]]; ++ dest[1] = otdata_g[output[1]]; ++ dest[b_out] = otdata_b[output[2]]; + } + + void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, + unsigned char *src, + unsigned char *dest, +- size_t length) ++ size_t length, ++ qcms_format_type output_format) + { + unsigned int i; + float (*mat)[4] = transform->matrix; +@@ -181,6 +185,8 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, + + /* working variables */ + __m128 vec_r, vec_g, vec_b, result; ++ const int r_out = output_format.r; ++ const int b_out = output_format.b; + unsigned char alpha; + + /* CYA */ +@@ -231,9 +237,9 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, + src += 4; + + /* use calc'd indices to output RGB values */ +- dest[0] = otdata_r[output[0]]; +- dest[1] = otdata_g[output[1]]; +- dest[2] = otdata_b[output[2]]; ++ dest[r_out] = otdata_r[output[0]]; ++ dest[1] = otdata_g[output[1]]; ++ dest[b_out] = otdata_b[output[2]]; + dest += 4; + } + +@@ -256,7 +262,7 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, + + _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result)); + +- dest[0] = otdata_r[output[0]]; +- dest[1] = otdata_g[output[1]]; +- dest[2] = otdata_b[output[2]]; ++ dest[r_out] = otdata_r[output[0]]; ++ dest[1] = otdata_g[output[1]]; ++ dest[b_out] = otdata_b[output[2]]; + } +diff --git a/src/transform.c b/src/transform.c +index 9a6562b..ae3f628 100644 +--- a/src/transform.c ++++ b/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; diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c index 36b7011..2454924 100644 --- a/third_party/qcms/src/iccread.c +++ b/third_party/qcms/src/iccread.c @@ -297,6 +297,11 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) sum[1] = rY + gY + bY; sum[2] = rZ + gZ + bZ; +#if defined (_MSC_VER) +#pragma warning(push) +/* Disable double to float truncation warning 4305 */ +#pragma warning(disable:4305) +#endif // Build our target vector (see mozilla bug 460629) target[0] = 0.96420; target[1] = 1.00000; @@ -310,6 +315,10 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) tolerance[1] = 0.02; tolerance[2] = 0.04; +#if defined (_MSC_VER) +/* Restore warnings */ +#pragma warning(pop) +#endif // Compare with our tolerance for (i = 0; i < 3; ++i) { if (!(((sum[i] - tolerance[i]) <= target[i]) && diff --git a/third_party/qcms/src/qcms.h b/third_party/qcms/src/qcms.h index 7d83623..1e3e125b 100644 --- a/third_party/qcms/src/qcms.h +++ b/third_party/qcms/src/qcms.h @@ -102,6 +102,12 @@ typedef enum { QCMS_DATA_GRAYA_8 } qcms_data_type; +/* Format of the output data for qcms_transform_data_type() */ +typedef enum { + QCMS_OUTPUT_RGBX, + QCMS_OUTPUT_BGRX +} qcms_output_type; + /* the names for the following two types are sort of ugly */ typedef struct { @@ -146,6 +152,7 @@ qcms_transform* qcms_transform_create( void qcms_transform_release(qcms_transform *); void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length); +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type); void qcms_enable_iccv4(); diff --git a/third_party/qcms/src/qcmsint.h b/third_party/qcms/src/qcmsint.h index 53a3420..63905de 100644 --- a/third_party/qcms/src/qcmsint.h +++ b/third_party/qcms/src/qcmsint.h @@ -45,6 +45,11 @@ struct precache_output #define ALIGN __attribute__(( aligned (16) )) #endif +typedef struct _qcms_format_type { + int r; + int b; +} qcms_format_type; + struct _qcms_transform { float ALIGN matrix[3][4]; float *input_gamma_table_r; @@ -88,7 +93,7 @@ struct _qcms_transform { struct precache_output *output_table_g; struct precache_output *output_table_b; - void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length); + void (*transform_fn)(struct _qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length, struct _qcms_format_type output_format); }; struct matrix { @@ -280,18 +285,22 @@ qcms_bool set_rgb_colorants(qcms_profile *profile, qcms_CIE_xyY white_point, qcm void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, unsigned char *src, unsigned char *dest, - size_t length); + size_t length, + qcms_format_type output_format); void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, unsigned char *src, unsigned char *dest, - size_t length); + size_t length, + qcms_format_type output_format); void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, unsigned char *src, unsigned char *dest, - size_t length); + size_t length, + qcms_format_type output_format); void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, unsigned char *src, unsigned char *dest, - size_t length); + size_t length, + qcms_format_type output_format); extern qcms_bool qcms_supports_iccv4; diff --git a/third_party/qcms/src/qcmstypes.h b/third_party/qcms/src/qcmstypes.h index 56d8de3..9a9b197 100644 --- a/third_party/qcms/src/qcmstypes.h +++ b/third_party/qcms/src/qcmstypes.h @@ -87,7 +87,12 @@ typedef unsigned __int64 uint64_t; #ifdef _WIN64 typedef unsigned __int64 uintptr_t; #else +#pragma warning(push) +/* Disable benign redefinition of type warning 4142 */ +#pragma warning(disable:4142) typedef unsigned long uintptr_t; +/* Restore warnings */ +#pragma warning(pop) #endif #elif defined (_AIX) diff --git a/third_party/qcms/src/transform-sse1.c b/third_party/qcms/src/transform-sse1.c index 2f34db5..aaee1bf 100644 --- a/third_party/qcms/src/transform-sse1.c +++ b/third_party/qcms/src/transform-sse1.c @@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] = void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, unsigned char *src, unsigned char *dest, - size_t length) + size_t length, + qcms_format_type output_format) { unsigned int i; float (*mat)[4] = transform->matrix; @@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, /* working variables */ __m128 vec_r, vec_g, vec_b, result; + const int r_out = output_format.r; + const int b_out = output_format.b; /* CYA */ if (!length) @@ -116,9 +119,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, src += 3; /* use calc'd indices to output RGB values */ - dest[0] = otdata_r[output[0]]; - dest[1] = otdata_g[output[1]]; - dest[2] = otdata_b[output[2]]; + dest[r_out] = otdata_r[output[0]]; + dest[1] = otdata_g[output[1]]; + dest[b_out] = otdata_b[output[2]]; dest += 3; } @@ -141,9 +144,9 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, result = _mm_movehl_ps(result, result); *((__m64 *)&output[2]) = _mm_cvtps_pi32(result); - dest[0] = otdata_r[output[0]]; - dest[1] = otdata_g[output[1]]; - dest[2] = otdata_b[output[2]]; + dest[r_out] = otdata_r[output[0]]; + dest[1] = otdata_g[output[1]]; + dest[b_out] = otdata_b[output[2]]; _mm_empty(); } @@ -151,7 +154,8 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform, void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, unsigned char *src, unsigned char *dest, - size_t length) + size_t length, + qcms_format_type output_format) { unsigned int i; float (*mat)[4] = transform->matrix; @@ -187,6 +191,8 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, /* working variables */ __m128 vec_r, vec_g, vec_b, result; + const int r_out = output_format.r; + const int b_out = output_format.b; unsigned char alpha; /* CYA */ @@ -239,9 +245,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, src += 4; /* use calc'd indices to output RGB values */ - dest[0] = otdata_r[output[0]]; - dest[1] = otdata_g[output[1]]; - dest[2] = otdata_b[output[2]]; + dest[r_out] = otdata_r[output[0]]; + dest[1] = otdata_g[output[1]]; + dest[b_out] = otdata_b[output[2]]; dest += 4; } @@ -266,9 +272,9 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform, result = _mm_movehl_ps(result, result); *((__m64 *)&output[2]) = _mm_cvtps_pi32(result); - dest[0] = otdata_r[output[0]]; - dest[1] = otdata_g[output[1]]; - dest[2] = otdata_b[output[2]]; + dest[r_out] = otdata_r[output[0]]; + dest[1] = otdata_g[output[1]]; + dest[b_out] = otdata_b[output[2]]; _mm_empty(); } diff --git a/third_party/qcms/src/transform-sse2.c b/third_party/qcms/src/transform-sse2.c index 6a5faf9..fa7f2d1 100644 --- a/third_party/qcms/src/transform-sse2.c +++ b/third_party/qcms/src/transform-sse2.c @@ -34,7 +34,8 @@ static const ALIGN float clampMaxValueX4[4] = void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, unsigned char *src, unsigned char *dest, - size_t length) + size_t length, + qcms_format_type output_format) { unsigned int i; float (*mat)[4] = transform->matrix; @@ -70,6 +71,8 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, /* working variables */ __m128 vec_r, vec_g, vec_b, result; + const int r_out = output_format.r; + const int b_out = output_format.b; /* CYA */ if (!length) @@ -114,9 +117,9 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, src += 3; /* use calc'd indices to output RGB values */ - dest[0] = otdata_r[output[0]]; - dest[1] = otdata_g[output[1]]; - dest[2] = otdata_b[output[2]]; + dest[r_out] = otdata_r[output[0]]; + dest[1] = otdata_g[output[1]]; + dest[b_out] = otdata_b[output[2]]; dest += 3; } @@ -137,15 +140,16 @@ void qcms_transform_data_rgb_out_lut_sse2(qcms_transform *transform, _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result)); - dest[0] = otdata_r[output[0]]; - dest[1] = otdata_g[output[1]]; - dest[2] = otdata_b[output[2]]; + dest[r_out] = otdata_r[output[0]]; + dest[1] = otdata_g[output[1]]; + dest[b_out] = otdata_b[output[2]]; } void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, unsigned char *src, unsigned char *dest, - size_t length) + size_t length, + qcms_format_type output_format) { unsigned int i; float (*mat)[4] = transform->matrix; @@ -181,6 +185,8 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, /* working variables */ __m128 vec_r, vec_g, vec_b, result; + const int r_out = output_format.r; + const int b_out = output_format.b; unsigned char alpha; /* CYA */ @@ -231,9 +237,9 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, src += 4; /* use calc'd indices to output RGB values */ - dest[0] = otdata_r[output[0]]; - dest[1] = otdata_g[output[1]]; - dest[2] = otdata_b[output[2]]; + dest[r_out] = otdata_r[output[0]]; + dest[1] = otdata_g[output[1]]; + dest[b_out] = otdata_b[output[2]]; dest += 4; } @@ -256,7 +262,7 @@ void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform, _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result)); - dest[0] = otdata_r[output[0]]; - dest[1] = otdata_g[output[1]]; - dest[2] = otdata_b[output[2]]; + dest[r_out] = otdata_r[output[0]]; + dest[1] = otdata_g[output[1]]; + dest[b_out] = otdata_b[output[2]]; } diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c index 9a6562b..ae3f628 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; |