]> git.sesse.net Git - casparcg/commitdiff
2.0. image_mixer/amcp: Added LEVELS, SATURATION, BRIGHTNESS, CONTRAST.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Mon, 27 Jun 2011 09:27:45 +0000 (09:27 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Mon, 27 Jun 2011 09:27:45 +0000 (09:27 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@959 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

core/mixer/gpu/shader.cpp
core/mixer/gpu/shader.h
core/mixer/image/image_kernel.cpp
core/producer/frame/image_transform.cpp
core/producer/frame/image_transform.h
protocol/amcp/AMCPCommandsImpl.cpp

index ca5a7f55957107c45991c0dc3fc9fe0974b88a17..8d2f098debc1bc4796c6498ca273a9c2ceb85ea7 100644 (file)
@@ -104,6 +104,11 @@ public:
        {\r
                GL(glUniform1f(get_location(name.c_str()), value));\r
        }\r
+\r
+       void set(const std::string& name, double value)\r
+       {\r
+               GL(glUniform1f(get_location(name.c_str()), static_cast<float>(value)));\r
+       }\r
 };\r
 \r
 \r
@@ -111,5 +116,6 @@ shader::shader(const std::string& vertex_source_str, const std::string& fragment
 void shader::use(){impl_->use();}\r
 void shader::set(const std::string& name, int value){impl_->set(name, value);}\r
 void shader::set(const std::string& name, float value){impl_->set(name, value);}\r
+void shader::set(const std::string& name, double value){impl_->set(name, value);}\r
 \r
 }}
\ No newline at end of file
index 08e8697a27d37a00fc8d8e64ff58c8f5e05d51aa..caea024b9af1e995d3cecba5c67c2e16f6d92866 100644 (file)
@@ -15,6 +15,7 @@ public:
        void use();\r
        void set(const std::string& name, int value);\r
        void set(const std::string& name, float value);\r
+       void set(const std::string& name, double value);\r
 private:\r
        struct implementation;\r
        safe_ptr<implementation> impl_;\r
index 322c3e0ba7d93414467e8b513e1b60175656002d..c5bade3910401f25f79f12d12083ed436145cf27 100644 (file)
@@ -79,8 +79,6 @@ struct image_kernel::implementation : boost::noncopyable
                        "uniform float          sat;                                                                                                                    \n"\r
                        "uniform float          con;                                                                                                                    \n"\r
                        "                                                                                                                                                                       \n"\r
-                       "uniform bool           desaturate;                                                                                                             \n"\r
-                       "uniform float          desaturation;                                                                                                   \n"\r
 \r
                        +\r
 \r
@@ -128,14 +126,14 @@ struct image_kernel::implementation : boost::noncopyable
                        "                                                                                                                                                                       \n"                                                                                                                                                       \r
                        "vec4 blend_color(vec4 fore)                                                                                                            \n"\r
                        "{                                                                                                                                                                      \n"\r
+                       "   fore.rgb = fore.bgr; // bgr to rgb                                                                                          \n"\r
                        "   vec4 back = texture2D(background, gl_TexCoord[1].st);                                                       \n"\r
-                       "   if(desaturate)                                                                                                                                      \n"\r
-                       "               fore.rgb = Desaturate(fore.rgb, desaturation);                                                          \n"\r
                        "   if(levels)                                                                                                                                          \n"\r
                        "               fore.rgb = LevelsControl(fore.rgb, min_input, max_input, gamma, min_output, max_output); \n"\r
                        "       if(csb)                                                                                                                                                 \n"\r
                        "               fore.rgb = ContrastSaturationBrightness(fore.rgb, brt, sat, con);                       \n"\r
-                       "   fore.rgb = get_blend_color(back.rgb, fore.rgb);                                                                     \n"\r
+                       "   fore.rgb = get_blend_color(back.bgr, fore.rgb);                                                                     \n"\r
+                       "   fore.rgb = fore.bgr; // rgb to bgr                                                                                          \n"\r
                        "       return vec4(fore.rgb * fore.a + back.rgb * (1.0-fore.a), back.a + fore.a);              \n"\r
                        "}                                                                                                                                                                      \n"\r
                        "                                                                                                                                                                       \n"\r
@@ -290,7 +288,7 @@ struct image_kernel::implementation : boost::noncopyable
                shader_->set("local_key",               4);\r
                shader_->set("layer_key",               5);\r
                shader_->set("background",              6);\r
-               shader_->set("gain",                    static_cast<GLfloat>(transform.get_gain()));\r
+               shader_->set("gain",                    transform.get_gain());\r
                shader_->set("is_hd",                   pix_desc.planes.at(0).height > 700 ? 1 : 0);\r
                shader_->set("has_local_key",   local_key ? 1 : 0);\r
                shader_->set("has_layer_key",   layer_key ? 1 : 0);\r
