14#include <QtCore/qatomic.h>
15#include <QtCore/qmath.h>
16#include <QtGui/qcolor.h>
17#include <QtGui/qimage.h>
18#include <QtGui/qtransform.h>
19#include <QtCore/private/qsimd_p.h>
27 if (trc.
m_type == QColorTrc::Type::Table)
29 if (trc.
m_type == QColorTrc::Type::Function)
43 for (
int i = 0;
i < 3; ++
i) {
53 for (
int i = 0;
i < 3; ++
i)
67 for (
int i = 0;
i < 3; ++
i) {
77 for (
int i = 0;
i < 3; ++
i)
136 if (
bool(d) !=
bool(
other.d))
148 for (
int i = 0;
i < 3; ++
i) {
161 for (
int i = 0;
i < 3; ++
i) {
182 constexpr float f = 1.0f / 255.0f;
185 return qRgba(
c.x * 255 + 0.5f,
c.y * 255 + 0.5f,
c.z * 255 + 0.5f,
qAlpha(argb));
197 constexpr float f = 1.0f / 65535.0f;
258 ?
QColorVector(clr.cyanF(), clr.magentaF(), clr.yellowF(), clr.blackF())
265 c.x = std::clamp(
c.x, 0.f, 1.f);
266 c.y = std::clamp(
c.y, 0.f, 1.f);
267 c.z = std::clamp(
c.z, 0.f, 1.f);
268 c.w = std::clamp(
c.w, 0.f, 1.f);
283template<ApplyMatrixForm doClamp = DoClamp>
287 const __m128 minV = _mm_set1_ps(0.0f);
288 const __m128 maxV = _mm_set1_ps(1.0f);
289 const __m128 xMat = _mm_loadu_ps(&colorMatrix.
r.
x);
290 const __m128 yMat = _mm_loadu_ps(&colorMatrix.
g.
x);
291 const __m128 zMat = _mm_loadu_ps(&colorMatrix.
b.
x);
294 __m128 cx = _mm_shuffle_ps(
c,
c, _MM_SHUFFLE(0, 0, 0, 0));
295 __m128 cy = _mm_shuffle_ps(
c,
c, _MM_SHUFFLE(1, 1, 1, 1));
296 __m128 cz = _mm_shuffle_ps(
c,
c, _MM_SHUFFLE(2, 2, 2, 2));
297 cx = _mm_mul_ps(cx, xMat);
298 cy = _mm_mul_ps(cy, yMat);
299 cz = _mm_mul_ps(cz, zMat);
300 cx = _mm_add_ps(cx, cy);
301 cx = _mm_add_ps(cx, cz);
304 cx = _mm_min_ps(cx, maxV);
305 cx = _mm_max_ps(cx, minV);
309#elif defined(__ARM_NEON__)
310 const float32x4_t minV = vdupq_n_f32(0.0f);
311 const float32x4_t maxV = vdupq_n_f32(1.0f);
312 const float32x4_t xMat = vld1q_f32(&colorMatrix.
r.
x);
313 const float32x4_t yMat = vld1q_f32(&colorMatrix.
g.
x);
314 const float32x4_t zMat = vld1q_f32(&colorMatrix.
b.
x);
317 float32x4_t cx = vmulq_n_f32(xMat, vgetq_lane_f32(
c, 0));
318 float32x4_t cy = vmulq_n_f32(yMat, vgetq_lane_f32(
c, 1));
319 float32x4_t cz = vmulq_n_f32(zMat, vgetq_lane_f32(
c, 2));
320 cx = vaddq_f32(cx, cy);
321 cx = vaddq_f32(cx, cz);
324 cx = vminq_f32(cx, maxV);
325 cx = vmaxq_f32(cx, minV);
333 buffer[
j].
x = std::clamp(cv.x, 0.f, 1.f);
334 buffer[
j].y = std::clamp(cv.y, 0.f, 1.f);
335 buffer[
j].z = std::clamp(cv.z, 0.f, 1.f);
343template<ApplyMatrixForm doClamp = DoClamp>
346 if constexpr (doClamp !=
DoClamp)
349 const __m128 minV = _mm_set1_ps(0.0f);
350 const __m128 maxV = _mm_set1_ps(1.0f);
353 c = _mm_min_ps(
c, maxV);
354 c = _mm_max_ps(
c, minV);
357#elif defined(__ARM_NEON__)
358 const float32x4_t minV = vdupq_n_f32(0.0f);
359 const float32x4_t maxV = vdupq_n_f32(1.0f);
362 c = vminq_f32(
c, maxV);
363 c = vmaxq_f32(
c, minV);
369 buffer[
j].
x = std::clamp(cv.x, 0.f, 1.f);
370 buffer[
j].y = std::clamp(cv.y, 0.f, 1.f);
371 buffer[
j].z = std::clamp(cv.z, 0.f, 1.f);
376#if defined(__SSE2__) || defined(__ARM_NEON__)
378static constexpr inline bool isArgb();
380constexpr inline bool isArgb<QRgb>() {
return true; }
382constexpr inline bool isArgb<QRgba64>() {
return false; }
385static inline int getAlpha(
const T &
p);
387inline int getAlpha<QRgb>(
const QRgb &
p)
390inline int getAlpha<QRgba64>(
const QRgba64 &
p)
399 return qAlpha(
r) * (1.f / 255.f);
407 return r.alpha() * (1.f / 65535.f);
422static inline void loadP(
const T &
p, __m128i &
v);
425inline void loadP<QRgb>(
const QRgb &
p, __m128i &
v)
427 v = _mm_cvtsi32_si128(
p);
428#if defined(__SSE4_1__)
429 v = _mm_cvtepu8_epi32(
v);
431 v = _mm_unpacklo_epi8(
v, _mm_setzero_si128());
432 v = _mm_unpacklo_epi16(
v, _mm_setzero_si128());
437inline void loadP<QRgba64>(
const QRgba64 &
p, __m128i &
v)
439 v = _mm_loadl_epi64((
const __m128i *)&
p);
440#if defined(__SSE4_1__)
441 v = _mm_cvtepu16_epi32(
v);
443 v = _mm_unpacklo_epi16(
v, _mm_setzero_si128());
451 const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
452 constexpr bool isARGB = isArgb<T>();
456 __m128 vf = _mm_cvtepi32_ps(
v);
458 __m128 va = _mm_shuffle_ps(vf, vf, _MM_SHUFFLE(3, 3, 3, 3));
459 __m128 via = _mm_rcp_ps(va);
460 via = _mm_sub_ps(_mm_add_ps(via, via), _mm_mul_ps(via, _mm_mul_ps(via, va)));
462 vf = _mm_mul_ps(vf, via);
465 __m128 vAlphaMask = _mm_cmpeq_ps(va, _mm_set1_ps(0.0f));
466 vf = _mm_andnot_ps(vAlphaMask, vf);
469 v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
470 const int ridx = isARGB ? _mm_extract_epi16(
v, 4) : _mm_extract_epi16(
v, 0);
471 const int gidx = _mm_extract_epi16(
v, 2);
472 const int bidx = isARGB ? _mm_extract_epi16(
v, 0) : _mm_extract_epi16(
v, 4);
476 vf = _mm_mul_ps(_mm_cvtepi32_ps(
v), iFF00);
486 const __m128 viFF00 = _mm_set1_ps(1.0f / (255 * 256));
487 const __m128 vZero = _mm_set1_ps(0.0f);
488 const __m128 vOne = _mm_set1_ps(1.0f);
490 __m128 vf = _mm_loadu_ps(&
src[
i].
r);
492 __m128 va = _mm_shuffle_ps(vf, vf, _MM_SHUFFLE(3, 3, 3, 3));
493 __m128 via = _mm_rcp_ps(va);
494 via = _mm_sub_ps(_mm_add_ps(via, via), _mm_mul_ps(via, _mm_mul_ps(via, va)));
496 vf = _mm_mul_ps(vf, via);
499 __m128 vAlphaMask = _mm_cmpeq_ps(va, vZero);
500 vf = _mm_andnot_ps(vAlphaMask, vf);
503 const __m128 under = _mm_cmplt_ps(vf, vZero);
504 const __m128 over = _mm_cmpgt_ps(vf, vOne);
505 if (_mm_movemask_ps(_mm_or_ps(under, over)) == 0) {
507 __m128i
v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
508 const int ridx = _mm_extract_epi16(
v, 0);
509 const int gidx = _mm_extract_epi16(
v, 2);
510 const int bidx = _mm_extract_epi16(
v, 4);
514 vf = _mm_mul_ps(_mm_cvtepi32_ps(
v), viFF00);
528static inline void loadPU(
const T &
p, __m128i &
v);
531inline void loadPU<QRgb>(
const QRgb &
p, __m128i &
v)
533 v = _mm_cvtsi32_si128(
p);
534#if defined(__SSE4_1__)
535 v = _mm_cvtepu8_epi32(
v);
537 v = _mm_unpacklo_epi8(
v, _mm_setzero_si128());
538 v = _mm_unpacklo_epi16(
v, _mm_setzero_si128());
544inline void loadPU<QRgba64>(
const QRgba64 &
p, __m128i &
v)
546 v = _mm_loadl_epi64((
const __m128i *)&
p);
547 v = _mm_sub_epi16(
v, _mm_srli_epi16(
v, 8));
548#if defined(__SSE4_1__)
549 v = _mm_cvtepu16_epi32(
v);
551 v = _mm_unpacklo_epi16(
v, _mm_setzero_si128());
559 constexpr bool isARGB = isArgb<T>();
560 const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
563 loadPU<T>(
src[
i],
v);
564 const int ridx = isARGB ? _mm_extract_epi16(
v, 4) : _mm_extract_epi16(
v, 0);
565 const int gidx = _mm_extract_epi16(
v, 2);
566 const int bidx = isARGB ? _mm_extract_epi16(
v, 0) : _mm_extract_epi16(
v, 4);
570 __m128 vf = _mm_mul_ps(_mm_cvtepi32_ps(
v), iFF00);
579 const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
580 const __m128 vZero = _mm_set1_ps(0.0f);
581 const __m128 vOne = _mm_set1_ps(1.0f);
583 __m128 vf = _mm_loadu_ps(&
src[
i].
r);
584 const __m128 under = _mm_cmplt_ps(vf, vZero);
585 const __m128 over = _mm_cmpgt_ps(vf, vOne);
586 if (_mm_movemask_ps(_mm_or_ps(under, over)) == 0) {
588 __m128i
v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
589 const int ridx = _mm_extract_epi16(
v, 0);
590 const int gidx = _mm_extract_epi16(
v, 2);
591 const int bidx = _mm_extract_epi16(
v, 4);
595 vf = _mm_mul_ps(_mm_cvtepi32_ps(
v), iFF00);
606#elif defined(__ARM_NEON__)
609static inline void loadP(
const T &
p, uint32x4_t &
v);
612inline void loadP<QRgb>(
const QRgb &
p, uint32x4_t &
v)
614 v = vmovl_u16(vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vmov_n_u32(
p)))));
618inline void loadP<QRgba64>(
const QRgba64 &
p, uint32x4_t &
v)
620 v = vmovl_u16(vreinterpret_u16_u64(vld1_u64(
reinterpret_cast<const uint64_t *
>(&
p))));
626 constexpr bool isARGB = isArgb<T>();
627 const float iFF00 = 1.0f / (255 * 256);
631 float32x4_t vf = vcvtq_f32_u32(
v);
633 float32x4_t va = vdupq_n_f32(vgetq_lane_f32(vf, 3));
634 float32x4_t via = vrecpeq_f32(va);
635 via = vmulq_f32(vrecpsq_f32(va, via), via);
638 vf = vmulq_f32(vf, via);
641#if defined(Q_PROCESSOR_ARM_64)
642 uint32x4_t vAlphaMask = vceqzq_f32(va);
644 uint32x4_t vAlphaMask = vceqq_f32(va, vdupq_n_f32(0.0));
646 vf = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(vf), vAlphaMask));
650 const int ridx = isARGB ? vgetq_lane_u32(
v, 2) : vgetq_lane_u32(
v, 0);
651 const int gidx = vgetq_lane_u32(
v, 1);
652 const int bidx = isARGB ? vgetq_lane_u32(
v, 0) : vgetq_lane_u32(
v, 2);
656 vf = vmulq_n_f32(vcvtq_f32_u32(
v), iFF00);
664static inline void loadPU(
const T &
p, uint32x4_t &
v);
667inline void loadPU<QRgb>(
const QRgb &
p, uint32x4_t &
v)
669 v = vmovl_u16(vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vmov_n_u32(
p)))));
674inline void loadPU<QRgba64>(
const QRgba64 &
p, uint32x4_t &
v)
676 uint16x4_t v16 = vreinterpret_u16_u64(vld1_u64(
reinterpret_cast<const uint64_t *
>(&
p)));
677 v16 = vsub_u16(v16, vshr_n_u16(v16, 8));
685 constexpr bool isARGB = isArgb<T>();
686 const float iFF00 = 1.0f / (255 * 256);
689 loadPU<T>(
src[
i],
v);
690 const int ridx = isARGB ? vgetq_lane_u32(
v, 2) : vgetq_lane_u32(
v, 0);
691 const int gidx = vgetq_lane_u32(
v, 1);
692 const int bidx = isARGB ? vgetq_lane_u32(
v, 0) : vgetq_lane_u32(
v, 2);
696 float32x4_t vf = vmulq_n_f32(vcvtq_f32_u32(
v), iFF00);
709 const int ridx = int(
qRed(
p) * ia + 0.5f);
710 const int gidx = int(
qGreen(
p) * ia + 0.5f);
711 const int bidx = int(
qBlue(
p) * ia + 0.5f);
729 const int ridx = int(
p.red() * ia + 0.5f);
730 const int gidx = int(
p.green() * ia + 0.5f);
731 const int bidx = int(
p.blue() * ia + 0.5f);
763#if !defined(__SSE2__)
771 const float ia = 1.0f /
a;
795static inline void storeP(T &
p, __m128i &
v,
int a);
797inline void storeP<QRgb>(
QRgb &
p, __m128i &
v,
int a)
799 v = _mm_packs_epi32(
v,
v);
800 v = _mm_insert_epi16(
v,
a, 3);
801 p = _mm_cvtsi128_si32(_mm_packus_epi16(
v,
v));
804inline void storeP<QRgba64>(
QRgba64 &
p, __m128i &
v,
int a)
806#if defined(__SSE4_1__)
807 v = _mm_packus_epi32(
v,
v);
808 v = _mm_insert_epi16(
v,
a, 3);
809 _mm_storel_epi64((__m128i *)&
p,
v);
811 const int r = _mm_extract_epi16(
v, 0);
812 const int g = _mm_extract_epi16(
v, 2);
813 const int b = _mm_extract_epi16(
v, 4);
818template<
typename D,
typename S,
819 typename = std::enable_if_t<!std::is_same_v<D, QRgbaFloat32>,
void>>
824 const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
825 constexpr bool isARGB = isArgb<D>();
827 const int a = getAlpha<S>(
src[
i]);
828 __m128 vf = _mm_loadu_ps(&
buffer[
i].
x);
829 __m128i
v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
830 __m128 va = _mm_mul_ps(_mm_set1_ps(
a), iFF00);
831 const int ridx = _mm_extract_epi16(
v, 0);
832 const int gidx = _mm_extract_epi16(
v, 2);
833 const int bidx = _mm_extract_epi16(
v, 4);
834 v = _mm_insert_epi16(
v, d_ptr->
colorSpaceOut->
lut[0]->m_fromLinear[ridx], isARGB ? 4 : 0);
836 v = _mm_insert_epi16(
v, d_ptr->
colorSpaceOut->
lut[2]->m_fromLinear[bidx], isARGB ? 0 : 4);
837 vf = _mm_cvtepi32_ps(
v);
838 vf = _mm_mul_ps(vf, va);
839 v = _mm_cvtps_epi32(vf);
850 const __m128 vZero = _mm_set1_ps(0.0f);
851 const __m128 vOne = _mm_set1_ps(1.0f);
852 const __m128 viFF00 = _mm_set1_ps(1.0f / (255 * 256));
854 const float a = getAlphaF<S>(
src[
i]);
855 __m128 va = _mm_set1_ps(
a);
856 __m128 vf = _mm_loadu_ps(&
buffer[
i].
x);
857 const __m128 under = _mm_cmplt_ps(vf, vZero);
858 const __m128 over = _mm_cmpgt_ps(vf, vOne);
859 if (_mm_movemask_ps(_mm_or_ps(under, over)) == 0) {
861 va = _mm_mul_ps(va, viFF00);
862 __m128i
v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
863 const int ridx = _mm_extract_epi16(
v, 0);
864 const int gidx = _mm_extract_epi16(
v, 2);
865 const int bidx = _mm_extract_epi16(
v, 4);
866 v = _mm_setzero_si128();
870 vf = _mm_mul_ps(_mm_cvtepi32_ps(
v), va);
871 _mm_store_ps(&
dst[
i].
r, vf);
876 vf = _mm_mul_ps(_mm_load_ps(&
dst[
i].
r), va);
877 _mm_store_ps(&
dst[
i].
r, vf);
884static inline void storePU(T &
p, __m128i &
v,
int a);
886inline void storePU<QRgb>(
QRgb &
p, __m128i &
v,
int a)
888 v = _mm_add_epi16(
v, _mm_set1_epi16(0x80));
889 v = _mm_srli_epi16(
v, 8);
890 v = _mm_insert_epi16(
v,
a, 3);
891 p = _mm_cvtsi128_si32(_mm_packus_epi16(
v,
v));
894inline void storePU<QRgba64>(
QRgba64 &
p, __m128i &
v,
int a)
896 v = _mm_add_epi16(
v, _mm_srli_epi16(
v, 8));
897 v = _mm_insert_epi16(
v,
a, 3);
898 _mm_storel_epi64((__m128i *)&
p,
v);
901template<
typename D,
typename S,
902 typename = std::enable_if_t<!std::is_same_v<D, QRgbaFloat32>,
void>>
907 constexpr bool isARGB = isArgb<D>();
909 const int a = getAlpha<S>(
src[
i]);
910 __m128 vf = _mm_loadu_ps(&
buffer[
i].
x);
911 __m128i
v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
912 const int ridx = _mm_extract_epi16(
v, 0);
913 const int gidx = _mm_extract_epi16(
v, 2);
914 const int bidx = _mm_extract_epi16(
v, 4);
915 v = _mm_setzero_si128();
916 v = _mm_insert_epi16(
v, d_ptr->
colorSpaceOut->
lut[0]->m_fromLinear[ridx], isARGB ? 2 : 0);
918 v = _mm_insert_epi16(
v, d_ptr->
colorSpaceOut->
lut[2]->m_fromLinear[bidx], isARGB ? 0 : 2);
929 const __m128 vZero = _mm_set1_ps(0.0f);
930 const __m128 vOne = _mm_set1_ps(1.0f);
931 const __m128 viFF00 = _mm_set1_ps(1.0f / (255 * 256));
933 const float a = getAlphaF<S>(
src[
i]);
934 __m128 vf = _mm_loadu_ps(&
buffer[
i].
x);
935 const __m128 under = _mm_cmplt_ps(vf, vZero);
936 const __m128 over = _mm_cmpgt_ps(vf, vOne);
937 if (_mm_movemask_ps(_mm_or_ps(under, over)) == 0) {
939 __m128i
v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
940 const int ridx = _mm_extract_epi16(
v, 0);
941 const int gidx = _mm_extract_epi16(
v, 2);
942 const int bidx = _mm_extract_epi16(
v, 4);
943 v = _mm_setzero_si128();
947 vf = _mm_mul_ps(_mm_cvtepi32_ps(
v), viFF00);
948 _mm_storeu_ps(&
dst[
i].
r, vf);
963 constexpr bool isARGB = isArgb<T>();
965 __m128 vf = _mm_loadu_ps(&
buffer[
i].
x);
966 __m128i
v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
967 const int ridx = _mm_extract_epi16(
v, 0);
968 const int gidx = _mm_extract_epi16(
v, 2);
969 const int bidx = _mm_extract_epi16(
v, 4);
970 v = _mm_setzero_si128();
971 v = _mm_insert_epi16(
v, d_ptr->
colorSpaceOut->
lut[0]->m_fromLinear[ridx], isARGB ? 2 : 0);
973 v = _mm_insert_epi16(
v, d_ptr->
colorSpaceOut->
lut[2]->m_fromLinear[bidx], isARGB ? 0 : 2);
974 storePU<T>(
dst[
i],
v, isARGB ? 255 : 0xffff);
983 const __m128 vZero = _mm_set1_ps(0.0f);
984 const __m128 vOne = _mm_set1_ps(1.0f);
985 const __m128 viFF00 = _mm_set1_ps(1.0f / (255 * 256));
987 __m128 vf = _mm_loadu_ps(&
buffer[
i].
x);
988 const __m128 under = _mm_cmplt_ps(vf, vZero);
989 const __m128 over = _mm_cmpgt_ps(vf, vOne);
990 if (_mm_movemask_ps(_mm_or_ps(under, over)) == 0) {
992 __m128i
v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
993 const int ridx = _mm_extract_epi16(
v, 0);
994 const int gidx = _mm_extract_epi16(
v, 2);
995 const int bidx = _mm_extract_epi16(
v, 4);
996 v = _mm_setzero_si128();
1000 vf = _mm_mul_ps(_mm_cvtepi32_ps(
v), viFF00);
1001 _mm_store_ps(&
dst[
i].
r, vf);
1011#elif defined(__ARM_NEON__)
1013static inline void storeP(T &
p,
const uint16x4_t &
v);
1015inline void storeP<QRgb>(
QRgb &
p,
const uint16x4_t &
v)
1017 p = vget_lane_u32(vreinterpret_u32_u8(vmovn_u16(vcombine_u16(
v,
v))), 0);
1020inline void storeP<QRgba64>(
QRgba64 &
p,
const uint16x4_t &
v)
1022 vst1_u16((uint16_t *)&
p,
v);
1025template<
typename D,
typename S,
1026 typename = std::enable_if_t<!std::is_same_v<D, QRgbaFloat32>,
void>>
1030 const float iFF00 = 1.0f / (255 * 256);
1031 constexpr bool isARGB = isArgb<D>();
1033 const int a = getAlpha<S>(
src[
i]);
1034 float32x4_t vf = vld1q_f32(&
buffer[
i].
x);
1036 const int ridx = vgetq_lane_u32(
v, 0);
1037 const int gidx = vgetq_lane_u32(
v, 1);
1038 const int bidx = vgetq_lane_u32(
v, 2);
1039 v = vsetq_lane_u32(d_ptr->
colorSpaceOut->
lut[0]->m_fromLinear[ridx],
v, isARGB ? 2 : 0);
1041 v = vsetq_lane_u32(d_ptr->
colorSpaceOut->
lut[2]->m_fromLinear[bidx],
v, isARGB ? 0 : 2);
1042 vf = vcvtq_f32_u32(
v);
1043 vf = vmulq_n_f32(vf,
a * iFF00);
1044 vf = vaddq_f32(vf, vdupq_n_f32(0.5f));
1045 v = vcvtq_u32_f32(vf);
1046 uint16x4_t v16 = vmovn_u32(
v);
1047 v16 = vset_lane_u16(
a, v16, 3);
1048 storeP<D>(
dst[
i], v16);
1053static inline void storePU(T &
p, uint16x4_t &
v,
int a);
1055inline void storePU<QRgb>(
QRgb &
p, uint16x4_t &
v,
int a)
1057 v = vadd_u16(
v, vdup_n_u16(0x80));
1058 v = vshr_n_u16(
v, 8);
1059 v = vset_lane_u16(
a,
v, 3);
1060 p = vget_lane_u32(vreinterpret_u32_u8(vmovn_u16(vcombine_u16(
v,
v))), 0);
1063inline void storePU<QRgba64>(
QRgba64 &
p, uint16x4_t &
v,
int a)
1065 v = vadd_u16(
v, vshr_n_u16(
v, 8));
1066 v = vset_lane_u16(
a,
v, 3);
1067 vst1_u16((uint16_t *)&
p,
v);
1070template<
typename D,
typename S,
1071 typename = std::enable_if_t<!std::is_same_v<D, QRgbaFloat32>,
void>>
1075 constexpr bool isARGB = isArgb<D>();
1077 const int a = getAlpha<S>(
src[
i]);
1078 float32x4_t vf = vld1q_f32(&
buffer[
i].
x);
1079 uint16x4_t
v = vmovn_u32(vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf,
float(
QColorTrcLut::Resolution)), vdupq_n_f32(0.5f))));
1080 const int ridx = vget_lane_u16(
v, 0);
1081 const int gidx = vget_lane_u16(
v, 1);
1082 const int bidx = vget_lane_u16(
v, 2);
1083 v = vset_lane_u16(d_ptr->
colorSpaceOut->
lut[0]->m_fromLinear[ridx],
v, isARGB ? 2 : 0);
1085 v = vset_lane_u16(d_ptr->
colorSpaceOut->
lut[2]->m_fromLinear[bidx],
v, isARGB ? 0 : 2);
1086 storePU<D>(
dst[
i],
v,
a);
1094 constexpr bool isARGB = isArgb<T>();
1096 float32x4_t vf = vld1q_f32(&
buffer[
i].
x);
1097 uint16x4_t
v = vmovn_u32(vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf,
float(
QColorTrcLut::Resolution)), vdupq_n_f32(0.5f))));
1098 const int ridx = vget_lane_u16(
v, 0);
1099 const int gidx = vget_lane_u16(
v, 1);
1100 const int bidx = vget_lane_u16(
v, 2);
1101 v = vset_lane_u16(d_ptr->
colorSpaceOut->
lut[0]->m_fromLinear[ridx],
v, isARGB ? 2 : 0);
1103 v = vset_lane_u16(d_ptr->
colorSpaceOut->
lut[2]->m_fromLinear[bidx],
v, isARGB ? 0 : 2);
1104 storePU<T>(
dst[
i],
v, isARGB ? 255 : 0xffff);
1113 const float fa =
a / (255.0f * 256.0f);
1117 dst[
i] =
qRgba(
r * fa + 0.5f,
g * fa + 0.5f,
b * fa + 0.5f,
a);
1128 dst[
i] = (
src[
i] & 0xff000000) | (
r << 16) | (
g << 8) | (
b << 0);
1139 dst[
i] = 0xff000000 | (
r << 16) | (
g << 8) | (
b << 0);
1149 const float fa =
a / (255.0f * 256.0f);
1181#if !defined(__SSE2__)
1252template <
typename T,
int Count = 1>
1256 operator T*() {
return reinterpret_cast<T *
>(
this); }
1258 alignas(T)
char data[
sizeof(T) * Count];
1263 const float f = 1.0f / 255.f;
1274 const float f = 1.0f / 255.f;
1286 const float f = 1.0f / 65535.f;
1322 const float f = 1.0f /
src[
i].alpha();
1332 const float f = 1.0f /
src[
i].a;
1345 dst[
i] = 0xff000000 | (
r << 16) | (
g << 8) | (
b << 0);
1356 dst[
i] = (
src[
i] & 0xff000000) | (
r << 16) | (
g << 8) | (
b << 0);
1368 const int k =
buffer[
i].w * 255.f;
1378 const int r =
buffer[
i].x * 65535.f;
1379 const int g =
buffer[
i].y * 65535.f;
1380 const int b =
buffer[
i].z * 65535.f;
1391 const int r =
buffer[
i].x * 65535.f;
1392 const int g =
buffer[
i].y * 65535.f;
1393 const int b =
buffer[
i].z * 65535.f;
1403 const int r =
buffer[
i].x * 65535.f;
1404 const int g =
buffer[
i].y * 65535.f;
1405 const int b =
buffer[
i].z * 65535.f;
1433 dst[
i] = (
src[
i] & 0xff000000) | (
r << 16) | (
g << 8) | (
b << 0);
1444 dst[
i] = 0xff000000 | (
r << 16) | (
g << 8) | (
b << 0);
1474 const int r =
buffer[
i].x * 65535.f;
1475 const int g =
buffer[
i].y * 65535.f;
1476 const int b =
buffer[
i].z * 65535.f;
1485 const int a =
src[
i].alpha();
1556 std::visit([&
c](
auto &&elm) {
visitElement(elm, &
c, 1); }, element);
1558 c.
x = std::clamp(
c.x, 0.0f, 1.0f);
1559 c.y = std::clamp(
c.y, 0.0f, 1.0f);
1560 c.z = std::clamp(
c.z, 0.0f, 1.0f);
1571 c.
x = std::clamp(
c.x, 0.0f, 1.0f);
1572 c.y = std::clamp(
c.y, 0.0f, 1.0f);
1573 c.z = std::clamp(
c.z, 0.0f, 1.0f);
1587 std::visit([&
c](
auto &&elm) {
visitElement(elm, &
c, 1); }, element);
1588 c.x = std::clamp(
c.x, 0.0f, 1.0f);
1589 c.y = std::clamp(
c.y, 0.0f, 1.0f);
1590 c.z = std::clamp(
c.z, 0.0f, 1.0f);
1608 std::visit([&
c](
auto &&elm) {
visitElement(elm, &
c, 1); }, element);
1626 std::visit([&
c](
auto &&elm) {
visitElement(elm, &
c, 1); }, element);
1635 if constexpr (!std::is_same_v<S, QCmyk32>) {
1654 if constexpr (std::is_same_v<S, QRgbaFloat16> || std::is_same_v<S, QRgbaFloat32>)
1662template<
typename D,
typename S>
1667 if constexpr (!std::is_same_v<D, QCmyk32>) {
1671 if constexpr (std::is_same_v<S, QCmyk32>) {
1723template<
typename D,
typename S>
1731 QUninitialized<QColorVector, WorkBlockSize>
buffer;
1751template<
typename D,
typename S>
1757 QUninitialized<QColorVector, WorkBlockSize>
buffer;
1781 if constexpr (!std::is_same_v<S, QCmyk32>) {
1787 QUninitialized<QColorVector, WorkBlockSize>
buffer;
1811template<
typename D,
typename S>
1816 if constexpr (std::is_same_v<D, QRgb> || std::is_same_v<D, QRgba64> || std::is_same_v<D, QRgbaFloat32> || std::is_same_v<D, QCmyk32>) {
1818 QUninitialized<QColorVector, WorkBlockSize>
buffer;
1850 if constexpr (!std::is_same_v<D, QCmyk32>) {
1856 QUninitialized<QColorVector, WorkBlockSize>
buffer;
QColorVector apply(const QColorVector &v) const
bool isIdentity() const noexcept
QColorVector map(const QColorVector &c) const
QColorSpace::TransformModel transformModel
bool isThreeComponentMatrix() const
static Q_CONSTINIT QBasicMutex s_lutWriteLock
struct QColorSpacePrivate::LUT lut
QColorSpace::TransferFunction transferFunction
QColorSpace::ColorModel colorModel
bool equals(const QColorSpacePrivate *other) const
static constexpr qsizetype Resolution
static std::shared_ptr< QColorTrcLut > fromTransferTable(const QColorTransferTable &transTable, Direction dir=BiLinear)
static constexpr uint32_t ShiftUp
static std::shared_ptr< QColorTrcLut > fromTransferFunction(const QColorTransferFunction &transFn, Direction dir=BiLinear)
static constexpr uint32_t ShiftDown
QColorTransferFunction m_fun
float applyInverseExtended(float x) const
float applyExtended(float x) const
float apply(float x) const
float applyInverse(float x) const
QColorTransferTable m_table
QColorVector labToXyz() const
QColorVector xyzToLab() const
The QColor class provides colors based on RGB, HSV or CMYK values.
QColor toRgb() const noexcept
Create and returns an RGB QColor based on this color.
QColor toCmyk() const noexcept
Creates and returns a CMYK QColor based on this color.
const T * constData() const noexcept
Returns a const pointer to the shared data object.
constexpr quint16 red() const
constexpr quint16 alpha() const
constexpr quint16 green() const
constexpr quint16 blue() const
static constexpr QRgba64 fromRgba64(quint64 c)
\keyword 16-bit Floating Point Support\inmodule QtCore \inheaderfile QFloat16
auto visit(Fn &&fn, QIODevice *socket, Args &&...args)
Combined button and popup list for selecting options.
constexpr const T & qMin(const T &a, const T &b)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLfloat GLfloat GLfloat alpha
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
constexpr int qRed(QRgb rgb)
constexpr int qGreen(QRgb rgb)
constexpr QRgb qRgba(int r, int g, int b, int a)
constexpr int qBlue(QRgb rgb)
constexpr int qAlpha(QRgb rgb)
constexpr QRgba64 qRgba64(quint16 r, quint16 g, quint16 b, quint16 a)
#define QT_DEFINE_QESDP_SPECIALIZATION_DTOR(Class)
QTextStream out(stdout)
[7]