1 //
2 // (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
3 //
4 #ifndef CHARLS_COLORTRANSFORM
5 #define CHARLS_COLORTRANSFORM
6 
7 
8 #include "util.h"
9 
10 
11 // This file defines simple classes that define (lossless) color transforms.
12 // They are invoked in processline.h to convert between decoded values and the internal line buffers.
13 // Color transforms work best for computer generated images.
14 //
15 #ifdef _MSC_VER
16 #pragma warning (disable: 4127) // conditional expression is constant (caused by some template methods that are not fully specialized) [VS2013]
17 #endif
18 
19 
20 template<typename sample>
21 struct TransformNoneImpl
22 {
23     typedef sample SAMPLE;
24 
operatorTransformNoneImpl25     inlinehint Triplet<SAMPLE> operator()(int v1, int v2, int v3) const
26     {
27         return Triplet<SAMPLE>(v1, v2, v3);
28     }
29 };
30 
31 
32 template<typename sample>
33 struct TransformNone : TransformNoneImpl<sample>
34 {
35     typedef struct TransformNoneImpl<sample> INVERSE;
36 };
37 
38 
39 template<typename sample>
40 struct TransformHp1
41 {
42     enum { RANGE = 1 << (sizeof(sample) * 8) };
43     typedef sample SAMPLE;
44 
45     struct INVERSE
46     {
47         explicit INVERSE(const TransformHp1&) {};
48 
49         inlinehint Triplet<SAMPLE> operator()(int v1, int v2, int v3) const
50         {
51             return Triplet<SAMPLE>(v1 + v2 - RANGE / 2, v2, v3 + v2 - RANGE / 2);
52         }
53     };
54 
55     inlinehint Triplet<SAMPLE> operator()(int R, int G, int B) const
56     {
57         Triplet<SAMPLE> hp1;
58         hp1.v2 = SAMPLE(G);
59         hp1.v1 = SAMPLE(R - G + RANGE / 2);
60         hp1.v3 = SAMPLE(B - G + RANGE / 2);
61         return hp1;
62     }
63 };
64 
65 
66 template<typename sample>
67 struct TransformHp2
68 {
69     enum { RANGE = 1 << (sizeof(sample) * 8) };
70     typedef sample SAMPLE;
71 
72     struct INVERSE
73     {
74         explicit INVERSE(const TransformHp2&) {};
75 
76         inlinehint Triplet<SAMPLE> operator() (int v1, int v2, int v3) const
77         {
78             Triplet<SAMPLE> rgb;
79             rgb.R  = SAMPLE(v1 + v2 - RANGE / 2);                     // new R
80             rgb.G  = SAMPLE(v2);                                    // new G
81             rgb.B  = SAMPLE(v3 + ((rgb.R + rgb.G) >> 1) - RANGE / 2); // new B
82             return rgb;
83         }
84     };
85 
86     inlinehint Triplet<SAMPLE> operator()(int R, int G, int B) const
87     {
88         return Triplet<SAMPLE>(R - G + RANGE / 2, G, B - ((R+G )>>1) - RANGE / 2);
89     }
90 };
91 
92 
93 template<typename sample>
94 struct TransformHp3
95 {
96     enum { RANGE = 1 << (sizeof(sample) * 8) };
97     typedef sample SAMPLE;
98 
99     struct INVERSE
100     {
101         explicit INVERSE(const TransformHp3&) {};
102 
103         inlinehint Triplet<SAMPLE> operator()(int v1, int v2, int v3) const
104         {
105             int G = v1 - ((v3 + v2) >> 2) + RANGE / 4;
106             Triplet<SAMPLE> rgb;
107             rgb.R  = SAMPLE(v3 + G - RANGE / 2); // new R
108             rgb.G  = SAMPLE(G);                  // new G
109             rgb.B  = SAMPLE(v2 + G - RANGE / 2); // new B
110             return rgb;
111         }
112     };
113 
114     inlinehint Triplet<SAMPLE> operator() (int R, int G, int B) const
115     {
116         Triplet<SAMPLE> hp3;
117         hp3.v2 = SAMPLE(B - G + RANGE / 2);
118         hp3.v3 = SAMPLE(R - G + RANGE / 2);
119         hp3.v1 = SAMPLE(G + ((hp3.v2 + hp3.v3)>>2)) - RANGE / 4;
120         return hp3;
121     }
122 };
123 
124 
125 // Transform class that shifts bits towards the high bit when bitcount is not 8 or 16
126 // needed to make the HP color transforms work correctly.
127 template<typename TRANSFORM>
128 struct TransformShifted
129 {
130     typedef typename TRANSFORM::SAMPLE SAMPLE;
131 
132     struct INVERSE
133     {
134         explicit INVERSE(const TransformShifted& transform) :
135             _shift(transform._shift),
136             _inverseTransform(transform._colortransform)
137         {
138         }
139 
140         inlinehint Triplet<SAMPLE> operator() (int v1, int v2, int v3)
141         {
142             Triplet<SAMPLE> result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift);
143             return Triplet<SAMPLE>(result.R >> _shift, result.G >> _shift, result.B >> _shift);
144         }
145 
146         inlinehint Quad<SAMPLE> operator() (int v1, int v2, int v3, int v4)
147         {
148             Triplet<SAMPLE> result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift);
149             return Quad<SAMPLE>(result.R >> _shift, result.G >> _shift, result.B >> _shift, v4);
150         }
151 
152         int _shift;
153         typename TRANSFORM::INVERSE _inverseTransform;
154     };
155 
156 
157     explicit TransformShifted(int shift) :
158         _shift(shift)
159     {
160     }
161 
162     inlinehint Triplet<SAMPLE> operator() (int R, int G, int B)
163     {
164         Triplet<SAMPLE> result = _colortransform(R << _shift, G << _shift, B << _shift);
165         return Triplet<SAMPLE>(result.R >> _shift, result.G >> _shift, result.B >> _shift);
166     }
167 
168     inlinehint Quad<SAMPLE> operator() (int R, int G, int B, int A)
169     {
170         Triplet<SAMPLE> result = _colortransform(R << _shift, G << _shift, B << _shift);
171         return Quad<SAMPLE>(result.R >> _shift, result.G >> _shift, result.B >> _shift, A);
172     }
173 
174     int _shift;
175     TRANSFORM _colortransform;
176 };
177 
178 
179 #endif
180