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 "error.hpp"
00037 #include "streaming_base.hpp"
00038 #include "reader.hpp"
00039 #include "pixel_buffer.hpp"
00040
00041 namespace png
00042 {
00043
00117 template< typename pixel,
00118 class pixcon,
00119 class info_holder = def_image_info_holder,
00120 bool interlacing_supported = false >
00121 class consumer
00122 : public streaming_base< pixel, info_holder >
00123 {
00124 public:
00125 typedef pixel_traits< pixel > traits;
00126
00130 struct transform_identity
00131 {
00132 void operator()(io_base&) const {}
00133 };
00134
00139 void read(std::istream& stream)
00140 {
00141 read(stream, transform_identity());
00142 }
00143
00152 template< class transformation >
00153 void read(std::istream& stream, transformation const& transform)
00154 {
00155 reader rd(stream);
00156 rd.read_info();
00157 transform(rd);
00158
00159
00160 size_t pass_count;
00161 if (rd.get_interlace_type() != interlace_none)
00162 {
00163 #ifdef PNG_READ_INTERLACING_SUPPORTED
00164 pass_count = rd.set_interlace_handling();
00165 #else
00166 throw error("Cannot read interlaced image --"
00167 " interlace handling disabled.");
00168 #endif
00169 }
00170 else
00171 {
00172 pass_count = 1;
00173 }
00174
00175 rd.update_info();
00176 if (rd.get_color_type() != traits::get_color_type()
00177 || rd.get_bit_depth() != traits::get_bit_depth())
00178 {
00179 throw std::logic_error("color type and/or bit depth mismatch"
00180 " in png::consumer::read()");
00181 }
00182
00183 this->get_info() = rd.get_image_info();
00184
00185 pixcon* pixel_con = static_cast< pixcon* >(this);
00186 if (pass_count > 1 && !interlacing_supported)
00187 {
00188 skip_interlaced_rows(rd, pass_count);
00189 pass_count = 1;
00190 }
00191 read_rows(rd, pass_count, pixel_con);
00192
00193 rd.read_end_info();
00194 }
00195
00196 protected:
00197 typedef streaming_base< pixel, info_holder > base;
00198
00203 explicit consumer(image_info& info)
00204 : base(info)
00205 {
00206 }
00207
00208 private:
00209 void skip_interlaced_rows(reader& rd, size_t pass_count)
00210 {
00211 typedef std::vector< pixel > row;
00212 typedef row_traits< row > row_traits_type;
00213 row dummy_row(this->get_info().get_width());
00214 for (size_t pass = 1; pass < pass_count; ++pass)
00215 {
00216 rd.read_row(reinterpret_cast< byte* >
00217 (row_traits_type::get_data(dummy_row)));
00218 }
00219 }
00220
00221 void read_rows(reader& rd, size_t pass_count, pixcon* pixel_con)
00222 {
00223 for (size_t pass = 0; pass < pass_count; ++pass)
00224 {
00225 pixel_con->reset(pass);
00226
00227 for (size_t pos = 0; pos < this->get_info().get_height(); ++pos)
00228 {
00229 rd.read_row(pixel_con->get_next_row(pos));
00230 }
00231 }
00232 }
00233 };
00234
00235 }
00236
00237 #endif // PNGPP_CONSUMER_HPP_INCLUDED