Patch committed upstream https://bitbucket.org/libgd/gd-libgd/commits/a79232c5fa692c3b6e3f5bc95ecfc455424c3f54?at=master Downloaded from Gentoo https://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/media-libs/gd/files/gd-2.1.1-webp.patch?revision=1.1&view=markup Signed-off-by: Bernd Kuhls --- https://bugs.gentoo.org/545956 From a79232c5fa692c3b6e3f5bc95ecfc455424c3f54 Mon Sep 17 00:00:00 2001 From: Pierre Joye Date: Tue, 20 Jan 2015 04:55:11 +0100 Subject: [PATCH] fix #129, drop VPX usage in favor of libwebp --- configure.ac | 80 +++++------------ src/gd_webp.c | 231 +++++++++++++++++++++----------------------------- tests/Makefile.am | 2 +- tests/webp/bug00111.c | 2 +- 4 files changed, 122 insertions(+), 193 deletions(-) diff --git a/configure.ac b/configure.ac index 1024a3a..8923186 100644 --- a/configure.ac +++ b/configure.ac @@ -317,63 +317,6 @@ if test "$with_xpm" != no; then fi AM_CONDITIONAL([HAVE_LIBXPM], test "$with_xpm" = yes) -dnl check for libvpx by default -AC_ARG_WITH(vpx,dnl -[ --with-vpx=DIR where to find the vpx library]) - -case $with_vpx in -no) ;; -yes|"") - PKG_CHECK_MODULES([LIBVPX], vpx, [with_vpx=yes], - [ - PKG_CHECK_MODULES([LIBVPX], libvpx, [with_vpx=yes], - [ - if test "$with_vpx" = yes; then - AC_MSG_ERROR([VPX support requested, but not found]) - fi - with_vpx=no - ]) - ]) - ;; -*) - save_LIBS="$LIBS" - save_CPPFLAGS="$CPPFLAGS" - - if test -d "$with_vpx"; then - LIBVPX_CFLAGS="-I$with_vpx/include" - LIBVPX_LIBS="-L$with_vpx/lib -lvpx" - fi - - CPPFLAGS="$CPPFLAGS $LIBVPX_CFLAGS" - LIBS="$LIBS $LIBVPX_LIBS" - - AC_CHECK_LIB(vpx,vpx_codec_destroy, - [ - if test -z "$LIBVPX_LIBS"; then - LIBVPX_LIBS="-lvpx" - fi - with_vpx=yes - ],[ - if test "$with_vpx" != ""; then - AC_MSG_ERROR([vpx support requested, but not found]) - else - with_vpx=no - fi - ]) - - CPPFLAGS="$save_CPPFLAGS" - LIBS="$save_LIBS" - ;; -esac - -if test "$with_vpx" != no; then - CPPFLAGS="$CPPFLAGS $LIBVPX_CFLAGS" - LIBS="$LIBS $LIBVPX_LIBS" - FEATURES="GD_VPX $FEATURES" - AC_DEFINE(HAVE_LIBVPX, 1, [ Define if you have the VPX library. ]) -fi -AM_CONDITIONAL([HAVE_LIBVPX], test "$with_vpx" = yes) - dnl check for libtiff by default AC_ARG_WITH(tiff,dnl [ --with-tiff=DIR where to find the TIFF library]) @@ -437,6 +380,27 @@ if test "$mingw_cv_win32_host" = yes; then AC_DEFINE([BGDWIN32], [], [Define is you are building for Win32 API]) fi + +dnl check for libwebp by default +AC_ARG_WITH(webp,dnl +[ --with-webp=DIR where to find the webp library], + [if test -d "$withval"; then + LDFLAGS="$LDFLAGS -L$withval/lib" + CFLAGS="$CFLAGS -I$withval/include" + fi], + withval=yes) + +if test "$withval" != no; then + AC_CHECK_LIB(webp,WebPGetInfo, + [LIBS="-lwebp $LIBS" + FEATURES="GD_WEBP $FEATURES" + AC_DEFINE(HAVE_LIBWEBP, 1, [ Define if you have the webp library. ])]) + with_webp=yes +else + with_webp=no +fi +AM_CONDITIONAL([HAVE_LIBWEBP], test "$with_webp" = yes) + dnl report configuration AC_MSG_RESULT([ ** Configuration summary for $PACKAGE $VERSION: @@ -444,7 +408,7 @@ AC_MSG_RESULT([ Support for Zlib: $with_zlib Support for PNG library: $with_png Support for JPEG library: $ac_cv_lib_jpeg_jpeg_set_defaults - Support for VPX library: $with_vpx + Support for WebP library: $with_webp Support for TIFF library: $with_tiff Support for Freetype 2.x library: $with_freetype Support for Fontconfig library: $with_fontconfig diff --git a/src/gd_webp.c b/src/gd_webp.c index a3ae1ac..c44bd80 100644 --- a/src/gd_webp.c +++ b/src/gd_webp.c @@ -2,33 +2,21 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_LIBWEBP #include #include #include #include #include "gd.h" #include "gd_errors.h" - -#ifdef HAVE_LIBVPX -#include "webpimg.h" #include "gdhelpers.h" +#include "webp/decode.h" +#include "webp/encode.h" -extern void gd_YUV420toRGBA(uint8* Y, - uint8* U, - uint8* V, - gdImagePtr im); - -extern void gd_RGBAToYUV420(gdImagePtr im2, - uint8* Y, - uint8* U, - uint8* V); - -const char * gdWebpGetVersionString() -{ - return "not defined"; -} +#define GD_WEBP_ALLOC_STEP (4*1024) -BGD_DECLARE(gdImagePtr) gdImageCreateFromWebp (FILE * inFile) +gdImagePtr gdImageCreateFromWebp (FILE * inFile) { gdImagePtr im; gdIOCtx *in = gdNewFileCtx(inFile); @@ -38,42 +26,16 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromWebp (FILE * inFile) return im; } -BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpPtr (int size, void *data) +gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile) { - int width, height, ret; - unsigned char *Y = NULL; - unsigned char *U = NULL; - unsigned char *V = NULL; - gdImagePtr im; - - ret = WebPDecode(data, size, &Y, &U, &V, &width, &height); - if (ret != webp_success) { - if (Y) free(Y); - if (U) free(U); - if (V) free(V); - gd_error("WebP decode: fail to decode input data"); - return NULL; - } - im = gdImageCreateTrueColor(width, height); - if (!im) { - return NULL; - } - gd_YUV420toRGBA(Y, U, V, im); - return im; -} - -#define GD_WEBP_ALLOC_STEP (4*1024) - -BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpCtx (gdIOCtx * infile) -{ - int width, height, ret; - unsigned char *filedata = NULL; + int width, height; + uint8_t *filedata = NULL; + uint8_t *argb = NULL; unsigned char *read, *temp; - unsigned char *Y = NULL; - unsigned char *U = NULL; - unsigned char *V = NULL; size_t size = 0, n; gdImagePtr im; + int x, y; + uint8_t *p; do { temp = gdRealloc(filedata, size+GD_WEBP_ALLOC_STEP); @@ -89,23 +51,97 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromWebpCtx (gdIOCtx * infile) } n = gdGetBuf(read, GD_WEBP_ALLOC_STEP, infile); - size += n; - } while (n>0); + if (n>0 && n!=EOF) { + size += n; + } + } while (n>0 && n!=EOF); - ret = WebPDecode(filedata, size, &Y, &U, &V, &width, &height); - gdFree(filedata); - if (ret != webp_success) { - if (Y) free(Y); - if (U) free(U); - if (V) free(V); - gd_error("WebP decode: fail to decode input data"); + if (WebPGetInfo(filedata,size, &width, &height) == 0) { + gd_error("gd-webp cannot get webp info"); return NULL; } + im = gdImageCreateTrueColor(width, height); - gd_YUV420toRGBA(Y, U, V, im); + if (!im) { + return NULL; + } + argb = WebPDecodeARGB(filedata, size, &width, &height); + if (!argb) { + gd_error("gd-webp cannot allocate temporary buffer"); + gdFree(argb); + return NULL; + } + for (y = 0, p = argb; y < height; y++) { + for (x = 0; x < width; x++) { + register uint8_t a = gdAlphaMax - (*(p++) >> 1); + register uint8_t r = *(p++); + register uint8_t g = *(p++); + register uint8_t b = *(p++); + im->tpixels[y][x] = gdTrueColorAlpha(r, g, b, a); + } + } + gdFree(filedata); + free(argb); + im->saveAlphaFlag = 1; return im; } +void gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization) +{ + uint8_t *argb; + int x, y; + uint8_t *p; + uint8_t *out; + size_t out_size; + + if (im == NULL) { + return; + } + + if (!gdImageTrueColor(im)) { + gd_error("Paletter image not supported by webp"); + return; + } + + if (quantization == -1) { + quantization = 80; + } + + argb = (uint8_t *)gdMalloc(gdImageSX(im) * 4 * gdImageSY(im)); + if (!argb) { + return; + } + p = argb; + for (y = 0; y < gdImageSY(im); y++) { + for (x = 0; x < gdImageSX(im); x++) { + register int c; + register char a; + c = im->tpixels[y][x]; + a = gdTrueColorGetAlpha(c); + if (a == 127) { + a = 0; + } else { + a = 255 - ((a << 1) + (a >> 6)); + } + *(p++) = gdTrueColorGetRed(c); + *(p++) = gdTrueColorGetGreen(c); + *(p++) = gdTrueColorGetBlue(c); + *(p++) = a; + } + } + out_size = WebPEncodeRGBA(argb, gdImageSX(im), gdImageSY(im), gdImageSX(im) * 4, quantization, &out); + printf("outsize: %i\n", out_size); + if (out_size == 0) { + gd_error("gd-webp encoding failed"); + goto freeargb; + } + gdPutBuf(out, out_size, outfile); + free(out); + +freeargb: + gdFree(argb); +} + BGD_DECLARE(void) gdImageWebpEx (gdImagePtr im, FILE * outFile, int quantization) { gdIOCtx *out = gdNewFileCtx(outFile); @@ -116,7 +152,7 @@ BGD_DECLARE(void) gdImageWebpEx (gdImagePtr im, FILE * outFile, int quantization BGD_DECLARE(void) gdImageWebp (gdImagePtr im, FILE * outFile) { gdIOCtx *out = gdNewFileCtx(outFile); - gdImageWebpCtx(im, out, -1); + gdImageWebpCtx(im, out, -1); out->gd_free(out); } @@ -140,75 +176,4 @@ BGD_DECLARE(void *) gdImageWebpPtrEx (gdImagePtr im, int *size, int quantization out->gd_free(out); return rv; } - -/* - * Maps normalized QP (quality) to VP8 QP - */ -int mapQualityToVP8QP(int quality) { -#define MIN_QUALITY 0 -#define MAX_QUALITY 100 -#define MIN_VP8QP 1 -#define MAX_VP8QP 63 - const float scale = MAX_VP8QP - MIN_VP8QP; - const float vp8qp = - scale * (MAX_QUALITY - quality) / (MAX_QUALITY - MIN_QUALITY) + MIN_VP8QP; - if (quality < MIN_QUALITY || quality > MAX_QUALITY) { - gd_error("Wrong quality value %d.", quality); - return -1; - } - - return (int)(vp8qp + 0.5); -} - -/* This routine is based in part on code from Dale Lutz (Safe Software Inc.) - * and in part on demo code from Chapter 15 of "PNG: The Definitive Guide" - * (http://www.cdrom.com/pub/png/pngbook.html). - */ -BGD_DECLARE(void) gdImageWebpCtx (gdImagePtr im, gdIOCtx * outfile, int quantization) -{ - int width = im->sx; - int height = im->sy; - - int yuv_width, yuv_height, yuv_nbytes, ret; - int vp8_quality; - unsigned char *Y = NULL, - *U = NULL, - *V = NULL; - unsigned char *filedata = NULL; - - /* Conversion to Y,U,V buffer */ - yuv_width = (width + 1) >> 1; - yuv_height = (height + 1) >> 1; - yuv_nbytes = width * height + 2 * yuv_width * yuv_height; - - if ((Y = (unsigned char *)gdCalloc(yuv_nbytes, sizeof(unsigned char))) == NULL) { - gd_error("gd-webp error: cannot allocate Y buffer"); - return; - } - if (quantization == -1) { - quantization = 80; - } - vp8_quality = mapQualityToVP8QP(quantization); - - U = Y + width * height; - V = U + yuv_width * yuv_height; - gd_RGBAToYUV420(im, Y, U, V); - - /* Encode Y,U,V and write data to file */ - ret = WebPEncode(Y, U, V, width, height, width, yuv_width, yuv_height, yuv_width, - vp8_quality, &filedata, &yuv_nbytes, NULL); - gdFree(Y); - - if (ret != webp_success) { - if (filedata) { - free(filedata); - } - gd_error("gd-webp error: WebP Encoder failed"); - return; - } - - gdPutBuf (filedata, yuv_nbytes, outfile); - free(filedata); -} - -#endif /* HAVE_LIBVPX */ +#endif /* HAVE_LIBWEBP */ -- 2.3.5