png++  0.2.9
pixel_buffer.hpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007,2008   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 row_type& row_access;
00069         typedef row_type const& row_const_access;
00070         typedef traits row_traits;
00071 
00075         basic_pixel_buffer()
00076             : m_width(0),
00077               m_height(0)
00078         {
00079         }
00080 
00084         basic_pixel_buffer(uint_32 width, uint_32 height)
00085             : m_width(0),
00086               m_height(0)
00087         {
00088             resize(width, height);
00089         }
00090 
00091         uint_32 get_width() const
00092         {
00093             return m_width;
00094         }
00095 
00096         uint_32 get_height() const
00097         {
00098             return m_height;
00099         }
00100 
00107         void resize(uint_32 width, uint_32 height)
00108         {
00109             m_width = width;
00110             m_height = height;
00111             m_rows.resize(height);
00112             for (typename row_vec::iterator r = m_rows.begin();
00113                  r != m_rows.end();
00114                  ++r)
00115             {
00116                 r->resize(width);
00117             }
00118         }
00119 
00128         row_access get_row(size_t index)
00129         {
00130             return m_rows.at(index);
00131         }
00132 
00139         row_const_access get_row(size_t index) const
00140         {
00141             return m_rows.at(index);
00142         }
00143 
00147         row_access operator[](size_t index)
00148         {
00149             return m_rows[index];
00150         }
00151 
00155         row_const_access operator[](size_t index) const
00156         {
00157             return m_rows[index];
00158         }
00159 
00163         void put_row(size_t index, row_type const& r)
00164         {
00165             assert(r.size() == m_width);
00166             m_rows.at(index) = r;
00167         }
00168 
00172         pixel get_pixel(size_t x, size_t y) const
00173         {
00174             return get_row(y).at(x);
00175         }
00176 
00180         void set_pixel(size_t x, size_t y, pixel p)
00181         {
00182             get_row(y).at(x) = p;
00183         }
00184 
00185     protected:
00186         uint_32 m_width;
00187         uint_32 m_height;
00188         typedef std::vector< row_type > row_vec;
00189         row_vec m_rows;
00190     };
00191 
00195     template< typename pixel >
00196     class row_traits< std::vector< pixel > >
00197     {
00198     public:
00202         static pixel* get_data(std::vector< pixel >& vec)
00203         {
00204             assert(vec.size());
00205             return & vec[0];
00206         }
00207     };
00208 
00212     template< typename pixel >
00213     class pixel_buffer
00214         : public basic_pixel_buffer< pixel, std::vector< pixel > >
00215     {
00216     public:
00217         pixel_buffer()
00218         {
00219         }
00220 
00221         pixel_buffer(uint_32 width, uint_32 height)
00222             : basic_pixel_buffer< pixel, std::vector< pixel > >(width, height)
00223         {
00224         }
00225     };
00226 
00227     namespace detail
00228     {
00229 
00230         template< class pixel, typename reference >
00231         class basic_packed_pixel_proxy
00232         {
00233         public:
00234             explicit basic_packed_pixel_proxy(reference ref)
00235                 : m_ref(ref),
00236                   m_shift(0)
00237             {
00238             }
00239 
00240             basic_packed_pixel_proxy(reference ref, size_t index)
00241                 : m_ref(ref),
00242                   m_shift(get_shift(index))
00243             {
00244             }
00245 
00246             operator pixel() const
00247             {
00248                 return pixel((m_ref >> m_shift) & pixel::get_bit_mask());
00249             }
00250 
00251         protected:
00252             /*
00253              * bits: . .   .
00254              *    1: 7 6 5 4 3 2 1 0
00255              *    2:   6   4   2   0
00256              *    4:       4       0
00257              */
00258             static size_t get_shift(size_t index)
00259             {
00260                 int const bits = pixel::get_bit_depth();
00261                 return (8 - bits) - (index % get_pixels_per_byte()) * bits;
00262             }
00263 
00264             static size_t get_pixels_per_byte()
00265             {
00266                 return 8 / pixel::get_bit_depth();
00267             }
00268 
00269             reference m_ref;
00270             size_t m_shift;
00271         };
00272 
00273         template< class pixel >
00274         class const_packed_pixel_proxy
00275             : public basic_packed_pixel_proxy< pixel, byte const& >
00276         {
00277         public:
00278             const_packed_pixel_proxy(byte const& ref, size_t index)
00279                 : basic_packed_pixel_proxy< pixel, byte const& >(ref, index)
00280             {
00281             }
00282         };
00283 
00284         template< class pixel >
00285         class packed_pixel_proxy
00286             : public basic_packed_pixel_proxy< pixel, byte& >
00287         {
00288         public:
00289             typedef basic_packed_pixel_proxy< pixel, byte& > basic_proxy;
00290 
00291             packed_pixel_proxy(byte& ref, size_t index)
00292                 : basic_proxy(ref, index)
00293             {
00294             }
00295 
00296             packed_pixel_proxy(packed_pixel_proxy const& other)
00297                 : basic_proxy(other.m_ref)
00298             {
00299                 this->m_shift = other.m_shift;
00300             }
00301 
00302             packed_pixel_proxy& operator=(packed_pixel_proxy const& other)
00303             {
00304                 return *this = static_cast< pixel >(other);
00305             }
00306 
00307             template< typename reference >
00308             packed_pixel_proxy&
00309             operator=(basic_packed_pixel_proxy< pixel, reference > const& other)
00310             {
00311                 return *this = static_cast< pixel >(other);
00312             }
00313 
00314             packed_pixel_proxy& operator=(pixel p)
00315             {
00316                 this->m_ref = (this->m_ref
00317                     & ~(pixel::get_bit_mask() << this->m_shift))
00318                     | (p << this->m_shift);
00319 
00320                 return *this;
00321             }
00322         };
00323 
00324     } // namespace detail
00325 
00332     template< class pixel >
00333     class packed_pixel_row
00334     {
00335     public:
00339         explicit packed_pixel_row(size_t size = 0)
00340         {
00341             resize(size);
00342         }
00343 
00344         size_t size() const
00345         {
00346             return m_size;
00347         }
00348 
00352         void resize(size_t size)
00353         {
00354             m_vec.resize(size / get_pixels_per_byte()
00355                          + (size % get_pixels_per_byte() ? 1 : 0));
00356             m_size = size;
00357         }
00358 
00362         typedef detail::const_packed_pixel_proxy< pixel > const_pixel_proxy;
00363 
00367         typedef detail::packed_pixel_proxy< pixel > pixel_proxy;
00368 
00373         const_pixel_proxy at(size_t index) const
00374         {
00375             return const_pixel_proxy(m_vec.at(index / get_pixels_per_byte()),
00376                                      index);
00377         }
00378 
00383         pixel_proxy at(size_t index)
00384         {
00385             return pixel_proxy(m_vec.at(index / get_pixels_per_byte()),
00386                                index);
00387         }
00388 
00393         const_pixel_proxy operator[](size_t index) const
00394         {
00395             return const_pixel_proxy(m_vec[index / get_pixels_per_byte()],
00396                                      index);
00397         }
00398 
00403         pixel_proxy operator[](size_t index)
00404         {
00405             return pixel_proxy(m_vec[index / get_pixels_per_byte()],
00406                                index);
00407         }
00408 
00412         byte* get_data()
00413         {
00414             assert(m_vec.size());
00415             return & m_vec[0];
00416         }
00417 
00418     private:
00419         static size_t get_pixels_per_byte()
00420         {
00421             return 8 / pixel::get_bit_depth();
00422         }
00423 
00424         std::vector< byte > m_vec;
00425         size_t m_size;
00426     };
00427 
00432     template< typename pixel >
00433     class row_traits< packed_pixel_row< pixel > >
00434     {
00435     public:
00439         static byte* get_data(packed_pixel_row< pixel >& row)
00440         {
00441             return row.get_data();
00442         }
00443     };
00444 
00449     template< int bits >
00450     class pixel_buffer< packed_gray_pixel< bits > >
00451         : public basic_pixel_buffer< packed_gray_pixel< bits >,
00452                                      packed_pixel_row< packed_gray_pixel
00453                                                        < bits > > >
00454     {
00455     public:
00456         typedef packed_gray_pixel< bits > pixel_type;
00457         typedef packed_pixel_row< pixel_type > pixel_row_type;
00458 
00459         pixel_buffer()
00460         {
00461         }
00462 
00463         pixel_buffer(uint_32 width, uint_32 height)
00464             : basic_pixel_buffer< pixel_type,
00465                                   pixel_row_type >(width, height)
00466         {
00467         }
00468     };
00469 
00474     template< int bits >
00475     class pixel_buffer< packed_index_pixel< bits > >
00476         : public basic_pixel_buffer< packed_index_pixel< bits >,
00477                                      packed_pixel_row< packed_index_pixel
00478                                                        < bits > > >
00479     {
00480     public:
00481         typedef packed_index_pixel< bits > pixel_type;
00482         typedef packed_pixel_row< pixel_type > pixel_row_type;
00483 
00484         pixel_buffer()
00485         {
00486         }
00487 
00488         pixel_buffer(uint_32 width, uint_32 height)
00489             : basic_pixel_buffer< pixel_type,
00490                                   pixel_row_type >(width, height)
00491         {
00492         }
00493     };
00494 
00495 } // namespace png
00496 
00497 #endif // PNGPP_PIXEL_BUFFER_HPP_INCLUDED