17#if defined(__ARM_NEON)
20 #include <immintrin.h>
22 #if defined(__clang__)
28 #include <smmintrin.h>
29 #include <avxintrin.h>
30 #include <avx2intrin.h>
31 #include <avx512fintrin.h>
32 #include <avx512dqintrin.h>
52 int32_t m_bits = (
bits & 0x007fffff) | 0x3f000000;
54 memcpy(&
m, &m_bits,
sizeof(
m));
56 return (
e - 124.225514990f
58 - 1.725879990f/(0.3520887068f +
m));
61 const float ln2 = 0.69314718f;
68 }
else if (
x < -127.0f) {
73 float fbits = (1.0f * (1<<23)) * (
x + 121.274057500f
75 + 27.728023300f/(4.84252568f -
fract));
81 if (fbits >= (
float)INT_MAX) {
83 }
else if (fbits < 0) {
87 int32_t
bits = (int32_t)fbits;
88 memcpy(&
x, &
bits,
sizeof(
x));
104 const float log2_e = 1.4426950408889634074f;
142 int enum_g = -
static_cast<int>(tf.
g);
144 if (
static_cast<float>(-enum_g) != tf.
g) {
151 memcpy(pq , &tf.
a,
sizeof(*pq ));
156 memcpy(hlg, &tf.
a,
sizeof(*hlg));
161 memcpy(hlg, &tf.
a,
sizeof(*hlg));
176 && tf.
a * tf.
d + tf.
b >= 0) {
197 float A,
float B,
float C,
198 float D,
float E,
float F) {
205 float K,
float R,
float G,
206 float a,
float b,
float c) {
213 float sign =
x < 0 ? -1.0f : 1.0f;
236 return sign * (
x < tf->
d ? tf->
c *
x + tf->
f
255 float t = ix - (
float)lo;
259 l = curve->
table_8[lo] * (1/255.0f);
260 h = curve->
table_8[hi] * (1/255.0f);
263 memcpy(&be_l, curve->
table_16 + 2*lo, 2);
264 memcpy(&be_h, curve->
table_16 + 2*hi, 2);
265 uint16_t le_l = ((be_l << 8) | (be_l >> 8)) & 0xffff;
266 uint16_t le_h = ((be_h << 8) | (be_h >> 8)) & 0xffff;
267 l = le_l * (1/65535.0f);
268 h = le_h * (1/65535.0f);
275 const float dx = 1.0f /
static_cast<float>(
N - 1);
277 for (uint32_t
i = 0;
i <
N;
i++) {
278 float x =
static_cast<float>(
i) *
dx,
326 memcpy(&be, ptr,
sizeof(be));
328 return _byteswap_ushort(be);
330 return __builtin_bswap16(be);
336 memcpy(&be, ptr,
sizeof(be));
338 return _byteswap_ulong(be);
340 return __builtin_bswap32(be);
349 return static_cast<float>(
read_big_i32(ptr)) * (1.0f / 65536.0f);
356 uint8_t cmm_type [ 4];
358 uint8_t profile_class [ 4];
359 uint8_t data_color_space [ 4];
361 uint8_t creation_date_time [12];
362 uint8_t signature [ 4];
363 uint8_t platform [ 4];
365 uint8_t device_manufacturer [ 4];
366 uint8_t device_model [ 4];
367 uint8_t device_attributes [ 8];
368 uint8_t rendering_intent [ 4];
369 uint8_t illuminant_X [ 4];
370 uint8_t illuminant_Y [ 4];
371 uint8_t illuminant_Z [ 4];
372 uint8_t creator [ 4];
373 uint8_t profile_id [16];
374 uint8_t reserved [28];
375 uint8_t tag_count [ 4];
379 uint8_t signature [4];
392 uint8_t reserved [ 4];
408 for (
int r = 0; r < 3; ++r)
409 for (
int c = 0; c < 3; ++c,
values += 4) {
419 uint8_t reserved [4];
453 uint8_t reserved_a [4];
454 uint8_t function_type [2];
455 uint8_t reserved_b [2];
456 uint8_t variable [1];
467 enum {
kG = 0, kGAB = 1, kGABC = 2, kGABCD = 3, kGABCDEF = 4 };
469 if (function_type > kGABCDEF) {
473 static const uint32_t curve_bytes[] = { 4, 12, 16, 20, 28 };
491 switch (function_type) {
530 uint8_t reserved [4];
531 uint8_t value_count [4];
532 uint8_t variable [1];
552 if (value_count < 2) {
560 if (value_count == 0) {
580 if (!buf ||
size < 4 || !curve) {
597 uint8_t reserved_a [ 4];
598 uint8_t input_channels [ 1];
599 uint8_t output_channels [ 1];
600 uint8_t grid_points [ 1];
601 uint8_t reserved_b [ 1];
608 uint8_t variable [1];
614 uint8_t input_table_entries [2];
615 uint8_t output_table_entries [2];
616 uint8_t variable [1];
625 a2b-> input_channels = mftTag-> input_channels[0];
651 b2a-> input_channels = mftTag-> input_channels[0];
673template <
typename A2B_or_B2A>
674static bool init_tables(
const uint8_t* table_base, uint64_t max_tables_len, uint32_t byte_width,
675 uint32_t input_table_entries, uint32_t output_table_entries,
678 uint32_t byte_len_per_input_table = input_table_entries * byte_width;
679 uint32_t byte_len_per_output_table = output_table_entries * byte_width;
682 uint32_t byte_len_all_input_tables =
out->input_channels * byte_len_per_input_table;
683 uint32_t byte_len_all_output_tables =
out->output_channels * byte_len_per_output_table;
685 uint64_t grid_size =
out->output_channels * byte_width;
686 for (uint32_t axis = 0; axis <
out->input_channels; ++axis) {
687 grid_size *=
out->grid_points[axis];
690 if (max_tables_len < byte_len_all_input_tables + grid_size + byte_len_all_output_tables) {
694 for (uint32_t
i = 0;
i <
out->input_channels; ++
i) {
695 out->input_curves[
i].table_entries = input_table_entries;
696 if (byte_width == 1) {
697 out->input_curves[
i].table_8 = table_base +
i * byte_len_per_input_table;
698 out->input_curves[
i].table_16 =
nullptr;
700 out->input_curves[
i].table_8 =
nullptr;
701 out->input_curves[
i].table_16 = table_base +
i * byte_len_per_input_table;
705 if (byte_width == 1) {
706 out->grid_8 = table_base + byte_len_all_input_tables;
707 out->grid_16 =
nullptr;
709 out->grid_8 =
nullptr;
710 out->grid_16 = table_base + byte_len_all_input_tables;
713 const uint8_t* output_table_base = table_base + byte_len_all_input_tables + grid_size;
714 for (uint32_t
i = 0;
i <
out->output_channels; ++
i) {
715 out->output_curves[
i].table_entries = output_table_entries;
716 if (byte_width == 1) {
717 out->output_curves[
i].table_8 = output_table_base +
i * byte_len_per_output_table;
718 out->output_curves[
i].table_16 =
nullptr;
720 out->output_curves[
i].table_8 =
nullptr;
721 out->output_curves[
i].table_16 = output_table_base +
i * byte_len_per_output_table;
728template <
typename A2B_or_B2A>
739 uint32_t input_table_entries = 256;
740 uint32_t output_table_entries = 256;
743 input_table_entries, output_table_entries,
out);
746template <
typename A2B_or_B2A>
761 if (input_table_entries < 2 || input_table_entries > 4096 ||
762 output_table_entries < 2 || output_table_entries > 4096) {
767 input_table_entries, output_table_entries,
out);
772 for (uint32_t
i = 0;
i < num_curves; ++
i) {
773 if (curve_offset >
size) {
777 uint32_t curve_bytes;
778 if (!
read_curve(buf + curve_offset,
size - curve_offset, &curves[
i], &curve_bytes)) {
782 if (curve_bytes > UINT32_MAX - 3) {
785 curve_bytes = (curve_bytes + 3) & ~3U;
787 uint64_t new_offset_64 = (uint64_t)curve_offset + curve_bytes;
788 curve_offset = (uint32_t)new_offset_64;
789 if (new_offset_64 != curve_offset) {
800 uint8_t reserved_a [ 4];
801 uint8_t input_channels [ 1];
802 uint8_t output_channels [ 1];
803 uint8_t reserved_b [ 2];
804 uint8_t b_curve_offset [ 4];
805 uint8_t matrix_offset [ 4];
806 uint8_t m_curve_offset [ 4];
807 uint8_t clut_offset [ 4];
808 uint8_t a_curve_offset [ 4];
812 uint8_t grid_points [16];
813 uint8_t grid_byte_width [ 1];
814 uint8_t reserved [ 3];
815 uint8_t variable [1];
844 if (0 == b_curve_offset) {
854 if (0 != m_curve_offset) {
855 if (0 == matrix_offset) {
868 float encoding_factor = pcs_is_xyz ? (65535 / 32768.0f) : 1.0f;
869 const uint8_t* mtx_buf = tag->
buf + matrix_offset;
883 if (0 != matrix_offset) {
890 if (0 != a_curve_offset) {
891 if (0 == clut_offset) {
904 if (
clut->grid_byte_width[0] == 1) {
907 }
else if (
clut->grid_byte_width[0] == 2) {
927 if (0 != clut_offset) {
969 if (0 == b_curve_offset) {
979 if (0 != m_curve_offset) {
980 if (0 == matrix_offset) {
994 float encoding_factor = pcs_is_xyz ? (32768 / 65535.0f) : 1.0f;
995 const uint8_t* mtx_buf = tag->
buf + matrix_offset;
1009 if (0 != matrix_offset) {
1015 if (0 != a_curve_offset) {
1016 if (0 == clut_offset) {
1031 if (
clut->grid_byte_width[0] == 1) {
1034 }
else if (
clut->grid_byte_width[0] == 2) {
1053 if (0 != clut_offset) {
1070 float* c,
float*
d,
float*
f =
nullptr) {
1082 const float dx = 1.0f /
static_cast<float>(
N - 1);
1086 float f_zero = 0.0f;
1096 for (
int i = 1;
i <
N; ++
i) {
1097 float x =
static_cast<float>(
i) *
dx;
1100 float slope_max_i = (
y + tol - *
f) /
x,
1101 slope_min_i = (
y - tol - *
f) /
x;
1102 if (slope_max_i < slope_min || slope_max < slope_min_i) {
1106 slope_max =
fminf_(slope_max, slope_max_i);
1107 slope_min =
fmaxf_(slope_min, slope_min_i);
1109 float cur_slope = (
y - *
f) /
x;
1110 if (slope_min <= cur_slope && cur_slope <= slope_max) {
1117 *
d =
static_cast<float>(lin_points - 1) *
dx;
1126 float c = 0.0f,
d = 0.0f,
f = 0.0f;
1190 uint8_t reserved [4];
1191 uint8_t color_primaries [1];
1192 uint8_t transfer_characteristics [1];
1193 uint8_t matrix_coefficients [1];
1194 uint8_t video_full_range_flag [1];
1213 if (idx >
profile->tag_count) {
return; }
1224 for (uint32_t
i = 0;
i <
profile->tag_count; ++
i) {
1242 const int priority[],
const int priorities,
1257 profile->buffer = (
const uint8_t*)buf;
1279 if (
fabsf_(illuminant_X - 0.9642f) > 0.0100f ||
1280 fabsf_(illuminant_Y - 1.0000f) > 0.0100f ||
1281 fabsf_(illuminant_Z - 0.8249f) > 0.0100f) {
1287 for (uint32_t
i = 0;
i <
profile->tag_count; ++
i) {
1290 uint64_t tag_end = (uint64_t)tag_offset + (uint64_t)tag_size;
1291 if (tag_size < 4 || tag_end >
profile->size) {
1315 profile->toXYZD50.vals[0][0] = illuminant_X;
1316 profile->toXYZD50.vals[1][1] = illuminant_Y;
1317 profile->toXYZD50.vals[2][2] = illuminant_Z;
1346 for (
int i = 0;
i < priorities;
i++) {
1348 if (priority[
i] < 0 || priority[
i] > 2) {
1363 for (
int i = 0;
i < priorities;
i++) {
1365 if (priority[
i] < 0 || priority[
i] > 2) {
1406 {{0, {2.4f, (
float)(1/1.055), (
float)(0.055/1.055), (
float)(1/12.92), 0.04045f, 0, 0}}},
1407 {{0, {2.4f, (
float)(1/1.055), (
float)(0.055/1.055), (
float)(1/12.92), 0.04045f, 0, 0}}},
1408 {{0, {2.4f, (
float)(1/1.055), (
float)(0.055/1.055), (
float)(1/12.92), 0.04045f, 0, 0}}},
1413 { 0.436065674f, 0.385147095f, 0.143066406f },
1414 { 0.222488403f, 0.716873169f, 0.060607910f },
1415 { 0.013916016f, 0.097076416f, 0.714096069f },
1422 {{0, {0,0, 0,0,0,0,0}}},
1423 {{0, {0,0, 0,0,0,0,0}}},
1424 {{0, {0,0, 0,0,0,0,0}}},
1425 {{0, {0,0, 0,0,0,0,0}}},
1433 {{0, {0,0, 0,0,0,0,0}}},
1434 {{0, {0,0, 0,0,0,0,0}}},
1435 {{0, {0,0, 0,0,0,0,0}}},
1445 {{0, {0,0, 0,0,0,0,0}}},
1446 {{0, {0,0, 0,0,0,0,0}}},
1447 {{0, {0,0, 0,0,0,0,0}}},
1455 {{0, {0,0, 0,0,0,0,0}}},
1456 {{0, {0,0, 0,0,0,0,0}}},
1457 {{0, {0,0, 0,0,0,0,0}}},
1467 {{0, {0,0, 0,0,0,0,0}}},
1468 {{0, {0,0, 0,0,0,0,0}}},
1469 {{0, {0,0, 0,0,0,0,0}}},
1477 {{0, {0,0, 0,0,0,0,0}}},
1478 {{0, {0,0, 0,0,0,0,0}}},
1479 {{0, {0,0, 0,0,0,0,0}}},
1480 {{0, {0,0, 0,0,0,0,0}}},
1487 return &sRGB_profile;
1502 {{0, {1,1, 0,0,0,0,0}}},
1503 {{0, {1,1, 0,0,0,0,0}}},
1504 {{0, {1,1, 0,0,0,0,0}}},
1518 {{0, {0,0, 0,0,0,0,0}}},
1519 {{0, {0,0, 0,0,0,0,0}}},
1520 {{0, {0,0, 0,0,0,0,0}}},
1521 {{0, {0,0, 0,0,0,0,0}}},
1529 {{0, {0,0, 0,0,0,0,0}}},
1530 {{0, {0,0, 0,0,0,0,0}}},
1531 {{0, {0,0, 0,0,0,0,0}}},
1541 {{0, {0,0, 0,0,0,0,0}}},
1542 {{0, {0,0, 0,0,0,0,0}}},
1543 {{0, {0,0, 0,0,0,0,0}}},
1551 {{0, {0,0, 0,0,0,0,0}}},
1552 {{0, {0,0, 0,0,0,0,0}}},
1553 {{0, {0,0, 0,0,0,0,0}}},
1563 {{0, {0,0, 0,0,0,0,0}}},
1564 {{0, {0,0, 0,0,0,0,0}}},
1565 {{0, {0,0, 0,0,0,0,0}}},
1573 {{0, {0,0, 0,0,0,0,0}}},
1574 {{0, {0,0, 0,0,0,0,0}}},
1575 {{0, {0,0, 0,0,0,0,0}}},
1576 {{0, {0,0, 0,0,0,0,0}}},
1584 return &XYZD50_profile;
1593 {0.416666657f, 1.137283325f, -0.0f, 12.920000076f, 0.003130805f, -0.054969788f, -0.0f};
1603 8, 179, 128, 204, 253, 38, 134, 184, 68, 102, 32, 138, 99, 39, 169, 215,
1604 119, 26, 3, 223, 95, 239, 52, 132, 114, 74, 81, 234, 97, 116, 244, 205, 30,
1605 154, 173, 12, 51, 159, 122, 153, 61, 226, 236, 178, 229, 55, 181, 220, 191,
1606 194, 160, 126, 168, 82, 131, 18, 180, 245, 163, 22, 246, 69, 235, 252, 57,
1607 108, 14, 6, 152, 240, 255, 171, 242, 20, 227, 177, 238, 96, 85, 16, 211,
1608 70, 200, 149, 155, 146, 127, 145, 100, 151, 109, 19, 165, 208, 195, 164,
1609 137, 254, 182, 248, 64, 201, 45, 209, 5, 147, 207, 210, 113, 162, 83, 225,
1610 9, 31, 15, 231, 115, 37, 58, 53, 24, 49, 197, 56, 120, 172, 48, 21, 214,
1611 129, 111, 11, 50, 187, 196, 34, 60, 103, 71, 144, 47, 203, 77, 80, 232,
1612 140, 222, 250, 206, 166, 247, 139, 249, 221, 72, 106, 27, 199, 117, 54,
1613 219, 135, 118, 40, 79, 41, 251, 46, 93, 212, 92, 233, 148, 28, 121, 63,
1614 123, 158, 105, 59, 29, 42, 143, 23, 0, 107, 176, 87, 104, 183, 156, 193,
1615 189, 90, 188, 65, 190, 17, 198, 7, 186, 161, 1, 124, 78, 125, 170, 133,
1616 174, 218, 67, 157, 75, 101, 89, 217, 62, 33, 141, 228, 25, 35, 91, 230, 4,
1617 2, 13, 73, 86, 167, 237, 84, 243, 44, 185, 66, 130, 110, 150, 142, 216, 88,
1618 112, 36, 224, 136, 202, 76, 94, 98, 175, 213
1640 if ((
A->data_color_space == CMYK) != (
B->data_color_space == CMYK)) {
1647 size_t npixels = 84;
1671 for (
size_t i = 0;
i < 252;
i++) {
1672 if (
abs((
int)dstA[
i] - (
int)dstB[
i]) > 1) {
1691 return 0 <=
x &&
x <= 1;
1698 for (
int row = 0; row < 3; ++row) {
1699 dst.vals[row] =
m->vals[row][0] * v->
vals[0]
1700 +
m->vals[row][1] * v->
vals[1]
1701 +
m->vals[row][2] * v->
vals[2];
1714 skcms_Vector3 wXYZ = { { wx / wy, 1, (1 - wx - wy) / wy } };
1723 { 0.8951f, 0.2664f, -0.1614f },
1724 { -0.7502f, 1.7135f, 0.0367f },
1725 { 0.0389f, -0.0685f, 1.0296f },
1728 { 0.9869929f, -0.1470543f, 0.1599627f },
1729 { 0.4323053f, 0.5183603f, 0.0492912f },
1730 { -0.0085287f, 0.0400428f, 0.9684867f },
1737 { dstCone.
vals[0] / srcCone.
vals[0], 0, 0 },
1738 { 0, dstCone.
vals[1] / srcCone.
vals[1], 0 },
1739 { 0, 0, dstCone.
vals[2] / srcCone.
vals[2] },
1764 { 1 - rx - ry, 1 - gx - gy, 1 - bx - by },
1772 skcms_Vector3 wXYZ = { { wx / wy, 1, (1 - wx - wy) / wy } };
1776 { XYZ.
vals[0], 0, 0 },
1777 { 0, XYZ.
vals[1], 0 },
1778 { 0, 0, XYZ.
vals[2] },
1793 double a00 =
src->vals[0][0],
1794 a01 =
src->vals[1][0],
1795 a02 =
src->vals[2][0],
1796 a10 =
src->vals[0][1],
1797 a11 =
src->vals[1][1],
1798 a12 =
src->vals[2][1],
1799 a20 =
src->vals[0][2],
1800 a21 =
src->vals[1][2],
1801 a22 =
src->vals[2][2];
1803 double b0 = a00*a11 - a01*a10,
1804 b1 = a00*a12 - a02*a10,
1805 b2 = a01*a12 - a02*a11,
1810 double determinant = b0*b5
1814 if (determinant == 0) {
1818 double invdet = 1.0 / determinant;
1819 if (invdet > +FLT_MAX || invdet < -FLT_MAX || !
isfinitef_((
float)invdet)) {
1830 dst->vals[0][0] = (
float)( a11*b5 - a12*b4 );
1831 dst->vals[1][0] = (
float)( a02*b4 - a01*b5 );
1833 dst->vals[0][1] = (
float)( a12*b3 - a10*b5 );
1834 dst->vals[1][1] = (
float)( a00*b5 - a02*b3 );
1836 dst->vals[0][2] = (
float)( a10*b4 - a11*b3 );
1837 dst->vals[1][2] = (
float)( a01*b3 - a00*b4 );
1840 for (
int r = 0; r < 3; ++r)
1841 for (
int c = 0; c < 3; ++c) {
1851 for (
int r = 0; r < 3; r++)
1852 for (
int c = 0; c < 3; c++) {
1853 m.vals[r][c] =
A->vals[r][0] *
B->vals[0][c]
1854 +
A->vals[r][1] *
B->vals[1][c]
1855 +
A->vals[r][2] *
B->vals[2][c];
1860#if defined(__clang__)
1861 [[clang::no_sanitize(
"float-divide-by-zero")]]
1872 , pq.
B, -pq.
E, 1.0f/pq.
C};
1877 , 1.0f/hlg.
a, hlg.
b, hlg.
c
1883 , 1.0f/hlg.
a, hlg.
b, hlg.
c
1901 if (
fabsf_(d_l - d_r) > 1/512.0f) {
1953 assert (
inv.a >= 0);
1964 float sign =
s < 0 ? -1.0f : 1.0f;
2021 const float g = tf->
g,
a = tf->
a,
b = tf->
b,
2022 c = tf->
c,
d = tf->
d,
f = tf->
f;
2033 dfdP[2] = g*
powf_(
Y, g-1)
2037 const float f_inv =
powf_(
Y, g)
2045 float x0,
float dx,
int N) {
2087 for (
int i = 0;
i <
N;
i++) {
2088 float x = x0 +
static_cast<float>(
i)*
dx;
2090 float dfdP[3] = {0,0,0};
2093 for (
int r = 0; r < 3; r++) {
2094 for (
int c = 0; c < 3; c++) {
2095 lhs.
vals[r][c] += dfdP[r] * dfdP[c];
2097 rhs.
vals[r] += dfdP[r] * resid;
2103 for (
int k = 0; k < 3; k++) {
2104 if (lhs.
vals[0][k]==0 && lhs.
vals[1][k]==0 && lhs.
vals[2][k]==0 &&
2105 lhs.
vals[k][0]==0 && lhs.
vals[k][1]==0 && lhs.
vals[k][2]==0) {
2118 tf->
g += dP.
vals[0];
2119 tf->
a += dP.
vals[1];
2120 tf->
b += dP.
vals[2];
2142 auto fixup_tf = [tf]() {
2150 if (tf->
a * tf->
d + tf->
b < 0) {
2151 tf->
b = -tf->
a * tf->
d;
2153 assert (tf->
a >= 0 &&
2154 tf->
a * tf->
d + tf->
b >= 0);
2158 tf->
e = tf->
c*tf->
d + tf->
f
2169 const float dx = 1.0f /
static_cast<float>(
N-1);
2176 if (init_error < best_max_error) {
2177 best_max_error = init_error;
2182 for (
int j = 0; j < 8; j++) {
2189 if (max_error < best_max_error) {
2190 best_max_error = max_error;
2202 if (!curve || !approx || !max_error) {
2217 const float dx = 1.0f /
static_cast<float>(
N - 1);
2220 const float kTolerances[] = { 1.5f / 65535.0f, 1.0f / 512.0f };
2221 for (
int t = 0; t <
ARRAY_COUNT(kTolerances); t++) {
2235 tf.
c = tf.
d = tf.
e = tf.
f = 0;
2236 }
else if (
L ==
N - 1) {
2243 - tf.
a *
static_cast<float>(
N-2)*
dx;
2247 int mid = (
L +
N) / 2;
2248 float mid_x =
static_cast<float>(mid) /
static_cast<float>(
N - 1);
2253 tf.
e = tf.
c*tf.
d + tf.
f
2292 if (*max_error > err) {
2303 #if defined(SKCMS_PORTABLE) || !defined(__x86_64__) || defined(SKCMS_FORCE_BASELINE)
2305 #elif defined(SKCMS_FORCE_HSW)
2307 #elif defined(SKCMS_FORCE_SKX)
2317 uint32_t eax, ebx, ecx, edx;
2318 __asm__ __volatile__(
"cpuid" :
"=a"(eax),
"=b"(ebx),
"=c"(ecx),
"=d"(edx)
2320 if ((edx & (1u<<25)) &&
2333 __asm__ __volatile__(
"cpuid" :
"=a"(eax),
"=b"(ebx),
"=c"(ecx),
"=d"(edx)
2336 uint32_t xcr0, dont_need_edx;
2337 __asm__ __volatile__(
"xgetbv" :
"=a"(xcr0),
"=d"(dont_need_edx) :
"c"(0));
2339 if ((xcr0 & (1u<<1)) &&
2343 if ((xcr0 & (1u<< 5)) &&
2344 (xcr0 & (1u<< 6)) &&
2345 (xcr0 & (1u<< 7)) &&
2363 return tf.
g > 0 && tf.
a == 1 &&
2364 tf.
b == 0 && tf.
c == 0 && tf.
d == 0 && tf.
e == 0 && tf.
f == 0;
2374 Op sGamma, sRGBish, PQish, HLGish, HLGinvish,
table;
2376 static constexpr OpType kOps[] = {
2377 { Op::gamma_r, Op::tf_r, Op::pq_r, Op::hlg_r, Op::hlginv_r, Op::table_r },
2378 { Op::gamma_g, Op::tf_g, Op::pq_g, Op::hlg_g, Op::hlginv_g, Op::table_g },
2379 { Op::gamma_b, Op::tf_b, Op::pq_b, Op::hlg_b, Op::hlginv_b, Op::table_b },
2380 { Op::gamma_a, Op::tf_a, Op::pq_a, Op::hlg_a, Op::hlginv_a, Op::table_a },
2382 const auto& op = kOps[channel];
2390 return tf.
g != 1 ?
OpAndArg{op.sGamma, &tf}
2409 for (
int index = numChannels; index-- > 0; ) {
2411 if (
ops[cursor].arg) {
2421 static constexpr FusableOps kFusableOps[] = {
2422 {Op::gamma_r, Op::gamma_g, Op::gamma_b, Op::gamma_rgb},
2423 {Op::tf_r, Op::tf_g, Op::tf_b, Op::tf_rgb},
2424 {Op::pq_r, Op::pq_g, Op::pq_b, Op::pq_rgb},
2425 {Op::hlg_r, Op::hlg_g, Op::hlg_b, Op::hlg_rgb},
2426 {Op::hlginv_r, Op::hlginv_g, Op::hlginv_b, Op::hlginv_rgb},
2429 int posR = cursor - 1;
2430 int posG = cursor - 2;
2431 int posB = cursor - 3;
2432 for (
const FusableOps& fusableOp : kFusableOps) {
2433 if (
ops[posR].op == fusableOp.r &&
2434 ops[posG].op == fusableOp.g &&
2435 ops[posB].op == fusableOp.b &&
2439 ops[posB].op = fusableOp.rgb;
2482 if (
profile->has_B2A) {
return true; }
2486 &&
profile->trc[0].table_entries == 0
2487 &&
profile->trc[1].table_entries == 0
2488 &&
profile->trc[2].table_entries == 0
2507 if (nz * dst_bpp > INT_MAX || nz * src_bpp > INT_MAX) {
2521 if (
dst ==
src && dst_bpp != src_bpp) {
2527 const void* context[32];
2530 const void** contexts = context;
2532 auto add_op = [&](
Op o) {
2534 *contexts++ =
nullptr;
2537 auto add_op_ctx = [&](
Op o,
const void* c) {
2542 auto add_curve_ops = [&](
const skcms_Curve* curves,
int numChannels) {
2548 for (
int i = 0;
i < numOps; ++
i) {
2549 add_op_ctx(oa[
i].op, oa[
i].arg);
2561 switch (srcFmt >> 1) {
2562 default:
return false;
2584 add_op(Op::load_8888);
2593 add_op(Op::swap_rb);
2599 gray_dst_profile = *dstProfile;
2601 dstProfile = &gray_dst_profile;
2613 add_op(Op::force_opaque);
2615 add_op(Op::unpremul);
2618 if (dstProfile != srcProfile) {
2622 &dst_curves[0].parametric,
2623 &dst_curves[1].parametric,
2624 &dst_curves[2].parametric)) {
2633 add_op_ctx(Op::clut_A2B, &srcProfile->
A2B);
2644 if (0 != memcmp(&
I, &srcProfile->
A2B.
matrix,
sizeof(
I))) {
2645 add_op_ctx(Op::matrix_3x4, &srcProfile->
A2B.
matrix);
2654 add_op(Op::lab_to_xyz);
2658 add_curve_ops(srcProfile->
trc, 3);
2669 add_op_ctx(Op::matrix_3x3, &srcProfile->
toXYZD50);
2673 add_op(Op::xyz_to_lab);
2686 if (0 != memcmp(&
I, &dstProfile->
B2A.
matrix,
sizeof(
I))) {
2687 add_op_ctx(Op::matrix_3x4, &dstProfile->
B2A.
matrix);
2695 add_op_ctx(Op::clut_B2A, &dstProfile->
B2A);
2705 { 1.0f, 0.0f, 0.0f },
2706 { 0.0f, 1.0f, 0.0f },
2707 { 0.0f, 0.0f, 1.0f },
2717 add_op_ctx(Op::matrix_3x3, &from_xyz);
2723 for (
int index = 0; index < numOps; ++index) {
2724 assert(oa[index].op != Op::table_r &&
2725 oa[index].op != Op::table_g &&
2726 oa[index].op != Op::table_b &&
2727 oa[index].op != Op::table_a);
2728 add_op_ctx(oa[index].op, oa[index].arg);
2752 add_op(Op::force_opaque);
2757 add_op(Op::swap_rb);
2759 switch (dstFmt >> 1) {
2760 default:
return false;
2782 add_op(Op::store_8888);
2787 assert(contexts <= context +
ARRAY_COUNT(context));
2792 #if !defined(SKCMS_DISABLE_SKX)
2798 #if !defined(SKCMS_DISABLE_HSW)
2807 run(program, context,
ops - program, (
const char*)
src, (
char*)
dst, n, src_bpp,dst_bpp);
2830 for (
int i = 0;
i < 3;
i++) {
2832 if (
profile->trc[
i].table_entries == 0
2845 for (
int i = 0;
i < 3; ++
i) {
2866 for (
int i = 0;
i < 3;
i++) {
2873 for (
int j = 0; j < 3; ++j) {
2876 if (min_max_error > err) {
2877 min_max_error = err;
2882 for (
int i = 0;
i < 3;
i++) {
static SkM44 inv(const SkM44 &m)
for(const auto glyph :glyphs)
static unsigned clamp(SkFixed fx, int max)
static bool ok(int result)
static int sign(SkScalar x)
static uint32_t premul(uint32_t color)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
FlutterSemanticsFlag flags
__asm__(".symver expf,expf@GLIBC_2.4")
unsigned useCenter Optional< SkMatrix > matrix
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
SIN Vec< N, float > abs(const Vec< N, float > &x)
SIN Vec< N, float > fract(const Vec< N, float > &x)
static SkString fmt(SkColor4f c)
static int32_t read_big_i32(const uint8_t *ptr)
bool skcms_ParseWithA2BPriority(const void *buf, size_t len, const int priority[], const int priorities, skcms_ICCProfile *profile)
static int fit_linear(const skcms_Curve *curve, int N, float tol, float *c, float *d, float *f=nullptr)
static float logf_(float x)
static bool read_b2a(const skcms_ICCTag *tag, skcms_B2A *b2a, bool pcs_is_xyz)
bool skcms_TransferFunction_isHLGish(const skcms_TransferFunction *tf)
static float fminf_(float x, float y)
static bool read_cicp(const skcms_ICCTag *tag, skcms_CICP *cicp)
bool skcms_PrimariesToXYZD50(float rx, float ry, float gx, float gy, float bx, float by, float wx, float wy, skcms_Matrix3x3 *toXYZD50)
bool skcms_Transform(const void *src, skcms_PixelFormat srcFmt, skcms_AlphaFormat srcAlpha, const skcms_ICCProfile *srcProfile, void *dst, skcms_PixelFormat dstFmt, skcms_AlphaFormat dstAlpha, const skcms_ICCProfile *dstProfile, size_t nz)
bool skcms_Matrix3x3_invert(const skcms_Matrix3x3 *src, skcms_Matrix3x3 *dst)
skcms_TFType skcms_TransferFunction_getType(const skcms_TransferFunction *tf)
static skcms_TFType classify(const skcms_TransferFunction &tf, TF_PQish *pq=nullptr, TF_HLGish *hlg=nullptr)
bool skcms_AreApproximateInverses(const skcms_Curve *curve, const skcms_TransferFunction *inv_tf)
void skcms_DisableRuntimeCPUDetection()
static bool read_curves(const uint8_t *buf, uint32_t size, uint32_t curve_offset, uint32_t num_curves, skcms_Curve *curves)
static float minus_1_ulp(float x)
bool skcms_MakeUsableAsDestinationWithSingleCurve(skcms_ICCProfile *profile)
static float expf_(float x)
static void assert_usable_as_destination(const skcms_ICCProfile *profile)
static bool read_tag_mft1(const skcms_ICCTag *tag, A2B_or_B2A *out)
static float eval_curve(const skcms_Curve *curve, float x)
float powf_(float x, float y)
static float log2f_(float x)
static bool tf_is_gamma(const skcms_TransferFunction &tf)
void skcms_GetTagByIndex(const skcms_ICCProfile *profile, uint32_t idx, skcms_ICCTag *tag)
bool skcms_TransferFunction_makeScaledHLGish(skcms_TransferFunction *tf, float K, float R, float G, float a, float b, float c)
static int select_curve_ops(const skcms_Curve *curves, int numChannels, OpAndArg *ops)
static bool read_mft_common(const mft_CommonLayout *mftTag, skcms_A2B *a2b)
static float max_roundtrip_error_checked(const skcms_Curve *curve, const skcms_TransferFunction *tf_inv)
const uint8_t skcms_252_random_bytes[]
static bool read_a2b(const skcms_ICCTag *tag, skcms_A2B *a2b, bool pcs_is_xyz)
const skcms_TransferFunction * skcms_sRGB_Inverse_TransferFunction()
static size_t bytes_per_pixel(skcms_PixelFormat fmt)
float skcms_TransferFunction_eval(const skcms_TransferFunction *tf, float x)
bool skcms_GetWTPT(const skcms_ICCProfile *profile, float xyz[3])
static bool read_to_XYZD50(const skcms_ICCTag *rXYZ, const skcms_ICCTag *gXYZ, const skcms_ICCTag *bXYZ, skcms_Matrix3x3 *toXYZ)
static float rg_nonlinear(float x, const skcms_Curve *curve, const skcms_TransferFunction *tf, float dfdP[3])
static skcms_Vector3 mv_mul(const skcms_Matrix3x3 *m, const skcms_Vector3 *v)
bool skcms_ApproximateCurve(const skcms_Curve *curve, skcms_TransferFunction *approx, float *max_error)
bool skcms_TransferFunction_invert(const skcms_TransferFunction *src, skcms_TransferFunction *dst)
const skcms_TransferFunction * skcms_Identity_TransferFunction()
static bool read_tag_mft2(const skcms_ICCTag *tag, A2B_or_B2A *out)
static float exp2f_(float x)
static bool sAllowRuntimeCPUDetection
const skcms_ICCProfile * skcms_sRGB_profile()
static uint16_t read_big_u16(const uint8_t *ptr)
static uint32_t read_big_u32(const uint8_t *ptr)
static bool read_tag_xyz(const skcms_ICCTag *tag, float *x, float *y, float *z)
static OpAndArg select_curve_op(const skcms_Curve *curve, int channel)
bool skcms_TRCs_AreApproximateInverse(const skcms_ICCProfile *profile, const skcms_TransferFunction *inv_tf)
static bool fit_nonlinear(const skcms_Curve *curve, int L, int N, skcms_TransferFunction *tf)
static const tag_Layout * get_tag_table(const skcms_ICCProfile *profile)
static CpuType cpu_type()
static bool prep_for_destination(const skcms_ICCProfile *profile, skcms_Matrix3x3 *fromXYZD50, skcms_TransferFunction *invR, skcms_TransferFunction *invG, skcms_TransferFunction *invB)
bool skcms_TransferFunction_isPQish(const skcms_TransferFunction *tf)
bool skcms_GetTagBySignature(const skcms_ICCProfile *profile, uint32_t sig, skcms_ICCTag *tag)
bool skcms_TransferFunction_makePQish(skcms_TransferFunction *tf, float A, float B, float C, float D, float E, float F)
bool skcms_ApproximatelyEqualProfiles(const skcms_ICCProfile *A, const skcms_ICCProfile *B)
static bool read_curve_para(const uint8_t *buf, uint32_t size, skcms_Curve *curve, uint32_t *curve_size)
bool skcms_TransferFunction_isSRGBish(const skcms_TransferFunction *tf)
static bool read_tag_mab(const skcms_ICCTag *tag, skcms_A2B *a2b, bool pcs_is_xyz)
static bool usable_as_src(const skcms_ICCProfile *profile)
static bool read_tag_mba(const skcms_ICCTag *tag, skcms_B2A *b2a, bool pcs_is_xyz)
static bool read_curve_curv(const uint8_t *buf, uint32_t size, skcms_Curve *curve, uint32_t *curve_size)
const skcms_ICCProfile * skcms_XYZD50_profile()
float skcms_MaxRoundtripError(const skcms_Curve *curve, const skcms_TransferFunction *inv_tf)
static float fmaxf_(float x, float y)
static bool gauss_newton_step(const skcms_Curve *curve, skcms_TransferFunction *tf, float x0, float dx, int N)
static void canonicalize_identity(skcms_Curve *curve)
static bool is_zero_to_one(float x)
const skcms_TransferFunction * skcms_sRGB_TransferFunction()
bool skcms_AdaptToXYZD50(float wx, float wy, skcms_Matrix3x3 *toXYZD50)
static float read_big_fixed(const uint8_t *ptr)
bool skcms_MakeUsableAsDestination(skcms_ICCProfile *profile)
static bool isfinitef_(float x)
static bool init_tables(const uint8_t *table_base, uint64_t max_tables_len, uint32_t byte_width, uint32_t input_table_entries, uint32_t output_table_entries, A2B_or_B2A *out)
static float TFKind_marker(skcms_TFType kind)
bool skcms_GetCHAD(const skcms_ICCProfile *profile, skcms_Matrix3x3 *m)
skcms_Matrix3x3 skcms_Matrix3x3_concat(const skcms_Matrix3x3 *A, const skcms_Matrix3x3 *B)
static bool read_curve(const uint8_t *buf, uint32_t size, skcms_Curve *curve, uint32_t *curve_size)
#define SAFE_FIXED_SIZE(type)
static float floorf_(float x)
static float fabsf_(float x)
@ skcms_PixelFormat_RGBA_8888_sRGB
@ skcms_PixelFormat_RGBA_16161616BE
@ skcms_PixelFormat_RGB_161616LE
@ skcms_PixelFormat_RGBA_ffff
@ skcms_PixelFormat_RGBA_1010102
@ skcms_PixelFormat_RGBA_hhhh
@ skcms_PixelFormat_RGB_fff
@ skcms_PixelFormat_RGB_hhh_Norm
@ skcms_PixelFormat_RGBA_8888
@ skcms_PixelFormat_RGB_hhh
@ skcms_PixelFormat_RGB_888
@ skcms_PixelFormat_ABGR_4444
@ skcms_PixelFormat_RGB_565
@ skcms_PixelFormat_RGB_161616BE
@ skcms_PixelFormat_RGBA_hhhh_Norm
@ skcms_PixelFormat_RGBA_10101010_XR
@ skcms_PixelFormat_RGB_101010x_XR
@ skcms_PixelFormat_RGBA_16161616LE
static void skcms_SetXYZD50(skcms_ICCProfile *p, const skcms_Matrix3x3 *m)
@ skcms_AlphaFormat_Unpremul
@ skcms_AlphaFormat_PremulAsEncoded
@ skcms_AlphaFormat_Opaque
static const char header[]
uint8_t video_full_range_flag[1]
uint8_t transfer_characteristics[1]
uint8_t color_primaries[1]
uint8_t matrix_coefficients[1]
uint8_t input_channels[1]
uint8_t output_channels[1]
uint8_t m_curve_offset[4]
uint8_t a_curve_offset[4]
uint8_t b_curve_offset[4]
mft_CommonLayout common[1]
uint8_t output_table_entries[2]
mft_CommonLayout common[1]
uint8_t input_table_entries[2]
uint8_t output_channels[1]
skcms_Curve matrix_curves[3]
skcms_Curve output_curves[3]
skcms_Curve input_curves[4]
skcms_Curve output_curves[4]
skcms_Curve matrix_curves[3]
skcms_Curve input_curves[3]
uint8_t matrix_coefficients
uint8_t video_full_range_flag
uint8_t transfer_characteristics
uint32_t data_color_space
skcms_TransferFunction parametric