@@ -58,8 +58,9 @@ boost::mutex GammaCurve::cacheMutex;
5858// definitions of static GammaCurve-derivatives' member variables to satisfy the linker
5959SimpleGammaCurvePtr NeutralGammaCurve::instance;
6060SimpleGammaCurvePtr SRGBGammaCurve::instance;
61- GammaCurvePtr ITURBT709GammaCurve::instance;
62- GammaCurvePtr Rec1361GammaCurve::instance;
61+ SimpleGammaCurvePtr BT709GammaCurve::instance;
62+ SimpleGammaCurvePtr BT1361GammaCurve::instance;
63+ SimpleGammaCurvePtr BT2020GammaCurve::instance;
6364
6465/* ******************************************************************************/
6566
@@ -200,53 +201,96 @@ int SRGBGammaCurve::GetTypeId() const
200201
201202/* ******************************************************************************/
202203
203- ITURBT709GammaCurve::ITURBT709GammaCurve () {}
204- GammaCurvePtr ITURBT709GammaCurve ::Get ()
204+ BT709GammaCurve::BT709GammaCurve () {}
205+ SimpleGammaCurvePtr BT709GammaCurve ::Get ()
205206{
206207 if (!instance)
207- instance.reset (new ITURBT709GammaCurve ());
208- return GammaCurvePtr (instance);
208+ instance.reset (new BT709GammaCurve ());
209+ return SimpleGammaCurvePtr (instance);
209210}
210- float ITURBT709GammaCurve ::Encode (float x) const
211+ float BT709GammaCurve ::Encode (float x) const
211212{
212213 if (x < 0 .018f ) return x * 4 .5f ;
213214 else return 1 .099f * pow (x, 0 .45f ) - 0 .099f ;
214215}
215- float ITURBT709GammaCurve ::Decode (float x) const
216+ float BT709GammaCurve ::Decode (float x) const
216217{
218+ // NB: ITU-R BT.709 does not officially specify a decoding transfer function. The following is the actual inverse
219+ // of the implemented transfer function.
217220 if (x < 0 .081f ) return x / 4 .5f ;
218221 else return pow ((x + 0 .099f ) / 1 .099f , 1 .0f /0 .45f );
219222}
220- float ITURBT709GammaCurve ::ApproximateDecodingGamma () const
223+ float BT709GammaCurve ::ApproximateDecodingGamma () const
221224{
222225 return 1 .9f ; // very rough approximation
223226}
227+ int BT709GammaCurve::GetTypeId () const
228+ {
229+ return kPOVList_GammaType_BT709 ;
230+ }
224231
225232/* ******************************************************************************/
226233
227- Rec1361GammaCurve::Rec1361GammaCurve () {}
228- GammaCurvePtr Rec1361GammaCurve ::Get ()
234+ BT1361GammaCurve::BT1361GammaCurve () {}
235+ SimpleGammaCurvePtr BT1361GammaCurve ::Get ()
229236{
230237 if (!instance)
231- instance.reset (new Rec1361GammaCurve ());
232- return GammaCurvePtr (instance);
238+ instance.reset (new BT1361GammaCurve ());
239+ return SimpleGammaCurvePtr (instance);
233240}
234- float Rec1361GammaCurve ::Encode (float x) const
241+ float BT1361GammaCurve ::Encode (float x) const
235242{
236243 if (x < -0 .0045f ) return (1 .099f * pow (-4 *x, 0 .45f ) - 0 .099f ) / 4 ;
237244 else if (x < 0 .018f ) return x * 4 .5f ;
238245 else return 1 .099f * pow (x,0 .45f ) - 0 .099f ;
239246}
240- float Rec1361GammaCurve ::Decode (float x) const
247+ float BT1361GammaCurve ::Decode (float x) const
241248{
242249 if (x < -0 .02025f ) return pow ((4 *x + 0 .099f ) / 1 .099f , 1 .0f /0 .45f ) / -4 ;
243250 else if (x < 0 .081f ) return x / 4 .5f ;
244251 else return pow ((x + 0 .099f ) / 1 .099f , 1 .0f /0 .45f );
245252}
246- float Rec1361GammaCurve ::ApproximateDecodingGamma () const
253+ float BT1361GammaCurve ::ApproximateDecodingGamma () const
247254{
248255 return 1 .9f ; // very rough approximation of the x>0 section
249256}
257+ int BT1361GammaCurve::GetTypeId () const
258+ {
259+ return kPOVList_GammaType_BT1361 ;
260+ }
261+
262+ /* ******************************************************************************/
263+
264+ BT2020GammaCurve::BT2020GammaCurve () {}
265+ SimpleGammaCurvePtr BT2020GammaCurve::Get ()
266+ {
267+ if (!instance)
268+ instance.reset (new BT2020GammaCurve ());
269+ return SimpleGammaCurvePtr (instance);
270+ }
271+ float BT2020GammaCurve::Encode (float x) const
272+ {
273+ // NB: We're using higher-precision coefficients than given in ITU-R BT.2020; note that this is perfectly in
274+ // accordance with the specification, as the numerical values given there are just approximations, and the
275+ // coefficients are instead defined as "the solutions to [a certain set of] simultaneous equations".
276+ if (x < 0 .01805396851080780734f ) return x * 4 .5f ;
277+ else return 1 .09929682680944294035f * pow (x, 0 .45f ) - 0 .09929682680944294035f ;
278+ }
279+ float BT2020GammaCurve::Decode (float x) const
280+ {
281+ // NB: ITU-R BT.2020 does not officially specify a decoding transfer function. The following is the actual inverse
282+ // of the implemented transfer function.
283+ if (x < 0 .08124285829863513301f ) return x / 4 .5f ;
284+ else return pow ((x + 0 .09929682680944294035f ) / 1 .09929682680944294035f , 1 .0f /0 .45f );
285+ }
286+ float BT2020GammaCurve::ApproximateDecodingGamma () const
287+ {
288+ return 1 .9f ; // very rough approximation
289+ }
290+ int BT2020GammaCurve::GetTypeId () const
291+ {
292+ return kPOVList_GammaType_BT2020 ;
293+ }
250294
251295/* ******************************************************************************/
252296
@@ -394,6 +438,9 @@ SimpleGammaCurvePtr GetGammaCurve(GammaTypeId type, float param)
394438 case kPOVList_GammaType_Neutral : return NeutralGammaCurve::Get ();
395439 case kPOVList_GammaType_PowerLaw : return PowerLawGammaCurve::GetByDecodingGamma (param);
396440 case kPOVList_GammaType_SRGB : return SRGBGammaCurve::Get ();
441+ case kPOVList_GammaType_BT709 : return BT709GammaCurve::Get ();
442+ case kPOVList_GammaType_BT1361 : return BT1361GammaCurve::Get ();
443+ case kPOVList_GammaType_BT2020 : return BT2020GammaCurve::Get ();
397444 default : return PowerLawGammaCurve::GetByDecodingGamma (DEFAULT_FILE_GAMMA);
398445 }
399446}
0 commit comments