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