diff --git a/SConstruct b/SConstruct index 1f85a2847..ae8b322b4 100644 --- a/SConstruct +++ b/SConstruct @@ -67,6 +67,7 @@ pretty_dep_names = { 'jpeg':'JPEG C library | configure with JPEG_LIBS & JPEG_INCLUDES', 'tiff':'TIFF C library | configure with TIFF_LIBS & TIFF_INCLUDES', 'png':'PNG C library | configure with PNG_LIBS & PNG_INCLUDES', + 'webp':'WEBP C library | configure with WEBP_LIBS & WEBP_INCLUDES', 'icuuc':'ICU C++ library | configure with ICU_LIBS & ICU_INCLUDES or use ICU_LIB_NAME to specify custom lib name | more info: http://site.icu-project.org/', 'z':'Z compression library | more info: http://www.zlib.net/', 'm':'Basic math library, part of C++ stlib', @@ -317,6 +318,9 @@ PathVariable.PathAccept), BoolVariable('TIFF', 'Build Mapnik with TIFF read and write support', 'True'), PathVariable('TIFF_INCLUDES', 'Search path for libtiff include files', '/usr/include', PathVariable.PathAccept), PathVariable('TIFF_LIBS', 'Search path for libtiff library files', '/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept), + BoolVariable('WEBP', 'Build Mapnik with WEBP read', 'False'), + PathVariable('WEBP_INCLUDES', 'Search path for libwebp include files', '/usr/include', PathVariable.PathAccept), + PathVariable('WEBP_LIBS','Search path for libwebp library files','/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept), BoolVariable('PROJ', 'Build Mapnik with proj4 support to enable transformations between many different projections', 'True'), PathVariable('PROJ_INCLUDES', 'Search path for PROJ.4 include files', '/usr/include', PathVariable.PathAccept), PathVariable('PROJ_LIBS', 'Search path for PROJ.4 library files', '/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept), @@ -1170,6 +1174,18 @@ if not preconfigured: else: env['SKIPPED_DEPS'].extend(['png']) + if env['WEBP']: + env.Append(CPPDEFINES = '-DHAVE_WEBP') + LIBSHEADERS.append(['webp', 'webp/decode.h', True,'C']) + LIBSHEADERS.append(['webp', 'webp/encode.h', True,'C']) + inc_path = env['%s_INCLUDES' % 'WEBP'] + lib_path = env['%s_LIBS' % 'WEBP'] + env.AppendUnique(CPPPATH = os.path.realpath(inc_path)) + env.AppendUnique(LIBPATH = os.path.realpath(lib_path)) + else: + env['SKIPPED_DEPS'].extend(['png']) + + if env['TIFF']: env.Append(CPPDEFINES = '-DHAVE_TIFF') LIBSHEADERS.append(['tiff', 'tiff.h', True,'C']) diff --git a/src/build.py b/src/build.py index e6b9b9b8f..73d9d3b5e 100644 --- a/src/build.py +++ b/src/build.py @@ -71,6 +71,9 @@ if env['JPEG']: if env['TIFF']: lib_env['LIBS'].append('tiff') +if env['WEBP']: + lib_env['LIBS'].append('webp') + if len(env['EXTRA_FREETYPE_LIBS']): lib_env['LIBS'].extend(copy(env['EXTRA_FREETYPE_LIBS'])) @@ -234,6 +237,13 @@ if env['PNG']: png_reader.cpp """) +if env['WEBP']: + source += Split( + """ + webp_reader.cpp + """) + + # agg backend source += Split( """ diff --git a/src/image_reader.cpp b/src/image_reader.cpp index 3bacd7cac..1ae83b42a 100644 --- a/src/image_reader.cpp +++ b/src/image_reader.cpp @@ -52,6 +52,14 @@ inline boost::optional type_from_bytes(char const* data, size_t siz } } + if (size>=12) + { + if (data[0] == 'R' && data[1] == 'I' && data[2] == 'F' && data[3] == 'F' && + data[8] == 'W' && data[9] == 'E' && data[10] == 'B' && data[11] == 'P') + { + return result_type("webp"); + } + } return result_type(); } diff --git a/src/webp_reader.cpp b/src/webp_reader.cpp new file mode 100644 index 000000000..755198f3d --- /dev/null +++ b/src/webp_reader.cpp @@ -0,0 +1,131 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2013 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// mapnik +#include +#include + +extern "C" +{ +#include +#include +} + +// boost +#include +#include +#include + +namespace mapnik +{ + +class webp_reader : public image_reader +{ +private: + uint8_t const* data_; + size_t size_; + unsigned width_; + unsigned height_; +public: + explicit webp_reader(char const* data, std::size_t size); + ~webp_reader(); + unsigned width() const; + unsigned height() const; + bool premultiplied_alpha() const { return false; } + void read(unsigned x,unsigned y,image_data_32& image); +private: + void init(); +}; + +namespace +{ +image_reader* create_webp_reader(char const * data, std::size_t size) +{ + return new webp_reader(data, size); +} + +const bool registered = register_image_reader("webp", create_webp_reader); + +} + +// ctor +webp_reader::webp_reader(char const* data, std::size_t size) + : data_(reinterpret_cast(data)), + size_(size), + width_(0), + height_(0) +{ + init(); +} + +// dtor +webp_reader::~webp_reader() +{ + // +} + +void webp_reader::init() +{ + WebPDecoderConfig config; + if (!WebPGetFeatures(data_, size_, &config.input) == VP8_STATUS_OK) + { + throw image_reader_exception("WEBP: can't open image"); + } + width_ = config.input.width; + height_ = config.input.height; +} + +unsigned webp_reader::width() const +{ + return width_; +} + +unsigned webp_reader::height() const +{ + return height_; +} + +void webp_reader::read(unsigned x0, unsigned y0,image_data_32& image) +{ + WebPDecoderConfig config; + config.options.use_cropping = 1; + config.options.crop_left = x0; + config.options.crop_top = y0; + config.options.crop_width = image.width(); + config.options.crop_height = image.height(); + + if (WebPGetFeatures(data_, size_, &config.input) != VP8_STATUS_OK) + { + throw image_reader_exception("WEBP reader: WebPGetFeatures failed"); + } + + config.output.colorspace = MODE_RGBA; + config.output.u.RGBA.rgba = (uint8_t*)image.getBytes(); + config.output.u.RGBA.stride = 4 * image.width(); + config.output.u.RGBA.size = image.width()*image.height()*4; + if (WebPDecode(data_, size_, &config) != VP8_STATUS_OK) + { + throw image_reader_exception("WEBP reader: WebPDecode failed"); + } +} + +}