| 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 <bernd.kuhls@t-online.de> |
| |
| --- |
| https://bugs.gentoo.org/545956 |
| |
| From a79232c5fa692c3b6e3f5bc95ecfc455424c3f54 Mon Sep 17 00:00:00 2001 |
| From: Pierre Joye <pierre.php@gmail.com> |
| 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 <stdio.h> |
| #include <math.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #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 |
| |