Yuv12.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,
26  MA 02110-1301 USA
27 */
28 
29 #ifndef PT_GFX_YUV12_H
30 #define PT_GFX_YUV12_H
31 
32 #include <Pt/Gfx/Api.h>
33 #include <Pt/Gfx/ImageFormat.h>
34 #include <Pt/Gfx/Color.h>
35 #include <Pt/Types.h>
36 
37 namespace Pt {
38 
39 namespace Gfx {
40 
43 class PT_GFX_API Yuv12Pixel
44 {
45  friend class Yuv12;
46  friend class Yuv12ConstPixel;
47 
48  public:
49  typedef Yuv12 FormatType;
50  typedef ColorF ColorType;
51 
52  protected:
53  Yuv12Pixel(Pt::uint8_t* data, const ViewBase& view,
54  Pt::ssize_t x, Pt::ssize_t y);
55 
56  public:
57  template <typename T>
58  Yuv12Pixel(T& view, Pt::ssize_t xpos, Pt::ssize_t ypos);
59 
60  Yuv12Pixel(const Yuv12Pixel& p)
61  : _view(p._view)
62  , _xpos(p._xpos)
63  , _ypos(p._ypos)
64  , _subStride(p._subStride)
65  , _y(p._y)
66  , _u(p._u)
67  , _v(p._v)
68  { }
69 
70  Yuv12Pixel& operator=(const Yuv12Pixel&) = delete;
71 
72  Yuv12Pixel& operator=(const ColorF& color);
73 
74  const ViewBase& view() const
75  { return _view; }
76 
77  Pt::ssize_t xpos() const
78  { return _xpos; }
79 
80  Pt::ssize_t ypos() const
81  { return _ypos; }
82 
83  Pt::uint8_t* ybase() const
84  { return _y; }
85 
86  Pt::uint8_t* ubase() const
87  { return _u; }
88 
89  Pt::uint8_t* vbase() const
90  { return _v; }
91 
92  Pt::uint8_t y() const
93  { return *_y; }
94 
95  void setY(Pt::uint8_t y) const
96  { *_y = y; }
97 
98  Pt::uint8_t u() const
99  { return *_u; }
100 
101  void setU(Pt::uint8_t u) const
102  { *_u = u; }
103 
104  Pt::uint8_t v() const
105  { return *_v; }
106 
107  void setV(Pt::uint8_t v) const
108  { *_v = v; }
109 
110  ColorF getColor() const;
111 
112  void advance();
113 
114  void skipPadding();
115 
116  void advance(Pt::ssize_t n);
117 
118  void advanceLines(Pt::ssize_t n);
119 
120  bool equals(const Yuv12Pixel& p) const;
121 
122  bool equals(const Yuv12ConstPixel& p) const;
123 
124  private:
125  const ViewBase& _view;
126  Pt::ssize_t _xpos;
127  Pt::ssize_t _ypos;
128  Pt::ssize_t _subStride;
129  Pt::uint8_t* _y;
130  Pt::uint8_t* _u;
131  Pt::uint8_t* _v;
132 };
133 
137 {
138  friend class Yuv12;
139  friend class Yuv12Pixel;
140 
141  public:
142  typedef Yuv12 FormatType;
143  typedef ColorF ColorType;
144 
145  protected:
146  Yuv12ConstPixel(const Pt::uint8_t* data, const ViewBase& view,
147  Pt::ssize_t xpos, Pt::ssize_t ypos);
148 
149  public:
150  template <typename T>
151  Yuv12ConstPixel(const T& view, Pt::ssize_t xpos, Pt::ssize_t ypos);
152 
153  template <typename T>
154  Yuv12ConstPixel(T& view, Pt::ssize_t xpos, Pt::ssize_t ypos);
155 
157  : _view(p._view)
158  , _xpos(p._xpos)
159  , _ypos(p._ypos)
160  , _subStride(p._subStride)
161  , _y(p._y)
162  , _u(p._u)
163  , _v(p._v)
164  { }
165 
166  explicit Yuv12ConstPixel(const Yuv12Pixel& p)
167  : _view(p._view)
168  , _xpos(p._xpos)
169  , _ypos(p._ypos)
170  , _subStride(p._subStride)
171  , _y(p._y)
172  , _u(p._u)
173  , _v(p._v)
174  { }
175 
176  Yuv12ConstPixel& operator=(const Yuv12ConstPixel&) = delete;
177 
178  const ViewBase& view() const
179  { return _view; }
180 
181  Pt::ssize_t xpos() const
182  { return _xpos; }
183 
184  Pt::ssize_t ypos() const
185  { return _ypos; }
186 
187  const Pt::uint8_t* ybase() const
188  { return _y; }
189 
190  const Pt::uint8_t* ubase() const
191  { return _u; }
192 
193  const Pt::uint8_t* vbase() const
194  { return _v; }
195 
196  Pt::uint8_t y() const
197  { return *_y; }
198 
199  Pt::uint8_t u() const
200  { return *_u; }
201 
202  Pt::uint8_t v() const
203  { return *_v; }
204 
205  ColorF getColor() const;
206 
207  void advance();
208 
209  void skipPadding();
210 
211  void advance(Pt::ssize_t n);
212 
213  void advanceLines(Pt::ssize_t n);
214 
215  bool equals(const Yuv12ConstPixel& p) const
216  { return _y == p._y; }
217 
218  bool equals(const Yuv12Pixel& p) const
219  { return _y == p._y; }
220 
221  private:
222  const ViewBase& _view;
223  Pt::ssize_t _xpos;
224  Pt::ssize_t _ypos;
225  Pt::ssize_t _subStride;
226  const Pt::uint8_t* _y;
227  const Pt::uint8_t* _u;
228  const Pt::uint8_t* _v;
229 };
230 
233 class PT_GFX_API Yuv12 final : public ImageFormat
234 {
235  public:
236  typedef Yuv12Pixel Pixel;
237  typedef Yuv12ConstPixel ConstPixel;
238 
239  public:
240  static const Yuv12& get()
241  {
242  static Yuv12 _yuv12;
243  return _yuv12;
244  }
245 
246  public:
247  Yuv12();
248 
249  Pt::ssize_t pixelStride() const
250  {
251  return 1;
252  }
253 
254  std::size_t imageSize(std::size_t width, std::size_t height,
255  std::size_t padding) const
256  {
257  Pt::ssize_t stride = width + padding;
258  Pt::ssize_t planeSize = stride * height;
259 
260  return planeSize + planeSize / 2;
261  }
262 
263  protected:
264  virtual std::unique_ptr<ImageFormat> onClone() const override
265  {
266  return std::unique_ptr<ImageFormat>(new Yuv12);
267  }
268 
269  virtual const std::type_info& onGetType() const override
270  {
271  return typeid(*this);
272  }
273 
274  virtual std::size_t onImageSize(Pt::ssize_t width, Pt::ssize_t height,
275  std::size_t padding) const override;
276 
277  virtual PixelBase* onCreatePixel(Pt::uint8_t* data, const ViewBase& view,
278  Pt::ssize_t x, Pt::ssize_t y,
279  PixelStorage& store) const override;
280 
281  public:
282  template <typename T>
283  static void advance(T*& y, T*& u, T*& v,
284  Pt::ssize_t& xpos,
285  Pt::ssize_t uvstride)
286  {
287  ++y;
288  ++xpos;
289 
290  if(xpos % 2 == 0)
291  {
292  ++u;
293  ++v;
294  }
295  }
296 
297  template <typename T>
298  static void advanceN(T*& y, T*& u, T*& v,
299  Pt::ssize_t& xpos,
300  Pt::ssize_t n)
301  {
302  Pt::ssize_t old_u_col = xpos / 2;
303  Pt::ssize_t new_u_col = (xpos + n) / 2;
304 
305  y += n;
306  xpos += n;
307 
308  Pt::ssize_t uv_diff = new_u_col - old_u_col;
309  u += uv_diff;
310  v += uv_diff;
311  }
312 
313  template <typename T>
314  static void skipPadding(T*& y, T*& u, T*& v,
315  Pt::ssize_t& xpos, Pt::ssize_t& ypos,
316  Pt::ssize_t padding, Pt::ssize_t uvstride)
317  {
318  ++u;
319  ++v;
320 
321  if(ypos % 2 == 0)
322  {
323  u -= uvstride;
324  v -= uvstride;
325  }
326 
327  xpos = 0;
328  ++ypos;
329  y += padding;
330  }
331 
332  template <typename T>
333  static void advanceLines(T*& y, T*& u, T*& v,
334  Pt::ssize_t& ypos,
335  Pt::ssize_t n,
336  Pt::ssize_t ystride,
337  Pt::ssize_t uvstride)
338  {
339  Pt::ssize_t old_u_row = ypos / 2;
340  Pt::ssize_t new_u_row = (ypos + n) / 2;
341 
342  y += n * ystride;
343  ypos += n;
344 
345  Pt::ssize_t uv_diff = (new_u_row - old_u_row) * uvstride;
346  u += uv_diff;
347  v += uv_diff;
348  }
349 
350  public:
351  static ColorF getColorF(Pt::uint8_t y, Pt::uint8_t u, Pt::uint8_t v)
352  {
353  Pt::uint32_t rv = 298 * (y - 16) + 409 * (v - 128) + 128;
354  Pt::uint32_t gv = 298 * (y - 16) - 100 * (u - 128) - 208 * (v - 128) + 128;
355  Pt::uint32_t bv = 298 * (y - 16) + 516 * (u - 128) + 128;
356 
357  Pt::uint16_t r = rv > 65535 ? 65535 : static_cast<Pt::uint16_t>(rv);
358  Pt::uint16_t g = gv > 65535 ? 65535 : static_cast<Pt::uint16_t>(gv);
359  Pt::uint16_t b = bv > 65535 ? 65535 : static_cast<Pt::uint16_t>(bv);
360 
361  return ColorF(r, g, b);
362  }
363 
364  static void fromColor(Pt::uint8_t* y, Pt::uint8_t* u, Pt::uint8_t* v,
365  const ColorF& color)
366  {
367  Pt::int32_t r = color.red();
368  Pt::int32_t g = color.green();
369  Pt::int32_t b = color.blue();
370 
371  Pt::int32_t yy = (( 66 * r + 129 * g + 25 * b + 128) >> 16) + 16;
372  Pt::int32_t uu = ((-38 * r - 74 * g + 112 * b + 128) >> 16) + 128;
373  Pt::int32_t vv = ((112 * r - 94 * g - 18 * b + 128) >> 16) + 128;
374 
375  *y = yy > 255 ? 255 : static_cast<Pt::uint8_t>(yy);
376  *u = uu > 255 ? 255 : static_cast<Pt::uint8_t>(uu);
377  *v = vv > 255 ? 255 : static_cast<Pt::uint8_t>(vv);
378  }
379 
380  template <typename T>
381  static Pt::ssize_t init(T* data, Pt::ssize_t stride,
382  Pt::ssize_t width, Pt::ssize_t height,
383  Pt::ssize_t xpos, Pt::ssize_t ypos,
384  T*& y, T*& u, T*& v)
385  {
386  Pt::ssize_t yOffset = stride * ypos + xpos;
387  y = data + yOffset;
388 
389  return initUV(data, stride, width, height, xpos, ypos, u, v);
390  }
391 
392  template <typename T>
393  static Pt::ssize_t initUV(T* data, Pt::ssize_t stride,
394  Pt::ssize_t width, Pt::ssize_t height,
395  Pt::ssize_t xpos, Pt::ssize_t ypos,
396  T*& u, T*& v)
397  {
398  Pt::ssize_t planeSize = stride * height;
399 
400  Pt::ssize_t uvstride = stride / 2;
401  Pt::ssize_t subPlaneSize = planeSize / 4;
402 
403  Pt::ssize_t subXPos = xpos / 2;
404  Pt::ssize_t subYPos = ypos / 2;
405  Pt::ssize_t subOffset = uvstride * subYPos + subXPos;
406 
407  Pt::ssize_t uOffset = planeSize + subOffset;
408  u = data + uOffset;
409 
410  Pt::ssize_t vOffset = uOffset + subPlaneSize;
411  v = data + vOffset;
412 
413  return uvstride;
414  }
415 
416  template <typename T>
417  static void advance(T*& y, T*& u, T*& v,
418  Pt::ssize_t& xpos, Pt::ssize_t& ypos,
419  Pt::ssize_t width, Pt::ssize_t padding,
420  Pt::ssize_t uvstride)
421  {
422  ++y;
423 
424  if( ++xpos >= width )
425  {
426  ++u;
427  ++v;
428 
429  if(ypos % 2 == 0)
430  {
431  u -= uvstride;
432  v -= uvstride;
433  }
434 
435  xpos = 0;
436  ++ypos;
437 
438  y += padding;
439  }
440  else if(xpos % 2 == 0)
441  {
442  ++u;
443  ++v;
444  }
445  }
446 
447  template <typename T>
448  static void advanceBy(T*& y, T*& u, T*& v, ssize_t n,
449  ssize_t& xpos, ssize_t& ypos, ssize_t width,
450  ssize_t ystride, ssize_t uvstride)
451  {
452  Pt::ssize_t new_abs_pos = (ypos * width) + xpos + n;
453  Pt::ssize_t new_ypos = new_abs_pos / width;
454  Pt::ssize_t new_xpos = new_abs_pos % width;
455 
456  y += (new_ypos - ypos) * ystride + (new_xpos - xpos);
457 
458  Pt::ssize_t old_u_row = ypos / 2;
459  Pt::ssize_t new_u_row = new_ypos / 2;
460 
461  Pt::ssize_t old_u_col = xpos / 2;
462  Pt::ssize_t new_u_col = new_xpos / 2;
463 
464  Pt::ssize_t uv_offset = (new_u_row - old_u_row) * uvstride + (new_u_col - old_u_col);
465 
466  u += uv_offset;
467  v += uv_offset;
468 
469  xpos = new_xpos;
470  ypos = new_ypos;
471  }
472 };
473 
474 } // namespace
475 
476 } // namespace
477 
478 #endif
479 
480 #include <Pt/Gfx/Yuv12.hpp>
Core module.
Definition: Allocator.h:33
Image format.
Definition: ImageFormat.h:53
YV-12 pixel.
Definition: Yuv12.h:44
YV-12 image format.
Definition: Yuv12.h:234
Pixel base class.
Definition: PixelBase.h:52
Definition: Color.h:137
uint_type uint8_t
Unsigned 8-bit integer type.
Definition: Api-Types.h:20
uint_type uint32_t
Unsigned 32-bit integer type.
Definition: Api-Types.h:48
int_type int32_t
Signed 32-bit integer type.
Definition: Api-Types.h:41
YV12 const pixel.
Definition: Yuv12.h:137
uint_type uint16_t
Unsigned 16-bit integer type.
Definition: Api-Types.h:34