diff --git a/Engine/ImageConvert.cpp b/Engine/ImageConvert.cpp index 77cb347f8..a12ad661e 100644 --- a/Engine/ImageConvert.cpp +++ b/Engine/ImageConvert.cpp @@ -115,6 +115,9 @@ lutFromColorspace(ViewerColorSpaceEnum cs) case eViewerColorSpaceRec709: lut = Color::LutManager::Rec709Lut(); break; + case eViewerColorSpaceBT1886: + lut = Color::LutManager::BT1886Lut(); + break; case eViewerColorSpaceLinear: default: lut = 0; diff --git a/Engine/Lut.cpp b/Engine/Lut.cpp index f3aa4ba60..66f557605 100644 --- a/Engine/Lut.cpp +++ b/Engine/Lut.cpp @@ -1293,6 +1293,12 @@ LutManager::sRGBLut() return LutManager::m_instance.getLut("sRGB", from_func_srgb, to_func_srgb); } +const Lut* +LutManager::BT1886Lut() +{ + return LutManager::m_instance.getLut("BT1886", from_func_bt1886, to_func_bt1886); +} + // Rec.709 and Rec.2020 share the same transfer function (and illuminant), except that // Rec.2020 is more precise. // https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2020-0-201208-S!!PDF-E.pdf diff --git a/Engine/Lut.h b/Engine/Lut.h index 6064a9f9b..a1359c2e3 100644 --- a/Engine/Lut.h +++ b/Engine/Lut.h @@ -89,6 +89,7 @@ class LutManager ///buit-ins color-spaces static const Lut* sRGBLut(); static const Lut* Rec709Lut(); + static const Lut* BT1886Lut(); static const Lut* CineonLut(); static const Lut* Gamma1_8Lut(); static const Lut* Gamma2_2Lut(); @@ -496,6 +497,18 @@ to_func_srgb(float v) } } +inline float +from_func_bt1886(float v) +{ + return std::pow(v, 2.4); +} + +inline float +to_func_bt1886(float v) +{ + return std::pow(v, 1.0/2.4); +} + // r,g,b values are from 0 to 1 // h = [0,NATRON_COLOR_HUE_CIRCLE], s = [0,1], v = [0,1] // if s == 0, then h = 0 (undefined) diff --git a/Engine/Project.cpp b/Engine/Project.cpp index 4b30403bc..1f4ffc4b0 100644 --- a/Engine/Project.cpp +++ b/Engine/Project.cpp @@ -1001,6 +1001,7 @@ Project::initializeKnobs() colorSpaces.push_back(ChoiceOption("Linear","","")); colorSpaces.push_back(ChoiceOption("sRGB","","")); colorSpaces.push_back(ChoiceOption("Rec.709","","")); + colorSpaces.push_back(ChoiceOption("BT1886","","")); _imp->colorSpace8u = AppManager::createKnob( this, tr("8-Bit LUT") ); _imp->colorSpace8u->setName("defaultColorSpace8u"); diff --git a/Engine/ViewerInstance.cpp b/Engine/ViewerInstance.cpp index e8b5b5166..bb6de8265 100644 --- a/Engine/ViewerInstance.cpp +++ b/Engine/ViewerInstance.cpp @@ -140,6 +140,9 @@ ViewerInstance::lutFromColorspace(ViewerColorSpaceEnum cs) case eViewerColorSpaceRec709: lut = Color::LutManager::Rec709Lut(); break; + case eViewerColorSpaceBT1886: + lut = Color::LutManager::BT1886Lut(); + break; case eViewerColorSpaceLinear: default: lut = 0; diff --git a/Global/Enums.h b/Global/Enums.h index d8c50a453..fbcb456ff 100644 --- a/Global/Enums.h +++ b/Global/Enums.h @@ -441,7 +441,8 @@ enum ViewerColorSpaceEnum { eViewerColorSpaceSRGB = 0, eViewerColorSpaceLinear, - eViewerColorSpaceRec709 + eViewerColorSpaceRec709, + eViewerColorSpaceBT1886 }; enum ImageBitDepthEnum diff --git a/Gui/Shaders.cpp b/Gui/Shaders.cpp index bfeb855ce..5fe11d0c6 100644 --- a/Gui/Shaders.cpp +++ b/Gui/Shaders.cpp @@ -42,21 +42,31 @@ const char* fragRGB = "float linear_to_rec709(float c) {" " return (c<0.018) ? (4.500*c) : (1.099*pow(c,0.45) - 0.099);\n" "}\n" - "void main(){\n" + "float linear_to_bt1886(float c) {" + " return pow(c,1.0/2.4);\n" + "}\n" + "void main() {\n" " vec4 color_tmp = texture2D(Tex,gl_TexCoord[0].st);\n" " color_tmp.rgb = (color_tmp.rgb * gain) + offset;\n" - " if(lut == 0){ // srgb\n" + " if (lut == 0) { // srgb\n" // << TO SRGB " color_tmp.r = linear_to_srgb(color_tmp.r);\n" " color_tmp.g = linear_to_srgb(color_tmp.g);\n" " color_tmp.b = linear_to_srgb(color_tmp.b);\n" // << END TO SRGB - " }\n" - " else if (lut == 2){ // Rec 709\n" // << TO REC 709 + " } else if (lut == 2) { // Rec 709\n" +// << TO REC 709 " color_tmp.r = linear_to_rec709(color_tmp.r);\n" " color_tmp.g = linear_to_rec709(color_tmp.g);\n" " color_tmp.b = linear_to_rec709(color_tmp.b);\n" - " }\n" // << END TO REC 709 +// << END TO REC 709 + " } else if (lut == 3) { // BT1886\n" +// << TO BT1886 + " color_tmp.r = linear_to_bt1886(color_tmp.r);\n" + " color_tmp.g = linear_to_bt1886(color_tmp.g);\n" + " color_tmp.b = linear_to_bt1886(color_tmp.b);\n" +// << END TO BT1886 + " }\n" " if (gamma <= 0.) {\n" " color_tmp.r = (color_tmp.r >= 1.) ? 1. : 0.;\n" " color_tmp.g = (color_tmp.g >= 1.) ? 1. : 0.;\n" diff --git a/Gui/ViewerTab.cpp b/Gui/ViewerTab.cpp index 42a31876a..8d8b7cd9c 100644 --- a/Gui/ViewerTab.cpp +++ b/Gui/ViewerTab.cpp @@ -528,6 +528,7 @@ ViewerTab::ViewerTab(const std::list & existingNodesContext, _imp->viewerColorSpace->addItem( QString::fromUtf8("Linear(None)") ); _imp->viewerColorSpace->addItem( QString::fromUtf8("sRGB") ); _imp->viewerColorSpace->addItem( QString::fromUtf8("Rec.709") ); + _imp->viewerColorSpace->addItem( QString::fromUtf8("BT1886") ); _imp->viewerColorSpace->setCurrentIndex(1); QPixmap pixCheckerboardEnabled, pixCheckerboardDisabld; diff --git a/Gui/ViewerTab10.cpp b/Gui/ViewerTab10.cpp index 4a6b15328..3832f4c2f 100644 --- a/Gui/ViewerTab10.cpp +++ b/Gui/ViewerTab10.cpp @@ -76,6 +76,8 @@ ViewerTab::onColorSpaceComboBoxChanged(int v) colorspace = eViewerColorSpaceSRGB; } else if (v == 2) { colorspace = eViewerColorSpaceRec709; + } else if (v == 3) { + colorspace = eViewerColorSpaceBT1886; } else { assert(false); throw std::logic_error("ViewerTab::onColorSpaceComboBoxChanged(): unknown colorspace"); diff --git a/Gui/ViewerTab30.cpp b/Gui/ViewerTab30.cpp index 7e3d9c0a1..330d49506 100644 --- a/Gui/ViewerTab30.cpp +++ b/Gui/ViewerTab30.cpp @@ -89,8 +89,11 @@ ViewerTab::getColorSpace() const return "Rec.709"; break; - default: + case eViewerColorSpaceBT1886: + return "BT1886"; + break; + default: return ""; break; }