image_reader* get_image_reader(std::string const& filename) { boost::optional<std::string> type = type_from_filename(filename); if (type) { return factory<image_reader,std::string,std::string const&>::instance().create_object(*type,filename); } else { throw image_reader_exception("image_reader: can't determine type from input data"); } }
void jpeg_reader<T>::read(unsigned x0, unsigned y0, image_data_32& image) { stream_.clear(); stream_.seekg(0, std::ios_base::beg); jpeg_decompress_struct cinfo; jpeg_info_guard iguard(&cinfo); jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jerr.error_exit = on_error; jerr.output_message = on_error_message; jpeg_create_decompress(&cinfo); attach_stream(&cinfo, &stream_); int ret = jpeg_read_header(&cinfo, TRUE); if (ret != JPEG_HEADER_OK) throw image_reader_exception("JPEG Reader read(): failed to read header"); jpeg_start_decompress(&cinfo); JSAMPARRAY buffer; int row_stride; unsigned char a,r,g,b; row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); unsigned w = std::min(unsigned(image.width()),width_ - x0); unsigned h = std::min(unsigned(image.height()),height_ - y0); const std::unique_ptr<unsigned int[]> out_row(new unsigned int[w]); unsigned row = 0; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, 1); if (row >= y0 && row < y0 + h) { for (unsigned int x = 0; x < w; ++x) { unsigned col = x + x0; a = 255; // alpha not supported in jpg r = buffer[0][cinfo.output_components * col]; if (cinfo.output_components > 2) { g = buffer[0][cinfo.output_components * col + 1]; b = buffer[0][cinfo.output_components * col + 2]; } else { g = r; b = r; } out_row[x] = color(r, g, b, a).rgba(); } image.setRow(row - y0, out_row.get(), w); } ++row; } jpeg_finish_decompress(&cinfo); }
png_reader<T>::png_reader(char const* data, std::size_t size) : source_(data,size), stream_(source_), width_(0), height_(0), bit_depth_(0), color_type_(0), has_alpha_(false) { if (!stream_) throw image_reader_exception("PNG reader: cannot open image stream"); init(); }
png_reader<T>::png_reader(std::string const& filename) : source_(), stream_(&source_), width_(0), height_(0), bit_depth_(0), color_type_(0), has_alpha_(false) { source_.open(filename, std::ios_base::in | std::ios_base::binary); if (!source_.is_open()) throw image_reader_exception("PNG reader: cannot open file '"+ filename + "'"); init(); }
tiff_reader<T>::tiff_reader(std::string const& file_name) : source_(file_name, std::ios_base::in | std::ios_base::binary), stream_(source_), read_method_(generic), width_(0), height_(0), rows_per_strip_(0), tile_width_(0), tile_height_(0), premultiplied_alpha_(false) { if (!stream_) throw image_reader_exception("TIFF reader: cannot open file "+ file_name); init(); }
tiff_reader<T>::tiff_reader(char const* data, std::size_t size) : source_(data, size), stream_(source_), read_method_(generic), width_(0), height_(0), rows_per_strip_(0), tile_width_(0), tile_height_(0), premultiplied_alpha_(false) { if (!stream_) throw image_reader_exception("TIFF reader: cannot open image stream "); stream_.seekg(0, std::ios::beg); init(); }
webp_reader<T>::webp_reader(std::string const& filename) : buffer_(), size_(0), width_(0), height_(0) { std::ifstream file(filename.c_str(), std::ios::binary); if (!file) { throw image_reader_exception("WEBP: Can't read file:" + filename); } std::streampos beg = file.tellg(); file.seekg (0, std::ios::end); std::streampos end = file.tellg(); std::size_t file_size = end - beg; file.seekg (0, std::ios::beg); buffer_ = std::auto_ptr<buffer_policy_type>(new buffer_policy_type(file_size)); file.read(reinterpret_cast<char*>(buffer_->data()), buffer_->size()); if (!file) { throw image_reader_exception("WEBP: Failed to read:" + filename); } init(); }
void JpegReader::init() { FILE *fp = fopen(fileName_.c_str(),"rb"); if (!fp) throw image_reader_exception("JPEG Reader: cannot open image file " + fileName_); struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, fp); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); width_ = cinfo.output_width; height_ = cinfo.output_height; //jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(fp); }
void user_error_fn(png_structp png_ptr, png_const_charp error_msg) { throw image_reader_exception("failed to read invalid png"); }
void png_reader<T>::read(unsigned x0, unsigned y0,image_data_32& image) { stream_.clear(); stream_.seekg(0, std::ios_base::beg); png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { throw image_reader_exception("failed to allocate png_ptr"); } // catch errors in a custom way to avoid the need for setjmp png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn); png_infop info_ptr; png_struct_guard sguard(&png_ptr,&info_ptr); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) throw image_reader_exception("failed to create info_ptr"); png_set_read_fn(png_ptr, (png_voidp)&stream_, png_read_data); png_read_info(png_ptr, info_ptr); if (color_type_ == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY && bit_depth_ < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (bit_depth_ == 16) png_set_strip_16(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY || color_type_ == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); // quick hack -- only work in >=libpng 1.2.7 png_set_add_alpha(png_ptr,0xff,PNG_FILLER_AFTER); //rgba double gamma; if (png_get_gAMA(png_ptr, info_ptr, &gamma)) png_set_gamma(png_ptr, 2.2, gamma); if (x0 == 0 && y0 == 0 && image.width() >= width_ && image.height() >= height_) { if (png_get_interlace_type(png_ptr,info_ptr) == PNG_INTERLACE_ADAM7) { png_set_interlace_handling(png_ptr); // FIXME: libpng bug? // according to docs png_read_image // "..automatically handles interlacing, // so you don't need to call png_set_interlace_handling()" } png_read_update_info(png_ptr, info_ptr); // we can read whole image at once // alloc row pointers const std::unique_ptr<png_bytep[]> rows(new png_bytep[height_]); for (unsigned i=0; i<height_; ++i) rows[i] = (png_bytep)image.getRow(i); png_read_image(png_ptr, rows.get()); } else { png_read_update_info(png_ptr, info_ptr); unsigned w=std::min(unsigned(image.width()),width_ - x0); unsigned h=std::min(unsigned(image.height()),height_ - y0); unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr); const std::unique_ptr<png_byte[]> row(new png_byte[rowbytes]); //START read image rows for (unsigned i = 0;i < height_; ++i) { png_read_row(png_ptr,row.get(),0); if (i >= y0 && i < (y0 + h)) { image.setRow(i-y0,reinterpret_cast<unsigned*>(&row[x0 * 4]),w); } } //END } png_read_end(png_ptr,0); }
void JpegReader::read(unsigned x0, unsigned y0, image_data_32& image) { struct jpeg_decompress_struct cinfo; FILE *fp = fopen(fileName_.c_str(),"rb"); if (!fp) throw image_reader_exception("JPEG Reader: cannot open image file " + fileName_); struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, fp); jpeg_read_header(&cinfo, TRUE); if (cinfo.out_color_space == JCS_UNKNOWN) throw image_reader_exception("JPEG Reader: failed to read unknown color space in " + fileName_); jpeg_start_decompress(&cinfo); if (cinfo.output_width == 0) { jpeg_destroy_decompress (&cinfo); fclose(fp); throw image_reader_exception("JPEG Reader: failed to read image size of " + fileName_); } JSAMPARRAY buffer; int row_stride; unsigned char a,r,g,b; row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); unsigned w = std::min(unsigned(image.width()),width_); unsigned h = std::min(unsigned(image.height()),height_); boost::scoped_array<unsigned int> out_row(new unsigned int[w]); // TODO - handle x0 for (unsigned i=0;i<h;++i) { jpeg_read_scanlines(&cinfo, buffer, 1); if (i>=y0 && i<h) { for (unsigned int x=0; x<w; x++) { a = 255; // alpha not supported in jpg r = buffer[0][cinfo.output_components * x]; if (cinfo.output_components > 2) { g = buffer[0][cinfo.output_components*x+1]; b = buffer[0][cinfo.output_components*x+2]; } else { g = r; b = r; } out_row[x] = color(r, g, b, a).rgba(); } image.setRow(i-y0, out_row.get(), w); } } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(fp); }
void user_error_fn(png_structp /*png_ptr*/, png_const_charp error_msg) { throw image_reader_exception(std::string("failed to read invalid png: '") + error_msg + "'"); }
void jpeg_reader<T>::on_error_message(j_common_ptr cinfo) { char buffer[JMSG_LENGTH_MAX]; (*cinfo->err->format_message)(cinfo, buffer); throw image_reader_exception(std::string("JPEG Reader: libjpeg could not read image: ") + buffer); }
void tiff_reader<T>::on_error(const char* , const char* fmt, va_list argptr) { char msg[10240]; vsprintf(msg, fmt, argptr); throw image_reader_exception(msg); }
void png_reader::read(unsigned x0, unsigned y0,image_data_32& image) { FILE *fp=fopen(fileName_.c_str(),"rb"); if (!fp) throw image_reader_exception("cannot open image file "+fileName_); png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { fclose(fp); throw image_reader_exception("failed to allocate png_ptr"); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw image_reader_exception("failed to create info_ptr"); } png_set_read_fn(png_ptr, (png_voidp)fp, png_read_data); png_read_info(png_ptr, info_ptr); if (color_type_ == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY && bit_depth_ < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (bit_depth_ == 16) png_set_strip_16(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY || color_type_ == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); // quick hack -- only work in >=libpng 1.2.7 png_set_add_alpha(png_ptr,0xff,PNG_FILLER_AFTER); //rgba double gamma; if (png_get_gAMA(png_ptr, info_ptr, &gamma)) png_set_gamma(png_ptr, 2.2, gamma); png_read_update_info(png_ptr, info_ptr); //START read image rows unsigned w=std::min(unsigned(image.width()),width_); unsigned h=std::min(unsigned(image.height()),height_); unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr); boost::scoped_array<png_byte> row(new png_byte[rowbytes]); for (unsigned i=0;i<height_;++i) { png_read_row(png_ptr,row.get(),0); if (i>=y0 && i<h) { image.setRow(i-y0,reinterpret_cast<unsigned*>(&row[x0]),w); } } //END png_read_end(png_ptr,0); png_destroy_read_struct(&png_ptr, &info_ptr,0); fclose(fp); }
void png_reader::init() { FILE *fp=fopen(fileName_.c_str(),"rb"); if (!fp) throw image_reader_exception("cannot open image file "+fileName_); png_byte header[8]; memset(header,0,8); if ( fread(header,1,8,fp) != 8) { fclose(fp); throw image_reader_exception("Could not read " + fileName_); } int is_png=!png_sig_cmp(header,0,8); if (!is_png) { fclose(fp); throw image_reader_exception(fileName_ + " is not a png file"); } png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { fclose(fp); throw image_reader_exception("failed to allocate png_ptr"); } // catch errors in a custom way to avoid the need for setjmp png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn); png_infop info_ptr; try { info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw image_reader_exception("failed to create info_ptr"); } } catch (std::exception const& ex) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw; } png_set_read_fn(png_ptr, (png_voidp)fp, png_read_data); png_set_sig_bytes(png_ptr,8); png_read_info(png_ptr, info_ptr); png_uint_32 width, height; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth_, &color_type_,0,0,0); width_=width; height_=height; MAPNIK_LOG_DEBUG(png_reader) << "png_reader: bit_depth=" << bit_depth_ << ",color_type=" << color_type_; png_destroy_read_struct(&png_ptr,&info_ptr,0); fclose(fp); }
void png_reader::read(unsigned x0, unsigned y0,image_data_32& image) { FILE *fp=fopen(fileName_.c_str(),"rb"); if (!fp) throw image_reader_exception("cannot open image file "+fileName_); png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { fclose(fp); throw image_reader_exception("failed to allocate png_ptr"); } // catch errors in a custom way to avoid the need for setjmp png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn); png_infop info_ptr; try { info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw image_reader_exception("failed to create info_ptr"); } } catch (std::exception const& ex) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw; } png_set_read_fn(png_ptr, (png_voidp)fp, png_read_data); png_read_info(png_ptr, info_ptr); if (color_type_ == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY && bit_depth_ < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (bit_depth_ == 16) png_set_strip_16(png_ptr); if (color_type_ == PNG_COLOR_TYPE_GRAY || color_type_ == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); // quick hack -- only work in >=libpng 1.2.7 png_set_add_alpha(png_ptr,0xff,PNG_FILLER_AFTER); //rgba double gamma; if (png_get_gAMA(png_ptr, info_ptr, &gamma)) png_set_gamma(png_ptr, 2.2, gamma); if (x0 == 0 && y0 == 0 && image.width() >= width_ && image.height() >= height_) { if (png_get_interlace_type(png_ptr,info_ptr) == PNG_INTERLACE_ADAM7) { png_set_interlace_handling(png_ptr); // FIXME: libpng bug? // according to docs png_read_image // "..automatically handles interlacing, // so you don't need to call png_set_interlace_handling()" } png_read_update_info(png_ptr, info_ptr); // we can read whole image at once // alloc row pointers boost::scoped_array<png_byte*> rows(new png_bytep[height_]); for (unsigned i=0; i<height_; ++i) rows[i] = (png_bytep)image.getRow(i); png_read_image(png_ptr, rows.get()); } else { png_read_update_info(png_ptr, info_ptr); unsigned w=std::min(unsigned(image.width()),width_); unsigned h=std::min(unsigned(image.height()),height_); unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr); boost::scoped_array<png_byte> row(new png_byte[rowbytes]); //START read image rows for (unsigned i=0;i<height_;++i) { png_read_row(png_ptr,row.get(),0); if (i>=y0 && i<h) { image.setRow(i-y0,reinterpret_cast<unsigned*>(&row[x0]),w); } } //END } png_read_end(png_ptr,0); png_destroy_read_struct(&png_ptr, &info_ptr,0); fclose(fp); }