1+ #ifdef HAVE_LIBWEBP
12#include <stdio.h>
23#include <math.h>
34#include <string.h>
45#include <stdlib.h>
56#include "gd.h"
6-
7-
8- #ifdef HAVE_LIBVPX
9- #include "webpimg.h"
107#include "gdhelpers.h"
8+ #include "webp/decode.h"
9+ #include "webp/encode.h"
1110
12- extern void gd_YUV420toRGBA (uint8 * Y ,
13- uint8 * U ,
14- uint8 * V ,
15- gdImagePtr im );
16-
17- extern void gd_RGBAToYUV420 (gdImagePtr im2 ,
18- uint8 * Y ,
19- uint8 * U ,
20- uint8 * V );
21-
22- const char * gdWebpGetVersionString ()
23- {
24- return "not defined" ;
25- }
11+ #define GD_WEBP_ALLOC_STEP (4*1024)
2612
2713gdImagePtr gdImageCreateFromWebp (FILE * inFile )
2814{
@@ -34,42 +20,28 @@ gdImagePtr gdImageCreateFromWebp (FILE * inFile)
3420 return im ;
3521}
3622
23+
3724gdImagePtr gdImageCreateFromWebpPtr (int size , void * data )
3825{
39- int width , height , ret ;
40- unsigned char * Y = NULL ;
41- unsigned char * U = NULL ;
42- unsigned char * V = NULL ;
4326 gdImagePtr im ;
44-
45- ret = WebPDecode (data , size , & Y , & U , & V , & width , & height );
46- if (ret != webp_success ) {
47- if (Y ) free (Y );
48- if (U ) free (U );
49- if (V ) free (V );
50- php_gd_error ("WebP decode: fail to decode input data" );
51- return NULL ;
52- }
53- im = gdImageCreateTrueColor (width , height );
54- if (!im ) {
55- return NULL ;
56- }
57- gd_YUV420toRGBA (Y , U , V , im );
27+ gdIOCtx * in = gdNewDynamicCtxEx (size , data , 0 );
28+ if (!in )
29+ return 0 ;
30+ im = gdImageCreateFromWebpCtx (in );
31+ in -> gd_free (in );
5832 return im ;
5933}
6034
61- #define GD_WEBP_ALLOC_STEP (4*1024)
62-
6335gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile )
6436{
65- int width , height , ret ;
66- unsigned char * filedata = NULL ;
37+ int width , height ;
38+ uint8_t * filedata = NULL ;
39+ uint8_t * argb = NULL ;
6740 unsigned char * read , * temp ;
68- unsigned char * Y = NULL ;
69- unsigned char * U = NULL ;
70- unsigned char * V = NULL ;
7141 size_t size = 0 , n ;
7242 gdImagePtr im ;
43+ int x , y ;
44+ uint8_t * p ;
7345
7446 do {
7547 temp = gdRealloc (filedata , size + GD_WEBP_ALLOC_STEP );
@@ -80,31 +52,106 @@ gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile)
8052 if (filedata ) {
8153 gdFree (filedata );
8254 }
83- php_gd_error ( "WebP decode: realloc failed" );
55+ zend_error ( E_ERROR , "WebP decode: realloc failed" );
8456 return NULL ;
8557 }
8658
8759 n = gdGetBuf (read , GD_WEBP_ALLOC_STEP , infile );
88- /* differs from upstream where gdGetBuf return 0 instead of EOF */
8960 if (n > 0 && n != EOF ) {
9061 size += n ;
9162 }
9263 } while (n > 0 && n != EOF );
9364
94- ret = WebPDecode (filedata , size , & Y , & U , & V , & width , & height );
95- gdFree (filedata );
96- if (ret != webp_success ) {
97- if (Y ) free (Y );
98- if (U ) free (U );
99- if (V ) free (V );
100- php_gd_error ("WebP decode: fail to decode input data" );
65+ if (WebPGetInfo (filedata ,size , & width , & height ) == 0 ) {
66+ zend_error (E_ERROR , "gd-webp cannot get webp info" );
67+ gdFree (temp );
10168 return NULL ;
10269 }
70+
10371 im = gdImageCreateTrueColor (width , height );
104- gd_YUV420toRGBA (Y , U , V , im );
72+ if (!im ) {
73+ gdFree (temp );
74+ return NULL ;
75+ }
76+ argb = WebPDecodeARGB (filedata , size , & width , & height );
77+ if (!argb ) {
78+ zend_error (E_ERROR , "gd-webp cannot allocate temporary buffer" );
79+ gdFree (temp );
80+ gdImageDestroy (im );
81+ return NULL ;
82+ }
83+ for (y = 0 , p = argb ; y < height ; y ++ ) {
84+ for (x = 0 ; x < width ; x ++ ) {
85+ register uint8_t a = gdAlphaMax - (* (p ++ ) >> 1 );
86+ register uint8_t r = * (p ++ );
87+ register uint8_t g = * (p ++ );
88+ register uint8_t b = * (p ++ );
89+ im -> tpixels [y ][x ] = gdTrueColorAlpha (r , g , b , a );
90+ }
91+ }
92+ gdFree (filedata );
93+ /* do not use gdFree here, in case gdFree/alloc is mapped to something else than libc */
94+ free (argb );
95+ gdFree (temp );
96+ im -> saveAlphaFlag = 1 ;
10597 return im ;
10698}
10799
100+ void gdImageWebpCtx (gdImagePtr im , gdIOCtx * outfile , int quantization )
101+ {
102+ uint8_t * argb ;
103+ int x , y ;
104+ uint8_t * p ;
105+ uint8_t * out ;
106+ size_t out_size ;
107+
108+ if (im == NULL ) {
109+ return ;
110+ }
111+
112+ if (!gdImageTrueColor (im )) {
113+ zend_error (E_ERROR , "Paletter image not supported by webp" );
114+ return ;
115+ }
116+
117+ if (quantization == -1 ) {
118+ quantization = 80 ;
119+ }
120+
121+ argb = (uint8_t * )gdMalloc (gdImageSX (im ) * 4 * gdImageSY (im ));
122+ if (!argb ) {
123+ return ;
124+ }
125+ p = argb ;
126+ for (y = 0 ; y < gdImageSY (im ); y ++ ) {
127+ for (x = 0 ; x < gdImageSX (im ); x ++ ) {
128+ register int c ;
129+ register char a ;
130+ c = im -> tpixels [y ][x ];
131+ a = gdTrueColorGetAlpha (c );
132+ if (a == 127 ) {
133+ a = 0 ;
134+ } else {
135+ a = 255 - ((a << 1 ) + (a >> 6 ));
136+ }
137+ * (p ++ ) = gdTrueColorGetRed (c );
138+ * (p ++ ) = gdTrueColorGetGreen (c );
139+ * (p ++ ) = gdTrueColorGetBlue (c );
140+ * (p ++ ) = a ;
141+ }
142+ }
143+ out_size = WebPEncodeRGBA (argb , gdImageSX (im ), gdImageSY (im ), gdImageSX (im ) * 4 , quantization , & out );
144+ if (out_size == 0 ) {
145+ zend_error (E_ERROR , "gd-webp encoding failed" );
146+ goto freeargb ;
147+ }
148+ gdPutBuf (out , out_size , outfile );
149+ free (out );
150+
151+ freeargb :
152+ gdFree (argb );
153+ }
154+
108155void gdImageWebpEx (gdImagePtr im , FILE * outFile , int quantization )
109156{
110157 gdIOCtx * out = gdNewFileCtx (outFile );
@@ -115,7 +162,7 @@ void gdImageWebpEx (gdImagePtr im, FILE * outFile, int quantization)
115162void gdImageWebp (gdImagePtr im , FILE * outFile )
116163{
117164 gdIOCtx * out = gdNewFileCtx (outFile );
118- gdImageWebpCtx (im , out , -1 );
165+ gdImageWebpCtx (im , out , -1 );
119166 out -> gd_free (out );
120167}
121168
@@ -139,74 +186,4 @@ void * gdImageWebpPtrEx (gdImagePtr im, int *size, int quantization)
139186 out -> gd_free (out );
140187 return rv ;
141188}
142-
143- /*
144- * Maps normalized QP (quality) to VP8 QP
145- */
146- int mapQualityToVP8QP (int quality ) {
147- #define MIN_QUALITY 0
148- #define MAX_QUALITY 100
149- #define MIN_VP8QP 1
150- #define MAX_VP8QP 63
151- const float scale = MAX_VP8QP - MIN_VP8QP ;
152- const float vp8qp =
153- scale * (MAX_QUALITY - quality ) / (MAX_QUALITY - MIN_QUALITY ) + MIN_VP8QP ;
154- if (quality < MIN_QUALITY || quality > MAX_QUALITY ) {
155- php_gd_error ("Wrong quality value %d." , quality );
156- return -1 ;
157- }
158-
159- return (int )(vp8qp + 0.5 );
160- }
161-
162- /* This routine is based in part on code from Dale Lutz (Safe Software Inc.)
163- * and in part on demo code from Chapter 15 of "PNG: The Definitive Guide"
164- * (http://www.cdrom.com/pub/png/pngbook.html).
165- */
166- void gdImageWebpCtx (gdImagePtr im , gdIOCtx * outfile , int quantization )
167- {
168- int width = im -> sx ;
169- int height = im -> sy ;
170- int colors = im -> colorsTotal ;
171- int * open = im -> open ;
172-
173- int yuv_width , yuv_height , yuv_nbytes , ret ;
174- int vp8_quality ;
175- unsigned char * Y = NULL ,
176- * U = NULL ,
177- * V = NULL ;
178- unsigned char * filedata = NULL ;
179-
180- /* Conversion to Y,U,V buffer */
181- yuv_width = (width + 1 ) >> 1 ;
182- yuv_height = (height + 1 ) >> 1 ;
183- yuv_nbytes = width * height + 2 * yuv_width * yuv_height ;
184-
185- if ((Y = (unsigned char * )gdCalloc (yuv_nbytes , sizeof (unsigned char ))) == NULL ) {
186- php_gd_error ("gd-webp error: cannot allocate Y buffer" );
187- return ;
188- }
189- vp8_quality = mapQualityToVP8QP (quantization );
190-
191- U = Y + width * height ;
192- V = U + yuv_width * yuv_height ;
193- gd_RGBAToYUV420 (im , Y , U , V );
194-
195- /* Encode Y,U,V and write data to file */
196- ret = WebPEncode (Y , U , V , width , height , width , yuv_width , yuv_height , yuv_width ,
197- vp8_quality , & filedata , & yuv_nbytes , NULL );
198- gdFree (Y );
199-
200- if (ret != webp_success ) {
201- if (filedata ) {
202- free (filedata );
203- }
204- php_gd_error ("gd-webp error: WebP Encoder failed" );
205- return ;
206- }
207-
208- gdPutBuf (filedata , yuv_nbytes , outfile );
209- free (filedata );
210- }
211-
212- #endif /* HAVE_LIBVPX */
189+ #endif /* HAVE_LIBWEBP */
0 commit comments