1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 // Adaptation for high precision colors has been sponsored by
17 // Liberty Technology Systems, Inc., visit http://lib-sys.com
19 // Liberty Technology Systems, Inc. is the provider of
20 // PostScript and PDF technology for software developers.
22 //----------------------------------------------------------------------------
24 #ifndef AGG_PIXFMT_RGB_INCLUDED
25 #define AGG_PIXFMT_RGB_INCLUDED
28 #include "agg_basics.h"
29 #include "agg_color_rgba.h"
30 #include "agg_rendering_buffer.h"
35 //=====================================================apply_gamma_dir_rgb
36 template<class ColorT
, class Order
, class GammaLut
> class apply_gamma_dir_rgb
39 typedef typename
ColorT::value_type value_type
;
41 apply_gamma_dir_rgb(const GammaLut
& gamma
) : m_gamma(gamma
) {}
43 AGG_INLINE
void operator () (value_type
* p
)
45 p
[Order::R
] = m_gamma
.dir(p
[Order::R
]);
46 p
[Order::G
] = m_gamma
.dir(p
[Order::G
]);
47 p
[Order::B
] = m_gamma
.dir(p
[Order::B
]);
51 const GammaLut
& m_gamma
;
56 //=====================================================apply_gamma_inv_rgb
57 template<class ColorT
, class Order
, class GammaLut
> class apply_gamma_inv_rgb
60 typedef typename
ColorT::value_type value_type
;
62 apply_gamma_inv_rgb(const GammaLut
& gamma
) : m_gamma(gamma
) {}
64 AGG_INLINE
void operator () (value_type
* p
)
66 p
[Order::R
] = m_gamma
.inv(p
[Order::R
]);
67 p
[Order::G
] = m_gamma
.inv(p
[Order::G
]);
68 p
[Order::B
] = m_gamma
.inv(p
[Order::B
]);
72 const GammaLut
& m_gamma
;
76 //=========================================================blender_rgb
77 template<class ColorT
, class Order
> struct blender_rgb
79 typedef ColorT color_type
;
80 typedef Order order_type
;
81 typedef typename
color_type::value_type value_type
;
82 typedef typename
color_type::calc_type calc_type
;
83 enum { base_shift
= color_type::base_shift
};
85 //--------------------------------------------------------------------
86 static AGG_INLINE
void blend_pix(value_type
* p
,
87 unsigned cr
, unsigned cg
, unsigned cb
,
91 p
[Order::R
] += (value_type
)(((cr
- p
[Order::R
]) * alpha
) >> base_shift
);
92 p
[Order::G
] += (value_type
)(((cg
- p
[Order::G
]) * alpha
) >> base_shift
);
93 p
[Order::B
] += (value_type
)(((cb
- p
[Order::B
]) * alpha
) >> base_shift
);
98 //======================================================blender_rgb_pre
99 template<class ColorT
, class Order
> struct blender_rgb_pre
101 typedef ColorT color_type
;
102 typedef Order order_type
;
103 typedef typename
color_type::value_type value_type
;
104 typedef typename
color_type::calc_type calc_type
;
105 enum { base_shift
= color_type::base_shift
};
107 //--------------------------------------------------------------------
108 static AGG_INLINE
void blend_pix(value_type
* p
,
109 unsigned cr
, unsigned cg
, unsigned cb
,
113 alpha
= color_type::base_mask
- alpha
;
114 cover
= (cover
+ 1) << (base_shift
- 8);
115 p
[Order::R
] = (value_type
)((p
[Order::R
] * alpha
+ cr
* cover
) >> base_shift
);
116 p
[Order::G
] = (value_type
)((p
[Order::G
] * alpha
+ cg
* cover
) >> base_shift
);
117 p
[Order::B
] = (value_type
)((p
[Order::B
] * alpha
+ cb
* cover
) >> base_shift
);
123 //===================================================blender_rgb_gamma
124 template<class ColorT
, class Order
, class Gamma
> class blender_rgb_gamma
127 typedef ColorT color_type
;
128 typedef Order order_type
;
129 typedef Gamma gamma_type
;
130 typedef typename
color_type::value_type value_type
;
131 typedef typename
color_type::calc_type calc_type
;
132 enum { base_shift
= color_type::base_shift
};
134 //--------------------------------------------------------------------
135 blender_rgb_gamma() : m_gamma(0) {}
136 void gamma(const gamma_type
& g
) { m_gamma
= &g
; }
138 //--------------------------------------------------------------------
139 AGG_INLINE
void blend_pix(value_type
* p
,
140 unsigned cr
, unsigned cg
, unsigned cb
,
144 calc_type r
= m_gamma
->dir(p
[Order::R
]);
145 calc_type g
= m_gamma
->dir(p
[Order::G
]);
146 calc_type b
= m_gamma
->dir(p
[Order::B
]);
147 p
[Order::R
] = m_gamma
->inv((((m_gamma
->dir(cr
) - r
) * alpha
) >> base_shift
) + r
);
148 p
[Order::G
] = m_gamma
->inv((((m_gamma
->dir(cg
) - g
) * alpha
) >> base_shift
) + g
);
149 p
[Order::B
] = m_gamma
->inv((((m_gamma
->dir(cb
) - b
) * alpha
) >> base_shift
) + b
);
153 const gamma_type
* m_gamma
;
159 //==================================================pixel_formats_rgb
160 template<class Blender
> class pixel_formats_rgb
163 typedef rendering_buffer::row_data row_data
;
164 typedef typename
Blender::color_type color_type
;
165 typedef typename
Blender::order_type order_type
;
166 typedef typename
color_type::value_type value_type
;
167 typedef typename
color_type::calc_type calc_type
;
170 base_shift
= color_type::base_shift
,
171 base_size
= color_type::base_size
,
172 base_mask
= color_type::base_mask
176 //--------------------------------------------------------------------
177 AGG_INLINE
void copy_or_blend_pix(value_type
* p
,
183 calc_type alpha
= (calc_type(c
.a
) * (cover
+ 1)) >> 8;
184 if(alpha
== base_mask
)
186 p
[order_type::R
] = c
.r
;
187 p
[order_type::G
] = c
.g
;
188 p
[order_type::B
] = c
.b
;
192 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, alpha
, cover
);
197 //--------------------------------------------------------------------
198 AGG_INLINE
void copy_or_blend_opaque_pix(value_type
* p
,
204 p
[order_type::R
] = c
.r
;
205 p
[order_type::G
] = c
.g
;
206 p
[order_type::B
] = c
.b
;
210 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, (cover
+ 1) << (base_shift
- 8), cover
);
216 //--------------------------------------------------------------------
217 pixel_formats_rgb(rendering_buffer
& rb
) :
221 //--------------------------------------------------------------------
222 Blender
& blender() { return m_blender
; }
224 //--------------------------------------------------------------------
225 AGG_INLINE
unsigned width() const { return m_rbuf
->width(); }
226 AGG_INLINE
unsigned height() const { return m_rbuf
->height(); }
228 //--------------------------------------------------------------------
229 AGG_INLINE color_type
pixel(int x
, int y
) const
231 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
232 return color_type(p
[order_type::R
],
237 //--------------------------------------------------------------------
238 row_data
span(int x
, int y
) const
242 m_rbuf
->row(y
) + x
* 3 * sizeof(value_type
));
245 //--------------------------------------------------------------------
246 AGG_INLINE
void copy_pixel(int x
, int y
, const color_type
& c
)
248 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
249 p
[order_type::R
] = c
.r
;
250 p
[order_type::G
] = c
.g
;
251 p
[order_type::B
] = c
.b
;
254 //--------------------------------------------------------------------
255 AGG_INLINE
void blend_pixel(int x
, int y
, const color_type
& c
, int8u cover
)
257 copy_or_blend_pix((value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
, c
, cover
);
261 //--------------------------------------------------------------------
262 AGG_INLINE
void copy_hline(int x
, int y
,
266 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
269 p
[order_type::R
] = c
.r
;
270 p
[order_type::G
] = c
.g
;
271 p
[order_type::B
] = c
.b
;
278 //--------------------------------------------------------------------
279 AGG_INLINE
void copy_vline(int x
, int y
,
283 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
286 p
[order_type::R
] = c
.r
;
287 p
[order_type::G
] = c
.g
;
288 p
[order_type::B
] = c
.b
;
289 p
= (value_type
*)m_rbuf
->next_row(p
);
295 //--------------------------------------------------------------------
296 void blend_hline(int x
, int y
,
303 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
304 calc_type alpha
= (calc_type(c
.a
) * (calc_type(cover
) + 1)) >> 8;
305 if(alpha
== base_mask
)
309 p
[order_type::R
] = c
.r
;
310 p
[order_type::G
] = c
.g
;
311 p
[order_type::B
] = c
.b
;
320 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, alpha
, cover
);
329 //--------------------------------------------------------------------
330 void blend_vline(int x
, int y
,
337 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
338 calc_type alpha
= (calc_type(c
.a
) * (cover
+ 1)) >> 8;
339 if(alpha
== base_mask
)
343 p
[order_type::R
] = c
.r
;
344 p
[order_type::G
] = c
.g
;
345 p
[order_type::B
] = c
.b
;
346 p
= (value_type
*)m_rbuf
->next_row(p
);
354 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, alpha
, cover
);
355 p
= (value_type
*)m_rbuf
->next_row(p
);
363 //--------------------------------------------------------------------
364 void blend_solid_hspan(int x
, int y
,
371 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
374 calc_type alpha
= (calc_type(c
.a
) * (calc_type(*covers
) + 1)) >> 8;
375 if(alpha
== base_mask
)
377 p
[order_type::R
] = c
.r
;
378 p
[order_type::G
] = c
.g
;
379 p
[order_type::B
] = c
.b
;
383 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, alpha
, *covers
);
393 //--------------------------------------------------------------------
394 void blend_solid_vspan(int x
, int y
,
401 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
404 calc_type alpha
= (calc_type(c
.a
) * (calc_type(*covers
) + 1)) >> 8;
405 if(alpha
== base_mask
)
407 p
[order_type::R
] = c
.r
;
408 p
[order_type::G
] = c
.g
;
409 p
[order_type::B
] = c
.b
;
413 m_blender
.blend_pix(p
, c
.r
, c
.g
, c
.b
, alpha
, *covers
);
415 p
= (value_type
*)m_rbuf
->next_row(p
);
423 //--------------------------------------------------------------------
424 void blend_color_hspan(int x
, int y
,
426 const color_type
* colors
,
430 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
435 copy_or_blend_pix(p
, *colors
++, *covers
++);
446 if(colors
->a
== base_mask
)
448 p
[order_type::R
] = colors
->r
;
449 p
[order_type::G
] = colors
->g
;
450 p
[order_type::B
] = colors
->b
;
454 copy_or_blend_pix(p
, *colors
, 255);
465 copy_or_blend_pix(p
, *colors
++, cover
);
475 //--------------------------------------------------------------------
476 void blend_color_vspan(int x
, int y
,
478 const color_type
* colors
,
482 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
487 copy_or_blend_pix(p
, *colors
++, *covers
++);
488 p
= (value_type
*)m_rbuf
->next_row(p
);
498 if(colors
->a
== base_mask
)
500 p
[order_type::R
] = colors
->r
;
501 p
[order_type::G
] = colors
->g
;
502 p
[order_type::B
] = colors
->b
;
506 copy_or_blend_pix(p
, *colors
, 255);
508 p
= (value_type
*)m_rbuf
->next_row(p
);
517 copy_or_blend_pix(p
, *colors
++, cover
);
518 p
= (value_type
*)m_rbuf
->next_row(p
);
526 //--------------------------------------------------------------------
527 void blend_opaque_color_hspan(int x
, int y
,
529 const color_type
* colors
,
533 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
538 copy_or_blend_opaque_pix(p
, *colors
++, *covers
++);
549 p
[order_type::R
] = colors
->r
;
550 p
[order_type::G
] = colors
->g
;
551 p
[order_type::B
] = colors
->b
;
561 copy_or_blend_opaque_pix(p
, *colors
++, cover
);
570 //--------------------------------------------------------------------
571 void blend_opaque_color_vspan(int x
, int y
,
573 const color_type
* colors
,
577 value_type
* p
= (value_type
*)m_rbuf
->row(y
) + x
+ x
+ x
;
582 copy_or_blend_opaque_pix(p
, *colors
++, *covers
++);
583 p
= (value_type
*)m_rbuf
->next_row(p
);
593 p
[order_type::R
] = colors
->r
;
594 p
[order_type::G
] = colors
->g
;
595 p
[order_type::B
] = colors
->b
;
596 p
= (value_type
*)m_rbuf
->next_row(p
);
605 copy_or_blend_opaque_pix(p
, *colors
++, cover
);
606 p
= (value_type
*)m_rbuf
->next_row(p
);
613 //--------------------------------------------------------------------
614 template<class Function
> void for_each_pixel(Function f
)
617 for(y
= 0; y
< height(); ++y
)
619 unsigned len
= width();
620 value_type
* p
= (value_type
*)m_rbuf
->row(y
);
630 //--------------------------------------------------------------------
631 template<class GammaLut
> void apply_gamma_dir(const GammaLut
& g
)
633 for_each_pixel(apply_gamma_dir_rgb
<color_type
, order_type
, GammaLut
>(g
));
636 //--------------------------------------------------------------------
637 template<class GammaLut
> void apply_gamma_inv(const GammaLut
& g
)
639 for_each_pixel(apply_gamma_inv_rgb
<color_type
, order_type
, GammaLut
>(g
));
642 //--------------------------------------------------------------------
643 void copy_from(const rendering_buffer
& from
,
648 memmove((value_type
*)m_rbuf
->row(ydst
) + xdst
* 3,
649 (const value_type
*)from
.row(ysrc
) + xsrc
* 3,
650 sizeof(value_type
) * 3 * len
);
654 //--------------------------------------------------------------------
655 template<class SrcPixelFormatRenderer
>
656 void blend_from(const SrcPixelFormatRenderer
& from
,
662 typedef typename
SrcPixelFormatRenderer::order_type src_order
;
664 const value_type
* psrc
= (const value_type
*)psrc_
;
665 value_type
* pdst
= (value_type
*)m_rbuf
->row(ydst
) + xdst
* 3;
668 value_type alpha
= psrc
[src_order::A
];
671 if(alpha
== base_mask
)
673 pdst
[order_type::R
] = psrc
[src_order::R
];
674 pdst
[order_type::G
] = psrc
[src_order::G
];
675 pdst
[order_type::B
] = psrc
[src_order::B
];
679 m_blender
.blend_pix(pdst
,
694 rendering_buffer
* m_rbuf
;
698 typedef pixel_formats_rgb
<blender_rgb
<rgba8
, order_rgb
> > pixfmt_rgb24
; //----pixfmt_rgb24
699 typedef pixel_formats_rgb
<blender_rgb
<rgba8
, order_bgr
> > pixfmt_bgr24
; //----pixfmt_bgr24
700 typedef pixel_formats_rgb
<blender_rgb
<rgba16
, order_rgb
> > pixfmt_rgb48
; //----pixfmt_rgb48
701 typedef pixel_formats_rgb
<blender_rgb
<rgba16
, order_bgr
> > pixfmt_bgr48
; //----pixfmt_bgr48
703 typedef pixel_formats_rgb
<blender_rgb_pre
<rgba8
, order_rgb
> > pixfmt_rgb24_pre
; //----pixfmt_rgb24_pre
704 typedef pixel_formats_rgb
<blender_rgb_pre
<rgba8
, order_bgr
> > pixfmt_bgr24_pre
; //----pixfmt_bgr24_pre
705 typedef pixel_formats_rgb
<blender_rgb_pre
<rgba16
, order_rgb
> > pixfmt_rgb48_pre
; //----pixfmt_rgb48_pre
706 typedef pixel_formats_rgb
<blender_rgb_pre
<rgba16
, order_bgr
> > pixfmt_bgr48_pre
; //----pixfmt_bgr48_pre
708 //-----------------------------------------------------pixfmt_rgb24_gamma
709 template<class Gamma
> class pixfmt_rgb24_gamma
:
710 public pixel_formats_rgb
<blender_rgb_gamma
<rgba8
, order_rgb
, Gamma
> >
713 pixfmt_rgb24_gamma(rendering_buffer
& rb
, const Gamma
& g
) :
714 pixel_formats_rgb
<blender_rgb_gamma
<rgba8
, order_rgb
, Gamma
> >(rb
)
716 this->blender().gamma(g
);
720 //-----------------------------------------------------pixfmt_bgr24_gamma
721 template<class Gamma
> class pixfmt_bgr24_gamma
:
722 public pixel_formats_rgb
<blender_rgb_gamma
<rgba8
, order_bgr
, Gamma
> >
725 pixfmt_bgr24_gamma(rendering_buffer
& rb
, const Gamma
& g
) :
726 pixel_formats_rgb
<blender_rgb_gamma
<rgba8
, order_bgr
, Gamma
> >(rb
)
728 this->blender().gamma(g
);
732 //-----------------------------------------------------pixfmt_rgb48_gamma
733 template<class Gamma
> class pixfmt_rgb48_gamma
:
734 public pixel_formats_rgb
<blender_rgb_gamma
<rgba16
, order_rgb
, Gamma
> >
737 pixfmt_rgb48_gamma(rendering_buffer
& rb
, const Gamma
& g
) :
738 pixel_formats_rgb
<blender_rgb_gamma
<rgba16
, order_rgb
, Gamma
> >(rb
)
740 this->blender().gamma(g
);
744 //-----------------------------------------------------pixfmt_bgr48_gamma
745 template<class Gamma
> class pixfmt_bgr48_gamma
:
746 public pixel_formats_rgb
<blender_rgb_gamma
<rgba16
, order_bgr
, Gamma
> >
749 pixfmt_bgr48_gamma(rendering_buffer
& rb
, const Gamma
& g
) :
750 pixel_formats_rgb
<blender_rgb_gamma
<rgba16
, order_bgr
, Gamma
> >(rb
)
752 this->blender().gamma(g
);