png++  0.2.1
consumer.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_CONSUMER_HPP_INCLUDED
32 #define PNGPP_CONSUMER_HPP_INCLUDED
33 
34 #include <cassert>
35 #include <stdexcept>
36 #include <iostream>
37 #include <istream>
38 
39 #include "config.hpp"
40 #include "error.hpp"
41 #include "streaming_base.hpp"
42 #include "reader.hpp"
43 #include "pixel_buffer.hpp"
44 
45 namespace png
46 {
47 
121  template< typename pixel,
122  class pixcon,
123  class info_holder = def_image_info_holder,
124  bool interlacing_supported = false >
125  class consumer
126  : public streaming_base< pixel, info_holder >
127  {
128  public:
129  typedef pixel_traits< pixel > traits;
130 
135  {
136  void operator()(io_base&) const {}
137  };
138 
143  template< typename istream >
144  void read(istream& stream)
145  {
146  read(stream, transform_identity());
147  }
148 
157  template< typename istream, class transformation >
158  void read(istream& stream, transformation const& transform)
159  {
160  reader< istream > rd(stream);
161  rd.read_info();
162  transform(rd);
163 
164 #if __BYTE_ORDER == __LITTLE_ENDIAN
165  if (pixel_traits< pixel >::get_bit_depth() == 16)
166  {
167 #ifdef PNG_READ_SWAP_SUPPORTED
168  rd.set_swap();
169 #else
170  throw error("Cannot read 16-bit image:"
171  " recompile with PNG_READ_SWAP_SUPPORTED.");
172 #endif
173  }
174 #endif
175 
176  // interlace handling _must_ be set up prior to info update
177  size_t pass_count;
179  {
180 #ifdef PNG_READ_INTERLACING_SUPPORTED
181  pass_count = rd.set_interlace_handling();
182 #else
183  throw error("Cannot read interlaced image:"
184  " interlace handling disabled.");
185 #endif
186  }
187  else
188  {
189  pass_count = 1;
190  }
191 
192  rd.update_info();
193  if (rd.get_color_type() != traits::get_color_type()
194  || rd.get_bit_depth() != traits::get_bit_depth())
195  {
196  throw std::logic_error("color type and/or bit depth mismatch"
197  " in png::consumer::read()");
198  }
199 
200  this->get_info() = rd.get_image_info();
201 
202  pixcon* pixel_con = static_cast< pixcon* >(this);
203  if (pass_count > 1 && !interlacing_supported)
204  {
205  skip_interlaced_rows(rd, pass_count);
206  pass_count = 1;
207  }
208  read_rows(rd, pass_count, pixel_con);
209 
210  rd.read_end_info();
211  }
212 
213  protected:
215 
221  : base(info)
222  {
223  }
224 
225  private:
226  template< typename istream >
227  void skip_interlaced_rows(reader< istream >& rd, size_t pass_count)
228  {
229  typedef std::vector< pixel > row;
230  typedef row_traits< row > row_traits_type;
231  row dummy_row(this->get_info().get_width());
232  for (size_t pass = 1; pass < pass_count; ++pass)
233  {
234  rd.read_row(reinterpret_cast< byte* >
235  (row_traits_type::get_data(dummy_row)));
236  }
237  }
238 
239  template< typename istream >
240  void read_rows(reader< istream >& rd, size_t pass_count,
241  pixcon* pixel_con)
242  {
243  for (size_t pass = 0; pass < pass_count; ++pass)
244  {
245  pixel_con->reset(pass);
246 
247  for (size_t pos = 0; pos < this->get_info().get_height(); ++pos)
248  {
249  rd.read_row(pixel_con->get_next_row(pos));
250  }
251  }
252  }
253  };
254 
255 } // namespace png
256 
257 #endif // PNGPP_CONSUMER_HPP_INCLUDED