]> git.sesse.net Git - casparcg/blob - core/producer/frame/frame_transform.cpp
2.0. Fixed mix transition.
[casparcg] / core / producer / frame / frame_transform.cpp
1 /*\r
2 * copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 *  This file is part of CasparCG.\r
5 *\r
6 *    CasparCG is free software: you can redistribute it and/or modify\r
7 *    it under the terms of the GNU General Public License as published by\r
8 *    the Free Software Foundation, either version 3 of the License, or\r
9 *    (at your option) any later version.\r
10 *\r
11 *    CasparCG is distributed in the hope that it will be useful,\r
12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 *    GNU General Public License for more details.\r
15 \r
16 *    You should have received a copy of the GNU General Public License\r
17 *    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 */\r
20 // TODO: Move layer specific stuff out of frame related classes.\r
21 #include "../../stdafx.h"\r
22 \r
23 #include "frame_transform.h"\r
24 \r
25 #include <common/utility/assert.h>\r
26 \r
27 namespace caspar { namespace core {\r
28                 \r
29 frame_transform::frame_transform() \r
30         : volume(1.0)\r
31         , opacity(1.0)\r
32         , brightness(1.0)\r
33         , contrast(1.0)\r
34         , saturation(1.0)\r
35         , field_mode(field_mode::progressive)\r
36         , is_key(false)\r
37         , is_mix(false)\r
38 {\r
39         std::fill(fill_translation.begin(), fill_translation.end(), 0.0);\r
40         std::fill(fill_scale.begin(), fill_scale.end(), 1.0);\r
41         std::fill(clip_translation.begin(), clip_translation.end(), 0.0);\r
42         std::fill(clip_scale.begin(), clip_scale.end(), 1.0);\r
43 }\r
44 \r
45 frame_transform& frame_transform::operator*=(const frame_transform &other)\r
46 {\r
47         volume                                  *= other.volume;\r
48         opacity                                 *= other.opacity;       \r
49         brightness                              *= other.brightness;\r
50         contrast                                *= other.contrast;\r
51         saturation                              *= other.saturation;\r
52         fill_translation[0]             += other.fill_translation[0]*fill_scale[0];\r
53         fill_translation[1]             += other.fill_translation[1]*fill_scale[1];\r
54         fill_scale[0]                   *= other.fill_scale[0];\r
55         fill_scale[1]                   *= other.fill_scale[1];\r
56         clip_translation[0]             += other.clip_translation[0]*clip_scale[0];\r
57         clip_translation[1]             += other.clip_translation[1]*clip_scale[1];\r
58         clip_scale[0]                   *= other.clip_scale[0];\r
59         clip_scale[1]                   *= other.clip_scale[1];\r
60         levels.min_input                 = std::max(levels.min_input,  other.levels.min_input);\r
61         levels.max_input                 = std::min(levels.max_input,  other.levels.max_input); \r
62         levels.min_output                = std::max(levels.min_output, other.levels.min_output);\r
63         levels.max_output                = std::min(levels.max_output, other.levels.max_output);\r
64         levels.gamma                    *= other.levels.gamma;\r
65         field_mode                               = static_cast<field_mode::type>(field_mode & other.field_mode);\r
66         is_key                                  |= other.is_key;\r
67         is_mix                                  |= other.is_mix;\r
68         return *this;\r
69 }\r
70 \r
71 frame_transform frame_transform::operator*(const frame_transform &other) const\r
72 {\r
73         return frame_transform(*this) *= other;\r
74 }\r
75 \r
76 frame_transform tween(double time, const frame_transform& source, const frame_transform& dest, double duration, const tweener_t& tweener)\r
77 {       \r
78         auto do_tween = [](double time, double source, double dest, double duration, const tweener_t& tweener)\r
79         {\r
80                 return tweener(time, source, dest-source, duration);\r
81         };\r
82         \r
83         frame_transform result; \r
84         result.volume                           = do_tween(time, source.volume,                                 dest.volume,                            duration, tweener);\r
85         result.brightness                       = do_tween(time, source.brightness,                             dest.brightness,                        duration, tweener);\r
86         result.contrast                         = do_tween(time, source.contrast,                               dest.contrast,                          duration, tweener);\r
87         result.saturation                       = do_tween(time, source.saturation,                             dest.saturation,                        duration, tweener);\r
88         result.opacity                          = do_tween(time, source.opacity,                                dest.opacity,                           duration, tweener);     \r
89         result.fill_translation[0]      = do_tween(time, source.fill_translation[0],    dest.fill_translation[0],       duration, tweener), \r
90         result.fill_translation[1]      = do_tween(time, source.fill_translation[1],    dest.fill_translation[1],       duration, tweener);             \r
91         result.fill_scale[0]            = do_tween(time, source.fill_scale[0],                  dest.fill_scale[0],                     duration, tweener), \r
92         result.fill_scale[1]            = do_tween(time, source.fill_scale[1],                  dest.fill_scale[1],                     duration, tweener);     \r
93         result.clip_translation[0]      = do_tween(time, source.clip_translation[0],    dest.clip_translation[0],       duration, tweener), \r
94         result.clip_translation[1]      = do_tween(time, source.clip_translation[1],    dest.clip_translation[1],       duration, tweener);             \r
95         result.clip_scale[0]            = do_tween(time, source.clip_scale[0],                  dest.clip_scale[0],                     duration, tweener), \r
96         result.clip_scale[1]            = do_tween(time, source.clip_scale[1],                  dest.clip_scale[1],                     duration, tweener);\r
97         result.levels.max_input         = do_tween(time, source.levels.max_input,               dest.levels.max_input,          duration, tweener);\r
98         result.levels.min_input         = do_tween(time, source.levels.min_input,               dest.levels.min_input,          duration, tweener);     \r
99         result.levels.max_output        = do_tween(time, source.levels.max_output,              dest.levels.max_output,         duration, tweener);\r
100         result.levels.min_output        = do_tween(time, source.levels.min_output,              dest.levels.min_output,         duration, tweener);\r
101         result.levels.gamma                     = do_tween(time, source.levels.gamma,                   dest.levels.gamma,                      duration, tweener);\r
102         result.field_mode                       = static_cast<field_mode::type>(source.field_mode & dest.field_mode);\r
103         result.is_key                           = source.is_key | dest.is_key;\r
104         result.is_mix                           = source.is_mix | dest.is_mix;\r
105         \r
106         return result;\r
107 }\r
108 \r
109 bool operator<(const frame_transform& lhs, const frame_transform& rhs)\r
110 {\r
111         return memcmp(&lhs, &rhs, sizeof(frame_transform)) < 0;\r
112 }\r
113 \r
114 bool operator==(const frame_transform& lhs, const frame_transform& rhs)\r
115 {\r
116         return memcmp(&lhs, &rhs, sizeof(frame_transform)) == 0;\r
117 }\r
118 \r
119 bool operator!=(const frame_transform& lhs, const frame_transform& rhs)\r
120 {\r
121         return !(lhs == rhs);\r
122 }\r
123 \r
124 }}