2 * copyright (c) 2010 Sveriges Television AB <info@casparcg.com>
\r
4 * This file is part of CasparCG.
\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
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
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
20 // TODO: Move layer specific stuff out of frame related classes.
\r
21 #include "../../stdafx.h"
\r
23 #include "frame_transform.h"
\r
25 #include <common/utility/assert.h>
\r
27 namespace caspar { namespace core {
\r
29 frame_transform::frame_transform()
\r
36 , field_mode(field_mode::progressive)
\r
38 std::fill(fill_translation.begin(), fill_translation.end(), 0.0);
\r
39 std::fill(fill_scale.begin(), fill_scale.end(), 1.0);
\r
40 std::fill(clip_translation.begin(), clip_translation.end(), 0.0);
\r
41 std::fill(clip_scale.begin(), clip_scale.end(), 1.0);
\r
44 frame_transform& frame_transform::operator*=(const frame_transform &other)
\r
46 volume *= other.volume;
\r
47 opacity *= other.opacity;
\r
48 brightness *= other.brightness;
\r
49 contrast *= other.contrast;
\r
50 saturation *= other.saturation;
\r
51 levels.min_input = std::max(levels.min_input, other.levels.min_input);
\r
52 levels.max_input = std::min(levels.max_input, other.levels.max_input);
\r
53 levels.min_output = std::max(levels.min_output, other.levels.min_output);
\r
54 levels.max_output = std::min(levels.max_output, other.levels.max_output);
\r
55 levels.gamma *= other.levels.gamma;
\r
56 field_mode = static_cast<field_mode::type>(field_mode & other.field_mode);
\r
57 is_key |= other.is_key;
\r
58 fill_translation[0] += other.fill_translation[0]*fill_scale[0];
\r
59 fill_translation[1] += other.fill_translation[1]*fill_scale[1];
\r
60 fill_scale[0] *= other.fill_scale[0];
\r
61 fill_scale[1] *= other.fill_scale[1];
\r
62 clip_translation[0] += other.clip_translation[0]*clip_scale[0];
\r
63 clip_translation[1] += other.clip_translation[1]*clip_scale[1];
\r
64 clip_scale[0] *= other.clip_scale[0];
\r
65 clip_scale[1] *= other.clip_scale[1];
\r
69 frame_transform frame_transform::operator*(const frame_transform &other) const
\r
71 return frame_transform(*this) *= other;
\r
74 frame_transform tween(double time, const frame_transform& source, const frame_transform& dest, double duration, const tweener_t& tweener)
\r
76 auto do_tween = [](double time, double source, double dest, double duration, const tweener_t& tweener)
\r
78 return tweener(time, source, dest-source, duration);
\r
81 frame_transform result;
\r
82 result.is_key = source.is_key | dest.is_key;
\r
83 result.field_mode = static_cast<field_mode::type>(source.field_mode & dest.field_mode);
\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
90 result.fill_translation[0] = do_tween(time, source.fill_translation[0], dest.fill_translation[0], duration, tweener),
\r
91 result.fill_translation[1] = do_tween(time, source.fill_translation[1], dest.fill_translation[1], duration, tweener);
\r
93 result.fill_scale[0] = do_tween(time, source.fill_scale[0], dest.fill_scale[0], duration, tweener),
\r
94 result.fill_scale[1] = do_tween(time, source.fill_scale[1], dest.fill_scale[1], duration, tweener);
\r
96 result.clip_translation[0] = do_tween(time, source.clip_translation[0], dest.clip_translation[0], duration, tweener),
\r
97 result.clip_translation[1] = do_tween(time, source.clip_translation[1], dest.clip_translation[1], duration, tweener);
\r
99 result.clip_scale[0] = do_tween(time, source.clip_scale[0], dest.clip_scale[0], duration, tweener),
\r
100 result.clip_scale[1] = do_tween(time, source.clip_scale[1], dest.clip_scale[1], duration, tweener);
\r
102 auto s_levels = source.levels;
\r
103 auto d_levels = dest.levels;
\r
105 result.levels.max_input = do_tween(time, s_levels.max_input, d_levels.max_input, duration, tweener);
\r
106 result.levels.min_input = do_tween(time, s_levels.min_input, d_levels.min_input, duration, tweener);
\r
107 result.levels.max_output = do_tween(time, s_levels.max_output, d_levels.max_output, duration, tweener);
\r
108 result.levels.min_output = do_tween(time, s_levels.min_output, d_levels.min_output, duration, tweener);
\r
109 result.levels.gamma = do_tween(time, s_levels.gamma, d_levels.gamma, duration, tweener);
\r
114 bool operator<(const frame_transform& lhs, const frame_transform& rhs)
\r
116 return memcmp(&lhs, &rhs, sizeof(frame_transform)) < 0;
\r
119 bool operator==(const frame_transform& lhs, const frame_transform& rhs)
\r
121 return memcmp(&lhs, &rhs, sizeof(frame_transform)) == 0;
\r
124 bool operator!=(const frame_transform& lhs, const frame_transform& rhs)
\r
126 return !(lhs == rhs);
\r