Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef PNGPP_CONSUMER_HPP_INCLUDED
00032 #define PNGPP_CONSUMER_HPP_INCLUDED
00033
00034 #include <cassert>
00035 #include <stdexcept>
00036 #include <iostream>
00037 #include <istream>
00038
00039 #include "config.hpp"
00040 #include "error.hpp"
00041 #include "streaming_base.hpp"
00042 #include "reader.hpp"
00043 #include "pixel_buffer.hpp"
00044
00045 namespace png
00046 {
00047
00121 template< typename pixel,
00122 class pixcon,
00123 class info_holder = def_image_info_holder,
00124 bool interlacing_supported = false >
00125 class consumer
00126 : public streaming_base< pixel, info_holder >
00127 {
00128 public:
00129 typedef pixel_traits< pixel > traits;
00130
00134 struct transform_identity
00135 {
00136 void operator()(io_base&) const {}
00137 };
00138
00143 template< typename istream >
00144 void read(istream& stream)
00145 {
00146 read(stream, transform_identity());
00147 }
00148
00157 template< typename istream, class transformation >
00158 void read(istream& stream, transformation const& transform)
00159 {
00160 reader< istream > rd(stream);
00161 rd.read_info();
00162 transform(rd);
00163
00164 #if __BYTE_ORDER == __LITTLE_ENDIAN
00165 if (pixel_traits< pixel >::get_bit_depth() == 16)
00166 {
00167 #ifdef PNG_READ_SWAP_SUPPORTED
00168 rd.set_swap();
00169 #else
00170 throw error("Cannot read 16-bit image:"
00171 " recompile with PNG_READ_SWAP_SUPPORTED.");
00172 #endif
00173 }
00174 #endif
00175
00176
00177 size_t pass_count;
00178 if (rd.get_interlace_type() != interlace_none)
00179 {
00180 #ifdef PNG_READ_INTERLACING_SUPPORTED
00181 pass_count = rd.set_interlace_handling();
00182 #else
00183 throw error("Cannot read interlaced image:"
00184 " interlace handling disabled.");
00185 #endif
00186 }
00187 else
00188 {
00189 pass_count = 1;
00190 }
00191
00192 rd.update_info();
00193 if (rd.get_color_type() != traits::get_color_type()
00194 || rd.get_bit_depth() != traits::get_bit_depth())
00195 {
00196 throw std::logic_error("color type and/or bit depth mismatch"
00197 " in png::consumer::read()");
00198 }
00199
00200 this->get_info() = rd.get_image_info();
00201
00202 pixcon* pixel_con = static_cast< pixcon* >(this);
00203 if (pass_count > 1 && !interlacing_supported)
00204 {
00205 skip_interlaced_rows(rd, pass_count);
00206 pass_count = 1;
00207 }
00208 read_rows(rd, pass_count, pixel_con);
00209
00210 rd.read_end_info();
00211 }
00212
00213 protected:
00214 typedef streaming_base< pixel, info_holder > base;
00215
00220 explicit consumer(image_info& info)
00221 : base(info)
00222 {
00223 }
00224
00225 private:
00226 template< typename istream >
00227 void skip_interlaced_rows(reader< istream >& rd, size_t pass_count)
00228 {
00229 typedef std::vector< pixel > row;
00230 typedef row_traits< row > row_traits_type;
00231 row dummy_row(this->get_info().get_width());
00232 for (size_t pass = 1; pass < pass_count; ++pass)
00233 {
00234 rd.read_row(reinterpret_cast< byte* >
00235 (row_traits_type::get_data(dummy_row)));
00236 }
00237 }
00238
00239 template< typename istream >
00240 void read_rows(reader< istream >& rd, size_t pass_count,
00241 pixcon* pixel_con)
00242 {
00243 for (size_t pass = 0; pass < pass_count; ++pass)
00244 {
00245 pixel_con->reset(pass);
00246
00247 for (size_t pos = 0; pos < this->get_info().get_height(); ++pos)
00248 {
00249 rd.read_row(pixel_con->get_next_row(pos));
00250 }
00251 }
00252 }
00253 };
00254
00255 }
00256
00257 #endif // PNGPP_CONSUMER_HPP_INCLUDED