// // (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use. // #ifndef CHARLS_COLORTRANSFORM #define CHARLS_COLORTRANSFORM #include "util.h" // This file defines simple classes that define (lossless) color transforms. // They are invoked in processline.h to convert between decoded values and the internal line buffers. // Color transforms work best for computer generated images. // #ifdef _MSC_VER #pragma warning (disable: 4127) // conditional expression is constant (caused by some template methods that are not fully specialized) [VS2013] #endif template struct TransformNoneImpl { typedef sample SAMPLE; inlinehint Triplet operator()(int v1, int v2, int v3) const { return Triplet(v1, v2, v3); } }; template struct TransformNone : TransformNoneImpl { typedef struct TransformNoneImpl INVERSE; }; template struct TransformHp1 { enum { RANGE = 1 << (sizeof(sample) * 8) }; typedef sample SAMPLE; struct INVERSE { explicit INVERSE(const TransformHp1&) {}; inlinehint Triplet operator()(int v1, int v2, int v3) const { return Triplet(v1 + v2 - RANGE / 2, v2, v3 + v2 - RANGE / 2); } }; inlinehint Triplet operator()(int R, int G, int B) const { Triplet hp1; hp1.v2 = SAMPLE(G); hp1.v1 = SAMPLE(R - G + RANGE / 2); hp1.v3 = SAMPLE(B - G + RANGE / 2); return hp1; } }; template struct TransformHp2 { enum { RANGE = 1 << (sizeof(sample) * 8) }; typedef sample SAMPLE; struct INVERSE { explicit INVERSE(const TransformHp2&) {}; inlinehint Triplet operator() (int v1, int v2, int v3) const { Triplet rgb; rgb.R = SAMPLE(v1 + v2 - RANGE / 2); // new R rgb.G = SAMPLE(v2); // new G rgb.B = SAMPLE(v3 + ((rgb.R + rgb.G) >> 1) - RANGE / 2); // new B return rgb; } }; inlinehint Triplet operator()(int R, int G, int B) const { return Triplet(R - G + RANGE / 2, G, B - ((R+G )>>1) - RANGE / 2); } }; template struct TransformHp3 { enum { RANGE = 1 << (sizeof(sample) * 8) }; typedef sample SAMPLE; struct INVERSE { explicit INVERSE(const TransformHp3&) {}; inlinehint Triplet operator()(int v1, int v2, int v3) const { int G = v1 - ((v3 + v2) >> 2) + RANGE / 4; Triplet rgb; rgb.R = SAMPLE(v3 + G - RANGE / 2); // new R rgb.G = SAMPLE(G); // new G rgb.B = SAMPLE(v2 + G - RANGE / 2); // new B return rgb; } }; inlinehint Triplet operator() (int R, int G, int B) const { Triplet hp3; hp3.v2 = SAMPLE(B - G + RANGE / 2); hp3.v3 = SAMPLE(R - G + RANGE / 2); hp3.v1 = SAMPLE(G + ((hp3.v2 + hp3.v3)>>2)) - RANGE / 4; return hp3; } }; // Transform class that shifts bits towards the high bit when bitcount is not 8 or 16 // needed to make the HP color transforms work correctly. template struct TransformShifted { typedef typename TRANSFORM::SAMPLE SAMPLE; struct INVERSE { explicit INVERSE(const TransformShifted& transform) : _shift(transform._shift), _inverseTransform(transform._colortransform) { } inlinehint Triplet operator() (int v1, int v2, int v3) { Triplet result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift); return Triplet(result.R >> _shift, result.G >> _shift, result.B >> _shift); } inlinehint Quad operator() (int v1, int v2, int v3, int v4) { Triplet result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift); return Quad(result.R >> _shift, result.G >> _shift, result.B >> _shift, v4); } int _shift; typename TRANSFORM::INVERSE _inverseTransform; }; explicit TransformShifted(int shift) : _shift(shift) { } inlinehint Triplet operator() (int R, int G, int B) { Triplet result = _colortransform(R << _shift, G << _shift, B << _shift); return Triplet(result.R >> _shift, result.G >> _shift, result.B >> _shift); } inlinehint Quad operator() (int R, int G, int B, int A) { Triplet result = _colortransform(R << _shift, G << _shift, B << _shift); return Quad(result.R >> _shift, result.G >> _shift, result.B >> _shift, A); } int _shift; TRANSFORM _colortransform; }; #endif