1 // 2 // (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. 3 // 4 5 #ifndef CHARLS_COLORTRANSFORM 6 #define CHARLS_COLORTRANSFORM 7 8 #include "util.h" 9 10 // This file defines simple classes that define (lossless) color transforms. 11 // They are invoked in processline.h to convert between decoded values and the internal line buffers. 12 // Color transforms work best for computer generated images, but are outside the official JPEG-LS specifications. 13 14 template<typename T> 15 struct TransformNoneImpl 16 { 17 static_assert(std::is_integral<T>::value, "Integral required."); 18 19 using size_type = T; 20 operatorTransformNoneImpl21 FORCE_INLINE Triplet<T> operator()(int v1, int v2, int v3) const noexcept 22 { 23 return Triplet<T>(v1, v2, v3); 24 } 25 }; 26 27 28 template<typename T> 29 struct TransformNone : TransformNoneImpl<T> 30 { 31 static_assert(std::is_integral<T>::value, "Integral required."); 32 33 using Inverse = TransformNoneImpl<T>; 34 }; 35 36 37 template<typename T> 38 struct TransformHp1 39 { 40 static_assert(std::is_integral<T>::value, "Integral required."); 41 42 using size_type = T; 43 44 struct Inverse 45 { InverseTransformHp1::Inverse46 explicit Inverse(const TransformHp1&) noexcept 47 { 48 } 49 operatorTransformHp1::Inverse50 FORCE_INLINE Triplet<T> operator()(int v1, int v2, int v3) const noexcept 51 { 52 return Triplet<T>(v1 + v2 - Range / 2, v2, v3 + v2 - Range / 2); 53 } 54 }; 55 operatorTransformHp156 FORCE_INLINE Triplet<T> operator()(int red, int green, int blue) const noexcept 57 { 58 Triplet<T> hp1; 59 hp1.v2 = static_cast<T>(green); 60 hp1.v1 = static_cast<T>(red - green + Range / 2); 61 hp1.v3 = static_cast<T>(blue - green + Range / 2); 62 return hp1; 63 } 64 65 private: 66 static constexpr size_t Range = 1 << (sizeof(T) * 8); 67 }; 68 69 70 template<typename T> 71 struct TransformHp2 72 { 73 static_assert(std::is_integral<T>::value, "Integral required."); 74 75 using size_type = T; 76 77 struct Inverse 78 { InverseTransformHp2::Inverse79 explicit Inverse(const TransformHp2&) noexcept 80 { 81 } 82 operatorTransformHp2::Inverse83 FORCE_INLINE Triplet<T> operator()(int v1, int v2, int v3) const noexcept 84 { 85 Triplet<T> rgb; 86 rgb.R = static_cast<T>(v1 + v2 - Range / 2); // new R 87 rgb.G = static_cast<T>(v2); // new G 88 rgb.B = static_cast<T>(v3 + ((rgb.R + rgb.G) >> 1) - Range / 2); // new B 89 return rgb; 90 } 91 }; 92 operatorTransformHp293 FORCE_INLINE Triplet<T> operator()(int red, int green, int blue) const noexcept 94 { 95 return Triplet<T>(red - green + Range / 2, green, blue - ((red + green) >> 1) - Range / 2); 96 } 97 98 private: 99 static constexpr size_t Range = 1 << (sizeof(T) * 8); 100 }; 101 102 103 template<typename T> 104 struct TransformHp3 105 { 106 static_assert(std::is_integral<T>::value, "Integral required."); 107 108 using size_type = T; 109 110 struct Inverse 111 { InverseTransformHp3::Inverse112 explicit Inverse(const TransformHp3&) noexcept 113 { 114 } 115 operatorTransformHp3::Inverse116 FORCE_INLINE Triplet<T> operator()(int v1, int v2, int v3) const noexcept 117 { 118 const int G = v1 - ((v3 + v2) >> 2) + Range / 4; 119 Triplet<T> rgb; 120 rgb.R = static_cast<T>(v3 + G - Range / 2); // new R 121 rgb.G = static_cast<T>(G); // new G 122 rgb.B = static_cast<T>(v2 + G - Range / 2); // new B 123 return rgb; 124 } 125 }; 126 operatorTransformHp3127 FORCE_INLINE Triplet<T> operator()(int red, int green, int blue) const noexcept 128 { 129 Triplet<T> hp3; 130 hp3.v2 = static_cast<T>(blue - green + Range / 2); 131 hp3.v3 = static_cast<T>(red - green + Range / 2); 132 hp3.v1 = static_cast<T>(green + ((hp3.v2 + hp3.v3) >> 2)) - Range / 4; 133 return hp3; 134 } 135 136 private: 137 static constexpr size_t Range = 1 << (sizeof(T) * 8); 138 }; 139 140 141 // Transform class that shifts bits towards the high bit when bit count is not 8 or 16 142 // needed to make the HP color transformations work correctly. 143 template<typename Transform> 144 struct TransformShifted 145 { 146 using size_type = typename Transform::size_type; 147 148 struct Inverse 149 { InverseTransformShifted::Inverse150 explicit Inverse(const TransformShifted& transform) noexcept 151 : _shift(transform._shift), 152 _inverseTransform(transform._colortransform) 153 { 154 } 155 operatorTransformShifted::Inverse156 FORCE_INLINE Triplet<size_type> operator()(int v1, int v2, int v3) noexcept 157 { 158 const Triplet<size_type> result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift); 159 return Triplet<size_type>(result.R >> _shift, result.G >> _shift, result.B >> _shift); 160 } 161 operatorTransformShifted::Inverse162 FORCE_INLINE Quad<size_type> operator()(int v1, int v2, int v3, int v4) 163 { 164 Triplet<size_type> result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift); 165 return Quad<size_type>(result.R >> _shift, result.G >> _shift, result.B >> _shift, v4); 166 } 167 168 private: 169 int _shift; 170 typename Transform::Inverse _inverseTransform; 171 }; 172 TransformShiftedTransformShifted173 explicit TransformShifted(int shift) noexcept 174 : _shift(shift) 175 { 176 } 177 operatorTransformShifted178 FORCE_INLINE Triplet<size_type> operator()(int red, int green, int blue) noexcept 179 { 180 const Triplet<size_type> result = _colortransform(red << _shift, green << _shift, blue << _shift); 181 return Triplet<size_type>(result.R >> _shift, result.G >> _shift, result.B >> _shift); 182 } 183 operatorTransformShifted184 FORCE_INLINE Quad<size_type> operator()(int red, int green, int blue, int alpha) 185 { 186 Triplet<size_type> result = _colortransform(red << _shift, green << _shift, blue << _shift); 187 return Quad<size_type>(result.R >> _shift, result.G >> _shift, result.B >> _shift, alpha); 188 } 189 190 private: 191 int _shift; 192 Transform _colortransform; 193 }; 194 195 196 #endif 197