Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_heif_import_tools.cpp
Go to the documentation of this file.
1
9
10#if XSIMD_UNIVERSAL_BUILD_PASS
11
12namespace Planar
13{
14#if !defined(XSIMD_NO_SUPPORTED_ARCHITECTURE)
15template<typename Arch,
16 LinearizePolicy linearizePolicy,
17 bool applyOOTF,
18 typename std::enable_if_t<!std::is_same<Arch, xsimd::generic>::value,
19 int> = 0>
20inline void linearize(float *pixelValues,
21 const double *lCoef,
22 float displayGamma,
23 float displayNits)
24{
25 using float_v = typename KoColorTransferFunctions<Arch>::float_v;
26 if (linearizePolicy == LinearizePolicy::LinearFromPQ) {
27 auto v = float_v::load_unaligned(pixelValues);
29 v.store_unaligned(pixelValues);
30 } else if (linearizePolicy == LinearizePolicy::LinearFromHLG) {
31 auto v = float_v::load_unaligned(pixelValues);
33 v.store_unaligned(pixelValues);
34 } else if (linearizePolicy == LinearizePolicy::LinearFromSMPTE428) {
35 auto v = float_v::load_unaligned(pixelValues);
37 v.store_unaligned(pixelValues);
38 }
39
40 if (linearizePolicy == LinearizePolicy::KeepTheSame) {
41 qSwap(pixelValues[0], pixelValues[2]);
42 } else if (linearizePolicy == LinearizePolicy::LinearFromHLG && applyOOTF) {
43 applyHLGOOTF(pixelValues, lCoef, displayGamma, displayNits);
44 }
45}
46#endif
47
48template<typename Arch,
49 LinearizePolicy linearizePolicy,
50 bool applyOOTF,
51 typename std::enable_if_t<std::is_same<Arch, xsimd::generic>::value,
52 int> = 0>
53inline void linearize(float *pixelValues,
54 const double *lCoef,
55 float displayGamma,
56 float displayNits)
57{
58 if (linearizePolicy == LinearizePolicy::KeepTheSame) {
59 qSwap(pixelValues[0], pixelValues[2]);
60 } else if (linearizePolicy == LinearizePolicy::LinearFromHLG && applyOOTF) {
61 applyHLGOOTF(pixelValues, lCoef, displayGamma, displayNits);
62 }
63}
64
65template<typename Arch,
66 int luma,
67 LinearizePolicy linearizePolicy,
68 typename std::enable_if_t<!std::is_same<Arch, xsimd::generic>::value,
69 int> = 0>
70inline float value(const uint8_t *img, int stride, int x, int y)
71{
72 if (luma == 8) {
73 return float(img[y * (stride) + x]) / 255.0f;
74 } else {
75 uint16_t source =
76 reinterpret_cast<const uint16_t *>(img)[y * (stride / 2) + x];
77 if (luma == 10) {
78 return float(0x03ff & (source)) * multiplier10bit;
79 } else if (luma == 12) {
80 return float(0x0fff & (source)) * multiplier12bit;
81 } else {
82 return float(source) * multiplier16bit;
83 }
84 }
85}
86
87template<LinearizePolicy policy>
88inline float linearizeValueAsNeeded(float value)
89{
90 if (policy == LinearizePolicy::LinearFromPQ) {
92 } else if (policy == LinearizePolicy::LinearFromHLG) {
93 return removeHLGCurve(value);
94 } else if (policy == LinearizePolicy::LinearFromSMPTE428) {
96 }
97 return value;
98}
99
100template<typename Arch,
101 int luma,
102 LinearizePolicy linearizePolicy,
103 typename std::enable_if_t<std::is_same<Arch, xsimd::generic>::value,
104 int> = 0>
105inline float value(const uint8_t *img, int stride, int x, int y)
106{
107 if (luma == 8) {
108 return linearizeValueAsNeeded<linearizePolicy>(
109 float(img[y * (stride) + x]) / 255.0f);
110 } else {
111 uint16_t source =
112 reinterpret_cast<const uint16_t *>(img)[y * (stride / 2) + x];
113 if (luma == 10) {
114 return linearizeValueAsNeeded<linearizePolicy>(
115 float(0x03ff & (source)) * multiplier10bit);
116 } else if (luma == 12) {
117 return linearizeValueAsNeeded<linearizePolicy>(
118 float(0x0fff & (source)) * multiplier12bit);
119 } else {
120 return linearizeValueAsNeeded<linearizePolicy>(float(source)
122 }
123 }
124}
125
126template<typename Arch,
127 typename std::enable_if_t<std::is_same<Arch, xsimd::generic>::value,
128 int> = 0>
129constexpr int bufferSize()
130{
131 return 4;
132}
133
134#if !defined(XSIMD_NO_SUPPORTED_ARCHITECTURE)
135template<typename Arch,
136 typename std::enable_if_t<!std::is_same<Arch, xsimd::generic>::value,
137 int> = 0>
138constexpr int bufferSize()
139{
140 return qMax<int>(4, KoStreamedMath<Arch>::float_v::size);
141}
142#endif
143
144template<typename Arch,
145 int luma,
146 LinearizePolicy linearizePolicy,
147 bool applyOOTF,
148 bool hasAlpha>
149inline void readLayer(const int width,
150 const int height,
151 const uint8_t *imgR,
152 const int strideR,
153 const uint8_t *imgG,
154 const int strideG,
155 const uint8_t *imgB,
156 const int strideB,
157 const uint8_t *imgA,
158 const int strideA,
160 float displayGamma,
161 float displayNits,
162 const KoColorSpace *colorSpace)
163{
164 const QVector<qreal> lCoef{colorSpace->lumaCoefficients()};
165 QVector<float> pixelValues(bufferSize<Arch>());
166 float *data = pixelValues.data();
167
168 for (int y = 0; y < height; y++) {
169 for (int x = 0; x < width; x++) {
170 for (int i = 0; i < bufferSize<Arch>(); i++) {
171 data[i] = 1.0f;
172 }
173
174 data[0] = value<Arch, luma, linearizePolicy>(imgR, strideR, x, y);
175 data[1] = value<Arch, luma, linearizePolicy>(imgG, strideG, x, y);
176 data[2] = value<Arch, luma, linearizePolicy>(imgB, strideB, x, y);
177
178 linearize<Arch, linearizePolicy, applyOOTF>(data,
179 lCoef.constData(),
180 displayGamma,
181 displayNits);
182
183 if (hasAlpha) {
184 data[3] =
185 value<Arch, luma, LinearizePolicy::KeepTheSame>(imgA,
186 strideA,
187 x,
188 y);
189 }
190
191 if (luma == 8) {
193 pixelValues);
194 } else if (luma > 8 && linearizePolicy != LinearizePolicy::KeepTheSame) {
196 pixelValues);
197 } else {
199 pixelValues);
200 }
201
202 it->nextPixel();
203 }
204
205 it->nextRow();
206 }
207}
208
209template<typename Arch,
210 int luma,
211 LinearizePolicy linearizePolicy,
212 bool applyOOTF,
213 typename... Args>
214inline auto readPlanarLayerWithAlpha(bool hasAlpha, Args &&...args)
215{
216 if (hasAlpha) {
217 return Planar::readLayer<Arch, luma, linearizePolicy, applyOOTF, true>(
218 std::forward<Args>(args)...);
219 } else {
220 return Planar::readLayer<Arch, luma, linearizePolicy, applyOOTF, false>(
221 std::forward<Args>(args)...);
222 }
223}
224
225template<typename Arch,
226 int luma,
227 LinearizePolicy linearizePolicy,
228 typename... Args>
229inline auto readPlanarLayerWithPolicy(bool applyOOTF, Args &&...args)
230{
231 if (applyOOTF) {
232 return readPlanarLayerWithAlpha<Arch, luma, linearizePolicy, true>(
233 std::forward<Args>(args)...);
234 } else {
235 return readPlanarLayerWithAlpha<Arch, luma, linearizePolicy, false>(
236 std::forward<Args>(args)...);
237 }
238}
239
240template<typename Arch, int luma, typename... Args>
241inline auto readPlanarLayerWithLuma(LinearizePolicy linearizePolicy,
242 Args &&...args)
243{
244 if (linearizePolicy == LinearizePolicy::LinearFromHLG) {
245 return readPlanarLayerWithPolicy<Arch, luma, LinearizePolicy::LinearFromHLG>(std::forward<Args>(args)...);
246 } else if (linearizePolicy == LinearizePolicy::LinearFromPQ) {
247 return readPlanarLayerWithPolicy<Arch, luma, LinearizePolicy::LinearFromPQ>(std::forward<Args>(args)...);
248 } else if (linearizePolicy == LinearizePolicy::LinearFromSMPTE428) {
249 return readPlanarLayerWithPolicy<Arch, luma, LinearizePolicy::LinearFromSMPTE428>(std::forward<Args>(args)...);
250 } else {
251 return readPlanarLayerWithPolicy<Arch, luma, LinearizePolicy::KeepTheSame>(std::forward<Args>(args)...);
252 }
253}
254
255template<typename Arch>
256void readLayerImpl::create(const int luma,
257 LinearizePolicy policy,
258 bool applyOOTF,
259 bool hasAlpha,
260 const int width,
261 const int height,
262 const uint8_t *imgR,
263 const int strideR,
264 const uint8_t *imgG,
265 const int strideG,
266 const uint8_t *imgB,
267 const int strideB,
268 const uint8_t *imgA,
269 const int strideA,
271 float displayGamma,
272 float displayNits,
273 const KoColorSpace *colorSpace)
274{
275 if (luma == 8) {
276 return readPlanarLayerWithLuma<xsimd::current_arch, 8>(policy,
277 applyOOTF,
278 hasAlpha,
279 width,
280 height,
281 imgR,
282 strideR,
283 imgG,
284 strideG,
285 imgB,
286 strideB,
287 imgA,
288 strideA,
289 it,
290 displayGamma,
291 displayNits,
292 colorSpace);
293 } else if (luma == 10) {
294 return readPlanarLayerWithLuma<xsimd::current_arch, 10>(policy,
295 applyOOTF,
296 hasAlpha,
297 width,
298 height,
299 imgR,
300 strideR,
301 imgG,
302 strideG,
303 imgB,
304 strideB,
305 imgA,
306 strideA,
307 it,
308 displayGamma,
309 displayNits,
310 colorSpace);
311 } else if (luma == 12) {
312 return readPlanarLayerWithLuma<xsimd::current_arch, 12>(policy,
313 applyOOTF,
314 hasAlpha,
315 width,
316 height,
317 imgR,
318 strideR,
319 imgG,
320 strideG,
321 imgB,
322 strideB,
323 imgA,
324 strideA,
325 it,
326 displayGamma,
327 displayNits,
328 colorSpace);
329 } else {
330 return readPlanarLayerWithLuma<xsimd::current_arch, 16>(policy,
331 applyOOTF,
332 hasAlpha,
333 width,
334 height,
335 imgR,
336 strideR,
337 imgG,
338 strideG,
339 imgB,
340 strideB,
341 imgA,
342 strideA,
343 it,
344 displayGamma,
345 displayNits,
346 colorSpace);
347 }
348}
349
350template void
351readLayerImpl::create<xsimd::current_arch>(const int luma,
352 LinearizePolicy policy,
353 bool applyOOTF,
354 bool hasAlpha,
355 const int width,
356 const int height,
357 const uint8_t *imgR,
358 const int strideR,
359 const uint8_t *imgG,
360 const int strideG,
361 const uint8_t *imgB,
362 const int strideB,
363 const uint8_t *imgA,
364 const int strideA,
366 float displayGamma,
367 float displayNits,
368 const KoColorSpace *colorSpace);
369
370} // namespace Planar
371
372namespace HDR
373{
374#if !defined(XSIMD_NO_SUPPORTED_ARCHITECTURE)
375template<typename Arch,
376 LinearizePolicy linearizePolicy,
377 bool applyOOTF,
378 typename std::enable_if_t<!std::is_same<Arch, xsimd::generic>::value,
379 int> = 0>
380inline void linearize(float *pixelValues,
381 const double *lCoef,
382 float displayGamma,
383 float displayNits)
384{
385 using float_v = typename KoColorTransferFunctions<Arch>::float_v;
386 if (linearizePolicy == LinearizePolicy::LinearFromPQ) {
387 auto v = float_v::load_unaligned(pixelValues);
389 v.store_unaligned(pixelValues);
390 } else if (linearizePolicy == LinearizePolicy::LinearFromHLG) {
391 auto v = float_v::load_unaligned(pixelValues);
393 v.store_unaligned(pixelValues);
394 } else if (linearizePolicy == LinearizePolicy::LinearFromSMPTE428) {
395 auto v = float_v::load_unaligned(pixelValues);
397 v.store_unaligned(pixelValues);
398 }
399
400 if (linearizePolicy == LinearizePolicy::KeepTheSame) {
401 qSwap(pixelValues[0], pixelValues[2]);
402 } else if (linearizePolicy == LinearizePolicy::LinearFromHLG && applyOOTF) {
403 applyHLGOOTF(pixelValues, lCoef, displayGamma, displayNits);
404 }
405}
406#endif
407
408template<typename Arch,
409 LinearizePolicy linearizePolicy,
410 bool applyOOTF,
411 typename std::enable_if_t<std::is_same<Arch, xsimd::generic>::value,
412 int> = 0>
413inline void linearize(float *pixelValues,
414 const double *lCoef,
415 float displayGamma,
416 float displayNits)
417{
418 if (linearizePolicy == LinearizePolicy::KeepTheSame) {
419 qSwap(pixelValues[0], pixelValues[2]);
420 } else if (linearizePolicy == LinearizePolicy::LinearFromHLG && applyOOTF) {
421 applyHLGOOTF(pixelValues, lCoef, displayGamma, displayNits);
422 }
423}
424
425template<typename Arch,
426 int luma,
427 LinearizePolicy linearizePolicy,
428 typename std::enable_if_t<!std::is_same<Arch, xsimd::generic>::value,
429 int> = 0>
430inline float valueInterleaved(const uint8_t *img,
431 int stride,
432 int x,
433 int y,
434 int channels,
435 int ch)
436{
437 uint16_t source = reinterpret_cast<const uint16_t *>(
438 img)[y * (stride / 2) + (x * channels) + ch];
439 if (luma == 10) {
440 return float(0x03ff & (source)) * multiplier10bit;
441 } else if (luma == 12) {
442 return float(0x0fff & (source)) * multiplier12bit;
443 } else {
444 return float(source) * multiplier16bit;
445 }
446}
447
448template<LinearizePolicy policy>
449inline float linearizeValueAsNeeded(float value)
450{
451 if (policy == LinearizePolicy::LinearFromPQ) {
453 } else if (policy == LinearizePolicy::LinearFromHLG) {
454 return removeHLGCurve(value);
455 } else if (policy == LinearizePolicy::LinearFromSMPTE428) {
457 }
458 return value;
459}
460
461template<typename Arch,
462 int luma,
463 LinearizePolicy linearizePolicy,
464 typename std::enable_if_t<std::is_same<Arch, xsimd::generic>::value,
465 int> = 0>
466inline float valueInterleaved(const uint8_t *img,
467 int stride,
468 int x,
469 int y,
470 int channels,
471 int ch)
472{
473 uint16_t source = reinterpret_cast<const uint16_t *>(
474 img)[y * (stride / 2) + (x * channels) + ch];
475 if (luma == 10) {
476 return linearizeValueAsNeeded<linearizePolicy>(float(0x03ff & (source))
478 } else if (luma == 12) {
479 return linearizeValueAsNeeded<linearizePolicy>(float(0x0fff & (source))
481 } else {
482 return linearizeValueAsNeeded<linearizePolicy>(float(source)
484 }
485}
486
487template<typename Arch,
488 int channels,
489 typename std::enable_if_t<std::is_same<Arch, xsimd::generic>::value,
490 int> = 0>
491constexpr int bufferSize()
492{
493 return channels;
494}
495
496#if !defined(XSIMD_NO_SUPPORTED_ARCHITECTURE)
497template<typename Arch,
498 int channels,
499 typename std::enable_if_t<!std::is_same<Arch, xsimd::generic>::value,
500 int> = 0>
501constexpr int bufferSize()
502{
503 return qMax<int>(channels, KoStreamedMath<Arch>::float_v::size);
504}
505#endif
506
507template<typename Arch,
508 int luma,
509 LinearizePolicy linearizePolicy,
510 bool applyOOTF,
511 int channels>
512inline void readLayer(const int width,
513 const int height,
514 const uint8_t *img,
515 const int stride,
517 float displayGamma,
518 float displayNits,
519 const KoColorSpace *colorSpace)
520{
521 const QVector<qreal> lCoef{colorSpace->lumaCoefficients()};
522 QVector<float> pixelValues(bufferSize<Arch, channels>());
523 float *data = pixelValues.data();
524
525 for (int y = 0; y < height; y++) {
526 for (int x = 0; x < width; x++) {
527 for (int i = 0; i < bufferSize<Arch, channels>(); i++) {
528 data[i] = 1.0f;
529 }
530
531 const int alphaPos = [&]() {
532 if (luma == 8) {
534 } else if (luma > 8
535 && linearizePolicy != LinearizePolicy::KeepTheSame) {
537 } else {
539 }
540 }();
541
542 for (int ch = 0; ch < channels; ch++) {
543 if (ch == alphaPos) {
544 data[ch] =
545 valueInterleaved<Arch,
546 luma,
548 stride,
549 x,
550 y,
551 channels,
552 ch);
553 } else {
554 data[ch] =
555 valueInterleaved<Arch, luma, linearizePolicy>(img,
556 stride,
557 x,
558 y,
559 channels,
560 ch);
561 }
562 }
563
564 linearize<Arch, linearizePolicy, applyOOTF>(data,
565 lCoef.constData(),
566 displayGamma,
567 displayNits);
568
569 if (luma == 8) {
571 pixelValues);
572 } else if (luma > 8 && linearizePolicy != LinearizePolicy::KeepTheSame) {
574 pixelValues);
575 } else {
577 pixelValues);
578 }
579
580 it->nextPixel();
581 }
582
583 it->nextRow();
584 }
585}
586
587template<typename Arch,
588 int luma,
589 LinearizePolicy linearizePolicy,
590 bool applyOOTF,
591 typename... Args>
592inline auto readInterleavedWithAlpha(bool hasAlpha, Args &&...args)
593{
594 if (hasAlpha) {
595 return HDR::readLayer<Arch, luma, linearizePolicy, applyOOTF, 4>(
596 std::forward<Args>(args)...);
597 } else {
598 return HDR::readLayer<Arch, luma, linearizePolicy, applyOOTF, 3>(
599 std::forward<Args>(args)...);
600 }
601}
602
603template<typename Arch,
604 int luma,
605 LinearizePolicy linearizePolicy,
606 typename... Args>
607inline auto readInterleavedWithPolicy(bool applyOOTF, Args &&...args)
608{
609 if (applyOOTF) {
610 return readInterleavedWithAlpha<Arch, luma, linearizePolicy, true>(
611 std::forward<Args>(args)...);
612 } else {
613 return readInterleavedWithAlpha<Arch, luma, linearizePolicy, false>(
614 std::forward<Args>(args)...);
615 }
616}
617
618template<typename Arch, int luma, typename... Args>
619inline auto readInterleavedWithLuma(LinearizePolicy linearizePolicy,
620 Args &&...args)
621{
622 if (linearizePolicy == LinearizePolicy::LinearFromHLG) {
623 return readInterleavedWithPolicy<Arch, luma, LinearizePolicy::LinearFromHLG>(std::forward<Args>(args)...);
624 } else if (linearizePolicy == LinearizePolicy::LinearFromPQ) {
625 return readInterleavedWithPolicy<Arch, luma, LinearizePolicy::LinearFromPQ>(std::forward<Args>(args)...);
626 } else if (linearizePolicy == LinearizePolicy::LinearFromSMPTE428) {
627 return readInterleavedWithPolicy<Arch, luma, LinearizePolicy::LinearFromSMPTE428>(std::forward<Args>(args)...);
628 } else {
629 return readInterleavedWithPolicy<Arch, luma, LinearizePolicy::KeepTheSame>(std::forward<Args>(args)...);
630 }
631}
632
633template<typename Arch>
634void readLayerImpl::create(const int luma,
635 LinearizePolicy linearizePolicy,
636 bool applyOOTF,
637 const int channels,
638 const int width,
639 const int height,
640 const uint8_t *img,
641 const int stride,
643 float displayGamma,
644 float displayNits,
645 const KoColorSpace *colorSpace)
646{
647 if (luma == 10) {
648 return readInterleavedWithLuma<Arch, 10>(linearizePolicy,
649 applyOOTF,
650 channels,
651 width,
652 height,
653 img,
654 stride,
655 it,
656 displayGamma,
657 displayNits,
658 colorSpace);
659 } else if (luma == 12) {
660 return readInterleavedWithLuma<Arch, 12>(linearizePolicy,
661 applyOOTF,
662 channels,
663 width,
664 height,
665 img,
666 stride,
667 it,
668 displayGamma,
669 displayNits,
670 colorSpace);
671 } else {
672 return readInterleavedWithLuma<Arch, 16>(linearizePolicy,
673 applyOOTF,
674 channels,
675 width,
676 height,
677 img,
678 stride,
679 it,
680 displayGamma,
681 displayNits,
682 colorSpace);
683 }
684}
685
686template void
687readLayerImpl::create<xsimd::current_arch>(const int luma,
688 LinearizePolicy linearizePolicy,
689 bool applyOOTF,
690 const int channels,
691 const int width,
692 const int height,
693 const uint8_t *img,
694 const int stride,
696 float displayGamma,
697 float displayNits,
698 const KoColorSpace *colorSpace);
699} // namespace HDR
700
701namespace SDR
702{
703#if !defined(XSIMD_NO_SUPPORTED_ARCHITECTURE)
704template<typename Arch,
705 LinearizePolicy linearizePolicy,
706 bool applyOOTF,
707 typename std::enable_if_t<!std::is_same<Arch, xsimd::generic>::value,
708 int> = 0>
709inline void linearize(float *pixelValues,
710 const double *lCoef,
711 float displayGamma,
712 float displayNits)
713{
714 using float_v = typename KoColorTransferFunctions<Arch>::float_v;
715 if (linearizePolicy == LinearizePolicy::LinearFromPQ) {
716 auto v = float_v::load_unaligned(pixelValues);
718 v.store_unaligned(pixelValues);
719 } else if (linearizePolicy == LinearizePolicy::LinearFromHLG) {
720 auto v = float_v::load_unaligned(pixelValues);
722 v.store_unaligned(pixelValues);
723 } else if (linearizePolicy == LinearizePolicy::LinearFromSMPTE428) {
724 auto v = float_v::load_unaligned(pixelValues);
726 v.store_unaligned(pixelValues);
727 }
728
729 if (linearizePolicy == LinearizePolicy::KeepTheSame) {
730 qSwap(pixelValues[0], pixelValues[2]);
731 } else if (linearizePolicy == LinearizePolicy::LinearFromHLG && applyOOTF) {
732 applyHLGOOTF(pixelValues, lCoef, displayGamma, displayNits);
733 }
734}
735#endif
736
737template<typename Arch,
738 LinearizePolicy linearizePolicy,
739 bool applyOOTF,
740 typename std::enable_if_t<std::is_same<Arch, xsimd::generic>::value,
741 int> = 0>
742inline void linearize(float *pixelValues,
743 const double *lCoef,
744 float displayGamma,
745 float displayNits)
746{
747 if (linearizePolicy == LinearizePolicy::KeepTheSame) {
748 qSwap(pixelValues[0], pixelValues[2]);
749 } else if (linearizePolicy == LinearizePolicy::LinearFromHLG && applyOOTF) {
750 applyHLGOOTF(pixelValues, lCoef, displayGamma, displayNits);
751 }
752}
753
754template<typename Arch,
755 LinearizePolicy linearizePolicy,
756 int channels,
757 typename std::enable_if_t<!std::is_same<Arch, xsimd::generic>::value,
758 int> = 0>
759inline float value(const uint8_t *img, int stride, int x, int y, int ch)
760{
761 uint8_t source = img[(y * stride) + (x * channels) + ch];
762 return float(source) / 255.0f;
763}
764
765template<LinearizePolicy policy>
766inline float linearizeValueAsNeeded(float value)
767{
768 if (policy == LinearizePolicy::LinearFromPQ) {
770 } else if (policy == LinearizePolicy::LinearFromHLG) {
771 return removeHLGCurve(value);
772 } else if (policy == LinearizePolicy::LinearFromSMPTE428) {
774 }
775 return value;
776}
777
778template<typename Arch,
779 LinearizePolicy linearizePolicy,
780 int channels,
781 typename std::enable_if_t<std::is_same<Arch, xsimd::generic>::value,
782 int> = 0>
783inline float value(const uint8_t *img, int stride, int x, int y, int ch)
784{
785 uint8_t source = img[(y * stride) + (x * channels) + ch];
786 return linearizeValueAsNeeded<linearizePolicy>(float(source) / 255.0f);
787}
788
789template<typename Arch,
790 int channels,
791 typename std::enable_if_t<std::is_same<Arch, xsimd::generic>::value,
792 int> = 0>
793constexpr int bufferSize()
794{
795 return channels;
796}
797
798#if !defined(XSIMD_NO_SUPPORTED_ARCHITECTURE)
799template<typename Arch,
800 int channels,
801 typename std::enable_if_t<!std::is_same<Arch, xsimd::generic>::value,
802 int> = 0>
803constexpr int bufferSize()
804{
805 return qMax<int>(channels, KoStreamedMath<Arch>::float_v::size);
806}
807#endif
808
809template<typename Arch,
810 LinearizePolicy linearizePolicy,
811 bool applyOOTF,
812 int channels>
813inline void readLayer(const int width,
814 const int height,
815 const uint8_t *img,
816 const int stride,
818 float displayGamma,
819 float displayNits,
820 const KoColorSpace *colorSpace)
821{
822 const QVector<qreal> lCoef{colorSpace->lumaCoefficients()};
823 QVector<float> pixelValues(bufferSize<Arch, channels>());
824 float *data = pixelValues.data();
825
826 for (int y = 0; y < height; y++) {
827 for (int x = 0; x < width; x++) {
828 for (int i = 0; i < bufferSize<Arch, channels>(); i++) {
829 data[i] = 0;
830 }
831
832 for (int ch = 0; ch < channels; ch++) {
833 if (ch == KoBgrU8Traits::alpha_pos) {
834 data[ch] =
835 value<Arch, LinearizePolicy::KeepTheSame, channels>(
836 img,
837 stride,
838 x,
839 y,
840 ch);
841 } else {
842 data[ch] = value<Arch, linearizePolicy, channels>(img,
843 stride,
844 x,
845 y,
846 ch);
847 }
848 }
849
850 linearize<Arch, linearizePolicy, applyOOTF>(data,
851 lCoef.constData(),
852 displayGamma,
853 displayNits);
854
856 pixelValues);
857
858 it->nextPixel();
859 }
860
861 it->nextRow();
862 }
863}
864
865template<typename Arch,
866 LinearizePolicy linearizePolicy,
867 bool applyOOTF,
868 typename... Args>
869inline auto readInterleavedWithAlpha(bool hasAlpha, Args &&...args)
870{
871 if (hasAlpha) {
872 return SDR::readLayer<Arch, linearizePolicy, applyOOTF, 4>(
873 std::forward<Args>(args)...);
874 } else {
875 return SDR::readLayer<Arch, linearizePolicy, applyOOTF, 3>(
876 std::forward<Args>(args)...);
877 }
878}
879
880template<typename Arch, LinearizePolicy linearizePolicy, typename... Args>
881inline auto readInterleavedWithPolicy(bool applyOOTF, Args &&...args)
882{
883 if (applyOOTF) {
884 return readInterleavedWithAlpha<Arch, linearizePolicy, true>(
885 std::forward<Args>(args)...);
886 } else {
887 return readInterleavedWithAlpha<Arch, linearizePolicy, false>(
888 std::forward<Args>(args)...);
889 }
890}
891
892template<typename Arch>
893void readLayerImpl::create(LinearizePolicy linearizePolicy,
894 bool applyOOTF,
895 bool hasAlpha,
896 const int width,
897 const int height,
898 const uint8_t *img,
899 const int stride,
901 float displayGamma,
902 float displayNits,
903 const KoColorSpace *colorSpace)
904{
905 if (linearizePolicy == LinearizePolicy::LinearFromHLG) {
906 return readInterleavedWithPolicy<Arch, LinearizePolicy::LinearFromHLG>(applyOOTF,
907 hasAlpha,
908 width,
909 height,
910 img,
911 stride,
912 it,
913 displayGamma,
914 displayNits,
915 colorSpace);
916 } else if (linearizePolicy == LinearizePolicy::LinearFromPQ) {
917 return readInterleavedWithPolicy<Arch, LinearizePolicy::LinearFromPQ>(applyOOTF,
918 hasAlpha,
919 width,
920 height,
921 img,
922 stride,
923 it,
924 displayGamma,
925 displayNits,
926 colorSpace);
927 } else if (linearizePolicy == LinearizePolicy::LinearFromSMPTE428) {
928 return readInterleavedWithPolicy<Arch, LinearizePolicy::LinearFromSMPTE428>(applyOOTF,
929 hasAlpha,
930 width,
931 height,
932 img,
933 stride,
934 it,
935 displayGamma,
936 displayNits,
937 colorSpace);
938 } else {
939 return readInterleavedWithPolicy<Arch, LinearizePolicy::KeepTheSame>(applyOOTF,
940 hasAlpha,
941 width,
942 height,
943 img,
944 stride,
945 it,
946 displayGamma,
947 displayNits,
948 colorSpace);
949 }
950}
951
952template void
953readLayerImpl::create<xsimd::current_arch>(LinearizePolicy linearizePolicy,
954 bool applyOOTF,
955 bool hasAlpha,
956 const int width,
957 const int height,
958 const uint8_t *img,
959 const int stride,
961 float displayGamma,
962 float displayNits,
963 const KoColorSpace *colorSpace);
964} // namespace SDR
965
966#endif // XSIMD_UNIVERSAL_BUILD_PASS
float value(const T *src, size_t ch)
float linearizeValueAsNeeded(float value)
qreal v
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
ALWAYS_INLINE void applyHLGOOTF(float *rgb, const double *lumaCoefficients, float gamma=1.2f, float nominalPeak=1000.0f) noexcept
ALWAYS_INLINE float removeHLGCurve(float x) noexcept
LinearizePolicy
The KoColorTransferFunctions class.
static constexpr float multiplier12bit
static constexpr float multiplier10bit
ALWAYS_INLINE float removeSMPTE_ST_428Curve(float x) noexcept
static constexpr float multiplier16bit
ALWAYS_INLINE float removeSmpte2048Curve(float x) noexcept
QVector< qreal > lumaCoefficients
void readLayer(const int width, const int height, KisHLineIteratorSP it, const uint8_t *imgG, const uint8_t *imgA, const int strideG, const int strideA)
static const qint32 alpha_pos
static void fromNormalisedChannelsValue(quint8 *pixel, const QVector< float > &values)
static ALWAYS_INLINE void removeSmpte2048Curve(float_v &x) noexcept
typename KoStreamedMath< Arch >::float_v float_v
static ALWAYS_INLINE void removeSMPTE_ST_428Curve(float_v &x) noexcept
static ALWAYS_INLINE void removeHLGCurve(float_v &x) noexcept
static void create(const int luma, LinearizePolicy policy, bool applyOOTF, bool hasAlpha, const int width, const int height, const uint8_t *imgR, const int strideR, const uint8_t *imgG, const int strideG, const uint8_t *imgB, const int strideB, const uint8_t *imgA, const int strideA, KisHLineIteratorSP it, float displayGamma, float displayNits, const KoColorSpace *colorSpace)