Anti-Grain Geometry - AGG (libagg)  2.5
agg-2.5/include/agg_pixfmt_gray.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 // Anti-Grain Geometry (AGG) - Version 2.5
00003 // A high quality rendering engine for C++
00004 // Copyright (C) 2002-2006 Maxim Shemanarev
00005 // Contact: mcseem@antigrain.com
00006 //          mcseemagg@yahoo.com
00007 //          http://antigrain.com
00008 // 
00009 // AGG is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License
00011 // as published by the Free Software Foundation; either version 2
00012 // of the License, or (at your option) any later version.
00013 // 
00014 // AGG is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU General Public License
00020 // along with AGG; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00022 // MA 02110-1301, USA.
00023 //----------------------------------------------------------------------------
00024 //
00025 // Adaptation for high precision colors has been sponsored by 
00026 // Liberty Technology Systems, Inc., visit http://lib-sys.com
00027 //
00028 // Liberty Technology Systems, Inc. is the provider of
00029 // PostScript and PDF technology for software developers.
00030 // 
00031 //----------------------------------------------------------------------------
00032 
00033 #ifndef AGG_PIXFMT_GRAY_INCLUDED
00034 #define AGG_PIXFMT_GRAY_INCLUDED
00035 
00036 #include <string.h>
00037 #include "agg_basics.h"
00038 #include "agg_color_gray.h"
00039 #include "agg_rendering_buffer.h"
00040 
00041 namespace agg
00042 {
00043  
00044     //============================================================blender_gray
00045     template<class ColorT> struct blender_gray
00046     {
00047         typedef ColorT color_type;
00048         typedef typename color_type::value_type value_type;
00049         typedef typename color_type::calc_type calc_type;
00050         enum base_scale_e { base_shift = color_type::base_shift };
00051 
00052         static AGG_INLINE void blend_pix(value_type* p, unsigned cv, 
00053                                          unsigned alpha, unsigned cover=0)
00054         {
00055             *p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift);
00056         }
00057     };
00058 
00059 
00060     //======================================================blender_gray_pre
00061     template<class ColorT> struct blender_gray_pre
00062     {
00063         typedef ColorT color_type;
00064         typedef typename color_type::value_type value_type;
00065         typedef typename color_type::calc_type calc_type;
00066         enum base_scale_e { base_shift = color_type::base_shift };
00067 
00068         static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
00069                                          unsigned alpha, unsigned cover)
00070         {
00071             alpha = color_type::base_mask - alpha;
00072             cover = (cover + 1) << (base_shift - 8);
00073             *p = (value_type)((*p * alpha + cv * cover) >> base_shift);
00074         }
00075 
00076         static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
00077                                          unsigned alpha)
00078         {
00079             *p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv);
00080         }
00081     };
00082     
00083 
00084 
00085     //=====================================================apply_gamma_dir_gray
00086     template<class ColorT, class GammaLut> class apply_gamma_dir_gray
00087     {
00088     public:
00089         typedef typename ColorT::value_type value_type;
00090 
00091         apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {}
00092 
00093         AGG_INLINE void operator () (value_type* p)
00094         {
00095             *p = m_gamma.dir(*p);
00096         }
00097 
00098     private:
00099         const GammaLut& m_gamma;
00100     };
00101 
00102 
00103 
00104     //=====================================================apply_gamma_inv_gray
00105     template<class ColorT, class GammaLut> class apply_gamma_inv_gray
00106     {
00107     public:
00108         typedef typename ColorT::value_type value_type;
00109 
00110         apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {}
00111 
00112         AGG_INLINE void operator () (value_type* p)
00113         {
00114             *p = m_gamma.inv(*p);
00115         }
00116 
00117     private:
00118         const GammaLut& m_gamma;
00119     };
00120 
00121 
00122 
00123     //=================================================pixfmt_alpha_blend_gray
00124     template<class Blender, class RenBuf, unsigned Step=1, unsigned Offset=0>
00125     class pixfmt_alpha_blend_gray
00126     {
00127     public:
00128         typedef RenBuf   rbuf_type;
00129         typedef typename rbuf_type::row_data row_data;
00130         typedef Blender  blender_type;
00131         typedef typename blender_type::color_type color_type;
00132         typedef int                               order_type; // A fake one
00133         typedef typename color_type::value_type   value_type;
00134         typedef typename color_type::calc_type    calc_type;
00135         enum base_scale_e 
00136         {
00137             base_shift = color_type::base_shift,
00138             base_scale = color_type::base_scale,
00139             base_mask  = color_type::base_mask,
00140             pix_width  = sizeof(value_type),
00141             pix_step   = Step,
00142             pix_offset = Offset
00143         };
00144 
00145     private:
00146         //--------------------------------------------------------------------
00147         static AGG_INLINE void copy_or_blend_pix(value_type* p, 
00148                                                  const color_type& c, 
00149                                                  unsigned cover)
00150         {
00151             if (c.a)
00152             {
00153                 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
00154                 if(alpha == base_mask)
00155                 {
00156                     *p = c.v;
00157                 }
00158                 else
00159                 {
00160                     Blender::blend_pix(p, c.v, alpha, cover);
00161                 }
00162             }
00163         }
00164 
00165 
00166         static AGG_INLINE void copy_or_blend_pix(value_type* p, 
00167                                                  const color_type& c)
00168         {
00169             if (c.a)
00170             {
00171                 if(c.a == base_mask)
00172                 {
00173                     *p = c.v;
00174                 }
00175                 else
00176                 {
00177                     Blender::blend_pix(p, c.v, c.a);
00178                 }
00179             }
00180         }
00181 
00182 
00183     public:
00184         //--------------------------------------------------------------------
00185         explicit pixfmt_alpha_blend_gray(rbuf_type& rb) :
00186             m_rbuf(&rb)
00187         {}
00188         void attach(rbuf_type& rb) { m_rbuf = &rb; }
00189         //--------------------------------------------------------------------
00190 
00191         template<class PixFmt>
00192         bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
00193         {
00194             rect_i r(x1, y1, x2, y2);
00195             if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
00196             {
00197                 int stride = pixf.stride();
00198                 m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), 
00199                                (r.x2 - r.x1) + 1,
00200                                (r.y2 - r.y1) + 1,
00201                                stride);
00202                 return true;
00203             }
00204             return false;
00205         }
00206 
00207         //--------------------------------------------------------------------
00208         AGG_INLINE unsigned width()  const { return m_rbuf->width();  }
00209         AGG_INLINE unsigned height() const { return m_rbuf->height(); }
00210         AGG_INLINE int      stride() const { return m_rbuf->stride(); }
00211 
00212         //--------------------------------------------------------------------
00213               int8u* row_ptr(int y)       { return m_rbuf->row_ptr(y); }
00214         const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
00215         row_data     row(int y)     const { return m_rbuf->row(y); }
00216 
00217         const int8u* pix_ptr(int x, int y) const
00218         {
00219             return m_rbuf->row_ptr(y) + x * Step + Offset;
00220         }
00221 
00222         int8u* pix_ptr(int x, int y)
00223         {
00224             return m_rbuf->row_ptr(y) + x * Step + Offset;
00225         }
00226 
00227         //--------------------------------------------------------------------
00228         AGG_INLINE static void make_pix(int8u* p, const color_type& c)
00229         {
00230             *(value_type*)p = c.v;
00231         }
00232 
00233         //--------------------------------------------------------------------
00234         AGG_INLINE color_type pixel(int x, int y) const
00235         {
00236             value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset;
00237             return color_type(*p);
00238         }
00239 
00240         //--------------------------------------------------------------------
00241         AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
00242         {
00243             *((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v;
00244         }
00245 
00246         //--------------------------------------------------------------------
00247         AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
00248         {
00249             copy_or_blend_pix((value_type*)
00250                                m_rbuf->row_ptr(x, y, 1) + x * Step + Offset, 
00251                                c, 
00252                                cover);
00253         }
00254 
00255 
00256         //--------------------------------------------------------------------
00257         AGG_INLINE void copy_hline(int x, int y, 
00258                                    unsigned len, 
00259                                    const color_type& c)
00260         {
00261             value_type* p = (value_type*)
00262                 m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
00263 
00264             do
00265             {
00266                 *p = c.v; 
00267                 p += Step;
00268             }
00269             while(--len);
00270         }
00271 
00272 
00273         //--------------------------------------------------------------------
00274         AGG_INLINE void copy_vline(int x, int y,
00275                                    unsigned len, 
00276                                    const color_type& c)
00277         {
00278             do
00279             {
00280                 value_type* p = (value_type*)
00281                     m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
00282 
00283                 *p = c.v;
00284             }
00285             while(--len);
00286         }
00287 
00288 
00289         //--------------------------------------------------------------------
00290         void blend_hline(int x, int y,
00291                          unsigned len, 
00292                          const color_type& c,
00293                          int8u cover)
00294         {
00295             if (c.a)
00296             {
00297                 value_type* p = (value_type*)
00298                     m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
00299 
00300                 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
00301                 if(alpha == base_mask)
00302                 {
00303                     do
00304                     {
00305                         *p = c.v; 
00306                         p += Step;
00307                     }
00308                     while(--len);
00309                 }
00310                 else
00311                 {
00312                     do
00313                     {
00314                         Blender::blend_pix(p, c.v, alpha, cover);
00315                         p += Step;
00316                     }
00317                     while(--len);
00318                 }
00319             }
00320         }
00321 
00322 
00323         //--------------------------------------------------------------------
00324         void blend_vline(int x, int y,
00325                          unsigned len, 
00326                          const color_type& c,
00327                          int8u cover)
00328         {
00329             if (c.a)
00330             {
00331                 value_type* p;
00332                 calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
00333                 if(alpha == base_mask)
00334                 {
00335                     do
00336                     {
00337                         p = (value_type*)
00338                             m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
00339 
00340                         *p = c.v; 
00341                     }
00342                     while(--len);
00343                 }
00344                 else
00345                 {
00346                     do
00347                     {
00348                         p = (value_type*)
00349                             m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
00350 
00351                         Blender::blend_pix(p, c.v, alpha, cover);
00352                     }
00353                     while(--len);
00354                 }
00355             }
00356         }
00357 
00358 
00359         //--------------------------------------------------------------------
00360         void blend_solid_hspan(int x, int y,
00361                                unsigned len, 
00362                                const color_type& c,
00363                                const int8u* covers)
00364         {
00365             if (c.a)
00366             {
00367                 value_type* p = (value_type*)
00368                     m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
00369 
00370                 do 
00371                 {
00372                     calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
00373                     if(alpha == base_mask)
00374                     {
00375                         *p = c.v;
00376                     }
00377                     else
00378                     {
00379                         Blender::blend_pix(p, c.v, alpha, *covers);
00380                     }
00381                     p += Step;
00382                     ++covers;
00383                 }
00384                 while(--len);
00385             }
00386         }
00387 
00388 
00389         //--------------------------------------------------------------------
00390         void blend_solid_vspan(int x, int y,
00391                                unsigned len, 
00392                                const color_type& c,
00393                                const int8u* covers)
00394         {
00395             if (c.a)
00396             {
00397                 do 
00398                 {
00399                     calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
00400 
00401                     value_type* p = (value_type*)
00402                         m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
00403 
00404                     if(alpha == base_mask)
00405                     {
00406                         *p = c.v;
00407                     }
00408                     else
00409                     {
00410                         Blender::blend_pix(p, c.v, alpha, *covers);
00411                     }
00412                     ++covers;
00413                 }
00414                 while(--len);
00415             }
00416         }
00417 
00418 
00419         //--------------------------------------------------------------------
00420         void copy_color_hspan(int x, int y,
00421                               unsigned len, 
00422                               const color_type* colors)
00423         {
00424             value_type* p = (value_type*)
00425                 m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
00426 
00427             do 
00428             {
00429                 *p = colors->v;
00430                 p += Step;
00431                 ++colors;
00432             }
00433             while(--len);
00434         }
00435 
00436 
00437         //--------------------------------------------------------------------
00438         void copy_color_vspan(int x, int y,
00439                               unsigned len, 
00440                               const color_type* colors)
00441         {
00442             do 
00443             {
00444                 value_type* p = (value_type*)
00445                     m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
00446                 *p = colors->v;
00447                 ++colors;
00448             }
00449             while(--len);
00450         }
00451 
00452 
00453         //--------------------------------------------------------------------
00454         void blend_color_hspan(int x, int y,
00455                                unsigned len, 
00456                                const color_type* colors,
00457                                const int8u* covers,
00458                                int8u cover)
00459         {
00460             value_type* p = (value_type*)
00461                 m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
00462 
00463             if(covers)
00464             {
00465                 do 
00466                 {
00467                     copy_or_blend_pix(p, *colors++, *covers++);
00468                     p += Step;
00469                 }
00470                 while(--len);
00471             }
00472             else
00473             {
00474                 if(cover == 255)
00475                 {
00476                     do 
00477                     {
00478                         if(colors->a == base_mask)
00479                         {
00480                             *p = colors->v;
00481                         }
00482                         else
00483                         {
00484                             copy_or_blend_pix(p, *colors);
00485                         }
00486                         p += Step;
00487                         ++colors;
00488                     }
00489                     while(--len);
00490                 }
00491                 else
00492                 {
00493                     do 
00494                     {
00495                         copy_or_blend_pix(p, *colors++, cover);
00496                         p += Step;
00497                     }
00498                     while(--len);
00499                 }
00500             }
00501         }
00502 
00503 
00504 
00505         //--------------------------------------------------------------------
00506         void blend_color_vspan(int x, int y,
00507                                unsigned len, 
00508                                const color_type* colors,
00509                                const int8u* covers,
00510                                int8u cover)
00511         {
00512             value_type* p;
00513             if(covers)
00514             {
00515                 do 
00516                 {
00517                     p = (value_type*)
00518                         m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
00519 
00520                     copy_or_blend_pix(p, *colors++, *covers++);
00521                 }
00522                 while(--len);
00523             }
00524             else
00525             {
00526                 if(cover == 255)
00527                 {
00528                     do 
00529                     {
00530                         p = (value_type*)
00531                             m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
00532 
00533                         if(colors->a == base_mask)
00534                         {
00535                             *p = colors->v;
00536                         }
00537                         else
00538                         {
00539                             copy_or_blend_pix(p, *colors);
00540                         }
00541                         ++colors;
00542                     }
00543                     while(--len);
00544                 }
00545                 else
00546                 {
00547                     do 
00548                     {
00549                         p = (value_type*)
00550                             m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
00551 
00552                         copy_or_blend_pix(p, *colors++, cover);
00553                     }
00554                     while(--len);
00555                 }
00556             }
00557         }
00558 
00559         //--------------------------------------------------------------------
00560         template<class Function> void for_each_pixel(Function f)
00561         {
00562             unsigned y;
00563             for(y = 0; y < height(); ++y)
00564             {
00565                 row_data r = m_rbuf->row(y);
00566                 if(r.ptr)
00567                 {
00568                     unsigned len = r.x2 - r.x1 + 1;
00569 
00570                     value_type* p = (value_type*)
00571                         m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset;
00572 
00573                     do
00574                     {
00575                         f(p);
00576                         p += Step;
00577                     }
00578                     while(--len);
00579                 }
00580             }
00581         }
00582 
00583         //--------------------------------------------------------------------
00584         template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
00585         {
00586             for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g));
00587         }
00588 
00589         //--------------------------------------------------------------------
00590         template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
00591         {
00592             for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g));
00593         }
00594 
00595         //--------------------------------------------------------------------
00596         template<class RenBuf2>
00597         void copy_from(const RenBuf2& from, 
00598                        int xdst, int ydst,
00599                        int xsrc, int ysrc,
00600                        unsigned len)
00601         {
00602             const int8u* p = from.row_ptr(ysrc);
00603             if(p)
00604             {
00605                 memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, 
00606                         p + xsrc * pix_width, 
00607                         len * pix_width);
00608             }
00609         }
00610 
00611         //--------------------------------------------------------------------
00612         template<class SrcPixelFormatRenderer>
00613         void blend_from_color(const SrcPixelFormatRenderer& from, 
00614                               const color_type& color,
00615                               int xdst, int ydst,
00616                               int xsrc, int ysrc,
00617                               unsigned len,
00618                               int8u cover)
00619         {
00620             typedef typename SrcPixelFormatRenderer::value_type src_value_type;
00621             const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
00622             if(psrc)
00623             {
00624                 value_type* pdst = 
00625                     (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
00626                 do 
00627                 {
00628                     copy_or_blend_pix(pdst, 
00629                                       color, 
00630                                       (*psrc * cover + base_mask) >> base_shift);
00631                     ++psrc;
00632                     ++pdst;
00633                 }
00634                 while(--len);
00635             }
00636         }
00637 
00638         //--------------------------------------------------------------------
00639         template<class SrcPixelFormatRenderer>
00640         void blend_from_lut(const SrcPixelFormatRenderer& from, 
00641                             const color_type* color_lut,
00642                             int xdst, int ydst,
00643                             int xsrc, int ysrc,
00644                             unsigned len,
00645                             int8u cover)
00646         {
00647             typedef typename SrcPixelFormatRenderer::value_type src_value_type;
00648             const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
00649             if(psrc)
00650             {
00651                 value_type* pdst = 
00652                     (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
00653                 do 
00654                 {
00655                     copy_or_blend_pix(pdst, color_lut[*psrc], cover);
00656                     ++psrc;
00657                     ++pdst;
00658                 }
00659                 while(--len);
00660             }
00661         }
00662 
00663     private:
00664         rbuf_type* m_rbuf;
00665     };
00666 
00667     typedef blender_gray<gray8>      blender_gray8;
00668     typedef blender_gray_pre<gray8>  blender_gray8_pre;
00669     typedef blender_gray<gray16>     blender_gray16;
00670     typedef blender_gray_pre<gray16> blender_gray16_pre;
00671 
00672     typedef pixfmt_alpha_blend_gray<blender_gray8,      rendering_buffer> pixfmt_gray8;      //----pixfmt_gray8
00673     typedef pixfmt_alpha_blend_gray<blender_gray8_pre,  rendering_buffer> pixfmt_gray8_pre;  //----pixfmt_gray8_pre
00674     typedef pixfmt_alpha_blend_gray<blender_gray16,     rendering_buffer> pixfmt_gray16;     //----pixfmt_gray16
00675     typedef pixfmt_alpha_blend_gray<blender_gray16_pre, rendering_buffer> pixfmt_gray16_pre; //----pixfmt_gray16_pre
00676 }
00677 
00678 #endif
00679 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines