File indexing completed on 2024-06-23 04:27:14

0001 /**
0002  *  SPDX-FileCopyrightText: 2020-2021 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
0003  *  SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #ifndef KIS_HEIF_IMPORT_TOOLS_H
0009 #define KIS_HEIF_IMPORT_TOOLS_H
0010 
0011 #include <cstdint>
0012 
0013 #include <KoColorSpace.h>
0014 #include <KoColorSpaceTraits.h>
0015 #include <KoColorTransferFunctions.h>
0016 #include <kis_iterator_ng.h>
0017 
0018 namespace Gray
0019 {
0020 template<int luma>
0021 inline void applyValue(KisHLineIteratorSP it,
0022                        const uint8_t *imgG,
0023                        int strideG,
0024                        int x,
0025                        int y)
0026 {
0027     if (luma == 8) {
0028         KoGrayU8Traits::setGray(it->rawData(), imgG[y * strideG + x]);
0029     } else {
0030         uint16_t source =
0031             KoGrayU16Traits::nativeArray(imgG)[y * (strideG / 2) + (x)];
0032 
0033         if (luma == 10) {
0034             KoGrayU16Traits::setGray(
0035                 it->rawData(),
0036                 static_cast<uint16_t>(float(0x03ffu & (source))
0037                                       * multiplier10bit * max16bit));
0038         } else if (luma == 12) {
0039             KoGrayU16Traits::setGray(
0040                 it->rawData(),
0041                 static_cast<uint16_t>(float(0x0fffu & (source))
0042                                       * multiplier12bit * max16bit));
0043         } else {
0044             KoGrayU16Traits::setGray(
0045                 it->rawData(),
0046                 static_cast<uint16_t>(float(source) * multiplier16bit));
0047         }
0048     }
0049 }
0050 
0051 template<int luma, bool hasAlpha>
0052 inline void applyAlpha(KisHLineIteratorSP it,
0053                        const uint8_t *imgA,
0054                        int strideA,
0055                        int x,
0056                        int y)
0057 {
0058     if (hasAlpha) {
0059         if (luma == 8) {
0060             KoGrayU8Traits::setOpacity(it->rawData(),
0061                                        quint8(imgA[y * strideA + x]),
0062                                        1);
0063         } else {
0064             uint16_t source =
0065                 KoGrayU16Traits::nativeArray(imgA)[y * (strideA / 2) + x];
0066             if (luma == 10) {
0067                 KoGrayU16Traits::setOpacity(
0068                     it->rawData(),
0069                     static_cast<qreal>(float(0x0fff & (source))
0070                                        * multiplier10bit),
0071                     1);
0072             } else if (luma == 12) {
0073                 KoGrayU16Traits::setOpacity(
0074                     it->rawData(),
0075                     static_cast<qreal>(float(0x0fff & (source))
0076                                        * multiplier12bit),
0077                     1);
0078             } else {
0079                 KoGrayU16Traits::setOpacity(
0080                     it->rawData(),
0081                     static_cast<qreal>(float(source) * multiplier16bit),
0082                     1);
0083             }
0084         }
0085     } else {
0086         if (luma == 8) {
0087             KoGrayU8Traits::setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1);
0088         } else {
0089             KoGrayU16Traits::setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1);
0090         }
0091     }
0092 }
0093 
0094 template<int luma, bool hasAlpha>
0095 inline void readLayer(const int width,
0096                       const int height,
0097                       KisHLineIteratorSP it,
0098                       const uint8_t *imgG,
0099                       const uint8_t *imgA,
0100                       const int strideG,
0101                       const int strideA)
0102 {
0103     for (int y = 0; y < height; y++) {
0104         for (int x = 0; x < width; x++) {
0105             applyValue<luma>(it, imgG, strideG, x, y);
0106 
0107             applyAlpha<luma, hasAlpha>(it, imgA, strideA, x, y);
0108             it->nextPixel();
0109         }
0110 
0111         it->nextRow();
0112     }
0113 }
0114 
0115 template<int luma, typename... Args>
0116 inline auto readPlanarWithLuma(bool hasAlpha, Args &&...args)
0117 {
0118     if (hasAlpha) {
0119         return Gray::readLayer<luma, true>(std::forward<Args>(args)...);
0120     } else {
0121         return Gray::readLayer<luma, false>(std::forward<Args>(args)...);
0122     }
0123 }
0124 
0125 template<typename... Args>
0126 inline auto readPlanarLayer(const int luma, Args &&...args)
0127 {
0128     if (luma == 8) {
0129         return readPlanarWithLuma<8>(std::forward<Args>(args)...);
0130     } else if (luma == 10) {
0131         return readPlanarWithLuma<10>(std::forward<Args>(args)...);
0132     } else if (luma == 12) {
0133         return readPlanarWithLuma<12>(std::forward<Args>(args)...);
0134     } else {
0135         return readPlanarWithLuma<16>(std::forward<Args>(args)...);
0136     }
0137 }
0138 } // namespace Gray
0139 
0140 namespace SDR
0141 {
0142 struct readLayerImpl {
0143     template<typename Arch>
0144     static void create(LinearizePolicy policy,
0145                        bool applyOOTF,
0146                        bool hasAlpha,
0147                        const int width,
0148                        const int height,
0149                        const uint8_t *img,
0150                        const int stride,
0151                        KisHLineIteratorSP it,
0152                        float displayGamma,
0153                        float displayNits,
0154                        const KoColorSpace *colorSpace);
0155 };
0156 } // namespace SDR
0157 
0158 namespace Planar
0159 {
0160 struct readLayerImpl {
0161     template<typename Arch>
0162     static void create(const int luma,
0163                        LinearizePolicy policy,
0164                        bool applyOOTF,
0165                        bool hasAlpha,
0166                        const int width,
0167                        const int height,
0168                        const uint8_t *imgR,
0169                        const int strideR,
0170                        const uint8_t *imgG,
0171                        const int strideG,
0172                        const uint8_t *imgB,
0173                        const int strideB,
0174                        const uint8_t *imgA,
0175                        const int strideA,
0176                        KisHLineIteratorSP it,
0177                        float displayGamma,
0178                        float displayNits,
0179                        const KoColorSpace *colorSpace);
0180 };
0181 } // namespace Planar
0182 
0183 namespace HDR
0184 {
0185 struct readLayerImpl {
0186     template<typename Arch>
0187     static void create(const int luma,
0188                        LinearizePolicy linearizePolicy,
0189                        bool applyOOTF,
0190                        const int channels,
0191                        const int width,
0192                        const int height,
0193                        const uint8_t *img,
0194                        const int stride,
0195                        KisHLineIteratorSP it,
0196                        float displayGamma,
0197                        float displayNits,
0198                        const KoColorSpace *colorSpace);
0199 };
0200 } // namespace HDR
0201 
0202 #endif // KIS_HEIF_IMPORT_TOOLS_H