X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fcolour_conversion.cc;h=5946273e7ca5f67f9b8bc2c5e95167beeaa033cc;hb=2da55dbe6da21975612584365db17db2ae9935b8;hp=59aadf1a865fb28530ed011966b2d9314692c54f;hpb=b223c577907878025ea926caf138f8008ac1c6bf;p=libdcp.git diff --git a/src/colour_conversion.cc b/src/colour_conversion.cc index 59aadf1a..5946273e 100644 --- a/src/colour_conversion.cc +++ b/src/colour_conversion.cc @@ -1,48 +1,71 @@ /* - Copyright (C) 2014 Carl Hetherington + Copyright (C) 2014-2021 Carl Hetherington - This program is free software; you can redistribute it and/or modify + This file is part of libdcp. + + libdcp is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + libdcp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - + along with libdcp. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. */ + +/** @file src/colour_conversion.cc + * @brief ColourConversion class + */ + + #include "colour_conversion.h" #include "gamma_transfer_function.h" #include "modified_gamma_transfer_function.h" -#include "colour_matrix.h" +#include "s_gamut3_transfer_function.h" +#include "identity_transfer_function.h" #include "dcp_assert.h" #include #include #include -using boost::shared_ptr; + +using std::shared_ptr; +using std::make_shared; using boost::optional; using namespace dcp; + ColourConversion const & ColourConversion::srgb_to_xyz () { - static ColourConversion* c = new ColourConversion ( - shared_ptr (new ModifiedGammaTransferFunction (2.4, 0.04045, 0.055, 12.92)), - YUV_TO_RGB_REC601, + static auto c = new ColourConversion ( + make_shared(2.4, 0.04045, 0.055, 12.92), + YUVToRGB::REC601, Chromaticity (0.64, 0.33), Chromaticity (0.3, 0.6), Chromaticity (0.15, 0.06), - /* D65 */ - Chromaticity (0.3127, 0.329), + Chromaticity::D65 (), optional (), - shared_ptr (new GammaTransferFunction (2.6)) + make_shared(2.6) ); return *c; } @@ -50,16 +73,15 @@ ColourConversion::srgb_to_xyz () ColourConversion const & ColourConversion::rec601_to_xyz () { - static ColourConversion* c = new ColourConversion ( - shared_ptr (new ModifiedGammaTransferFunction (1 / 0.45, 0.081, 0.099, 4.5)), - YUV_TO_RGB_REC601, + static auto c = new ColourConversion ( + make_shared(2.2), + YUVToRGB::REC601, Chromaticity (0.64, 0.33), Chromaticity (0.3, 0.6), Chromaticity (0.15, 0.06), - /* D65 */ - Chromaticity (0.3127, 0.329), + Chromaticity::D65 (), optional (), - shared_ptr (new GammaTransferFunction (2.6)) + make_shared(2.6) ); return *c; } @@ -67,20 +89,89 @@ ColourConversion::rec601_to_xyz () ColourConversion const & ColourConversion::rec709_to_xyz () { - static ColourConversion* c = new ColourConversion ( - shared_ptr (new ModifiedGammaTransferFunction (1 / 0.45, 0.081, 0.099, 4.5)), - YUV_TO_RGB_REC709, + static auto c = new ColourConversion ( + make_shared(2.2), + YUVToRGB::REC709, Chromaticity (0.64, 0.33), Chromaticity (0.3, 0.6), Chromaticity (0.15, 0.06), - /* D65 */ - Chromaticity (0.3127, 0.329), + Chromaticity::D65 (), + optional (), + make_shared(2.6) + ); + return *c; +} + +ColourConversion const & +ColourConversion::p3_to_xyz () +{ + static auto c = new ColourConversion ( + make_shared(2.6), + YUVToRGB::REC709, + Chromaticity (0.68, 0.32), + Chromaticity (0.265, 0.69), + Chromaticity (0.15, 0.06), + Chromaticity (0.314, 0.351), optional (), - shared_ptr (new GammaTransferFunction (2.6)) + make_shared(2.6) ); return *c; } +ColourConversion const & +ColourConversion::rec1886_to_xyz () +{ + /* According to Olivier on DCP-o-matic bug #832, Rec. 1886 is Rec. 709 with + 2.4 gamma, so here goes ... + */ + static auto c = new ColourConversion ( + make_shared(2.4), + YUVToRGB::REC709, + Chromaticity (0.64, 0.33), + Chromaticity (0.3, 0.6), + Chromaticity (0.15, 0.06), + Chromaticity::D65 (), + optional (), + make_shared(2.6) + ); + return *c; +} + +ColourConversion const & +ColourConversion::rec2020_to_xyz () +{ + static auto c = new ColourConversion ( + make_shared(2.4), + YUVToRGB::REC2020, + Chromaticity (0.708, 0.292), + Chromaticity (0.170, 0.797), + Chromaticity (0.131, 0.046), + Chromaticity::D65 (), + optional (), + make_shared(2.6) + ); + return *c; +} + +/** Sony S-Gamut3/S-Log3 */ +ColourConversion const & +ColourConversion::s_gamut3_to_xyz () +{ + static auto c = new ColourConversion ( + make_shared(), + YUVToRGB::REC709, + Chromaticity (0.73, 0.280), + Chromaticity (0.140, 0.855), + Chromaticity (0.100, -0.050), + Chromaticity::D65 (), + optional (), + make_shared() + ); + return *c; +} + + + ColourConversion::ColourConversion ( shared_ptr in, YUVToRGB yuv_to_rgb, @@ -100,9 +191,10 @@ ColourConversion::ColourConversion ( , _adjusted_white (adjusted_white) , _out (out) { - + } + bool ColourConversion::about_equal (ColourConversion const & other, float epsilon) const { @@ -112,7 +204,9 @@ ColourConversion::about_equal (ColourConversion const & other, float epsilon) co !_green.about_equal (other._green, epsilon) || !_blue.about_equal (other._blue, epsilon) || !_white.about_equal (other._white, epsilon) || - !_out->about_equal (other._out, epsilon)) { + (!_out && other._out) || + (_out && !other._out) || + (_out && !_out->about_equal (other._out, epsilon))) { return false; } @@ -132,6 +226,7 @@ ColourConversion::about_equal (ColourConversion const & other, float epsilon) co return false; } + boost::numeric::ublas::matrix ColourConversion::rgb_to_xyz () const { @@ -155,13 +250,14 @@ ColourConversion::rgb_to_xyz () const return C; } + boost::numeric::ublas::matrix ColourConversion::xyz_to_rgb () const { - boost::numeric::ublas::matrix A (rgb_to_xyz ()); + boost::numeric::ublas::matrix A (rgb_to_xyz()); /* permutation matrix for the LU-factorization */ - boost::numeric::ublas::permutation_matrix pm (A.size1 ()); + boost::numeric::ublas::permutation_matrix pm (A.size1()); /* perform LU-factorization */ int const r = lu_factorize (A, pm); @@ -169,14 +265,15 @@ ColourConversion::xyz_to_rgb () const /* create identity matrix of inverse */ boost::numeric::ublas::matrix xyz_to_rgb (3, 3); - xyz_to_rgb.assign (boost::numeric::ublas::identity_matrix (A.size1 ())); + xyz_to_rgb.assign (boost::numeric::ublas::identity_matrix (A.size1())); /* backsubstitute to get the inverse */ lu_substitute (A, pm, xyz_to_rgb); - + return xyz_to_rgb; } + boost::numeric::ublas::matrix ColourConversion::bradford () const {