pixel_buffer.hpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007   Alex Shulgin
00003  *
00004  * This file is part of png++ the C++ wrapper for libpng.  Png++ is free
00005  * software; the exact copying conditions are as follows:
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright notice,
00011  * this list of conditions and the following disclaimer.
00012  *
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  * notice, this list of conditions and the following disclaimer in the
00015  * documentation and/or other materials provided with the distribution.
00016  *
00017  * 3. The name of the author may not be used to endorse or promote products
00018  * derived from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00021  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00022  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00023  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00024  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00025  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00026  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00027  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00028  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00029  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 #ifndef PNGPP_PIXEL_BUFFER_HPP_INCLUDED
00032 #define PNGPP_PIXEL_BUFFER_HPP_INCLUDED
00033 
00034 #include <cassert>
00035 #include <cstddef>
00036 #include <stdexcept>
00037 #include <vector>
00038 
00039 #include "packed_pixel.hpp"
00040 #include "gray_pixel.hpp"
00041 #include "index_pixel.hpp"
00042 
00043 namespace png
00044 {
00045 
00053     template< typename row > class row_traits;
00054 
00058     template< typename pixel,
00059               typename row,
00060               class traits = row_traits< row > >
00061     class basic_pixel_buffer
00062     {
00063     public:
00067         typedef row row_type;
00068         typedef traits row_traits;
00069 
00073         basic_pixel_buffer()
00074             : m_width(0),
00075               m_height(0)
00076         {
00077         }
00078 
00082         basic_pixel_buffer(size_t width, size_t height)
00083             : m_width(0),
00084               m_height(0)
00085         {
00086             resize(width, height);
00087         }
00088 
00089         size_t get_width() const
00090         {
00091             return m_width;
00092         }
00093 
00094         size_t get_height() const
00095             {
00096             return m_height;
00097             }
00098 
00105         void resize(size_t width, size_t height)
00106         {
00107             m_width = width;
00108             m_height = height;
00109             m_rows.resize(height);
00110             for (typename row_vec::iterator r = m_rows.begin();
00111                  r != m_rows.end();
00112                  ++r)
00113             {
00114                 r->resize(width);
00115             }
00116         }
00117 
00126         row_type& get_row(size_t index)
00127         {
00128             return m_rows.at(index);
00129         }
00130 
00137         row_type const& get_row(size_t index) const
00138         {
00139             return m_rows.at(index);
00140         }
00141 
00145         row_type& operator[](size_t index)
00146         {
00147             return m_rows[index];
00148         }
00149 
00153         row_type const& operator[](size_t index) const
00154         {
00155             return m_rows[index];
00156         }
00157 
00161         void put_row(size_t index, row_type const& r)
00162         {
00163             assert(r.size() == m_width);
00164             m_rows.at(index) = r;
00165         }
00166 
00170         pixel get_pixel(size_t x, size_t y) const
00171         {
00172             return get_row(y).at(x);
00173         }
00174 
00178         void set_pixel(size_t x, size_t y, pixel p)
00179         {
00180             get_row(y).at(x) = p;
00181         }
00182 
00183     protected:
00184         size_t m_width;
00185         size_t m_height;
00186         typedef std::vector< row_type > row_vec;
00187         row_vec m_rows;
00188     };
00189 
00193     template< typename pixel >
00194     class row_traits< std::vector< pixel > >
00195     {
00196     public:
00200         static pixel* get_data(std::vector< pixel >& vec)
00201         {
00202             assert(vec.size());
00203             return & vec[0];
00204         }
00205     };
00206 
00210     template< typename pixel >
00211     class pixel_buffer
00212         : public basic_pixel_buffer< pixel, std::vector< pixel > >
00213     {
00214     public:
00215         pixel_buffer()
00216         {
00217         }
00218 
00219         pixel_buffer(size_t width, size_t height)
00220             : basic_pixel_buffer< pixel, std::vector< pixel > >(width, height)
00221         {
00222         }
00223     };
00224 
00225     namespace detail
00226     {
00227 
00228         template< class pixel, typename reference >
00229         class basic_packed_pixel_proxy
00230         {
00231         public:
00232             explicit basic_packed_pixel_proxy(reference ref)
00233                 : m_ref(ref),
00234                   m_shift(0)
00235             {
00236             }
00237 
00238             basic_packed_pixel_proxy(reference ref, size_t index)
00239                 : m_ref(ref),
00240                   m_shift(get_shift(index))
00241             {
00242             }
00243 
00244             operator pixel() const
00245             {
00246                 return pixel((m_ref >> m_shift) & pixel::get_bit_mask());
00247             }
00248 
00249         protected:
00250             /*
00251              * bits: . .   .
00252              *    1: 7 6 5 4 3 2 1 0
00253              *    2:   6   4   2   0
00254              *    4:       4       0
00255              */
00256             static size_t get_shift(size_t index)
00257             {
00258                 size_t const bits = pixel::get_bit_depth();
00259                 return (8 - bits) - (index % get_pixels_per_byte()) * bits;
00260             }
00261 
00262             static size_t get_pixels_per_byte()
00263             {
00264                 return 8 / pixel::get_bit_depth();
00265             }
00266 
00267             reference m_ref;
00268             size_t m_shift;
00269         };
00270 
00271         template< class pixel >
00272         class const_packed_pixel_proxy
00273             : public basic_packed_pixel_proxy< pixel, byte const& >
00274         {
00275         public:
00276             const_packed_pixel_proxy(byte const& ref, size_t index)
00277                 : basic_packed_pixel_proxy< pixel, byte const& >(ref, index)
00278             {
00279             }
00280         };
00281 
00282         template< class pixel >
00283         class packed_pixel_proxy
00284             : public basic_packed_pixel_proxy< pixel, byte& >
00285         {
00286         public:
00287             typedef basic_packed_pixel_proxy< pixel, byte& > basic_proxy;
00288 
00289             packed_pixel_proxy(byte& ref, size_t index)
00290                 : basic_proxy(ref, index)
00291             {
00292             }
00293 
00294             packed_pixel_proxy(packed_pixel_proxy const& other)
00295                 : basic_proxy(other.m_ref)
00296             {
00297                 this->m_shift = other.m_shift;
00298             }
00299 
00300             packed_pixel_proxy& operator=(packed_pixel_proxy const& other)
00301             {
00302                 return *this = static_cast< pixel >(other);
00303             }
00304 
00305             template< typename reference >
00306             packed_pixel_proxy&
00307             operator=(basic_packed_pixel_proxy< pixel, reference > const& other)
00308             {
00309                 return *this = static_cast< pixel >(other);
00310             }
00311 
00312             packed_pixel_proxy& operator=(pixel p)
00313             {
00314                 this->m_ref = this->m_ref
00315                     & ~(pixel::get_bit_mask() << this->m_shift)
00316                     | (p << this->m_shift);
00317 
00318                 return *this;
00319             }
00320         };
00321 
00322     } // namespace detail
00323 
00330     template< class pixel >
00331     class packed_pixel_row
00332     {
00333     public:
00337         explicit packed_pixel_row(size_t size = 0)
00338         {
00339             resize(size);
00340         }
00341 
00342         size_t size() const
00343         {
00344             return m_size;
00345         }
00346 
00350         void resize(size_t size)
00351         {
00352             m_vec.resize(size / get_pixels_per_byte()
00353                          + (size % get_pixels_per_byte() ? 1 : 0));
00354             m_size = size;
00355         }
00356 
00360         typedef detail::const_packed_pixel_proxy< pixel > const_pixel_proxy;
00361 
00365         typedef detail::packed_pixel_proxy< pixel > pixel_proxy;
00366 
00371         const_pixel_proxy at(size_t index) const
00372         {
00373             return const_pixel_proxy(m_vec.at(index / get_pixels_per_byte()),
00374                                      index);
00375         }
00376 
00381         pixel_proxy at(size_t index)
00382         {
00383             return pixel_proxy(m_vec.at(index / get_pixels_per_byte()),
00384                                index);
00385         }
00386 
00391         const_pixel_proxy operator[](size_t index) const
00392         {
00393             return const_pixel_proxy(m_vec[index / get_pixels_per_byte()],
00394                                      index);
00395         }
00396 
00401         pixel_proxy operator[](size_t index)
00402         {
00403             return pixel_proxy(m_vec[index / get_pixels_per_byte()],
00404                                index);
00405         }
00406 
00410         byte* get_data()
00411         {
00412             assert(m_vec.size());
00413             return & m_vec[0];
00414         }
00415 
00416     private:
00417         static size_t get_pixels_per_byte()
00418         {
00419             return 8 / pixel::get_bit_depth();
00420         }
00421 
00422         std::vector< byte > m_vec;
00423         size_t m_size;
00424     };
00425 
00430     template< typename pixel >
00431     class row_traits< packed_pixel_row< pixel > >
00432     {
00433     public:
00437         static byte* get_data(packed_pixel_row< pixel >& row)
00438         {
00439             return row.get_data();
00440         }
00441     };
00442 
00447     template< size_t bits >
00448     class pixel_buffer< packed_gray_pixel< bits > >
00449         : public basic_pixel_buffer< packed_gray_pixel< bits >,
00450                                      packed_pixel_row< packed_gray_pixel
00451                                                        < bits > > >
00452     {
00453     public:
00454         typedef packed_gray_pixel< bits > pixel_type;
00455         typedef packed_pixel_row< pixel_type > pixel_row_type;
00456 
00457         pixel_buffer()
00458         {
00459         }
00460 
00461         pixel_buffer(size_t width, size_t height)
00462             : basic_pixel_buffer< pixel_type,
00463                                   pixel_row_type >(width, height)
00464         {
00465         }
00466     };
00467 
00472     template< size_t bits >
00473     class pixel_buffer< packed_index_pixel< bits > >
00474         : public basic_pixel_buffer< packed_index_pixel< bits >,
00475                                      packed_pixel_row< packed_index_pixel
00476                                                        < bits > > >
00477     {
00478     public:
00479         typedef packed_index_pixel< bits > pixel_type;
00480         typedef packed_pixel_row< pixel_type > pixel_row_type;
00481 
00482         pixel_buffer()
00483         {
00484         }
00485 
00486         pixel_buffer(size_t width, size_t height)
00487             : basic_pixel_buffer< pixel_type,
00488                                   pixel_row_type >(width, height)
00489         {
00490         }
00491     };
00492 
00493 } // namespace png
00494 
00495 #endif // PNGPP_PIXEL_BUFFER_HPP_INCLUDED

Generated on Sat Dec 8 13:43:56 2007 for png++ by  doxygen 1.5.3-20071008