Argb32Image.h
1 /* Copyright (C) 2016-2016 Marc Boris Duerner
2  Copyright (C) 2017-2017 Aloysius Indrayanto
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 of the License, or (at your option) any later version.
8 
9  As a special exception, you may use this file as part of a free
10  software library without restriction. Specifically, if other files
11  instantiate templates or use macros or inline functions from this
12  file, or you compile this file and link it with other files to
13  produce an executable, this file does not by itself cause the
14  resulting executable to be covered by the GNU General Public
15  License. This exception does not however invalidate any other
16  reasons why the executable file might be covered by the GNU Library
17  General Public License.
18 
19  This library is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  Lesser General Public License for more details.
23 
24  You should have received a copy of the GNU Lesser General Public
25  License along with this library; if not, write to the Free Software
26  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27  02110-1301 USA
28 */
29 
30 #ifndef PT_GFX_ARGB32IMAGE_H
31 #define PT_GFX_ARGB32IMAGE_H
32 
33 #include <Pt/Gfx/Api.h>
34 #include <Pt/Gfx/Color.h>
35 #include <Pt/Gfx/CompositionMode.h>
36 #include <Pt/Gfx/BasicImage.h>
37 #include <Pt/Types.h>
38 
39 namespace Pt {
40 
41 namespace Gfx {
42 
43 
47 {
48  public:
49  class Pixel;
50  class ConstPixel;
51 
52  static std::size_t imageSize(const Size& size, Pt::ssize_t padding)
53  {
54  std::size_t l = (size.width() * 4) + padding;
55  std::size_t n = l * size.height();
56  return n;
57  }
58 
59  static Pt::ssize_t pixelStride()
60  {
61  return 4;
62  }
63 
64  public:
65  static Color toColor(const Pt::uint8_t* p)
66  {
67  const Pt::uint32_t pixel = *reinterpret_cast<const Pt::uint32_t*>(p);
68 
69  const Pt::uint16_t ta = pixel >> 24;
70  const Pt::uint16_t tr = (pixel & 0x00FF0000) >> 16;
71  const Pt::uint16_t tg = (pixel & 0x0000FF00) >> 8;
72  const Pt::uint16_t tb = pixel & 0x000000FF;
73 
74  Pt::uint16_t a = (ta << 8) + ta;
75  Pt::uint16_t r = (tr << 8) + tr;
76  Pt::uint16_t g = (tg << 8) + tg;
77  Pt::uint16_t b = (tb << 8) + tb;
78 
79  return Color(a, r, g, b);
80  }
81 
82  static void fromColor(Pt::uint8_t* p, const Color& c)
83  {
84  Pt::uint32_t* pixel = reinterpret_cast<Pt::uint32_t*>(p);
85 
86  *pixel = ( Pt::uint32_t(c.alpha() & 0xFF00) << 16 ) |
87  ( Pt::uint32_t(c.red () & 0xFF00) << 8 ) |
88  Pt::uint32_t(c.green() & 0xFF00) |
89  ( Pt::uint32_t(c.blue () ) >> 8 );
90  }
91 
92  static void sourceOver(Pt::uint8_t* to, const Pt::uint8_t* from)
93  {
94  const Pt::uint32_t alphaSrc = from[3];
95  const Pt::uint32_t alphaInv = 255 - alphaSrc;
96 
97  to[0] = (Pt::uint8_t) ( (alphaSrc * from[0] + alphaInv * to[0]) >> 8 );
98  to[1] = (Pt::uint8_t) ( (alphaSrc * from[1] + alphaInv * to[1]) >> 8 );
99  to[2] = (Pt::uint8_t) ( (alphaSrc * from[2] + alphaInv * to[2]) >> 8 );
100  to[3] = (Pt::uint8_t) ( (alphaSrc * alphaSrc + alphaInv * to[3]) >> 8 );
101  }
102 
103  static void sourceOver(Pt::uint8_t* to, const Pt::Gfx::Color& from)
104  {
105  const Pt::uint32_t alpha = from.alpha() >> 8;
106  const Pt::uint32_t alphaSrc = alpha;
107  const Pt::uint32_t alphaInv = 255 - alpha;
108 
109  to[0] = (Pt::uint8_t) ( (alphaSrc * (from.blue () >> 8) + alphaInv * to[0]) >> 8 );
110  to[1] = (Pt::uint8_t) ( (alphaSrc * (from.green() >> 8) + alphaInv * to[1]) >> 8 );
111  to[2] = (Pt::uint8_t) ( (alphaSrc * (from.red () >> 8) + alphaInv * to[2]) >> 8 );
112  to[3] = (Pt::uint8_t) ( (alphaSrc * alpha + alphaInv * to[3]) >> 8 );
113  }
114 
115  static void assign(Pt::uint8_t* to, const Color& c,
116  CompositionMode mode)
117  {
118  switch(mode) {
119  default:
120  case CompositionMode::SourceCopy:
121  Argb32Model::fromColor(to, c);
122  break;
123 
124  case CompositionMode::SourceOver:
125  Argb32Model::sourceOver(to, c);
126  break;
127  }
128  }
129 
130  static void assign(Pt::uint8_t* to, const Pt::uint8_t* from,
131  CompositionMode mode)
132  {
133  switch(mode) {
134  default:
135  case CompositionMode::SourceCopy:
136  *((Pt::uint32_t*) to) = *((const Pt::uint32_t*) from);
137  break;
138 
139  case CompositionMode::SourceOver:
140  Argb32Model::sourceOver(to, from);
141  break;
142  }
143  }
144 
145  static void assign(Pt::uint8_t* to, const Color& c,
146  CompositionMode mode, Pt::uint8_t blendingAlpha)
147  {
148  switch(mode) {
149  default:
150  case CompositionMode::SourceCopy:
151  {
152  const Pt::uint32_t blendAlphaSrc = blendingAlpha;
153  const Pt::uint32_t blendAlphaInv = 255 - blendingAlpha;
154  to[0] = (blendAlphaSrc * (c.blue () >> 8) + blendAlphaInv * to[0]) >> 8;
155  to[1] = (blendAlphaSrc * (c.green() >> 8) + blendAlphaInv * to[1]) >> 8;
156  to[2] = (blendAlphaSrc * (c.red () >> 8) + blendAlphaInv * to[2]) >> 8;
157  to[3] = (blendAlphaSrc * (c.alpha() >> 8) + blendAlphaInv * to[3]) >> 8;
158  break;
159  }
160 
161  case CompositionMode::SourceOver:
162  {
163  const Pt::uint32_t colorAlpha = c.alpha() >> 8;
164  const Pt::uint32_t blendAlphaSrc = colorAlpha * blendingAlpha / 255;
165  const Pt::uint32_t blendAlphaInv = 255 - blendAlphaSrc;
166  to[0] = (blendAlphaSrc * (c.blue () >> 8) + blendAlphaInv * to[0]) >> 8;
167  to[1] = (blendAlphaSrc * (c.green() >> 8) + blendAlphaInv * to[1]) >> 8;
168  to[2] = (blendAlphaSrc * (c.red () >> 8) + blendAlphaInv * to[2]) >> 8;
169  to[3] = (blendAlphaSrc * colorAlpha + blendAlphaInv * to[3]) >> 8;
170  break;
171  }
172  }
173  }
174 
175  static void assign(Pt::uint8_t* to, const Pt::uint8_t* from,
176  CompositionMode mode, Pt::uint8_t blendingAlpha)
177  {
178  switch(mode) {
179  default:
180  case CompositionMode::SourceCopy:
181  {
182  const Pt::uint32_t blendAlphaSrc = blendingAlpha;
183  const Pt::uint32_t blendAlphaInv = 255 - blendingAlpha;
184  to[0] = (blendAlphaSrc * from[0] + blendAlphaInv * to[0]) >> 8;
185  to[1] = (blendAlphaSrc * from[1] + blendAlphaInv * to[1]) >> 8;
186  to[2] = (blendAlphaSrc * from[2] + blendAlphaInv * to[2]) >> 8;
187  to[3] = (blendAlphaSrc * from[3] + blendAlphaInv * to[3]) >> 8;
188  break;
189  }
190 
191  case CompositionMode::SourceOver:
192  {
193  const Pt::uint32_t colorAlpha = from[3];
194  const Pt::uint32_t blendAlphaSrc = colorAlpha * blendingAlpha / 255;
195  const Pt::uint32_t blendAlphaInv = 255 - blendAlphaSrc;
196  to[0] = (blendAlphaSrc * from[0] + blendAlphaInv * to[0]) >> 8;
197  to[1] = (blendAlphaSrc * from[1] + blendAlphaInv * to[1]) >> 8;
198  to[2] = (blendAlphaSrc * from[2] + blendAlphaInv * to[2]) >> 8;
199  to[3] = (blendAlphaSrc * colorAlpha + blendAlphaInv * to[3]) >> 8;
200  break;
201  }
202  }
203  }
204 
205  static void assign(Pt::uint8_t* to, const Color& c, size_t length,
206  CompositionMode mode);
207 
208  static void assign(Pt::uint8_t* to, const Pt::uint8_t* from, size_t length,
209  CompositionMode mode);
210 
211  template <typename T>
212  static void advance(T*& p, Pt::ssize_t& xpos, Pt::ssize_t& ypos,
213  const BasicView<Argb32Model>& view)
214  {
215  if( ++xpos >= view.width() )
216  {
217  xpos = 0;
218  ++ypos;
219 
220  p += view.padding();
221  }
222 
223  p += 4;
224  }
225 
226  template <typename T>
227  static void advance(T*& p, Pt::ssize_t n, Pt::ssize_t& xpos, Pt::ssize_t& ypos,
228  const BasicView<Argb32Model>& view, T* data)
229  {
230  Pt::ssize_t off = xpos + n;
231  ypos += off / view.width();
232  xpos = off % view.width();
233 
234  p = data + view.stride() * ypos + xpos * 4;
235  }
236 };
237 
238 
242 {
243  friend class Pixel;
244 
245  public:
246  ConstPixel(const BasicView<Argb32Model>& view, Pt::ssize_t xpos, Pt::ssize_t ypos)
247  : _view(0)
248  , _xpos(0)
249  , _ypos(0)
250  , _p(0)
251  {
252  reset(view, xpos, ypos);
253  }
254 
255  ConstPixel(const ConstPixel& p)
256  : _view(p._view)
257  , _xpos(p._xpos)
258  , _ypos(p._ypos)
259  , _p(p._p)
260  { }
261 
262  void reset(const BasicView<Argb32Model>& view, Pt::ssize_t xpos, Pt::ssize_t ypos)
263  {
264  _view = &view;
265  _xpos = xpos;
266  _ypos = ypos;
267 
268  Pt::ssize_t off = view.stride() * ypos + (xpos * 4);
269  _p = view.data() + off;
270  }
271 
272  void reset(const ConstPixel& p)
273  {
274  _view = p._view;
275  _xpos = p._xpos;
276  _ypos = p._ypos;
277 
278  _p = p._p;
279  }
280 
281  void advance()
282  {
283  Argb32Model::advance(_p, _xpos, _ypos, *_view);
284  }
285 
286  void advance( Pt::ssize_t n )
287  {
288  Argb32Model::advance(_p, n, _xpos, _ypos, *_view, _view->data());
289  }
290 
291  Color toColor() const
292  {
293  return Argb32Model::toColor(_p);
294  }
295 
296  Pt::uint8_t alpha() const
297  {
298  const Pt::uint32_t* val = reinterpret_cast<const Pt::uint32_t*>(_p);
299  return *val >> 24;
300  }
301 
302  Pt::uint8_t red() const
303  {
304  const Pt::uint32_t* val = reinterpret_cast<const Pt::uint32_t*>(_p);
305  return (*val & 0x00FF0000) >> 16;
306  }
307 
308  Pt::uint8_t green() const
309  {
310  const Pt::uint32_t* val = reinterpret_cast<const Pt::uint32_t*>(_p);
311  return (*val & 0x0000FF00) >> 8;
312  }
313 
314  Pt::uint8_t blue() const
315  {
316  const Pt::uint32_t* val = reinterpret_cast<const Pt::uint32_t*>(_p);
317  return *val & 0x000000FF;
318  }
319 
320  bool operator!=(const ConstPixel& p) const
321  {
322  return _p != p._p;
323  }
324 
325  bool operator==(const ConstPixel& p) const
326  {
327  return _p == p._p;
328  }
329 
330  private:
331  ConstPixel& operator=(const ConstPixel&);
332 
333  private:
334  const BasicView<Argb32Model>* _view;
335  Pt::ssize_t _xpos;
336  Pt::ssize_t _ypos;
337  const Pt::uint8_t* _p;
338 };
339 
340 
344 {
345  public:
346  Pixel(BasicView<Argb32Model>& view, Pt::ssize_t xpos, Pt::ssize_t ypos)
347  : _view(0)
348  , _xpos(0)
349  , _ypos(0)
350  , _p(0)
351  {
352  reset(view, xpos, ypos);
353  }
354 
355  Pixel(const Pixel& p)
356  : _view(p._view)
357  , _xpos(p._xpos)
358  , _ypos(p._ypos)
359  , _p(p._p)
360  { }
361 
362  Pixel& operator=(const Pixel& p)
363  {
364  assign(p, CompositionMode::SourceCopy);
365  return *this;
366  }
367 
368  Pixel& operator=(const ConstPixel& p)
369  {
370  assign(p, CompositionMode::SourceCopy);
371  return *this;
372  }
373 
374  Pixel& operator=(const Color& color)
375  {
376  assign(color, CompositionMode::SourceCopy);
377  return *this;
378  }
379 
380  void reset(BasicView<Argb32Model>& view, Pt::ssize_t xpos, Pt::ssize_t ypos)
381  {
382  _view = &view;
383  _xpos = xpos;
384  _ypos = ypos;
385 
386  Pt::ssize_t off = view.stride() * ypos + (xpos * 4);
387  _p = view.data() + off;
388  }
389 
390  void reset(const Pixel& p)
391  {
392  _view = p._view;
393  _xpos = p._xpos;
394  _ypos = p._ypos;
395 
396  _p = p._p;
397  }
398 
399  void advance()
400  {
401  Argb32Model::advance(_p, _xpos, _ypos, *_view);
402  }
403 
404  void advance( Pt::ssize_t n )
405  {
406  Argb32Model::advance(_p, n, _xpos, _ypos, *_view, _view->data());
407  }
408 
409  void assign(const Color& c, CompositionMode mode)
410  {
411  Argb32Model::assign(_p, c, mode);
412  }
413 
414  void assign(const Pixel& p, CompositionMode mode)
415  {
416  Argb32Model::assign(_p, p._p, mode);
417  }
418 
419  void assign(const ConstPixel& p, CompositionMode mode)
420  {
421  Argb32Model::assign(_p, p._p, mode);
422  }
423 
424  Color toColor() const
425  {
426  return Argb32Model::toColor(_p);
427  }
428 
429  Pt::uint8_t alpha() const
430  {
431  const Pt::uint32_t* val = reinterpret_cast<const Pt::uint32_t*>(_p);
432  return *val >> 24;
433  }
434 
435  Pt::uint8_t red() const
436  {
437  const Pt::uint32_t* val = reinterpret_cast<const Pt::uint32_t*>(_p);
438  return (*val & 0x00FF0000) >> 16;
439  }
440 
441  Pt::uint8_t green() const
442  {
443  const Pt::uint32_t* val = reinterpret_cast<const Pt::uint32_t*>(_p);
444  return (*val & 0x0000FF00) >> 8;
445  }
446 
447  Pt::uint8_t blue() const
448  {
449  const Pt::uint32_t* val = reinterpret_cast<const Pt::uint32_t*>(_p);
450  return *val & 0x000000FF;
451  }
452 
453  void setAlpha(Pt::uint8_t a)
454  {
455  Pt::uint32_t* val = reinterpret_cast<Pt::uint32_t*>(_p);
456  *val = (*val & 0x00FFFFFF) | (uint32_t(a) << 24);
457  }
458 
459  void setRed(Pt::uint8_t r)
460  {
461  Pt::uint32_t* val = reinterpret_cast<Pt::uint32_t*>(_p);
462  *val = (*val & 0xFF00FFFF) | (uint32_t(r) << 16);
463  }
464 
465  void setGreen(Pt::uint8_t g)
466  {
467  Pt::uint32_t* val = reinterpret_cast<Pt::uint32_t*>(_p);
468  *val = (*val & 0xFFFF00FF) | (uint32_t(g) << 8);
469  }
470 
471  void setBlue(Pt::uint8_t b)
472  {
473  Pt::uint32_t* val = reinterpret_cast<Pt::uint32_t*>(_p);
474  *val = (*val & 0xFFFFFF00) | uint32_t(b);
475  }
476 
477  bool operator!=(const Pixel& p) const
478  { return _p != p._p; }
479 
480  bool operator==(const Pixel& p) const
481  { return _p == p._p; }
482 
483  private:
484  BasicView<Argb32Model>* _view;
485  Pt::ssize_t _xpos;
486  Pt::ssize_t _ypos;
487  Pt::uint8_t* _p;
488 };
489 
490 
493 class Argb32Image : public BasicImage<Argb32Model>
494 {
495  public:
498  Argb32Image(const Size& size, size_t padding = 0)
499  : BasicImage(size, padding)
500  { }
501 
504  Argb32Image(Pt::uint8_t* data, const Size& size, size_t padding = 0)
505  : BasicImage(data, size, padding)
506  { }
507 };
508 
509 
510 } // namespace
511 } // namespace
512 
513 
514 #endif
uint_type uint16_t
Unsigned 16-bit integer type.
Definition: Types.h:30
T width() const
Returns the width.
Definition: Size.h:65
ARGB-32 image model.
Definition: Argb32Image.h:46
Const pixel in a ARGB-32 Image.
Definition: Argb32Image.h:241
T height() const
Returns the height.
Definition: Size.h:69
Const pixel in a ARGB-32 Image.
Definition: Argb32Image.h:343
Argb32Image(const Size &size, size_t padding=0)
Constructor.
Definition: Argb32Image.h:498
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
ARGB-32 image.
Definition: Argb32Image.h:493
Argb32Image(Pt::uint8_t *data, const Size &size, size_t padding=0)
Construct from external buffer.
Definition: Argb32Image.h:504