]> git.sesse.net Git - casparcg/blob - core/producer/frame/image_transform.cpp
2.0. Started with deinterlace framework.
[casparcg] / core / producer / frame / image_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 #include "../../stdafx.h"\r
21 \r
22 #include "image_transform.h"\r
23 \r
24 #include <common/utility/assert.h>\r
25 \r
26 namespace caspar { namespace core {\r
27                 \r
28 image_transform::image_transform() \r
29         : opacity_(1.0)\r
30         , gain_(1.0)\r
31         , mode_(video_mode::invalid)\r
32         , is_key_(false)\r
33         , deinterlace_(false)\r
34 {\r
35         std::fill(fill_translation_.begin(), fill_translation_.end(), 0.0);\r
36         std::fill(fill_scale_.begin(), fill_scale_.end(), 1.0);\r
37         std::fill(clip_translation_.begin(), clip_translation_.end(), 0.0);\r
38         std::fill(clip_scale_.begin(), clip_scale_.end(), 1.0);\r
39 }\r
40 \r
41 void image_transform::set_opacity(double value)\r
42 {\r
43         opacity_ = std::max(value, 0.0);\r
44 }\r
45 \r
46 double image_transform::get_opacity() const\r
47 {\r
48         return opacity_;\r
49 }\r
50 \r
51 void image_transform::set_gain(double value)\r
52 {\r
53         gain_ = std::max(0.0, value);\r
54 }\r
55 \r
56 double image_transform::get_gain() const\r
57 {\r
58         return gain_;\r
59 }\r
60 \r
61 void image_transform::set_fill_translation(double x, double y)\r
62 {\r
63         fill_translation_[0] = x;\r
64         fill_translation_[1] = y;\r
65 }\r
66 \r
67 void image_transform::set_fill_scale(double x, double y)\r
68 {\r
69         fill_scale_[0] = x;\r
70         fill_scale_[1] = y;     \r
71 }\r
72 \r
73 std::array<double, 2> image_transform::get_fill_translation() const\r
74 {\r
75         return fill_translation_;\r
76 }\r
77 \r
78 std::array<double, 2> image_transform::get_fill_scale() const\r
79 {\r
80         return fill_scale_;\r
81 }\r
82 \r
83 void image_transform::set_clip_translation(double x, double y)\r
84 {\r
85         clip_translation_[0] = x;\r
86         clip_translation_[1] = y;\r
87 }\r
88 \r
89 void image_transform::set_clip_scale(double x, double y)\r
90 {\r
91         clip_scale_[0] = x;\r
92         clip_scale_[1] = y;     \r
93 }\r
94 \r
95 std::array<double, 2> image_transform::get_clip_translation() const\r
96 {\r
97         return clip_translation_;\r
98 }\r
99 \r
100 std::array<double, 2> image_transform::get_clip_scale() const\r
101 {\r
102         return clip_scale_;\r
103 }\r
104 \r
105 void image_transform::set_mode(video_mode::type mode)\r
106 {\r
107         mode_ = mode;\r
108 }\r
109 \r
110 video_mode::type image_transform::get_mode() const\r
111 {\r
112         return mode_;\r
113 }\r
114 \r
115 void image_transform::set_deinterlace(bool value)\r
116 {\r
117         deinterlace_ = value;\r
118 }\r
119 \r
120 bool image_transform::get_deinterlace() const\r
121 {\r
122         return deinterlace_;\r
123 }\r
124 \r
125 image_transform& image_transform::operator*=(const image_transform &other)\r
126 {\r
127         opacity_                                *= other.opacity_;\r
128         \r
129         if(other.mode_ != video_mode::invalid)\r
130                 mode_ = other.mode_;\r
131 \r
132         gain_                                   *= other.gain_;\r
133         deinterlace_                    |= other.deinterlace_;\r
134         is_key_                                 |= other.is_key_;\r
135         fill_translation_[0]    += other.fill_translation_[0]*fill_scale_[0];\r
136         fill_translation_[1]    += other.fill_translation_[1]*fill_scale_[1];\r
137         fill_scale_[0]                  *= other.fill_scale_[0];\r
138         fill_scale_[1]                  *= other.fill_scale_[1];\r
139         clip_translation_[0]    += other.clip_translation_[0]*clip_scale_[0];\r
140         clip_translation_[1]    += other.clip_translation_[1]*clip_scale_[1];\r
141         clip_scale_[0]                  *= other.clip_scale_[0];\r
142         clip_scale_[1]                  *= other.clip_scale_[1];\r
143         return *this;\r
144 }\r
145 \r
146 const image_transform image_transform::operator*(const image_transform &other) const\r
147 {\r
148         return image_transform(*this) *= other;\r
149 }\r
150 \r
151 void image_transform::set_is_key(bool value){is_key_ = value;}\r
152 bool image_transform::get_is_key() const{return is_key_;}\r
153 \r
154 image_transform tween(double time, const image_transform& source, const image_transform& dest, double duration, const tweener_t& tweener)\r
155 {       \r
156         auto do_tween = [](double time, double source, double dest, double duration, const tweener_t& tweener)\r
157         {\r
158                 return tweener(time, source, dest-source, duration);\r
159         };\r
160 \r
161         CASPAR_ASSERT(source.get_mode() == dest.get_mode() || source.get_mode() == video_mode::invalid || dest.get_mode() == video_mode::invalid);\r
162 \r
163         image_transform result; \r
164         result.set_mode                         (dest.get_mode() != video_mode::invalid ? dest.get_mode() : source.get_mode());\r
165         result.set_is_key                       (source.get_is_key() | dest.get_is_key());\r
166         result.set_deinterlace          (source.get_deinterlace() | dest.get_deinterlace());\r
167         result.set_gain                         (do_tween(time, source.get_gain(), dest.get_gain(), duration, tweener));\r
168         result.set_opacity                      (do_tween(time, source.get_opacity(), dest.get_opacity(), duration, tweener));\r
169         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
170         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
171         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
172         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
173         \r
174         return result;\r
175 }\r
176 \r
177 }}