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