@@ -298,10 +296,37 @@ struct image_kernel::implementation : boost::noncopyable
                shader_->set("interlace_mode",  transform.get_mode());\r
                shader_->set("pixel_format",    pix_desc.pix_fmt);      \r
 \r
-               shader_->set("levels",                  false); \r
-               shader_->set("csb",                             false); \r
-               shader_->set("desaturate",              false); \r
+               auto levels = transform.get_levels();\r
 \r
+               if(levels.min_input  > 0.001 ||\r
+                  levels.max_input  < 0.999 ||\r
+                  levels.min_output > 0.001 ||\r
+                  levels.max_output < 0.999 ||\r
+                  std::abs(levels.gamma - 1.0) > 0.001)\r
+               {\r
+                       shader_->set("levels", true);   \r
+                       shader_->set("min_input", levels.min_input);    \r
+                       shader_->set("max_input", levels.max_input);\r
+                       shader_->set("min_output", levels.min_output);\r
+                       shader_->set("max_output", levels.max_output);\r
+                       shader_->set("gamma", levels.gamma);\r
+               }\r
+               else\r
+                       shader_->set("levels", false);  \r
+\r
+               if(std::abs(transform.get_brightness() - 1.0) > 0.001 ||\r
+                  std::abs(transform.get_saturation() - 1.0) > 0.001 ||\r
+                  std::abs(transform.get_contrast() - 1.0) > 0.001)\r
+               {\r
+                       shader_->set("csb",     true);  \r
+                       \r
+                       shader_->set("brt", transform.get_brightness());        \r
+                       shader_->set("sat", transform.get_saturation());\r
+                       shader_->set("con", transform.get_contrast());\r
+               }\r
+               else\r
+                       shader_->set("csb",     false); \r
+               \r
                // Setup drawing area\r
 \r
                GL(glColor4d(1.0, 1.0, 1.0, transform.get_opacity()));\r
