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_RGB_INCLUDED
25#define AGG_PIXFMT_RGB_INCLUDED
26
27#include <string.h>
28#include "agg_basics.h"
29#include "agg_color_rgba.h"
30#include "agg_rendering_buffer.h"
31
32namespace agg
33{
34
35    //=====================================================apply_gamma_dir_rgb
36    template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb
37    {
38    public:
39        typedef typename ColorT::value_type value_type;
40
41        apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
42
43        AGG_INLINE void operator () (value_type* p)
44        {
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]);
48        }
49
50    private:
51        const GammaLut& m_gamma;
52    };
53
54
55
56    //=====================================================apply_gamma_inv_rgb
57    template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb
58    {
59    public:
60        typedef typename ColorT::value_type value_type;
61
62        apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
63
64        AGG_INLINE void operator () (value_type* p)
65        {
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]);
69        }
70
71    private:
72        const GammaLut& m_gamma;
73    };
74
75
76    //=========================================================blender_rgb
77    template<class ColorT, class Order> struct blender_rgb
78    {
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_scale_e { base_shift = color_type::base_shift };
84
85        //--------------------------------------------------------------------
86        static AGG_INLINE void blend_pix(value_type* p,
87                                         unsigned cr, unsigned cg, unsigned cb,
88                                         unsigned alpha,
89                                         unsigned cover=0)
90        {
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);
94        }
95    };
96
97
98    //======================================================blender_rgb_pre
99    template<class ColorT, class Order> struct blender_rgb_pre
100    {
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_scale_e { base_shift = color_type::base_shift };
106
107        //--------------------------------------------------------------------
108        static AGG_INLINE void blend_pix(value_type* p,
109                                         unsigned cr, unsigned cg, unsigned cb,
110                                         unsigned alpha,
111                                         unsigned cover)
112        {
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);
118        }
119
120        //--------------------------------------------------------------------
121        static AGG_INLINE void blend_pix(value_type* p,
122                                         unsigned cr, unsigned cg, unsigned cb,
123                                         unsigned alpha)
124        {
125            alpha = color_type::base_mask - alpha;
126            p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr);
127            p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg);
128            p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb);
129        }
130
131    };
132
133
134
135    //===================================================blender_rgb_gamma
136    template<class ColorT, class Order, class Gamma> class blender_rgb_gamma
137    {
138    public:
139        typedef ColorT color_type;
140        typedef Order order_type;
141        typedef Gamma gamma_type;
142        typedef typename color_type::value_type value_type;
143        typedef typename color_type::calc_type calc_type;
144        enum base_scale_e { base_shift = color_type::base_shift };
145
146        //--------------------------------------------------------------------
147        blender_rgb_gamma() : m_gamma(0) {}
148        void gamma(const gamma_type& g) { m_gamma = &g; }
149
150        //--------------------------------------------------------------------
151        AGG_INLINE void blend_pix(value_type* p,
152                                  unsigned cr, unsigned cg, unsigned cb,
153                                  unsigned alpha,
154                                  unsigned cover=0)
155        {
156            calc_type r = m_gamma->dir(p[Order::R]);
157            calc_type g = m_gamma->dir(p[Order::G]);
158            calc_type b = m_gamma->dir(p[Order::B]);
159            p[Order::R] = m_gamma->inv((((m_gamma->dir(cr) - r) * alpha) >> base_shift) + r);
160            p[Order::G] = m_gamma->inv((((m_gamma->dir(cg) - g) * alpha) >> base_shift) + g);
161            p[Order::B] = m_gamma->inv((((m_gamma->dir(cb) - b) * alpha) >> base_shift) + b);
162        }
163
164    private:
165        const gamma_type* m_gamma;
166    };
167
168
169
170
171    //==================================================pixfmt_alpha_blend_rgb
172    template<class Blender, class RenBuf> class pixfmt_alpha_blend_rgb
173    {
174    public:
175        typedef RenBuf   rbuf_type;
176        typedef Blender  blender_type;
177        typedef typename rbuf_type::row_data row_data;
178        typedef typename blender_type::color_type color_type;
179        typedef typename blender_type::order_type order_type;
180        typedef typename color_type::value_type value_type;
181        typedef typename color_type::calc_type calc_type;
182        enum base_scale_e
183        {
184            base_shift = color_type::base_shift,
185            base_scale = color_type::base_scale,
186            base_mask  = color_type::base_mask,
187            pix_width  = sizeof(value_type) * 3
188        };
189
190    private:
191        //--------------------------------------------------------------------
192        AGG_INLINE void copy_or_blend_pix(value_type* p,
193                                          const color_type& c,
194                                          unsigned cover)
195        {
196            if (c.a)
197            {
198                calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
199                if(alpha == base_mask)
200                {
201                    p[order_type::R] = c.r;
202                    p[order_type::G] = c.g;
203                    p[order_type::B] = c.b;
204                }
205                else
206                {
207                    m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
208                }
209            }
210        }
211
212        //--------------------------------------------------------------------
213        AGG_INLINE void copy_or_blend_pix(value_type* p,
214                                          const color_type& c)
215        {
216            if (c.a)
217            {
218                if(c.a == base_mask)
219                {
220                    p[order_type::R] = c.r;
221                    p[order_type::G] = c.g;
222                    p[order_type::B] = c.b;
223                }
224                else
225                {
226                    m_blender.blend_pix(p, c.r, c.g, c.b, c.a);
227                }
228            }
229        }
230
231
232    public:
233        //--------------------------------------------------------------------
234        pixfmt_alpha_blend_rgb(rbuf_type& rb) :
235            m_rbuf(&rb)
236        {}
237        void attach(rbuf_type& rb) { m_rbuf = &rb; }
238
239        //--------------------------------------------------------------------
240        template<class PixFmt>
241        bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
242        {
243            rect_i r(x1, y1, x2, y2);
244            if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
245            {
246                int stride = pixf.stride();
247                m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
248                               (r.x2 - r.x1) + 1,
249                               (r.y2 - r.y1) + 1,
250                               stride);
251                return true;
252            }
253            return false;
254        }
255
256        //--------------------------------------------------------------------
257        Blender& blender() { return m_blender; }
258
259        //--------------------------------------------------------------------
260        AGG_INLINE unsigned width()  const { return m_rbuf->width();  }
261        AGG_INLINE unsigned height() const { return m_rbuf->height(); }
262        AGG_INLINE int      stride() const { return m_rbuf->stride(); }
263
264        //--------------------------------------------------------------------
265        AGG_INLINE       int8u* row_ptr(int y)       { return m_rbuf->row_ptr(y); }
266        AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
267        AGG_INLINE row_data     row(int y)     const { return m_rbuf->row(y); }
268
269        //--------------------------------------------------------------------
270        AGG_INLINE int8u* pix_ptr(int x, int y)
271        {
272            return m_rbuf->row_ptr(y) + x * pix_width;
273        }
274
275        AGG_INLINE const int8u* pix_ptr(int x, int y) const
276        {
277            return m_rbuf->row_ptr(y) + x * pix_width;
278        }
279
280        //--------------------------------------------------------------------
281        AGG_INLINE static void make_pix(int8u* p, const color_type& c)
282        {
283            ((value_type*)p)[order_type::R] = c.r;
284            ((value_type*)p)[order_type::G] = c.g;
285            ((value_type*)p)[order_type::B] = c.b;
286        }
287
288        //--------------------------------------------------------------------
289        AGG_INLINE color_type pixel(int x, int y) const
290        {
291            value_type* p = (value_type*)m_rbuf->row_ptr(y) + x + x + x;
292            return color_type(p[order_type::R],
293                              p[order_type::G],
294                              p[order_type::B]);
295        }
296
297        //--------------------------------------------------------------------
298        AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
299        {
300            value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x;
301            p[order_type::R] = c.r;
302            p[order_type::G] = c.g;
303            p[order_type::B] = c.b;
304        }
305
306        //--------------------------------------------------------------------
307        AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
308        {
309            copy_or_blend_pix((value_type*)m_rbuf->row_ptr(x, y, 1) + x + x + x, c, cover);
310        }
311
312
313        //--------------------------------------------------------------------
314        AGG_INLINE void copy_hline(int x, int y,
315                                   unsigned len,
316                                   const color_type& c)
317        {
318            value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + x + x + x;
319            do
320            {
321                p[order_type::R] = c.r;
322                p[order_type::G] = c.g;
323                p[order_type::B] = c.b;
324                p += 3;
325            }
326            while(--len);
327        }
328
329
330        //--------------------------------------------------------------------
331        AGG_INLINE void copy_vline(int x, int y,
332                                   unsigned len,
333                                   const color_type& c)
334        {
335            do
336            {
337                value_type* p = (value_type*)
338                    m_rbuf->row_ptr(x, y++, 1) + x + x + x;
339                p[order_type::R] = c.r;
340                p[order_type::G] = c.g;
341                p[order_type::B] = c.b;
342            }
343            while(--len);
344        }
345
346
347        //--------------------------------------------------------------------
348        void blend_hline(int x, int y,
349                         unsigned len,
350                         const color_type& c,
351                         int8u cover)
352        {
353            if (c.a)
354            {
355                value_type* p = (value_type*)
356                    m_rbuf->row_ptr(x, y, len) + x + x + x;
357
358                calc_type alpha = (calc_type(c.a) * (calc_type(cover) + 1)) >> 8;
359                if(alpha == base_mask)
360                {
361                    do
362                    {
363                        p[order_type::R] = c.r;
364                        p[order_type::G] = c.g;
365                        p[order_type::B] = c.b;
366                        p += 3;
367                    }
368                    while(--len);
369                }
370                else
371                {
372                    do
373                    {
374                        m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
375                        p += 3;
376                    }
377                    while(--len);
378                }
379            }
380        }
381
382
383        //--------------------------------------------------------------------
384        void blend_vline(int x, int y,
385                         unsigned len,
386                         const color_type& c,
387                         int8u cover)
388        {
389            if (c.a)
390            {
391                value_type* p;
392                calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
393                if(alpha == base_mask)
394                {
395                    do
396                    {
397                        p = (value_type*)
398                            m_rbuf->row_ptr(x, y++, 1) + x + x + x;
399
400                        p[order_type::R] = c.r;
401                        p[order_type::G] = c.g;
402                        p[order_type::B] = c.b;
403                    }
404                    while(--len);
405                }
406                else
407                {
408                    do
409                    {
410                        p = (value_type*)
411                            m_rbuf->row_ptr(x, y++, 1) + x + x + x;
412
413                        m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover);
414                    }
415                    while(--len);
416                }
417            }
418        }
419
420
421        //--------------------------------------------------------------------
422        void blend_solid_hspan(int x, int y,
423                               unsigned len,
424                               const color_type& c,
425                               const int8u* covers)
426        {
427            if (c.a)
428            {
429                value_type* p = (value_type*)
430                    m_rbuf->row_ptr(x, y, len) + x + x + x;
431
432                do
433                {
434                    calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
435                    if(alpha == base_mask)
436                    {
437                        p[order_type::R] = c.r;
438                        p[order_type::G] = c.g;
439                        p[order_type::B] = c.b;
440                    }
441                    else
442                    {
443                        m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
444                    }
445                    p += 3;
446                    ++covers;
447                }
448                while(--len);
449            }
450        }
451
452
453        //--------------------------------------------------------------------
454        void blend_solid_vspan(int x, int y,
455                               unsigned len,
456                               const color_type& c,
457                               const int8u* covers)
458        {
459            if (c.a)
460            {
461                do
462                {
463                    value_type* p = (value_type*)
464                        m_rbuf->row_ptr(x, y++, 1) + x + x + x;
465
466                    calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
467                    if(alpha == base_mask)
468                    {
469                        p[order_type::R] = c.r;
470                        p[order_type::G] = c.g;
471                        p[order_type::B] = c.b;
472                    }
473                    else
474                    {
475                        m_blender.blend_pix(p, c.r, c.g, c.b, alpha, *covers);
476                    }
477                    ++covers;
478                }
479                while(--len);
480            }
481        }
482
483
484        //--------------------------------------------------------------------
485        void copy_color_hspan(int x, int y,
486                              unsigned len,
487                              const color_type* colors)
488        {
489            value_type* p = (value_type*)
490                m_rbuf->row_ptr(x, y, len) + x + x + x;
491
492            do
493            {
494                p[order_type::R] = colors->r;
495                p[order_type::G] = colors->g;
496                p[order_type::B] = colors->b;
497                ++colors;
498                p += 3;
499            }
500            while(--len);
501        }
502
503
504        //--------------------------------------------------------------------
505        void copy_color_vspan(int x, int y,
506                              unsigned len,
507                              const color_type* colors)
508        {
509            do
510            {
511                value_type* p = (value_type*)
512                    m_rbuf->row_ptr(x, y++, 1) + x + x + x;
513                p[order_type::R] = colors->r;
514                p[order_type::G] = colors->g;
515                p[order_type::B] = colors->b;
516                ++colors;
517            }
518            while(--len);
519        }
520
521
522        //--------------------------------------------------------------------
523        void blend_color_hspan(int x, int y,
524                               unsigned len,
525                               const color_type* colors,
526                               const int8u* covers,
527                               int8u cover)
528        {
529            value_type* p = (value_type*)
530                m_rbuf->row_ptr(x, y, len) + x + x + x;
531
532            if(covers)
533            {
534                do
535                {
536                    copy_or_blend_pix(p, *colors++, *covers++);
537                    p += 3;
538                }
539                while(--len);
540            }
541            else
542            {
543                if(cover == 255)
544                {
545                    do
546                    {
547                        copy_or_blend_pix(p, *colors++);
548                        p += 3;
549                    }
550                    while(--len);
551                }
552                else
553                {
554                    do
555                    {
556                        copy_or_blend_pix(p, *colors++, cover);
557                        p += 3;
558                    }
559                    while(--len);
560                }
561            }
562        }
563
564
565
566        //--------------------------------------------------------------------
567        void blend_color_vspan(int x, int y,
568                               unsigned len,
569                               const color_type* colors,
570                               const int8u* covers,
571                               int8u cover)
572        {
573            value_type* p;
574            if(covers)
575            {
576                do
577                {
578                    p = (value_type*)
579                        m_rbuf->row_ptr(x, y++, 1) + x + x + x;
580
581                    copy_or_blend_pix(p, *colors++, *covers++);
582                }
583                while(--len);
584            }
585            else
586            {
587                if(cover == 255)
588                {
589                    do
590                    {
591                        p = (value_type*)
592                            m_rbuf->row_ptr(x, y++, 1) + x + x + x;
593
594                        copy_or_blend_pix(p, *colors++);
595                    }
596                    while(--len);
597                }
598                else
599                {
600                    do
601                    {
602                        p = (value_type*)
603                            m_rbuf->row_ptr(x, y++, 1) + x + x + x;
604
605                        copy_or_blend_pix(p, *colors++, cover);
606                    }
607                    while(--len);
608                }
609            }
610        }
611
612        //--------------------------------------------------------------------
613        template<class Function> void for_each_pixel(Function f)
614        {
615            unsigned y;
616            for(y = 0; y < height(); ++y)
617            {
618                row_data r = m_rbuf->row(y);
619                if(r.ptr)
620                {
621                    unsigned len = r.x2 - r.x1 + 1;
622                    value_type* p = (value_type*)
623                        m_rbuf->row_ptr(r.x1, y, len) + r.x1 * 3;
624                    do
625                    {
626                        f(p);
627                        p += 3;
628                    }
629                    while(--len);
630                }
631            }
632        }
633
634        //--------------------------------------------------------------------
635        template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
636        {
637            for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g));
638        }
639
640        //--------------------------------------------------------------------
641        template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
642        {
643            for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g));
644        }
645
646        //--------------------------------------------------------------------
647        template<class RenBuf2>
648        void copy_from(const RenBuf2& from,
649                       int xdst, int ydst,
650                       int xsrc, int ysrc,
651                       unsigned len)
652        {
653            const int8u* p = from.row_ptr(ysrc);
654            if(p)
655            {
656                memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
657                        p + xsrc * pix_width,
658                        len * pix_width);
659            }
660        }
661
662
663        //--------------------------------------------------------------------
664        template<class SrcPixelFormatRenderer>
665        void blend_from(const SrcPixelFormatRenderer& from,
666                        int xdst, int ydst,
667                        int xsrc, int ysrc,
668                        unsigned len,
669                        int8u cover)
670        {
671            typedef typename SrcPixelFormatRenderer::order_type src_order;
672
673            const value_type* psrc = (const value_type*)from.row_ptr(ysrc);
674            if(psrc)
675            {
676                psrc += xsrc * 4;
677                value_type* pdst =
678                    (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst * 3;
679
680                if(cover == 255)
681                {
682                    do
683                    {
684                        value_type alpha = psrc[src_order::A];
685                        if(alpha)
686                        {
687                            if(alpha == base_mask)
688                            {
689                                pdst[order_type::R] = psrc[src_order::R];
690                                pdst[order_type::G] = psrc[src_order::G];
691                                pdst[order_type::B] = psrc[src_order::B];
692                            }
693                            else
694                            {
695                                m_blender.blend_pix(pdst,
696                                                    psrc[src_order::R],
697                                                    psrc[src_order::G],
698                                                    psrc[src_order::B],
699                                                    alpha);
700                            }
701                        }
702                        psrc += 4;
703                        pdst += 3;
704                    }
705                    while(--len);
706                }
707                else
708                {
709                    color_type color;
710                    do
711                    {
712                        color.r = psrc[src_order::R];
713                        color.g = psrc[src_order::G];
714                        color.b = psrc[src_order::B];
715                        color.a = psrc[src_order::A];
716                        copy_or_blend_pix(pdst, color, cover);
717                        psrc += 4;
718                        pdst += 3;
719                    }
720                    while(--len);
721                }
722            }
723        }
724
725    private:
726        rbuf_type* m_rbuf;
727        Blender    m_blender;
728    };
729
730    typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8,  order_rgb>, rendering_buffer> pixfmt_rgb24;    //----pixfmt_rgb24
731    typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8,  order_bgr>, rendering_buffer> pixfmt_bgr24;    //----pixfmt_bgr24
732    typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48;    //----pixfmt_rgb48
733    typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48;    //----pixfmt_bgr48
734
735    typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8,  order_rgb>, rendering_buffer> pixfmt_rgb24_pre; //----pixfmt_rgb24_pre
736    typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba8,  order_bgr>, rendering_buffer> pixfmt_bgr24_pre; //----pixfmt_bgr24_pre
737    typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_rgb>, rendering_buffer> pixfmt_rgb48_pre; //----pixfmt_rgb48_pre
738    typedef pixfmt_alpha_blend_rgb<blender_rgb_pre<rgba16, order_bgr>, rendering_buffer> pixfmt_bgr48_pre; //----pixfmt_bgr48_pre
739
740    //-----------------------------------------------------pixfmt_rgb24_gamma
741    template<class Gamma> class pixfmt_rgb24_gamma :
742    public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>
743    {
744    public:
745        pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) :
746            pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer>(rb)
747        {
748            this->blender().gamma(g);
749        }
750    };
751
752    //-----------------------------------------------------pixfmt_bgr24_gamma
753    template<class Gamma> class pixfmt_bgr24_gamma :
754    public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>
755    {
756    public:
757        pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) :
758            pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer>(rb)
759        {
760            this->blender().gamma(g);
761        }
762    };
763
764    //-----------------------------------------------------pixfmt_rgb48_gamma
765    template<class Gamma> class pixfmt_rgb48_gamma :
766    public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>
767    {
768    public:
769        pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) :
770            pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer>(rb)
771        {
772            this->blender().gamma(g);
773        }
774    };
775
776    //-----------------------------------------------------pixfmt_bgr48_gamma
777    template<class Gamma> class pixfmt_bgr48_gamma :
778    public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>
779    {
780    public:
781        pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) :
782            pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer>(rb)
783        {
784            this->blender().gamma(g);
785        }
786    };
787
788
789}
790
791#endif
792
793