- Main Page
- Namespaces
- Classes
- Files

- File List

# 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 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