|
|
@ -90,6 +90,98 @@ namespace png{ |
|
|
|
|
|
|
|
typedef ostream<> colored_ostream; |
|
|
|
typedef ostream<pixel_formats::gray> 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 <typename Pixel> |
|
|
|
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<char> row; |
|
|
|
uint32_t stride; |
|
|
|
uint32_t x; |
|
|
|
uint32_t y; |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|