1
+ #ifdef HAVE_LIBWEBP
1
2
#include <stdio.h>
2
3
#include <math.h>
3
4
#include <string.h>
4
5
#include <stdlib.h>
5
6
#include "gd.h"
6
-
7
-
8
- #ifdef HAVE_LIBVPX
9
- #include "webpimg.h"
10
7
#include "gdhelpers.h"
8
+ #include "webp/decode.h"
9
+ #include "webp/encode.h"
11
10
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)
26
12
27
13
gdImagePtr gdImageCreateFromWebp (FILE * inFile )
28
14
{
@@ -34,42 +20,28 @@ gdImagePtr gdImageCreateFromWebp (FILE * inFile)
34
20
return im ;
35
21
}
36
22
23
+
37
24
gdImagePtr gdImageCreateFromWebpPtr (int size , void * data )
38
25
{
39
- int width , height , ret ;
40
- unsigned char * Y = NULL ;
41
- unsigned char * U = NULL ;
42
- unsigned char * V = NULL ;
43
26
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 );
58
32
return im ;
59
33
}
60
34
61
- #define GD_WEBP_ALLOC_STEP (4*1024)
62
-
63
35
gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile )
64
36
{
65
- int width , height , ret ;
66
- unsigned char * filedata = NULL ;
37
+ int width , height ;
38
+ uint8_t * filedata = NULL ;
39
+ uint8_t * argb = NULL ;
67
40
unsigned char * read , * temp ;
68
- unsigned char * Y = NULL ;
69
- unsigned char * U = NULL ;
70
- unsigned char * V = NULL ;
71
41
size_t size = 0 , n ;
72
42
gdImagePtr im ;
43
+ int x , y ;
44
+ uint8_t * p ;
73
45
74
46
do {
75
47
temp = gdRealloc (filedata , size + GD_WEBP_ALLOC_STEP );
@@ -80,31 +52,106 @@ gdImagePtr gdImageCreateFromWebpCtx (gdIOCtx * infile)
80
52
if (filedata ) {
81
53
gdFree (filedata );
82
54
}
83
- php_gd_error ( "WebP decode: realloc failed" );
55
+ zend_error ( E_ERROR , "WebP decode: realloc failed" );
84
56
return NULL ;
85
57
}
86
58
87
59
n = gdGetBuf (read , GD_WEBP_ALLOC_STEP , infile );
88
- /* differs from upstream where gdGetBuf return 0 instead of EOF */
89
60
if (n > 0 && n != EOF ) {
90
61
size += n ;
91
62
}
92
63
} while (n > 0 && n != EOF );
93
64
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 );
101
68
return NULL ;
102
69
}
70
+
103
71
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 ;
105
97
return im ;
106
98
}
107
99
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
+
108
155
void gdImageWebpEx (gdImagePtr im , FILE * outFile , int quantization )
109
156
{
110
157
gdIOCtx * out = gdNewFileCtx (outFile );
@@ -115,7 +162,7 @@ void gdImageWebpEx (gdImagePtr im, FILE * outFile, int quantization)
115
162
void gdImageWebp (gdImagePtr im , FILE * outFile )
116
163
{
117
164
gdIOCtx * out = gdNewFileCtx (outFile );
118
- gdImageWebpCtx (im , out , -1 );
165
+ gdImageWebpCtx (im , out , -1 );
119
166
out -> gd_free (out );
120
167
}
121
168
@@ -139,74 +186,4 @@ void * gdImageWebpPtrEx (gdImagePtr im, int *size, int quantization)
139
186
out -> gd_free (out );
140
187
return rv ;
141
188
}
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