From 160d15b45b45136d273b16fefb59d9071dd77d6d Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 17 Feb 2019 11:50:39 +0000 Subject: add webp image handler --- Makefile | 2 + Makefile.defaults | 4 + content/handlers/image/Makefile | 4 +- content/handlers/image/image.c | 7 ++ content/handlers/image/jpeg.c | 8 +- content/handlers/image/webp.c | 232 ++++++++++++++++++++++++++++++++++++++++ content/handlers/image/webp.h | 29 +++++ 7 files changed, 283 insertions(+), 3 deletions(-) create mode 100644 content/handlers/image/webp.c create mode 100644 content/handlers/image/webp.h diff --git a/Makefile b/Makefile index f86042897..0d4f3ae7d 100644 --- a/Makefile +++ b/Makefile @@ -535,6 +535,7 @@ LDFLAGS += -lz # Optional libraries with pkgconfig # define additional CFLAGS and LDFLAGS requirements for pkg-configed libs +NETSURF_FEATURE_WEBP_CFLAGS := -DWITH_WEBP NETSURF_FEATURE_PNG_CFLAGS := -DWITH_PNG NETSURF_FEATURE_BMP_CFLAGS := -DWITH_BMP NETSURF_FEATURE_GIF_CFLAGS := -DWITH_GIF @@ -558,6 +559,7 @@ else endif $(eval $(call pkg_config_find_and_add_enabled,OPENSSL,openssl,OpenSSL)) +$(eval $(call pkg_config_find_and_add_enabled,WEBP,libwebp,WEBP)) $(eval $(call pkg_config_find_and_add_enabled,PNG,libpng,PNG)) $(eval $(call pkg_config_find_and_add_enabled,BMP,libnsbmp,BMP)) $(eval $(call pkg_config_find_and_add_enabled,GIF,libnsgif,GIF)) diff --git a/Makefile.defaults b/Makefile.defaults index 51090109e..cebd41cf8 100644 --- a/Makefile.defaults +++ b/Makefile.defaults @@ -59,6 +59,10 @@ NETSURF_USE_PNG := YES # Valid options: YES, NO NETSURF_USE_VIDEO := NO +# Enable NetSurf's use of libwebp for displaying WEBPs. +# Valid options: YES, NO, AUTO +NETSURF_USE_WEBP := AUTO + # Enable NetSurf's use of duktape for javascript # Valid options: YES, NO NETSURF_USE_DUKTAPE := YES diff --git a/content/handlers/image/Makefile b/content/handlers/image/Makefile index 541cd2cf9..1c27f74d7 100644 --- a/content/handlers/image/Makefile +++ b/content/handlers/image/Makefile @@ -3,13 +3,15 @@ # S_IMAGE are sources related to image management S_IMAGE_YES := image.c image_cache.c S_IMAGE_NO := -S_IMAGE_$(NETSURF_USE_BMP) += bmp.c ico.c +S_IMAGE_$(NETSURF_USE_BMP) += bmp.c S_IMAGE_$(NETSURF_USE_GIF) += gif.c +S_IMAGE_$(NETSURF_USE_BMP) += ico.c S_IMAGE_$(NETSURF_USE_JPEG) += jpeg.c S_IMAGE_$(NETSURF_USE_ROSPRITE) += nssprite.c S_IMAGE_$(NETSURF_USE_PNG) += png.c S_IMAGE_$(NETSURF_USE_NSSVG) += svg.c S_IMAGE_$(NETSURF_USE_RSVG) += rsvg.c S_IMAGE_$(NETSURF_USE_VIDEO) += video.c +S_IMAGE_$(NETSURF_USE_WEBP) += webp.c S_IMAGE := $(S_IMAGE_YES) diff --git a/content/handlers/image/image.c b/content/handlers/image/image.c index 675fdd691..4eb366e0b 100644 --- a/content/handlers/image/image.c +++ b/content/handlers/image/image.c @@ -35,6 +35,7 @@ #include "image/png.h" #include "image/rsvg.h" #include "image/svg.h" +#include "image/webp.h" #include "image/image.h" /** @@ -94,6 +95,12 @@ nserror image_init(void) return error; #endif +#ifdef WITH_WEBP + error = nswebp_init(); + if (error != NSERROR_OK) + return error; +#endif + return error; } diff --git a/content/handlers/image/jpeg.c b/content/handlers/image/jpeg.c index 123a0bf70..e2f5f8f26 100644 --- a/content/handlers/image/jpeg.c +++ b/content/handlers/image/jpeg.c @@ -17,8 +17,9 @@ * along with this program. If not, see . */ -/** \file - * Content for image/jpeg (implementation). +/** + * \file + * implementation of content handling for image/jpeg * * This implementation uses the IJG JPEG library. */ @@ -161,6 +162,9 @@ static void nsjpeg_error_exit(j_common_ptr cinfo) longjmp(*setjmp_buffer, 1); } +/** + * create a bitmap from jpeg content. + */ static struct bitmap * jpeg_cache_convert(struct content *c) { diff --git a/content/handlers/image/webp.c b/content/handlers/image/webp.c new file mode 100644 index 000000000..66a86c9f4 --- /dev/null +++ b/content/handlers/image/webp.c @@ -0,0 +1,232 @@ +/* + * Copyright 2019 Vincent Sanders + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file + * implementation of content handling for image/webp + * + * This implementation uses the google webp library. + * Image cache handling is performed by the generic NetSurf handler. + */ + +#include +#include +#include + +#include + +#include "utils/utils.h" +#include "utils/log.h" +#include "utils/messages.h" +#include "netsurf/bitmap.h" +#include "content/llcache.h" +#include "content/content_protected.h" +#include "desktop/gui_internal.h" + +#include "image/image_cache.h" + +#include "webp.h" + +/** + * Content create entry point. + * + * create a content object for the webp + */ +static nserror +webp_create(const content_handler *handler, + lwc_string *imime_type, + const struct http_parameter *params, + llcache_handle *llcache, + const char *fallback_charset, + bool quirks, + struct content **c) +{ + struct content *webp_c; /* webp content object */ + nserror res; + + webp_c = calloc(1, sizeof(struct content)); + if (webp_c == NULL) { + return NSERROR_NOMEM; + } + + res = content__init(webp_c, + handler, + imime_type, + params, + llcache, + fallback_charset, + quirks); + if (res != NSERROR_OK) { + free(webp_c); + return res; + } + + *c = webp_c; + + return NSERROR_OK; +} + +/** + * create a bitmap from webp content. + */ +static struct bitmap * +webp_cache_convert(struct content *c) +{ + const uint8_t *source_data; /* webp source data */ + unsigned long source_size; /* length of webp source data */ + VP8StatusCode webpres; + WebPBitstreamFeatures webpfeatures; + unsigned int bmap_flags; + uint8_t *pixels = NULL; + uint8_t *decoded; + size_t rowstride; + struct bitmap *bitmap = NULL; + + source_data = (uint8_t *)content__get_source_data(c, &source_size); + + webpres = WebPGetFeatures(source_data, source_size, &webpfeatures); + + if (webpres != VP8_STATUS_OK) { + return NULL; + } + + if (webpfeatures.has_alpha == 0) { + bmap_flags = BITMAP_NEW | BITMAP_OPAQUE; + } else { + bmap_flags = BITMAP_NEW; + } + + /* create bitmap */ + bitmap = guit->bitmap->create(webpfeatures.width, + webpfeatures.height, + bmap_flags); + if (bitmap == NULL) { + /* empty bitmap could not be created */ + return NULL; + } + + pixels = guit->bitmap->get_buffer(bitmap); + if (pixels == NULL) { + /* bitmap with no buffer available */ + guit->bitmap->destroy(bitmap); + return NULL; + } + + rowstride = guit->bitmap->get_rowstride(bitmap); + + decoded = WebPDecodeBGRAInto(source_data, + source_size, + pixels, + webpfeatures.width * webpfeatures.height * 4, + rowstride); + if (decoded == NULL) { + /* decode failed */ + guit->bitmap->destroy(bitmap); + return NULL; + } + + return bitmap; +} + +/** + * Convert the webp source data content. + * + * This ensures there is valid webp source data in the content object + * and then adds it to the image cache ready to be converted on + * demand. + * + * \param c The webp content object + * \return true on successful processing of teh webp content else false + */ +static bool webp_convert(struct content *c) +{ + int res; + unsigned long data_size; + const uint8_t* data; + int width; + int height; + + data = (uint8_t *)content__get_source_data(c, &data_size); + + res = WebPGetInfo(data, data_size, &width, &height); + if (res == 0) { + NSLOG(netsurf, INFO, "WebPGetInfo failed:%p", c); + return false; + } + + c->width = width; + c->height = height; + c->size = c->width * c->height * 4; + + image_cache_add(c, NULL, webp_cache_convert); + + content_set_ready(c); + content_set_done(c); + + return true; +} + +/** + * Clone content. + */ +static nserror webp_clone(const struct content *old, struct content **new_c) +{ + struct content *webp_c; /* cloned webp content */ + nserror res; + + webp_c = calloc(1, sizeof(struct content)); + if (webp_c == NULL) { + return NSERROR_NOMEM; + } + + res = content__clone(old, webp_c); + if (res != NSERROR_OK) { + content_destroy(webp_c); + return res; + } + + /* re-convert if the content is ready */ + if ((old->status == CONTENT_STATUS_READY) || + (old->status == CONTENT_STATUS_DONE)) { + if (webp_convert(webp_c) == false) { + content_destroy(webp_c); + return NSERROR_CLONE_FAILED; + } + } + + *new_c = webp_c; + + return NSERROR_OK; +} + +static const content_handler webp_content_handler = { + .create = webp_create, + .data_complete = webp_convert, + .destroy = image_cache_destroy, + .redraw = image_cache_redraw, + .clone = webp_clone, + .get_internal = image_cache_get_internal, + .type = image_cache_content_type, + .no_share = false, +}; + +static const char *webp_types[] = { + "image/webp" +}; + +CONTENT_FACTORY_REGISTER_TYPES(nswebp, webp_types, webp_content_handler); diff --git a/content/handlers/image/webp.h b/content/handlers/image/webp.h new file mode 100644 index 000000000..b219f2576 --- /dev/null +++ b/content/handlers/image/webp.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Vincent Sanders + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file + * Interface to image/webp content handlers + */ + +#ifndef _NETSURF_IMAGE_WEBP_H_ +#define _NETSURF_IMAGE_WEBP_H_ + +nserror nswebp_init(void); + +#endif -- cgit v1.2.3