Anti-Grain Geometry Tutorial
agg_pixfmt_gray.h
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 //
16 // Adaptation for high precision colors has been sponsored by
17 // Liberty Technology Systems, Inc., visit http://lib-sys.com
18 //
19 // Liberty Technology Systems, Inc. is the provider of
20 // PostScript and PDF technology for software developers.
21 //
22 //----------------------------------------------------------------------------
23 
24 #ifndef AGG_PIXFMT_GRAY_INCLUDED
25 #define AGG_PIXFMT_GRAY_INCLUDED
26 
27 #include <cstring>
28 #include "agg_pixfmt_base.h"
29 #include "agg_rendering_buffer.h"
30 
31 namespace agg
32 {
33 
34  //============================================================blender_gray
35  template<class ColorT> struct blender_gray
36  {
37  typedef ColorT color_type;
38  typedef typename color_type::value_type value_type;
39  typedef typename color_type::calc_type calc_type;
40  typedef typename color_type::long_type long_type;
41 
42  // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's
43  // compositing function. Since the render buffer is opaque we skip the
44  // initial premultiply and final demultiply.
45 
46  static AGG_INLINE void blend_pix(value_type* p,
47  value_type cv, value_type alpha, cover_type cover)
48  {
49  blend_pix(p, cv, color_type::mult_cover(alpha, cover));
50  }
51 
52  static AGG_INLINE void blend_pix(value_type* p,
53  value_type cv, value_type alpha)
54  {
55  *p = color_type::lerp(*p, cv, alpha);
56  }
57  };
58 
59 
60  //======================================================blender_gray_pre
61  template<class ColorT> struct blender_gray_pre
62  {
63  typedef ColorT color_type;
64  typedef typename color_type::value_type value_type;
65  typedef typename color_type::calc_type calc_type;
66  typedef typename color_type::long_type long_type;
67 
68  // Blend pixels using the premultiplied form of Alvy-Ray Smith's
69  // compositing function.
70 
71  static AGG_INLINE void blend_pix(value_type* p,
72  value_type cv, value_type alpha, cover_type cover)
73  {
74  blend_pix(p, color_type::mult_cover(cv, cover), color_type::mult_cover(alpha, cover));
75  }
76 
77  static AGG_INLINE void blend_pix(value_type* p,
78  value_type cv, value_type alpha)
79  {
80  *p = color_type::prelerp(*p, cv, alpha);
81  }
82  };
83 
84 
85 
86  //=====================================================apply_gamma_dir_gray
87  template<class ColorT, class GammaLut> class apply_gamma_dir_gray
88  {
89  public:
90  typedef typename ColorT::value_type value_type;
91 
92  apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {}
93 
94  AGG_INLINE void operator () (value_type* p)
95  {
96  *p = m_gamma.dir(*p);
97  }
98 
99  private:
100  const GammaLut& m_gamma;
101  };
102 
103 
104 
105  //=====================================================apply_gamma_inv_gray
106  template<class ColorT, class GammaLut> class apply_gamma_inv_gray
107  {
108  public:
109  typedef typename ColorT::value_type value_type;
110 
111  apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {}
112 
113  AGG_INLINE void operator () (value_type* p)
114  {
115  *p = m_gamma.inv(*p);
116  }
117 
118  private:
119  const GammaLut& m_gamma;
120  };
121 
122 
123 
124  //=================================================pixfmt_alpha_blend_gray
125  template<class Blender, class RenBuf, unsigned Step = 1, unsigned Offset = 0>
127  {
128  public:
130  typedef RenBuf rbuf_type;
131  typedef typename rbuf_type::row_data row_data;
132  typedef Blender blender_type;
133  typedef typename blender_type::color_type color_type;
134  typedef int order_type; // A fake one
135  typedef typename color_type::value_type value_type;
136  typedef typename color_type::calc_type calc_type;
137  enum
138  {
139  num_components = 1,
140  pix_width = sizeof(value_type) * Step,
141  pix_step = Step,
142  pix_offset = Offset,
143  };
144  struct pixel_type
145  {
146  value_type c[num_components];
147 
148  void set(value_type v)
149  {
150  c[0] = v;
151  }
152 
153  void set(const color_type& color)
154  {
155  set(color.v);
156  }
157 
158  void get(value_type& v) const
159  {
160  v = c[0];
161  }
162 
163  color_type get() const
164  {
165  return color_type(c[0]);
166  }
167 
168  pixel_type* next()
169  {
170  return (pixel_type*)(c + pix_step);
171  }
172 
173  const pixel_type* next() const
174  {
175  return (const pixel_type*)(c + pix_step);
176  }
177 
178  pixel_type* advance(int n)
179  {
180  return (pixel_type*)(c + n * pix_step);
181  }
182 
183  const pixel_type* advance(int n) const
184  {
185  return (const pixel_type*)(c + n * pix_step);
186  }
187  };
188 
189  private:
190  //--------------------------------------------------------------------
191  AGG_INLINE void blend_pix(pixel_type* p,
192  value_type v, value_type a,
193  unsigned cover)
194  {
195  blender_type::blend_pix(p->c, v, a, cover);
196  }
197 
198  //--------------------------------------------------------------------
199  AGG_INLINE void blend_pix(pixel_type* p, value_type v, value_type a)
200  {
201  blender_type::blend_pix(p->c, v, a);
202  }
203 
204  //--------------------------------------------------------------------
205  AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover)
206  {
207  blender_type::blend_pix(p->c, c.v, c.a, cover);
208  }
209 
210  //--------------------------------------------------------------------
211  AGG_INLINE void blend_pix(pixel_type* p, const color_type& c)
212  {
213  blender_type::blend_pix(p->c, c.v, c.a);
214  }
215 
216  //--------------------------------------------------------------------
217  AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover)
218  {
219  if (!c.is_transparent())
220  {
221  if (c.is_opaque() && cover == cover_mask)
222  {
223  p->set(c);
224  }
225  else
226  {
227  blend_pix(p, c, cover);
228  }
229  }
230  }
231 
232  //--------------------------------------------------------------------
233  AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c)
234  {
235  if (!c.is_transparent())
236  {
237  if (c.is_opaque())
238  {
239  p->set(c);
240  }
241  else
242  {
243  blend_pix(p, c);
244  }
245  }
246  }
247 
248  public:
249  //--------------------------------------------------------------------
250  explicit pixfmt_alpha_blend_gray(rbuf_type& rb) :
251  m_rbuf(&rb)
252  {}
253  void attach(rbuf_type& rb) { m_rbuf = &rb; }
254  //--------------------------------------------------------------------
255 
256  template<class PixFmt>
257  bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
258  {
259  rect_i r(x1, y1, x2, y2);
260  if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
261  {
262  int stride = pixf.stride();
263  m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
264  (r.x2 - r.x1) + 1,
265  (r.y2 - r.y1) + 1,
266  stride);
267  return true;
268  }
269  return false;
270  }
271 
272  //--------------------------------------------------------------------
273  AGG_INLINE unsigned width() const { return m_rbuf->width(); }
274  AGG_INLINE unsigned height() const { return m_rbuf->height(); }
275  AGG_INLINE int stride() const { return m_rbuf->stride(); }
276 
277  //--------------------------------------------------------------------
278  int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
279  const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
280  row_data row(int y) const { return m_rbuf->row(y); }
281 
282  //--------------------------------------------------------------------
283  AGG_INLINE int8u* pix_ptr(int x, int y)
284  {
285  return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
286  }
287 
288  AGG_INLINE const int8u* pix_ptr(int x, int y) const
289  {
290  return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
291  }
292 
293  // Return pointer to pixel value, forcing row to be allocated.
294  AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len)
295  {
296  return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_offset));
297  }
298 
299  // Return pointer to pixel value, or null if row not allocated.
300  AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const
301  {
302  int8u* p = m_rbuf->row_ptr(y);
303  return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step + pix_offset)) : 0;
304  }
305 
306  // Get pixel pointer from raw buffer pointer.
307  AGG_INLINE static pixel_type* pix_value_ptr(void* p)
308  {
309  return (pixel_type*)((value_type*)p + pix_offset);
310  }
311 
312  // Get pixel pointer from raw buffer pointer.
313  AGG_INLINE static const pixel_type* pix_value_ptr(const void* p)
314  {
315  return (const pixel_type*)((const value_type*)p + pix_offset);
316  }
317 
318  //--------------------------------------------------------------------
319  AGG_INLINE static void write_plain_color(void* p, color_type c)
320  {
321  // Grayscale formats are implicitly premultiplied.
322  c.premultiply();
323  pix_value_ptr(p)->set(c);
324  }
325 
326  //--------------------------------------------------------------------
327  AGG_INLINE static color_type read_plain_color(const void* p)
328  {
329  return pix_value_ptr(p)->get();
330  }
331 
332  //--------------------------------------------------------------------
333  AGG_INLINE static void make_pix(int8u* p, const color_type& c)
334  {
335  ((pixel_type*)p)->set(c);
336  }
337 
338  //--------------------------------------------------------------------
339  AGG_INLINE color_type pixel(int x, int y) const
340  {
341  if (const pixel_type* p = pix_value_ptr(x, y))
342  {
343  return p->get();
344  }
345  return color_type::no_color();
346  }
347 
348  //--------------------------------------------------------------------
349  AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
350  {
351  pix_value_ptr(x, y, 1)->set(c);
352  }
353 
354  //--------------------------------------------------------------------
355  AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
356  {
357  copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover);
358  }
359 
360  //--------------------------------------------------------------------
361  AGG_INLINE void copy_hline(int x, int y,
362  unsigned len,
363  const color_type& c)
364  {
365  pixel_type* p = pix_value_ptr(x, y, len);
366  do
367  {
368  p->set(c);
369  p = p->next();
370  }
371  while(--len);
372  }
373 
374 
375  //--------------------------------------------------------------------
376  AGG_INLINE void copy_vline(int x, int y,
377  unsigned len,
378  const color_type& c)
379  {
380  do
381  {
382  pix_value_ptr(x, y++, 1)->set(c);
383  }
384  while (--len);
385  }
386 
387 
388  //--------------------------------------------------------------------
389  void blend_hline(int x, int y,
390  unsigned len,
391  const color_type& c,
392  int8u cover)
393  {
394  if (!c.is_transparent())
395  {
396  pixel_type* p = pix_value_ptr(x, y, len);
397 
398  if (c.is_opaque() && cover == cover_mask)
399  {
400  do
401  {
402  p->set(c);
403  p = p->next();
404  }
405  while (--len);
406  }
407  else
408  {
409  do
410  {
411  blend_pix(p, c, cover);
412  p = p->next();
413  }
414  while (--len);
415  }
416  }
417  }
418 
419 
420  //--------------------------------------------------------------------
421  void blend_vline(int x, int y,
422  unsigned len,
423  const color_type& c,
424  int8u cover)
425  {
426  if (!c.is_transparent())
427  {
428  if (c.is_opaque() && cover == cover_mask)
429  {
430  do
431  {
432  pix_value_ptr(x, y++, 1)->set(c);
433  }
434  while (--len);
435  }
436  else
437  {
438  do
439  {
440  blend_pix(pix_value_ptr(x, y++, 1), c, cover);
441  }
442  while (--len);
443  }
444  }
445  }
446 
447 
448  //--------------------------------------------------------------------
449  void blend_solid_hspan(int x, int y,
450  unsigned len,
451  const color_type& c,
452  const int8u* covers)
453  {
454  if (!c.is_transparent())
455  {
456  pixel_type* p = pix_value_ptr(x, y, len);
457 
458  do
459  {
460  if (c.is_opaque() && *covers == cover_mask)
461  {
462  p->set(c);
463  }
464  else
465  {
466  blend_pix(p, c, *covers);
467  }
468  p = p->next();
469  ++covers;
470  }
471  while (--len);
472  }
473  }
474 
475 
476  //--------------------------------------------------------------------
477  void blend_solid_vspan(int x, int y,
478  unsigned len,
479  const color_type& c,
480  const int8u* covers)
481  {
482  if (!c.is_transparent())
483  {
484  do
485  {
486  pixel_type* p = pix_value_ptr(x, y++, 1);
487 
488  if (c.is_opaque() && *covers == cover_mask)
489  {
490  p->set(c);
491  }
492  else
493  {
494  blend_pix(p, c, *covers);
495  }
496  ++covers;
497  }
498  while (--len);
499  }
500  }
501 
502 
503  //--------------------------------------------------------------------
504  void copy_color_hspan(int x, int y,
505  unsigned len,
506  const color_type* colors)
507  {
508  pixel_type* p = pix_value_ptr(x, y, len);
509 
510  do
511  {
512  p->set(*colors++);
513  p = p->next();
514  }
515  while (--len);
516  }
517 
518 
519  //--------------------------------------------------------------------
520  void copy_color_vspan(int x, int y,
521  unsigned len,
522  const color_type* colors)
523  {
524  do
525  {
526  pix_value_ptr(x, y++, 1)->set(*colors++);
527  }
528  while (--len);
529  }
530 
531 
532  //--------------------------------------------------------------------
533  void blend_color_hspan(int x, int y,
534  unsigned len,
535  const color_type* colors,
536  const int8u* covers,
537  int8u cover)
538  {
539  pixel_type* p = pix_value_ptr(x, y, len);
540 
541  if (covers)
542  {
543  do
544  {
545  copy_or_blend_pix(p, *colors++, *covers++);
546  p = p->next();
547  }
548  while (--len);
549  }
550  else
551  {
552  if (cover == cover_mask)
553  {
554  do
555  {
556  copy_or_blend_pix(p, *colors++);
557  p = p->next();
558  }
559  while (--len);
560  }
561  else
562  {
563  do
564  {
565  copy_or_blend_pix(p, *colors++, cover);
566  p = p->next();
567  }
568  while (--len);
569  }
570  }
571  }
572 
573 
574  //--------------------------------------------------------------------
575  void blend_color_vspan(int x, int y,
576  unsigned len,
577  const color_type* colors,
578  const int8u* covers,
579  int8u cover)
580  {
581  if (covers)
582  {
583  do
584  {
585  copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++);
586  }
587  while (--len);
588  }
589  else
590  {
591  if (cover == cover_mask)
592  {
593  do
594  {
595  copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++);
596  }
597  while (--len);
598  }
599  else
600  {
601  do
602  {
603  copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover);
604  }
605  while (--len);
606  }
607  }
608  }
609 
610  //--------------------------------------------------------------------
611  template<class Function> void for_each_pixel(Function f)
612  {
613  unsigned y;
614  for (y = 0; y < height(); ++y)
615  {
616  row_data r = m_rbuf->row(y);
617  if (r.ptr)
618  {
619  unsigned len = r.x2 - r.x1 + 1;
620  pixel_type* p = pix_value_ptr(r.x1, y, len);
621  do
622  {
623  f(p->c);
624  p = p->next();
625  }
626  while (--len);
627  }
628  }
629  }
630 
631  //--------------------------------------------------------------------
632  template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
633  {
635  }
636 
637  //--------------------------------------------------------------------
638  template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
639  {
641  }
642 
643  //--------------------------------------------------------------------
644  template<class RenBuf2>
645  void copy_from(const RenBuf2& from,
646  int xdst, int ydst,
647  int xsrc, int ysrc,
648  unsigned len)
649  {
650  if (const int8u* p = from.row_ptr(ysrc))
651  {
652  std::memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
653  p + xsrc * pix_width,
654  len * pix_width);
655  }
656  }
657 
658  //--------------------------------------------------------------------
659  // Blend from single color, using grayscale surface as alpha channel.
660  template<class SrcPixelFormatRenderer>
661  void blend_from_color(const SrcPixelFormatRenderer& from,
662  const color_type& color,
663  int xdst, int ydst,
664  int xsrc, int ysrc,
665  unsigned len,
666  int8u cover)
667  {
668  typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
669  typedef typename SrcPixelFormatRenderer::color_type src_color_type;
670 
671  if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
672  {
673  pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
674 
675  do
676  {
677  copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0]));
678  psrc = psrc->next();
679  pdst = pdst->next();
680  }
681  while (--len);
682  }
683  }
684 
685  //--------------------------------------------------------------------
686  // Blend from color table, using grayscale surface as indexes into table.
687  // Obviously, this only works for integer value types.
688  template<class SrcPixelFormatRenderer>
689  void blend_from_lut(const SrcPixelFormatRenderer& from,
690  const color_type* color_lut,
691  int xdst, int ydst,
692  int xsrc, int ysrc,
693  unsigned len,
694  int8u cover)
695  {
696  typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
697 
698  if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
699  {
700  pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
701 
702  do
703  {
704  copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover);
705  psrc = psrc->next();
706  pdst = pdst->next();
707  }
708  while (--len);
709  }
710  }
711 
712  private:
713  rbuf_type* m_rbuf;
714  };
715 
720 
725 
730 
735 }
736 
737 #endif
738 
Definition: agg_arc.cpp:24