webp: cleanup option handling

This commit is contained in:
Dane Springmeyer 2013-10-03 23:59:10 -07:00
parent 0fb718a4fd
commit be7d0a55c2
2 changed files with 39 additions and 40 deletions

View file

@ -39,6 +39,27 @@
namespace mapnik { namespace mapnik {
struct webp_options {
double quality; // 0 lowest, 100 highest
int method; // 0 if fastest, 6 slowest
int lossless; // Lossless encoding (0=lossy(default), 1=lossless).
int image_hint; // used when lossless=1
/*
WEBP_HINT_DEFAULT = 0, // default preset.
WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot
WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting
WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc).
WEBP_HINT_LAST
*/
bool alpha;
webp_options() :
quality(90.0),
method(3),
lossless(0),
image_hint(3),
alpha(true) {}
};
template <typename T> template <typename T>
int webp_stream_write(const uint8_t* data, size_t data_size, const WebPPicture* picture) int webp_stream_write(const uint8_t* data, size_t data_size, const WebPPicture* picture)
{ {
@ -138,24 +159,20 @@ inline int import_image_data(image_data_32 const& im,
template <typename T1, typename T2> template <typename T1, typename T2>
void save_as_webp(T1& file, void save_as_webp(T1& file,
float quality, T2 const& image,
int method, webp_options const& opts)
int lossless,
int image_hint,
bool alpha,
T2 const& image)
{ {
WebPConfig config; WebPConfig config;
if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, quality)) if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, static_cast<float>(opts.quality)))
{ {
throw std::runtime_error("version mismatch"); throw std::runtime_error("version mismatch");
} }
// Add additional tuning // Add additional tuning
if (method >= 0) config.method = method; if (opts.method >= 0) config.method = opts.method;
#if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1
config.lossless = !!lossless; config.lossless = !!opts.lossless;
config.image_hint = static_cast<WebPImageHint>(image_hint); config.image_hint = static_cast<WebPImageHint>(opts.image_hint);
#else #else
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma NOTE(compiling against webp that does not support lossless flag) #pragma NOTE(compiling against webp that does not support lossless flag)
@ -179,7 +196,7 @@ void save_as_webp(T1& file,
pic.height = image.height(); pic.height = image.height();
int ok = 0; int ok = 0;
#if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1 #if (WEBP_ENCODER_ABI_VERSION >> 8) >= 1
pic.use_argb = !!lossless; pic.use_argb = !!opts.lossless;
// lossless fast track // lossless fast track
if (pic.use_argb) if (pic.use_argb)
{ {
@ -206,10 +223,10 @@ void save_as_webp(T1& file,
{ {
// different approach for lossy since ImportYUVAFromRGBA is needed // different approach for lossy since ImportYUVAFromRGBA is needed
// to prepare WebPPicture and working with view pixels is not viable // to prepare WebPPicture and working with view pixels is not viable
ok = import_image_data(image,pic,alpha); ok = import_image_data(image,pic,opts.alpha);
} }
#else #else
ok = import_image_data(image,pic,alpha); ok = import_image_data(image,pic,opts.alpha);
#endif #endif
if (!ok) if (!ok)
{ {
@ -218,14 +235,12 @@ void save_as_webp(T1& file,
pic.writer = webp_stream_write<T1>; pic.writer = webp_stream_write<T1>;
pic.custom_ptr = &file; pic.custom_ptr = &file;
ok = WebPEncode(&config, &pic); ok = WebPEncode(&config, &pic);
WebPPictureFree(&pic); WebPPictureFree(&pic);
if (!ok) if (!ok)
{ {
throw std::runtime_error(webp_encoding_error(pic.error_code)); throw std::runtime_error(webp_encoding_error(pic.error_code));
} }
file.flush(); file.flush();
} }
} }

View file

@ -247,12 +247,7 @@ void handle_png_options(std::string const& type,
#if defined(HAVE_WEBP) #if defined(HAVE_WEBP)
void handle_webp_options(std::string const& type, void handle_webp_options(std::string const& type,
double & quality, webp_options & opts)
int & method,
int & lossless,
int & image_hint,
bool & alpha
)
{ {
if (type == "webp") if (type == "webp")
{ {
@ -268,7 +263,7 @@ void handle_webp_options(std::string const& type,
std::string val = t.substr(8); std::string val = t.substr(8);
if (!val.empty()) if (!val.empty())
{ {
if (!mapnik::util::string2double(val,quality) || quality < 0.0 || quality > 100.0) if (!mapnik::util::string2double(val,opts.quality) || opts.quality < 0.0 || opts.quality > 100.0)
{ {
throw ImageWriterException("invalid webp quality: '" + val + "'"); throw ImageWriterException("invalid webp quality: '" + val + "'");
} }
@ -279,7 +274,7 @@ void handle_webp_options(std::string const& type,
std::string val = t.substr(7); std::string val = t.substr(7);
if (!val.empty()) if (!val.empty())
{ {
if (!mapnik::util::string2int(val,method) || method < 0 || method > 6) if (!mapnik::util::string2int(val,opts.method) || opts.method < 0 || opts.method > 6)
{ {
throw ImageWriterException("invalid webp method: '" + val + "'"); throw ImageWriterException("invalid webp method: '" + val + "'");
} }
@ -290,7 +285,7 @@ void handle_webp_options(std::string const& type,
std::string val = t.substr(9); std::string val = t.substr(9);
if (!val.empty()) if (!val.empty())
{ {
if (!mapnik::util::string2int(val,lossless) || lossless < 0 || lossless > 1) if (!mapnik::util::string2int(val,opts.lossless) || opts.lossless < 0 || opts.lossless > 1)
{ {
throw ImageWriterException("invalid webp lossless: '" + val + "'"); throw ImageWriterException("invalid webp lossless: '" + val + "'");
} }
@ -301,7 +296,7 @@ void handle_webp_options(std::string const& type,
std::string val = t.substr(11); std::string val = t.substr(11);
if (!val.empty()) if (!val.empty())
{ {
if (!mapnik::util::string2int(val,image_hint) || image_hint < 0 || image_hint > 3) if (!mapnik::util::string2int(val,opts.image_hint) || opts.image_hint < 0 || opts.image_hint > 3)
{ {
throw ImageWriterException("invalid webp image_hint: '" + val + "'"); throw ImageWriterException("invalid webp image_hint: '" + val + "'");
} }
@ -312,7 +307,7 @@ void handle_webp_options(std::string const& type,
std::string val = t.substr(6); std::string val = t.substr(6);
if (!val.empty()) if (!val.empty())
{ {
if (!mapnik::util::string2bool(val,alpha)) if (!mapnik::util::string2bool(val,opts.alpha))
{ {
throw ImageWriterException("invalid webp alpha: '" + val + "'"); throw ImageWriterException("invalid webp alpha: '" + val + "'");
} }
@ -425,20 +420,9 @@ void save_to_stream(T const& image,
else if (boost::algorithm::starts_with(t, "webp")) else if (boost::algorithm::starts_with(t, "webp"))
{ {
#if defined(HAVE_WEBP) #if defined(HAVE_WEBP)
double quality = 90.0; // 0 lowest, 100 highest webp_options opts;
int method = 3; // 0 if fastest, 6 slowest handle_webp_options(t,opts);
int lossless = 0; // Lossless encoding (0=lossy(default), 1=lossless). save_as_webp(stream, image, opts);
int image_hint = 3; // used when lossless=1
bool alpha = true;
/*
WEBP_HINT_DEFAULT = 0, // default preset.
WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot
WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting
WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc).
WEBP_HINT_LAST
*/
handle_webp_options(t,quality,method,lossless, image_hint, alpha);
save_as_webp(stream, static_cast<float>(quality), method, lossless, image_hint, alpha, image);
#else #else
throw ImageWriterException("webp output is not enabled in your build of Mapnik"); throw ImageWriterException("webp output is not enabled in your build of Mapnik");
#endif #endif