]> git.sesse.net Git - casparcg/blob - modules/image/util/image_view.h
Merged image_scroll_producer changes to 2.1
[casparcg] / modules / image / util / image_view.h
1 /*\r
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 * This file is part of CasparCG (www.casparcg.com).\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 * Author: Helge Norberg, helge.norberg@svt.se\r
20 */\r
21 \r
22 #pragma once\r
23 \r
24 #include <boost/iterator/filter_iterator.hpp>\r
25 \r
26 namespace caspar { namespace image {\r
27 \r
28 /**\r
29  * A POD pixel with a compatible memory layout as a 8bit BGRA pixel (32bits in\r
30  * total).\r
31  * <p>\r
32  * Models the PackedPixel concept used by for example image_view. Also models\r
33  * the RGBAPixel concept which does not care about the order between RGBA but\r
34  * only requires that all 4 channel has accessors.\r
35  */\r
36 class bgra_pixel\r
37 {\r
38         uint8_t b_;\r
39         uint8_t g_;\r
40         uint8_t r_;\r
41         uint8_t a_;\r
42 public:\r
43         bgra_pixel(uint8_t b = 0, uint8_t g = 0, uint8_t r = 0, uint8_t a = 0) : b_(b), g_(g), r_(r), a_(a) {}\r
44         inline const uint8_t& b() const { return b_; }\r
45         inline uint8_t& b() { return b_; }\r
46         inline const uint8_t& g() const { return g_; }\r
47         inline uint8_t& g() { return g_; }\r
48         inline const uint8_t& r() const { return r_; }\r
49         inline uint8_t& r() { return r_; }\r
50         inline const uint8_t& a() const { return a_; }\r
51         inline uint8_t& a() { return a_; }\r
52 };\r
53 \r
54 template<class PackedPixel> class image_sub_view;\r
55 \r
56 /**\r
57  * An image view abstracting raw packed pixel data\r
58  * <p>\r
59  * This is only a view, it does not own the data.\r
60  * <p>\r
61  * Models the the ImageView concept.\r
62  */\r
63 template<class PackedPixel>\r
64 class image_view\r
65 {\r
66 public:\r
67         typedef PackedPixel pixel_type;\r
68 \r
69         image_view(void* raw_start, int width, int height)\r
70                 : begin_(static_cast<PackedPixel*>(raw_start))\r
71                 , end_(begin_ + (width * height))\r
72                 , width_(width)\r
73                 , height_(height)\r
74         {\r
75         }\r
76 \r
77         PackedPixel* begin()\r
78         {\r
79                 return begin_;\r
80         }\r
81 \r
82         const PackedPixel* begin() const\r
83         {\r
84                 return begin_;\r
85         }\r
86 \r
87         PackedPixel* end()\r
88         {\r
89                 return end_;\r
90         }\r
91 \r
92         const PackedPixel* end() const\r
93         {\r
94                 return end_;\r
95         }\r
96 \r
97         template<class PackedPixelIter>\r
98         inline PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y)\r
99         {\r
100                 auto pixel_distance = delta_x + width_ * delta_y;\r
101                 PackedPixel* to_address = &(*to);\r
102                 auto result = to_address + pixel_distance;\r
103 \r
104                 if (result < begin_ || result >= end_)\r
105                         return nullptr;\r
106                 else\r
107                         return result;\r
108         }\r
109 \r
110         template<class PackedPixelIter>\r
111         inline const PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y) const\r
112         {\r
113                 //auto x_distance\r
114                 auto pixel_distance = delta_x + width_ * delta_y;\r
115                 const PackedPixel* to_address = &(*to);\r
116                 auto result = to_address + pixel_distance;\r
117 \r
118                 /*if (delta_x != 0)\r
119                 {\r
120                         auto actual_delta_y = result % width_\r
121                 }*/\r
122 \r
123                 if (result < begin_ || result >= end_)\r
124                         return nullptr;\r
125                 else\r
126                         return result;\r
127         }\r
128 \r
129         int width() const\r
130         {\r
131                 return width_;\r
132         }\r
133 \r
134         int height() const\r
135         {\r
136                 return height_;\r
137         }\r
138 \r
139         image_sub_view<PackedPixel> subview(int x, int y, int width, int height)\r
140         {\r
141                 return image_sub_view<PackedPixel>(*this, x, y, width, height);\r
142         }\r
143 \r
144         const image_sub_view<PackedPixel> subview(int x, int y, int width, int height) const\r
145         {\r
146                 return image_sub_view<PackedPixel>(*this, x, y, width, height);\r
147         }\r
148 private:\r
149         PackedPixel* begin_;\r
150         PackedPixel* end_;\r
151         int width_;\r
152         int height_;\r
153 };\r
154 \r
155 template<class PackedPixel>\r
156 class is_within_view\r
157 {\r
158 public:\r
159         is_within_view(const PackedPixel* begin, int width, int stride)\r
160                 : begin_(begin)\r
161                 , width_(width)\r
162                 , stride_(stride)\r
163                 , no_check_(width == stride)\r
164         {\r
165         }\r
166 \r
167         inline bool operator()(const PackedPixel& pixel) const\r
168         {\r
169                 if (no_check_)\r
170                         return true;\r
171 \r
172                 const PackedPixel* position = &pixel;\r
173                 int distance_from_row_start = (position - begin_) % stride_;\r
174 \r
175                 return distance_from_row_start < width_;\r
176         }\r
177 private:\r
178         const PackedPixel* begin_;\r
179         int width_;\r
180         int stride_;\r
181         bool no_check_;\r
182 };\r
183 \r
184 template <class PackedPixel>\r
185 struct image_stride_iterator : public boost::filter_iterator<is_within_view<PackedPixel>, PackedPixel*>\r
186 {\r
187         image_stride_iterator(PackedPixel* begin, PackedPixel* end, int width, int stride)\r
188                 : boost::filter_iterator<is_within_view<PackedPixel>, PackedPixel*>::filter_iterator(\r
189                         is_within_view<PackedPixel>(begin, width, stride), begin, end)\r
190         {\r
191         }\r
192 };\r
193 \r
194 /**\r
195  * A sub view created from an image_view.\r
196  * <p>\r
197  * This also models the ImageView concept.\r
198  */\r
199 template<class PackedPixel>\r
200 class image_sub_view\r
201 {\r
202 public:\r
203         typedef PackedPixel pixel_type;\r
204 \r
205         image_sub_view(image_view<PackedPixel>& root_view, int x, int y, int width, int height)\r
206                 : root_view_(root_view)\r
207                 , relative_to_root_x_(x)\r
208                 , relative_to_root_y_(y)\r
209                 , width_(width)\r
210                 , height_(height)\r
211                 , raw_begin_(root_view.relative(root_view.begin(), x, y))\r
212                 , raw_end_(root_view.relative(raw_begin_, width - 1, height_ - 1) + 1)\r
213         {\r
214         }\r
215 \r
216         image_stride_iterator<PackedPixel> begin()\r
217         {\r
218                 return image_stride_iterator<PackedPixel>(raw_begin_, raw_end_, width_, root_view_.width());\r
219         }\r
220 \r
221         image_stride_iterator<const PackedPixel> begin() const\r
222         {\r
223                 return image_stride_iterator<const PackedPixel>(raw_begin_, raw_end_, width_, root_view_.width());\r
224         }\r
225 \r
226         image_stride_iterator<PackedPixel> end()\r
227         {\r
228                 return image_stride_iterator<PackedPixel>(raw_end_, raw_end_, width_, root_view_.width());\r
229         }\r
230 \r
231         image_stride_iterator<const PackedPixel> end() const\r
232         {\r
233                 return image_stride_iterator<const PackedPixel>(raw_end_, raw_end_, width_, root_view_.width());\r
234         }\r
235 \r
236         template<class PackedPixelIter>\r
237         PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y)\r
238         {\r
239                 return root_view_.relative(to, delta_x, delta_y);\r
240         }\r
241 \r
242         template<class PackedPixelIter>\r
243         const PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y) const\r
244         {\r
245                 return root_view_.relative(to, delta_x, delta_y);\r
246         }\r
247 \r
248         int width() const\r
249         {\r
250                 return width_;\r
251         }\r
252 \r
253         int height() const\r
254         {\r
255                 return height_;\r
256         }\r
257 \r
258         image_sub_view<PackedPixel> subview(int x, int y, int width, int height)\r
259         {\r
260                 return root_view_.subview(relative_to_root_x_ + x, relative_to_root_y_ + y, width, height);\r
261         }\r
262 \r
263         const image_sub_view<PackedPixel> subview(int x, int y, int width, int height) const\r
264         {\r
265                 return root_view_.subview(relative_to_root_x_ + x, relative_to_root_y_ + y, width, height);\r
266         }\r
267 private:\r
268         image_view<PackedPixel> root_view_;\r
269         int relative_to_root_x_;\r
270         int relative_to_root_y_;\r
271         int width_;\r
272         int height_;\r
273         PackedPixel* raw_begin_;\r
274         PackedPixel* raw_end_;\r
275 };\r
276 \r
277 }}\r