00001 // 00002 // (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. 00003 // 00004 #ifndef CHARLS_COLORTRANSFORM 00005 #define CHARLS_COLORTRANSFORM 00006 00007 // 00008 // This file defines simple classes that define (lossless) color transforms. 00009 // They are invoked in processline.h to convert between decoded values and the internal line buffers. 00010 // Color transforms work best for computer generated images. 00011 // 00012 00013 template<class sample> 00014 struct TransformNoneImpl 00015 { 00016 typedef sample SAMPLE; 00017 00018 inlinehint Triplet<SAMPLE> operator() (int v1, int v2, int v3) 00019 { return Triplet<SAMPLE>(v1, v2, v3); } 00020 }; 00021 00022 00023 template<class sample> 00024 struct TransformNone : public TransformNoneImpl<sample> 00025 { 00026 typedef struct TransformNoneImpl<sample> INVERSE; 00027 }; 00028 00029 00030 00031 template<class sample> 00032 struct TransformHp1 00033 { 00034 enum { RANGE = 1 << sizeof(sample)*8 }; 00035 typedef sample SAMPLE; 00036 00037 struct INVERSE 00038 { 00039 INVERSE(const TransformHp1&) {}; 00040 00041 inlinehint Triplet<SAMPLE> operator() (int v1, int v2, int v3) 00042 { return Triplet<SAMPLE>(v1 + v2 - RANGE/2, v2, v3 + v2 - RANGE/2); } 00043 }; 00044 00045 inlinehint Triplet<SAMPLE> operator() (int R, int G, int B) 00046 { 00047 Triplet<SAMPLE> hp1; 00048 hp1.v2 = SAMPLE(G); 00049 hp1.v1 = SAMPLE(R - G + RANGE/2); 00050 hp1.v3 = SAMPLE(B - G + RANGE/2); 00051 return hp1; 00052 } 00053 }; 00054 00055 00056 00057 00058 00059 template<class sample> 00060 struct TransformHp2 00061 { 00062 enum { RANGE = 1 << sizeof(sample)*8 }; 00063 typedef sample SAMPLE; 00064 00065 struct INVERSE 00066 { 00067 INVERSE(const TransformHp2&) {}; 00068 00069 inlinehint Triplet<SAMPLE> operator() (int v1, int v2, int v3) 00070 { 00071 Triplet<SAMPLE> rgb; 00072 rgb.R = SAMPLE(v1 + v2 - RANGE/2); // new R 00073 rgb.G = SAMPLE(v2); // new G 00074 rgb.B = SAMPLE(v3 + ((rgb.R + rgb.G) >> 1) - RANGE/2); // new B 00075 return rgb; 00076 } 00077 }; 00078 00079 inlinehint Triplet<SAMPLE> operator() (int R, int G, int B) 00080 { 00081 return Triplet<SAMPLE>(R - G + RANGE/2, G, B - ((R+G )>>1) - RANGE/2); 00082 } 00083 00084 00085 }; 00086 00087 00088 00089 template<class sample> 00090 struct TransformHp3 00091 { 00092 enum { RANGE = 1 << sizeof(sample)*8 }; 00093 typedef sample SAMPLE; 00094 00095 struct INVERSE 00096 { 00097 INVERSE(const TransformHp3&) {}; 00098 00099 inlinehint Triplet<SAMPLE> operator() (int v1, int v2, int v3) 00100 { 00101 int G = v1 - ((v3 + v2)>>2) + RANGE/4; 00102 Triplet<SAMPLE> rgb; 00103 rgb.R = SAMPLE(v3 + G - RANGE/2); // new R 00104 rgb.G = SAMPLE(G); // new G 00105 rgb.B = SAMPLE(v2 + G - RANGE/2); // new B 00106 return rgb; 00107 } 00108 }; 00109 00110 inlinehint Triplet<SAMPLE> operator() (int R, int G, int B) 00111 { 00112 Triplet<SAMPLE> hp3; 00113 hp3.v2 = SAMPLE(B - G + RANGE/2); 00114 hp3.v3 = SAMPLE(R - G + RANGE/2); 00115 hp3.v1 = SAMPLE(G + ((hp3.v2 + hp3.v3)>>2)) - RANGE/4; 00116 return hp3; 00117 } 00118 }; 00119 00120 00121 // Transform class that shifts bits towards the high bit when bitcount is not 8 or 16 00122 // needed to make the HP color transforms work correctly. 00123 00124 template<class TRANSFORM> 00125 struct TransformShifted 00126 { 00127 typedef typename TRANSFORM::SAMPLE SAMPLE; 00128 00129 struct INVERSE 00130 { 00131 INVERSE(const TransformShifted& transform) : 00132 _shift(transform._shift), 00133 _inverseTransform(transform._colortransform) 00134 {} 00135 00136 inlinehint Triplet<SAMPLE> operator() (int v1, int v2, int v3) 00137 { 00138 Triplet<SAMPLE> result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift); 00139 00140 return Triplet<SAMPLE>(result.R >> _shift, result.G >> _shift, result.B >> _shift); 00141 } 00142 00143 inlinehint Quad<SAMPLE> operator() (int v1, int v2, int v3, int v4) 00144 { 00145 Triplet<SAMPLE> result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift); 00146 00147 return Quad<SAMPLE>(result.R >> _shift, result.G >> _shift, result.B >> _shift, v4); 00148 } 00149 00150 int _shift; 00151 typename TRANSFORM::INVERSE _inverseTransform; 00152 }; 00153 00154 00155 TransformShifted(int shift) : 00156 _shift(shift) 00157 { 00158 } 00159 00160 inlinehint Triplet<SAMPLE> operator() (int R, int G, int B) 00161 { 00162 Triplet<SAMPLE> result = _colortransform(R << _shift, G << _shift, B << _shift); 00163 00164 return Triplet<SAMPLE>(result.R >> _shift, result.G >> _shift, result.B >> _shift); 00165 } 00166 00167 inlinehint Quad<SAMPLE> operator() (int R, int G, int B, int A) 00168 { 00169 Triplet<SAMPLE> result = _colortransform(R << _shift, G << _shift, B << _shift); 00170 00171 return Quad<SAMPLE>(result.R >> _shift, result.G >> _shift, result.B >> _shift, A); 00172 } 00173 00174 int _shift; 00175 TRANSFORM _colortransform; 00176 }; 00177 00178 00179 00180 #endif