diff --git a/include/png.hpp b/include/png.hpp index d37a861..541e026 100644 --- a/include/png.hpp +++ b/include/png.hpp @@ -90,6 +90,98 @@ namespace png{ typedef ostream<> colored_ostream; typedef ostream gray_ostream; + + struct istream{ + //typedef pixel pixel; + + istream(std::string filename) + : fp(0) + , png_ptr(0) + , info_ptr(0) + , row() + , stride(0) + , x(0) + , y(0) + { + fp = fopen(filename.c_str(), "rb"); + if(!fp) throw std::runtime_error(filename + " could not be opened"); + + png_byte header[8]; + fread(header, 1, 8, fp); + + if(png_sig_cmp(header, 0, 8) != 0) throw std::runtime_error("File is not a PNG file."); + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + if(!png_ptr) throw std::runtime_error("PNG structure could not be allocated"); + + info_ptr = png_create_info_struct(png_ptr); + if(!info_ptr) throw std::runtime_error("PNG information structure could not be allocated"); + + png_init_io(png_ptr, fp); + + png_set_sig_bytes(png_ptr, 8); + + png_read_info(png_ptr, info_ptr); + + if(png_get_interlace_type(png_ptr, info_ptr) != PNG_INTERLACE_NONE) + throw std::runtime_error("Interalced PNG's are not supported"); + + auto width = png_get_image_width(png_ptr, info_ptr); + auto bit_depth = png_get_bit_depth(png_ptr, info_ptr); + auto channels = png_get_channels(png_ptr, info_ptr); + + // number of bytes in one row + stride = bit_depth * channels / 8; + size_t row_size = width * stride; + + if(bit_depth < 8) throw std::runtime_error("Bitdepths lower than 8 are not supported (yet)"); + + row.resize(row_size); + png_read_row(png_ptr, (png_bytep)row.data(), 0); + } + + ~istream(){ + png_read_end(png_ptr, 0); + png_destroy_read_struct(&png_ptr, &info_ptr, 0); + fclose(fp); + } + + template + istream& operator>>(Pixel & p){ + p = row[x]; + + if(++x >= row.size()){ + x = 0; + ++y; + if(*this) + png_read_row(png_ptr, (png_bytep)row.data(), 0); + } + + return (*this); + } + + operator bool() const { + uint32_t height = 183; + png_get_IHDR(png_ptr, info_ptr, 0, &height, 0, 0, 0, 0, 0); + + if(y >= height) return false; + else return true; + } + + uint32_t width() const { + return row.size(); + } + + private: + FILE* fp; + png_structp png_ptr; + png_infop info_ptr; + + std::vector row; + uint32_t stride; + uint32_t x; + uint32_t y; + }; } #endif