8#ifndef KIS_HEIF_EXPORT_TOOLS_H
9#define KIS_HEIF_EXPORT_TOOLS_H
22template<
int endValue0,
int endValue1,
int luma>
24applyValue(
const quint8 *data, uint8_t *ptrG,
int strideG,
int x,
int y)
29 uint16_t
v = qBound<uint16_t>(
34 ptrG[(x * 2) + y * strideG + endValue0] =
static_cast<uint8_t
>(
v >> 8);
35 ptrG[(x * 2) + y * strideG + endValue1] =
36 static_cast<uint8_t
>(
v & 0xFF);
40template<
int endValue0,
int endValue1,
int luma,
bool hasAlpha>
42applyAlpha(
const quint8 *data, uint8_t *ptrA,
const int strideA,
int x,
int y)
48 uint16_t vA = qBound<uint16_t>(
53 ptrA[(x * 2) + y * strideA + endValue0] = (uint8_t)(vA >> 8);
54 ptrA[(x * 2) + y * strideA + endValue1] = (uint8_t)(vA & 0xFF);
59template<
int endValue0,
int endValue1,
int luma,
bool hasAlpha>
68 for (
int y = 0; y < height; y++) {
69 for (
int x = 0; x < width; x++) {
72 applyValue<endValue0, endValue1, luma>(data, ptrG, strideG, x, y);
74 applyAlpha<endValue0, endValue1, luma, hasAlpha>(data,
87template<
int endValue0,
int endValue1,
int luma,
typename... Args>
91 return Gray::writeLayer<endValue0, endValue1, luma, true>(
92 std::forward<Args>(args)...);
94 return Gray::writeLayer<endValue0, endValue1, luma, false>(
95 std::forward<Args>(args)...);
99template<
int endValue0,
int endValue1,
typename... Args>
103 return writePlanarWithAlpha<endValue0, endValue1, 8>(
104 std::forward<Args>(args)...);
106 return writePlanarWithAlpha<endValue0, endValue1, 12>(
107 std::forward<Args>(args)...);
111template<
typename... Args>
114 if (endian == QSysInfo::LittleEndian) {
115 return Gray::writePlanarWithLuma<1, 0>(std::forward<Args>(args)...);
117 return Gray::writePlanarWithLuma<0, 1>(std::forward<Args>(args)...);
124template<
bool hasAlpha>
137 for (
int y = 0; y < height; y++) {
138 for (
int x = 0; x < width; x++) {
157template<
typename... Args>
161 return Planar::writeLayerImpl<true>(std::forward<Args>(args)...);
163 return Planar::writeLayerImpl<false>(std::forward<Args>(args)...);
170template<
int endValue0,
int endValue1,
int channels>
177 std::array<KoBgrU16Traits::channels_type, channels> pixelValues{};
179 for (
int y = 0; y < height; y++) {
180 for (
int x = 0; x < width; x++) {
190 for (
int ch = 0; ch < channels; ch++) {
191 uint16_t
v = qBound<uint16_t>(
193 static_cast<uint16_t
>(
float(pixelValues[ch])
196 ptr[2 * (x * channels) + y * stride + endValue0 + (ch * 2)] =
197 static_cast<uint8_t
>(
v >> 8);
198 ptr[2 * (x * channels) + y * stride + endValue1 + (ch * 2)] =
199 static_cast<uint8_t
>(
v & 0xFF);
209template<
int endValue0,
int endValue1,
typename... Args>
213 return HDRInt::writeLayerImpl<endValue0, endValue1, 4>(
214 std::forward<Args>(args)...);
216 return HDRInt::writeLayerImpl<endValue0, endValue1, 3>(
217 std::forward<Args>(args)...);
221template<
typename... Args>
224 if (endian == QSysInfo::LittleEndian) {
225 return writeInterleavedWithAlpha<1, 0>(std::forward<Args>(args)...);
227 return writeInterleavedWithAlpha<0, 1>(std::forward<Args>(args)...);
235template<ConversionPolicy policy>
248template<
typename CSTrait,
249 QSysInfo::Endian endianness,
251 bool convertToRec2020,
261 float hlgNominalPeak,
264 const int endValue0 = endianness == QSysInfo::LittleEndian ? 1 : 0;
265 const int endValue1 = endianness == QSysInfo::LittleEndian ? 0 : 1;
270 double *src = pixelValuesLinear.data();
271 float *dst = pixelValues.data();
273 for (
int y = 0; y < height; y++) {
274 for (
int x = 0; x < width; x++) {
275 CSTrait::normalisedChannelsValue(it->
rawDataConst(), pixelValues);
276 if (!convertToRec2020 && !isLinear) {
277 for (
int i = 0; i < 4; i++) {
278 src[i] =
static_cast<double>(dst[i]);
281 for (
int i = 0; i < 4; i++) {
282 dst[i] =
static_cast<float>(src[i]);
287 removeHLGOOTF(dst, lCoef.constData(), hlgGamma, hlgNominalPeak);
290 for (
int ch = 0; ch < channels; ch++) {
292 if (ch == CSTrait::alpha_pos) {
293 v = qBound<uint16_t>(
295 static_cast<uint16_t
>(
296 applyCurveAsNeeded<ConversionPolicy::KeepTheSame>(
301 v = qBound<uint16_t>(
303 static_cast<uint16_t
>(
304 applyCurveAsNeeded<conversionPolicy>(dst[ch])
308 ptr[2 * (x * channels) + y * stride + endValue0 + (ch * 2)] =
310 ptr[2 * (x * channels) + y * stride + endValue1 + (ch * 2)] =
320template<
typename CSTrait,
321 QSysInfo::Endian endianness,
323 bool convertToRec2020,
336 true>(std::forward<Args>(args)...);
344 false>(std::forward<Args>(args)...);
348template<
typename CSTrait,
349 QSysInfo::Endian endianness,
351 bool convertToRec2020,
388template<
typename CSTrait,
389 QSysInfo::Endian endianness,
391 bool convertToRec2020,
400 true>(std::forward<Args>(args)...);
406 false>(std::forward<Args>(args)...);
410template<
typename CSTrait,
411 QSysInfo::Endian endianness,
416 if (convertToRec2020) {
417 return writeInterleavedWithRec2020<CSTrait, endianness, channels, true>(
418 std::forward<Args>(args)...);
423 false>(std::forward<Args>(args)...);
427template<
typename CSTrait, QSysInfo::Endian endianness,
typename... Args>
431 return writeInterleavedWithAlpha<CSTrait, endianness, 4>(
432 std::forward<Args>(args)...);
434 return writeInterleavedWithAlpha<CSTrait, endianness, 3>(
435 std::forward<Args>(args)...);
439template<
typename CSTrait,
typename... Args>
442 if (endian == QSysInfo::LittleEndian) {
443 return writeInterleavedWithEndian<CSTrait, QSysInfo::LittleEndian>(
444 std::forward<Args>(args)...);
446 return writeInterleavedWithEndian<CSTrait, QSysInfo::BigEndian>(
447 std::forward<Args>(args)...);
451template<
typename... Args>
456 return writeInterleavedWithDepth<KoBgrF16Traits>(
457 std::forward<Args>(args)...);
463 return writeInterleavedWithDepth<KoBgrF32Traits>(
464 std::forward<Args>(args)...);
float value(const T *src, size_t ch)
const KoID Float16BitsColorDepthID("F16", ki18n("16-bit float/channel"))
ALWAYS_INLINE void removeHLGOOTF(float *rgb, const double *lumaCoefficients, float gamma=1.2f, float nominalPeak=1000.0f) noexcept
static constexpr float max16bit
static constexpr uint16_t max12bit
static constexpr float multiplier16bit
ALWAYS_INLINE float applySmpte2048Curve(float x) noexcept
ALWAYS_INLINE float applySMPTE_ST_428Curve(float x) noexcept
ALWAYS_INLINE float applyHLGCurve(float x) noexcept
virtual const quint8 * rawDataConst() const =0
virtual bool nextPixel()=0
QVector< qreal > lumaCoefficients
virtual const KoColorProfile * profile() const =0
void applyValue(const quint8 *data, uint8_t *ptrG, int strideG, int x, int y)
auto writePlanarWithAlpha(bool hasAlpha, Args &&...args)
void applyAlpha(const quint8 *data, uint8_t *ptrA, const int strideA, int x, int y)
void writeLayer(const int width, const int height, uint8_t *ptrG, const int strideG, uint8_t *ptrA, const int strideA, KisHLineConstIteratorSP it)
auto writePlanarLayer(QSysInfo::Endian endian, Args &&...args)
auto writePlanarWithLuma(const int luma, Args &&...args)
auto writeInterleavedWithEndian(bool hasAlpha, Args &&...args)
auto writeInterleavedWithLinear(ConversionPolicy linearizePolicy, Args &&...args)
float applyCurveAsNeeded(float value)
auto writeInterleavedWithPolicy(bool removeOOTF, Args &&...args)
auto writeInterleavedWithRec2020(bool isLinear, Args &&...args)
auto writeInterleavedLayer(const KoID &id, Args &&...args)
auto writeInterleavedWithAlpha(bool convertToRec2020, Args &&...args)
void writeFloatLayerImpl(const int width, const int height, uint8_t *ptr, const int stride, KisHLineConstIteratorSP it, float hlgGamma, float hlgNominalPeak, const KoColorSpace *cs)
auto writeInterleavedWithDepth(QSysInfo::Endian endian, Args &&...args)
auto writeInterleavedLayer(QSysInfo::Endian endian, Args &&...args)
void writeLayerImpl(const int width, const int height, uint8_t *ptr, const int stride, KisHLineConstIteratorSP it)
auto writeInterleavedWithAlpha(bool hasAlpha, Args &&...args)
auto writeLayer(bool hasAlpha, Args &&...args)
void writeLayerImpl(const int width, const int height, uint8_t *ptrR, const int strideR, uint8_t *ptrG, const int strideG, uint8_t *ptrB, const int strideB, uint8_t *ptrA, const int strideA, KisHLineConstIteratorSP it)
static channels_type blue(const quint8 *data)
static channels_type green(const quint8 *data)
static channels_type red(const quint8 *data)
virtual void linearizeFloatValue(QVector< qreal > &Value) const =0
static quint8 opacityU8(const quint8 *U8_pixel)
_channels_type_ channels_type
the type of the value of the channels of this color space
static qreal opacityF(const quint8 *U8_pixel)
static channels_type gray(const quint8 *data)