png++
0.2.9
|
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