From 1b90879d120ac5049e454fc939653139a857ff46 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 16 Apr 2013 10:48:21 +0100 Subject: [PATCH] webp_reader : implement reading from file --- src/webp_reader.cpp | 119 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 104 insertions(+), 15 deletions(-) diff --git a/src/webp_reader.cpp b/src/webp_reader.cpp index 1b0ffe6f3..1c4cc3ddd 100644 --- a/src/webp_reader.cpp +++ b/src/webp_reader.cpp @@ -34,14 +34,63 @@ extern "C" #include #include #include +// stl +#include namespace mapnik { +struct external_buffer_policy +{ + external_buffer_policy( uint8_t const* data, std::size_t size) + : data_(data), + size_(size) {} + + uint8_t const* data() const + { + return data_; + } + + std::size_t size() const + { + return size_; + } + + uint8_t const* data_; + std::size_t size_; +}; + +struct internal_buffer_policy +{ + internal_buffer_policy(std::size_t size) + : data_((size!=0) ? static_cast(::operator new(sizeof(uint8_t) * size)) : 0), + size_(size) + {} + + uint8_t * data() const + { + return data_; + } + + std::size_t size() const + { + return size_; + } + + ~internal_buffer_policy() + { + ::operator delete(data_), data_=0; + } + + uint8_t * data_; + std::size_t size_; +}; + +template class webp_reader : public image_reader { + typedef T buffer_policy_type; private: - struct config_guard { config_guard(WebPDecoderConfig & config) @@ -53,13 +102,13 @@ private: } WebPDecoderConfig & config_; }; - - uint8_t const* data_; + std::unique_ptr buffer_; size_t size_; unsigned width_; unsigned height_; public: explicit webp_reader(char const* data, std::size_t size); + explicit webp_reader(std::string const& filename); ~webp_reader(); unsigned width() const; unsigned height() const; @@ -73,33 +122,70 @@ namespace { image_reader* create_webp_reader(char const * data, std::size_t size) { - return new webp_reader(data, size); + return new webp_reader(data, size); } +image_reader* create_webp_reader2(std::string const& filename) +{ + return new webp_reader(filename); +} + + const bool registered = register_image_reader("webp", create_webp_reader); +const bool registered2 = register_image_reader("webp", create_webp_reader2); } // ctor -webp_reader::webp_reader(char const* data, std::size_t size) - : data_(reinterpret_cast(data)), - size_(size), +template +webp_reader::webp_reader(char const* data, std::size_t size) + : buffer_(new buffer_policy_type(reinterpret_cast(data), size)), width_(0), height_(0) { init(); } +template +webp_reader::webp_reader(std::string const& filename) + : buffer_(0), + 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); + std::unique_ptr buffer(new buffer_policy_type(file_size)); + file.read(reinterpret_cast(buffer->data()), buffer->size()); + if (!file) + { + throw image_reader_exception("WEBP: Failed to read:" + filename); + } + buffer_ = std::move(buffer); + init(); +} + + // dtor -webp_reader::~webp_reader() +template +webp_reader::~webp_reader() { // } -void webp_reader::init() +template +void webp_reader::init() { int width, height; - if (!WebPGetInfo(data_, size_, &width, &height)) + if (!WebPGetInfo(buffer_->data(), buffer_->size(), &width, &height)) { throw image_reader_exception("WEBP reader: WebPGetInfo failed"); } @@ -107,17 +193,20 @@ void webp_reader::init() height_ = height; } -unsigned webp_reader::width() const +template +unsigned webp_reader::width() const { return width_; } -unsigned webp_reader::height() const +template +unsigned webp_reader::height() const { return height_; } -void webp_reader::read(unsigned x0, unsigned y0,image_data_32& image) +template +void webp_reader::read(unsigned x0, unsigned y0,image_data_32& image) { WebPDecoderConfig config; config_guard guard(config); @@ -132,7 +221,7 @@ void webp_reader::read(unsigned x0, unsigned y0,image_data_32& image) config.options.crop_width = std::min(width_ - x0, image.width()); config.options.crop_height = std::min(height_ - y0, image.height()); - if (WebPGetFeatures(data_, size_, &config.input) != VP8_STATUS_OK) + if (WebPGetFeatures(buffer_->data(), buffer_->size(), &config.input) != VP8_STATUS_OK) { throw image_reader_exception("WEBP reader: WebPGetFeatures failed"); } @@ -142,7 +231,7 @@ void webp_reader::read(unsigned x0, unsigned y0,image_data_32& image) config.output.u.RGBA.stride = 4 * image.width(); config.output.u.RGBA.size = image.width() * image.height() * 4; config.output.is_external_memory = 1; - if (WebPDecode(data_, size_, &config) != VP8_STATUS_OK) + if (WebPDecode(buffer_->data(), buffer_->size(), &config) != VP8_STATUS_OK) { throw image_reader_exception("WEBP reader: WebPDecode failed"); }