png++  0.2.1
pixel_buffer.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007,2008 Alex Shulgin
3  *
4  * This file is part of png++ the C++ wrapper for libpng. PNG++ is free
5  * software; the exact copying conditions are as follows:
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * 3. The name of the author may not be used to endorse or promote products
18  * derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
23  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 #ifndef PNGPP_PIXEL_BUFFER_HPP_INCLUDED
32 #define PNGPP_PIXEL_BUFFER_HPP_INCLUDED
33 
34 #include <cassert>
35 #include <cstddef>
36 #include <stdexcept>
37 #include <vector>
38 
39 #include "packed_pixel.hpp"
40 #include "gray_pixel.hpp"
41 #include "index_pixel.hpp"
42 
43 namespace png
44 {
45 
53  template< typename row > class row_traits;
54 
58  template< typename pixel,
59  typename row,
60  class traits = row_traits< row > >
62  {
63  public:
67  typedef row row_type;
68  typedef traits row_traits;
69 
74  : m_width(0),
75  m_height(0)
76  {
77  }
78 
82  basic_pixel_buffer(size_t width, size_t height)
83  : m_width(0),
84  m_height(0)
85  {
86  resize(width, height);
87  }
88 
89  size_t get_width() const
90  {
91  return m_width;
92  }
93 
94  size_t get_height() const
95  {
96  return m_height;
97  }
98 
105  void resize(size_t width, size_t height)
106  {
107  m_width = width;
108  m_height = height;
109  m_rows.resize(height);
110  for (typename row_vec::iterator r = m_rows.begin();
111  r != m_rows.end();
112  ++r)
113  {
114  r->resize(width);
115  }
116  }
117 
126  row_type& get_row(size_t index)
127  {
128  return m_rows.at(index);
129  }
130 
137  row_type const& get_row(size_t index) const
138  {
139  return m_rows.at(index);
140  }
141 
145  row_type& operator[](size_t index)
146  {
147  return m_rows[index];
148  }
149 
153  row_type const& operator[](size_t index) const
154  {
155  return m_rows[index];
156  }
157 
161  void put_row(size_t index, row_type const& r)
162  {
163  assert(r.size() == m_width);
164  m_rows.at(index) = r;
165  }
166 
170  pixel get_pixel(size_t x, size_t y) const
171  {
172  return get_row(y).at(x);
173  }
174 
178  void set_pixel(size_t x, size_t y, pixel p)
179  {
180  get_row(y).at(x) = p;
181  }
182 
183  protected:
184  size_t m_width;
185  size_t m_height;
186  typedef std::vector< row_type > row_vec;
188  };
189 
193  template< typename pixel >
194  class row_traits< std::vector< pixel > >
195  {
196  public:
200  static pixel* get_data(std::vector< pixel >& vec)
201  {
202  assert(vec.size());
203  return & vec[0];
204  }
205  };
206 
210  template< typename pixel >
212  : public basic_pixel_buffer< pixel, std::vector< pixel > >
213  {
214  public:
216  {
217  }
218 
219  pixel_buffer(size_t width, size_t height)
220  : basic_pixel_buffer< pixel, std::vector< pixel > >(width, height)
221  {
222  }
223  };
224 
225  namespace detail
226  {
227 
228  template< class pixel, typename reference >
230  {
231  public:
232  explicit basic_packed_pixel_proxy(reference ref)
233  : m_ref(ref),
234  m_shift(0)
235  {
236  }
237 
238  basic_packed_pixel_proxy(reference ref, size_t index)
239  : m_ref(ref),
240  m_shift(get_shift(index))
241  {
242  }
243 
244  operator pixel() const
245  {
246  return pixel((m_ref >> m_shift) & pixel::get_bit_mask());
247  }
248 
249  protected:
250  /*
251  * bits: . . .
252  * 1: 7 6 5 4 3 2 1 0
253  * 2: 6 4 2 0
254  * 4: 4 0
255  */
256  static size_t get_shift(size_t index)
257  {
258  size_t const bits = pixel::get_bit_depth();
259  return (8 - bits) - (index % get_pixels_per_byte()) * bits;
260  }
261 
262  static size_t get_pixels_per_byte()
263  {
264  return 8 / pixel::get_bit_depth();
265  }
266 
267  reference m_ref;
268  size_t m_shift;
269  };
270 
271  template< class pixel >
273  : public basic_packed_pixel_proxy< pixel, byte const& >
274  {
275  public:
276  const_packed_pixel_proxy(byte const& ref, size_t index)
277  : basic_packed_pixel_proxy< pixel, byte const& >(ref, index)
278  {
279  }
280  };
281 
282  template< class pixel >
284  : public basic_packed_pixel_proxy< pixel, byte& >
285  {
286  public:
288 
289  packed_pixel_proxy(byte& ref, size_t index)
290  : basic_proxy(ref, index)
291  {
292  }
293 
295  : basic_proxy(other.m_ref)
296  {
297  this->m_shift = other.m_shift;
298  }
299 
301  {
302  return *this = static_cast< pixel >(other);
303  }
304 
305  template< typename reference >
308  {
309  return *this = static_cast< pixel >(other);
310  }
311 
313  {
314  this->m_ref = (this->m_ref
315  & ~(pixel::get_bit_mask() << this->m_shift))
316  | (p << this->m_shift);
317 
318  return *this;
319  }
320  };
321 
322  } // namespace detail
323 
330  template< class pixel >
332  {
333  public:
337  explicit packed_pixel_row(size_t size = 0)
338  {
339  resize(size);
340  }
341 
342  size_t size() const
343  {
344  return m_size;
345  }
346 
350  void resize(size_t size)
351  {
352  m_vec.resize(size / get_pixels_per_byte()
353  + (size % get_pixels_per_byte() ? 1 : 0));
354  m_size = size;
355  }
356 
361 
366 
371  const_pixel_proxy at(size_t index) const
372  {
373  return const_pixel_proxy(m_vec.at(index / get_pixels_per_byte()),
374  index);
375  }
376 
381  pixel_proxy at(size_t index)
382  {
383  return pixel_proxy(m_vec.at(index / get_pixels_per_byte()),
384  index);
385  }
386 
391  const_pixel_proxy operator[](size_t index) const
392  {
393  return const_pixel_proxy(m_vec[index / get_pixels_per_byte()],
394  index);
395  }
396 
401  pixel_proxy operator[](size_t index)
402  {
403  return pixel_proxy(m_vec[index / get_pixels_per_byte()],
404  index);
405  }
406 
411  {
412  assert(m_vec.size());
413  return & m_vec[0];
414  }
415 
416  private:
417  static size_t get_pixels_per_byte()
418  {
419  return 8 / pixel::get_bit_depth();
420  }
421 
422  std::vector< byte > m_vec;
423  size_t m_size;
424  };
425 
430  template< typename pixel >
431  class row_traits< packed_pixel_row< pixel > >
432  {
433  public:
437  static byte* get_data(packed_pixel_row< pixel >& row)
438  {
439  return row.get_data();
440  }
441  };
442 
447  template< size_t bits >
449  : public basic_pixel_buffer< packed_gray_pixel< bits >,
450  packed_pixel_row< packed_gray_pixel
451  < bits > > >
452  {
453  public:
456 
458  {
459  }
460 
461  pixel_buffer(size_t width, size_t height)
463  pixel_row_type >(width, height)
464  {
465  }
466  };
467 
472  template< size_t bits >
474  : public basic_pixel_buffer< packed_index_pixel< bits >,
475  packed_pixel_row< packed_index_pixel
476  < bits > > >
477  {
478  public:
481 
483  {
484  }
485 
486  pixel_buffer(size_t width, size_t height)
488  pixel_row_type >(width, height)
489  {
490  }
491  };
492 
493 } // namespace png
494 
495 #endif // PNGPP_PIXEL_BUFFER_HPP_INCLUDED