index c23a57b9412e0a007e72462c12d6c93f4cb583a7..a51c6f00e5bfe831a6b8d104066cd9132a7baa83 100644 (file)
@@ -30,6 +30,9 @@ namespace caspar { namespace core {
 image_transform::image_transform() \r
        : opacity_(1.0)\r
        , gain_(1.0)\r
+       , brightness_(1.0)\r
+       , contrast_(1.0)\r
+       , saturation_(1.0)\r
        , mode_(video_mode::invalid)\r
        , is_key_(false)\r
        , deinterlace_(false)\r
@@ -61,6 +64,47 @@ double image_transform::get_gain() const
        return gain_;\r
 }\r
 \r
+void image_transform::set_brightness(double value)\r
+{\r
+       brightness_ = std::max(0.0, value);\r
+}\r
+\r
+double image_transform::get_brightness() const\r
+{\r
+       return brightness_;\r
+}\r
+\r
+void image_transform::set_contrast(double value)\r
+{\r
+       contrast_ = std::max(0.0, value);\r
+}\r
+\r
+double image_transform::get_contrast() const\r
+{\r
+       return contrast_;\r
+}\r
+\r
+void image_transform::set_saturation(double value)\r
+{\r
+       saturation_ = std::max(0.0, value);\r
+}\r
+\r
+double image_transform::get_saturation() const\r
+{\r
+       return saturation_;\r
+}\r
+\r
+void image_transform::set_levels(const image_transform::levels& value)\r
+{\r
+       levels_ = value;\r
+}\r
+\r
+image_transform::levels image_transform::get_levels() const\r
+{\r
+       return levels_;\r
+}\r
+\r
+\r
 void image_transform::set_fill_translation(double x, double y)\r
 {\r
        fill_translation_[0] = x;\r
@@ -144,6 +188,18 @@ image_transform& image_transform::operator*=(const image_transform &other)
 \r
        blend_mode_                              = std::max(blend_mode_, other.blend_mode_);\r
        gain_                                   *= other.gain_;\r
+       brightness_                             *= other.brightness_;\r
+       contrast_                               *= other.contrast_;\r
+       saturation_                             *= other.saturation_;\r
+\r
+       levels_.min_input               = std::max(levels_.min_input, other.levels_.min_input);\r
+       levels_.max_input               = std::min(levels_.max_input, other.levels_.max_input);\r
+       \r
+       levels_.min_output              = std::max(levels_.min_output, other.levels_.min_output);\r
+       levels_.max_output              = std::min(levels_.max_output, other.levels_.max_output);\r
+\r
+       levels_.gamma                   *= other.levels_.gamma;\r
+\r
        deinterlace_                    |= other.deinterlace_;\r
        is_key_                                 |= other.is_key_;\r
        fill_translation_[0]    += other.fill_translation_[0]*fill_scale_[0];\r
@@ -180,12 +236,28 @@ image_transform tween(double time, const image_transform& source, const image_tr
        result.set_is_key                       (source.get_is_key() | dest.get_is_key());\r
        result.set_deinterlace          (source.get_deinterlace() | dest.get_deinterlace());\r
        result.set_gain                         (do_tween(time, source.get_gain(), dest.get_gain(), duration, tweener));\r
+       result.set_brightness           (do_tween(time, source.get_brightness(), dest.get_brightness(), duration, tweener));\r
+       result.set_contrast                     (do_tween(time, source.get_contrast(), dest.get_contrast(), duration, tweener));\r
+       result.set_saturation           (do_tween(time, source.get_saturation(), dest.get_saturation(), duration, tweener));\r
        result.set_opacity                      (do_tween(time, source.get_opacity(), dest.get_opacity(), duration, tweener));\r
        result.set_fill_translation     (do_tween(time, source.get_fill_translation()[0], dest.get_fill_translation()[0], duration, tweener), do_tween(time, source.get_fill_translation()[1], dest.get_fill_translation()[1], duration, tweener));\r
        result.set_fill_scale           (do_tween(time, source.get_fill_scale()[0], dest.get_fill_scale()[0], duration, tweener), do_tween(time, source.get_fill_scale()[1], dest.get_fill_scale()[1], duration, tweener));\r
        result.set_clip_translation     (do_tween(time, source.get_clip_translation()[0], dest.get_clip_translation()[0], duration, tweener), do_tween(time, source.get_clip_translation()[1], dest.get_clip_translation()[1], duration, tweener));\r
        result.set_clip_scale           (do_tween(time, source.get_clip_scale()[0], dest.get_clip_scale()[0], duration, tweener), do_tween(time, source.get_clip_scale()[1], dest.get_clip_scale()[1], duration, tweener));\r
        \r
+       auto s_levels = source.get_levels();\r
+       auto d_levels = dest.get_levels();\r
+\r
+       d_levels.max_input = do_tween(time, s_levels.max_input, d_levels.max_input, duration, tweener);\r
+       d_levels.min_input = do_tween(time, s_levels.min_input, d_levels.min_input, duration, tweener);\r
+       \r
+       d_levels.max_output = do_tween(time, s_levels.max_output, d_levels.max_output, duration, tweener);\r
+       d_levels.min_output = do_tween(time, s_levels.min_output, d_levels.min_output, duration, tweener);\r
+\r
+       d_levels.gamma = do_tween(time, s_levels.gamma, d_levels.gamma, duration, tweener);\r
+\r
+       result.set_levels(d_levels);\r
+\r
        return result;\r
 }\r
 \r
@@ -241,8 +313,8 @@ image_transform::blend_mode get_blend_mode(const std::wstring& str)
                return image_transform::glow;\r
        else if(boost::iequals(str, L"phoenix"))\r
                return image_transform::phoenix;\r
-       else if(boost::iequals(str, L"hue"))\r
-               return image_transform::hue;\r
+       else if(boost::iequals(str, L"contrast"))\r
+               return image_transform::contrast;\r
        else if(boost::iequals(str, L"saturation"))\r
                return image_transform::saturation;\r
        else if(boost::iequals(str, L"color"))\r
index fc078978e64d559163fa115aa7c42871a7fcc881..4d3038cad44dde42c1e7c05aeec3ceb0d9974dec 100644 (file)
@@ -32,7 +32,7 @@ struct pixel_format_desc;
 class image_transform \r
 {\r
 public:\r
-\r
+       \r
        enum blend_mode\r
        {\r
                normal = 0,\r
@@ -60,13 +60,30 @@ public:
                reflect,\r
                glow,\r
                phoenix,\r
-               hue,\r
+               contrast,\r
                saturation,\r
                color,\r
                luminosity,\r
                blend_mode_count \r
        };\r
 \r
+       struct levels\r
+       {\r
+               levels() \r
+                       : min_input(0.0)\r
+                       , max_input(1.0)\r
+                       , gamma(1.0)\r
+                       , min_output(0.0)\r
+                       , max_output(1.0)\r
+               {               \r
+               }\r
+               double min_input;\r
+               double max_input;\r
+               double gamma;\r
+               double min_output;\r
+               double max_output;\r
+       };\r
+\r
        image_transform();\r
 \r
        void set_opacity(double value);\r
@@ -74,6 +91,18 @@ public:
 \r
        void set_gain(double value);\r
        double get_gain() const;\r
+\r
+       void set_brightness(double value);\r
+       double get_brightness() const;\r
+\r
+       void set_contrast(double value);\r
+       double get_contrast() const;\r
+\r
+       void set_saturation(double value);\r
+       double get_saturation() const;\r
+       \r
+       void set_levels(const levels& value);\r
+       levels get_levels() const;\r
        \r
        void set_fill_translation(double x, double y);\r
        std::array<double, 2> get_fill_translation() const;\r
@@ -105,6 +134,11 @@ public:
 private:\r
        double opacity_;\r
        double gain_;\r
+       double contrast_;\r
+       double brightness_;\r
+       double saturation_;\r
+       double desaturation_;\r
+       levels levels_;\r
        std::array<double, 2> fill_translation_; \r
        std::array<double, 2> fill_scale_; \r
        std::array<double, 2> clip_translation_; \r
index a6c2acc1a5f64d945ef18e7358849acb1961291b..d84e6148dadf9522a5312947c0e797d7fc0e78db 100644 (file)
@@ -316,6 +316,7 @@ bool MixerCommand::DoExecute()
                        else if(_parameters[1] == L"BLEND")\r
                        {\r
                                auto blend_str = _parameters.at(2);\r
+\r
                                auto transform = [=](image_transform transform) -> image_transform\r
                                {\r
                                        transform.set_blend_mode(get_blend_mode(blend_str));\r
@@ -323,7 +324,69 @@ bool MixerCommand::DoExecute()
                                };\r
                                \r
                                int layer = GetLayerIndex();\r
-                               GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, 0);    \r
+                               GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform);       \r
+                       }\r
+                       else if(_parameters[1] == L"BRIGHTNESS")\r
+                       {\r
+                               auto value = boost::lexical_cast<double>(_parameters.at(2));\r
+                               int duration = _parameters.size() > 3 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 4 ? _parameters[4] : L"linear";\r
+                               auto transform = [=](image_transform transform) -> image_transform\r
+                               {\r
+                                       transform.set_brightness(value);\r
+                                       return transform;\r
+                               };\r
+                               \r
+                               int layer = GetLayerIndex();\r
+                               GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, duration, tween);      \r
+                       }\r
+                       else if(_parameters[1] == L"SATURATION")\r
+                       {\r
+                               auto value = boost::lexical_cast<double>(_parameters.at(2));\r
+                               int duration = _parameters.size() > 3 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 4 ? _parameters[4] : L"linear";\r
+                               auto transform = [=](image_transform transform) -> image_transform\r
+                               {\r
+                                       transform.set_saturation(value);\r
+                                       return transform;\r
+                               };\r
+                               \r
+                               int layer = GetLayerIndex();\r
+                               GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, duration, tween);      \r
+                       }\r
+                       else if(_parameters[1] == L"CONTRAST")\r
+                       {\r
+                               auto value = boost::lexical_cast<double>(_parameters.at(2));\r
+                               int duration = _parameters.size() > 3 ? lexical_cast_or_default(_parameters[3], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 4 ? _parameters[4] : L"linear";\r
+                               auto transform = [=](image_transform transform) -> image_transform\r
+                               {\r
+                                       transform.set_contrast(value);\r
+                                       return transform;\r
+                               };\r
+                               \r
+                               int layer = GetLayerIndex();\r
+                               GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, duration, tween);      \r
+                       }\r
+                       else if(_parameters[1] == L"LEVELS")\r
+                       {\r
+                               image_transform::levels value;\r
+                               value.min_input  = boost::lexical_cast<double>(_parameters.at(2));\r
+                               value.max_input  = boost::lexical_cast<double>(_parameters.at(3));\r
+                               value.gamma              = boost::lexical_cast<double>(_parameters.at(4));\r
+                               value.min_output = boost::lexical_cast<double>(_parameters.at(5));\r
+                               value.max_output = boost::lexical_cast<double>(_parameters.at(6));\r
+                               int duration = _parameters.size() > 7 ? lexical_cast_or_default(_parameters[7], 0) : 0;\r
+                               std::wstring tween = _parameters.size() > 8 ? _parameters[8] : L"linear";\r
+\r
+                               auto transform = [=](image_transform transform) -> image_transform\r
+                               {\r
+                                       transform.set_levels(value);\r
+                                       return transform;\r
+                               };\r
+                               \r
+                               int layer = GetLayerIndex();\r
+                               GetChannel()->mixer()->apply_image_transform(GetLayerIndex(), transform, duration, tween);      \r
                        }\r
                        else if(_parameters[1] == L"RESET")\r
                        {\r