Yuv12Image.h
1 /* Copyright (C) 2016 Marc Boris Duerner
2 
3  This library is free software; you can redistribute it and/or
4  modify it under the terms of the GNU Lesser General Public
5  License as published by the Free Software Foundation; either
6  version 2.1 of the License, or (at your option) any later version.
7 
8  As a special exception, you may use this file as part of a free
9  software library without restriction. Specifically, if other files
10  instantiate templates or use macros or inline functions from this
11  file, or you compile this file and link it with other files to
12  produce an executable, this file does not by itself cause the
13  resulting executable to be covered by the GNU General Public
14  License. This exception does not however invalidate any other
15  reasons why the executable file might be covered by the GNU Library
16  General Public License.
17 
18  This library is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  Lesser General Public License for more details.
22 
23  You should have received a copy of the GNU Lesser General Public
24  License along with this library; if not, write to the Free Software
25  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26  02110-1301 USA
27 */
28 
29 #ifndef PT_GFX_YUV12IMAGE_H
30 #define PT_GFX_YUV12IMAGE_H
31 
32 #include <Pt/Gfx/Api.h>
33 #include <Pt/Gfx/Color.h>
34 #include <Pt/Gfx/CompositionMode.h>
35 #include <Pt/Gfx/BasicImage.h>
36 #include <Pt/Types.h>
37 
38 namespace Pt {
39 
40 namespace Gfx {
41 
45 {
46  public:
47  class Pixel;
48  class ConstPixel;
49 
50  static std::size_t imageSize(const Size& size, Pt::ssize_t padding)
51  {
52  Pt::ssize_t stride = size.width() + padding;
53  Pt::ssize_t planeSize = stride * size.height();
54 
55  return planeSize + planeSize / 2;
56  }
57 
58  static Pt::ssize_t pixelStride()
59  {
60  return 1;
61  }
62 
63  public:
64  static Color toColor(Pt::uint8_t y, Pt::uint8_t u, Pt::uint8_t v)
65  {
66  Pt::uint32_t rv = 298 * (y - 16) + 409 * (v - 128) + 128;
67  Pt::uint32_t gv = 298 * (y - 16) - 100 * (u - 128) - 208 * (v - 128) + 128;
68  Pt::uint32_t bv = 298 * (y - 16) + 516 * (u - 128) + 128;
69 
70  Pt::uint16_t r = rv > 65535 ? 65535 : static_cast<Pt::uint16_t>(rv);
71  Pt::uint16_t g = gv > 65535 ? 65535 : static_cast<Pt::uint16_t>(gv);
72  Pt::uint16_t b = bv > 65535 ? 65535 : static_cast<Pt::uint16_t>(bv);
73 
74  return Color(r, g, b);
75  }
76 
77  static void fromColor(Pt::uint8_t& y, Pt::uint8_t& u, Pt::uint8_t& v,
78  const Color& color)
79  {
80  Pt::int32_t r = color.red();
81  Pt::int32_t g = color.green();
82  Pt::int32_t b = color.blue();
83 
84  Pt::int32_t yy = (( 66 * r + 129 * g + 25 * b + 128) >> 16) + 16;
85  Pt::int32_t uu = ((-38 * r - 74 * g + 112 * b + 128) >> 16) + 128;
86  Pt::int32_t vv = ((112 * r - 94 * g - 18 * b + 128) >> 16) + 128;
87 
88  y = yy > 255 ? 255 : static_cast<Pt::uint8_t>(yy);
89  u = uu > 255 ? 255 : static_cast<Pt::uint8_t>(uu);
90  v = vv > 255 ? 255 : static_cast<Pt::uint8_t>(vv);
91  }
92 
93  template <typename T>
94  static Pt::ssize_t init(T* data, Pt::ssize_t stride, const Size& size,
95  Pt::ssize_t xpos, Pt::ssize_t ypos,
96  T*& y, T*& u, T*& v)
97  {
98  Pt::ssize_t yOffset = stride * ypos + xpos;
99  y = data + yOffset;
100 
101  return init(data, stride, size, xpos, ypos, u, v);
102  }
103 
104  template <typename T>
105  static Pt::ssize_t init(T* data, Pt::ssize_t stride, const Size& size,
106  Pt::ssize_t xpos, Pt::ssize_t ypos,
107  T*& u, T*& v)
108  {
109  Pt::ssize_t planeSize = stride * size.height();
110 
111  Pt::ssize_t subStride = stride / 2;
112  Pt::ssize_t subPlaneSize = planeSize / 4;
113 
114  Pt::ssize_t subXPos = xpos / 2;
115  Pt::ssize_t subYPos = ypos / 2;
116  Pt::ssize_t subOffset = subStride * subYPos + subXPos;
117 
118  Pt::ssize_t uOffset = planeSize + subOffset;
119  u = data + uOffset;
120 
121  Pt::ssize_t vOffset = uOffset + subPlaneSize;
122  v = data + vOffset;
123 
124  return subStride;
125  }
126 
127  template <typename T>
128  static void advance(T*& y, T*& u, T*& v,
129  Pt::ssize_t& xpos, Pt::ssize_t& ypos,
130  T* data, Pt::ssize_t stride, const Size& size,
131  Pt::ssize_t padding, Pt::ssize_t subStride)
132  {
133  ++y;
134 
135  if( ++xpos >= size.width() )
136  {
137  ++u;
138  ++v;
139 
140  if(ypos % 2 == 0)
141  {
142  u -= subStride;
143  v -= subStride;
144  }
145 
146  xpos = 0;
147  ++ypos;
148 
149  y += padding;
150  }
151  else if(xpos % 2 == 0)
152  {
153  ++u;
154  ++v;
155  }
156  }
157 
158  template <typename T>
159  static void advance(T*& y, T*& u, T*& v, Pt::ssize_t n,
160  Pt::ssize_t& xpos, Pt::ssize_t& ypos,
161  T* data, Pt::ssize_t stride, const Size& size)
162  {
163  Pt::ssize_t off = xpos + n;
164  ypos += off / size.width();
165  xpos = off % size.width();
166 
167  init(data, stride, size,xpos, ypos, y, u, v);
168  }
169 };
170 
174 {
175  public:
176  ConstPixel(const BasicView<Yuv12Model>& view, Pt::ssize_t xpos, Pt::ssize_t ypos)
177  : _view(0)
178  , _xpos(0)
179  , _ypos(0)
180  , _subStride(0)
181  , _y(0)
182  , _u(0)
183  , _v(0)
184  {
185  reset(view, xpos, ypos);
186  }
187 
188  ConstPixel(const ConstPixel& p)
189  : _view(p._view)
190  , _xpos(p._xpos)
191  , _ypos(p._ypos)
192  , _subStride(p._subStride)
193  , _y(p._y)
194  , _u(p._u)
195  , _v(p._v)
196  { }
197 
198  void reset(const BasicView<Yuv12Model>& view, Pt::ssize_t xpos, Pt::ssize_t ypos)
199  {
200  _view = &view;
201  _xpos = xpos;
202  _ypos = ypos;
203 
204  _subStride = Yuv12Model::init(view.data(), view.stride(), view.size(), xpos, ypos, _y, _u, _v);
205  }
206 
207  void reset(const ConstPixel& p)
208  {
209  _view = p._view;
210  _xpos = p._xpos;
211  _ypos = p._ypos;
212  _subStride = p._subStride;
213 
214  _y = p._y;
215  _u = p._u;
216  _v = p._v;
217  }
218 
219  void advance()
220  {
221  Yuv12Model::advance(_y, _u, _v, _xpos, _ypos,
222  _view->data(), _view->stride(),
223  _view->size(), _view->padding(), _subStride);
224  }
225 
226  void advance( Pt::ssize_t n )
227  {
228  Yuv12Model::advance(_y, _u, _v, n, _xpos, _ypos,
229  _view->data(), _view->stride(),_view->size());
230  }
231 
232  Color toColor() const
233  {
234  return Yuv12Model::toColor(*_y, *_u, *_v);
235  }
236 
237  Pt::uint8_t y() const
238  { return *_y; }
239 
240  Pt::uint8_t u() const
241  { return *_u; }
242 
243  Pt::uint8_t v() const
244  { return *_v; }
245 
246  bool operator!=(const ConstPixel& p) const
247  { return _y != p._y; }
248 
249  bool operator==(const ConstPixel& p) const
250  { return _y == p._y; }
251 
252  private:
253  ConstPixel& operator=(const ConstPixel&);
254 
255  private:
256  const BasicView<Yuv12Model>* _view;
257  Pt::ssize_t _xpos;
258  Pt::ssize_t _ypos;
259  Pt::ssize_t _subStride;
260  const Pt::uint8_t* _y;
261  const Pt::uint8_t* _u;
262  const Pt::uint8_t* _v;
263 };
264 
268 {
269  public:
270  Pixel(BasicView<Yuv12Model>& view, Pt::ssize_t xpos, Pt::ssize_t ypos)
271  : _view(&view)
272  , _xpos(xpos)
273  , _ypos(ypos)
274  , _subStride(0)
275  , _y(0)
276  , _u(0)
277  , _v(0)
278  {
279  _subStride = Yuv12Model::init(view.data(), view.stride(), view.size(), xpos, ypos, _y, _u, _v);
280  }
281 
282  Pixel(const Pixel& p)
283  : _view(p._view)
284  , _xpos(p._xpos)
285  , _ypos(p._ypos)
286  , _subStride(p._subStride)
287  , _y(p._y)
288  , _u(p._u)
289  , _v(p._v)
290  { }
291 
292  Pixel& operator=(const Pixel& p)
293  {
294  assign(p, CompositionMode::SourceCopy);
295  return *this;
296  }
297 
298  Pixel& operator=(const ConstPixel& p)
299  {
300  assign(p, CompositionMode::SourceCopy);
301  return *this;
302  }
303 
304  Pixel& operator=(const Color& color)
305  {
306  assign(color, CompositionMode::SourceCopy);
307  return *this;
308  }
309 
310  void reset(BasicView<Yuv12Model>& view, Pt::ssize_t xpos, Pt::ssize_t ypos)
311  {
312  _view = &view;
313  _xpos = xpos;
314  _ypos = ypos;
315 
316  _subStride = Yuv12Model::init(view.data(), view.stride(), view.size(), xpos, ypos, _u, _v);
317  }
318 
319  void reset(const Pixel& p)
320  {
321  _view = p._view;
322  _xpos = p._xpos;
323  _ypos = p._ypos;
324  _subStride = p._subStride;
325 
326  _y = p._y;
327  _u = p._u;
328  _v = p._v;
329  }
330 
331  void advance()
332  {
333  Yuv12Model::advance(_y, _u, _v, _xpos, _ypos,
334  _view->data(), _view->stride(),
335  _view->size(), _view->padding(), _subStride);
336  }
337 
338  void advance( Pt::ssize_t n )
339  {
340  Yuv12Model::advance(_y, _u, _v, n, _xpos, _ypos,
341  _view->data(), _view->stride(),_view->size());
342  }
343 
344  void assign(const Color& color, CompositionMode)
345  {
346  Yuv12Model::fromColor(*_y, *_u, *_v, color);
347  }
348 
349  void assign(const Pixel& p, CompositionMode)
350  {
351  *_y = *(p._y);
352  *_u = *(p._u);
353  *_v = *(p._v);
354  }
355 
356  void assign(const ConstPixel& p, CompositionMode)
357  {
358  *_y = p.y();
359  *_u = p.u();
360  *_v = p.v();
361  }
362 
363  Color toColor() const
364  {
365  return Yuv12Model::toColor(*_y, *_u, *_v);
366  }
367 
368  Pt::uint8_t y() const
369  { return *_y; }
370 
371  void setY(Pt::uint8_t y) const
372  { *_y = y; }
373 
374  Pt::uint8_t u() const
375  { return *_u; }
376 
377  void setU(Pt::uint8_t u) const
378  { *_u = u; }
379 
380  Pt::uint8_t v() const
381  { return *_v; }
382 
383  void setV(Pt::uint8_t v) const
384  { *_v = v; }
385 
386  bool operator!=(const Pixel& p) const
387  { return _y != p._y; }
388 
389  bool operator==(const Pixel& p) const
390  { return _y == p._y; }
391 
392  private:
393  BasicView<Yuv12Model>* _view;
394  Pt::ssize_t _xpos;
395  Pt::ssize_t _ypos;
396  Pt::ssize_t _subStride;
397  Pt::uint8_t* _y;
398  Pt::uint8_t* _u;
399  Pt::uint8_t* _v;
400 };
401 
408 class Yuv12Image : public BasicImage<Yuv12Model>
409 {
410  public:
413  Yuv12Image(const Size& size, size_t padding = 0)
414  : BasicImage(size, padding)
415  { }
416 
419  Yuv12Image(Pt::uint8_t* data, const Size& size, size_t padding = 0)
420  : BasicImage(data, size, padding)
421  { }
422 };
423 
424 } // namespace
425 
426 } // namespace
427 
428 #endif
uint_type uint16_t
Unsigned 16-bit integer type.
Definition: Types.h:30
T width() const
Returns the width.
Definition: Size.h:65
YV-12 image.
Definition: Yuv12Image.h:408
int_type int32_t
Signed 32-bit integer type.
Definition: Types.h:36
Yuv12Image(const Size &size, size_t padding=0)
Constructor.
Definition: Yuv12Image.h:413
YV-12 image model.
Definition: Yuv12Image.h:44
Const pixel in a YV-12 Image.
Definition: Yuv12Image.h:173
T height() const
Returns the height.
Definition: Size.h:69
Yuv12Image(Pt::uint8_t *data, const Size &size, size_t padding=0)
Construct from external buffer.
Definition: Yuv12Image.h:419
uint_type uint32_t
Unsigned 32-bit integer type.
Definition: Types.h:42
uint_type uint8_t
Unsigned 8-bit integer type.
Definition: Types.h:18
Pixel in a YV-12 Image.
Definition: Yuv12Image.h:267