consumer.hpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007   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_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 <endian.h>
00040 
00041 #include "error.hpp"
00042 #include "streaming_base.hpp"
00043 #include "reader.hpp"
00044 #include "pixel_buffer.hpp"
00045 
00046 namespace png
00047 {
00048 
00122     template< typename pixel,
00123               class pixcon,
00124               class info_holder = def_image_info_holder,
00125               bool interlacing_supported = false >
00126     class consumer
00127         : public streaming_base< pixel, info_holder >
00128     {
00129     public:
00130         typedef pixel_traits< pixel > traits;
00131 
00135         struct transform_identity
00136         {
00137             void operator()(io_base&) const {}
00138         };
00139 
00144         template< typename istream >
00145         void read(istream& stream)
00146         {
00147             read(stream, transform_identity());
00148         }
00149 
00158         template< typename istream, class transformation >
00159         void read(istream& stream, transformation const& transform)
00160         {
00161             reader< istream > rd(stream);
00162             rd.read_info();
00163             transform(rd);
00164 
00165 #if __BYTE_ORDER == __LITTLE_ENDIAN
00166             if (pixel_traits< pixel >::get_bit_depth() == 16)
00167             {
00168 #ifdef PNG_READ_SWAP_SUPPORTED
00169                 rd.set_swap();
00170 #else
00171                 throw error("Cannot read 16-bit image --"
00172                             " recompile with PNG_READ_SWAP_SUPPORTED.");
00173 #endif
00174             }
00175 #endif
00176 
00177             // interlace handling _must_ be set up prior to info update
00178             size_t pass_count;
00179             if (rd.get_interlace_type() != interlace_none)
00180             {
00181 #ifdef PNG_READ_INTERLACING_SUPPORTED
00182                 pass_count = rd.set_interlace_handling();
00183 #else
00184                 throw error("Cannot read interlaced image --"
00185                             " interlace handling disabled.");
00186 #endif
00187             }
00188             else
00189             {
00190                 pass_count = 1;
00191             }
00192 
00193             rd.update_info();
00194             if (rd.get_color_type() != traits::get_color_type()
00195                 || rd.get_bit_depth() != traits::get_bit_depth())
00196             {
00197                 throw std::logic_error("color type and/or bit depth mismatch"
00198                                        " in png::consumer::read()");
00199             }
00200 
00201             this->get_info() = rd.get_image_info();
00202 
00203             pixcon* pixel_con = static_cast< pixcon* >(this);
00204             if (pass_count > 1 && !interlacing_supported)
00205             {
00206                 skip_interlaced_rows(rd, pass_count);
00207                 pass_count = 1;
00208             }
00209             read_rows(rd, pass_count, pixel_con);
00210 
00211             rd.read_end_info();
00212         }
00213 
00214     protected:
00215         typedef streaming_base< pixel, info_holder > base;
00216 
00221         explicit consumer(image_info& info)
00222             : base(info)
00223         {
00224         }
00225 
00226     private:
00227         template< typename istream >
00228         void skip_interlaced_rows(reader< istream >& rd, size_t pass_count)
00229         {
00230             typedef std::vector< pixel > row;
00231             typedef row_traits< row > row_traits_type;
00232             row dummy_row(this->get_info().get_width());
00233             for (size_t pass = 1; pass < pass_count; ++pass)
00234             {
00235                 rd.read_row(reinterpret_cast< byte* >
00236                             (row_traits_type::get_data(dummy_row)));
00237             }
00238         }
00239 
00240         template< typename istream >
00241         void read_rows(reader< istream >& rd, size_t pass_count,
00242                        pixcon* pixel_con)
00243         {
00244             for (size_t pass = 0; pass < pass_count; ++pass)
00245             {
00246                 pixel_con->reset(pass);
00247 
00248                 for (size_t pos = 0; pos < this->get_info().get_height(); ++pos)
00249                 {
00250                     rd.read_row(pixel_con->get_next_row(pos));
00251                 }
00252             }
00253         }
00254     };
00255 
00256 } // namespace png
00257 
00258 #endif // PNGPP_CONSUMER_HPP_INCLUDED

Generated on Sat Dec 8 13:43:56 2007 for png++ by  doxygen 1.5.3-20071008