xref: /PHP-7.4/ext/gd/gd.c (revision d50532be)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) The PHP Group                                          |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
16    |          Stig Bakken <ssb@php.net>                                   |
17    |          Jim Winstead <jimw@php.net>                                 |
18    +----------------------------------------------------------------------+
19  */
20 
21 /* gd 1.2 is copyright 1994, 1995, Quest Protein Database Center,
22    Cold Spring Harbor Labs. */
23 
24 /* Note that there is no code from the gd package in this file */
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include "php.h"
31 #include "php_ini.h"
32 #include "ext/standard/head.h"
33 #include <math.h>
34 #include "SAPI.h"
35 #include "php_gd.h"
36 #include "ext/standard/info.h"
37 #include "php_open_temporary_file.h"
38 
39 
40 #ifdef HAVE_SYS_WAIT_H
41 # include <sys/wait.h>
42 #endif
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
46 #ifdef PHP_WIN32
47 # include <io.h>
48 # include <fcntl.h>
49 # include <windows.h>
50 # include <Winuser.h>
51 # include <Wingdi.h>
52 #endif
53 
54 #if defined(HAVE_GD_XPM) && defined(HAVE_GD_BUNDLED)
55 # include <X11/xpm.h>
56 #endif
57 
58 # include "gd_compat.h"
59 
60 
61 static int le_gd, le_gd_font;
62 
63 #ifdef HAVE_GD_BUNDLED
64 # include "libgd/gd.h"
65 # include "libgd/gd_errors.h"
66 # include "libgd/gdfontt.h"  /* 1 Tiny font */
67 # include "libgd/gdfonts.h"  /* 2 Small font */
68 # include "libgd/gdfontmb.h" /* 3 Medium bold font */
69 # include "libgd/gdfontl.h"  /* 4 Large font */
70 # include "libgd/gdfontg.h"  /* 5 Giant font */
71 #else
72 # include <gd.h>
73 # include <gd_errors.h>
74 # include <gdfontt.h>  /* 1 Tiny font */
75 # include <gdfonts.h>  /* 2 Small font */
76 # include <gdfontmb.h> /* 3 Medium bold font */
77 # include <gdfontl.h>  /* 4 Large font */
78 # include <gdfontg.h>  /* 5 Giant font */
79 #endif
80 
81 #if defined(HAVE_GD_FREETYPE) && defined(HAVE_GD_BUNDLED)
82 # include <ft2build.h>
83 # include FT_FREETYPE_H
84 #endif
85 
86 #if defined(HAVE_GD_XPM) && defined(HAVE_GD_BUNDLED)
87 # include "X11/xpm.h"
88 #endif
89 
90 #ifndef M_PI
91 #define M_PI 3.14159265358979323846
92 #endif
93 
94 #ifdef HAVE_GD_FREETYPE
95 static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int, int);
96 #endif
97 
98 #include "gd_ctx.c"
99 
100 /* as it is not really public, duplicate declaration here to avoid
101    pointless warnings */
102 int overflow2(int a, int b);
103 
104 /* Section Filters Declarations */
105 /* IMPORTANT NOTE FOR NEW FILTER
106  * Do not forget to update:
107  * IMAGE_FILTER_MAX: define the last filter index
108  * IMAGE_FILTER_MAX_ARGS: define the biggest amount of arguments
109  * image_filter array in PHP_FUNCTION(imagefilter)
110  * */
111 #define IMAGE_FILTER_NEGATE         0
112 #define IMAGE_FILTER_GRAYSCALE      1
113 #define IMAGE_FILTER_BRIGHTNESS     2
114 #define IMAGE_FILTER_CONTRAST       3
115 #define IMAGE_FILTER_COLORIZE       4
116 #define IMAGE_FILTER_EDGEDETECT     5
117 #define IMAGE_FILTER_EMBOSS         6
118 #define IMAGE_FILTER_GAUSSIAN_BLUR  7
119 #define IMAGE_FILTER_SELECTIVE_BLUR 8
120 #define IMAGE_FILTER_MEAN_REMOVAL   9
121 #define IMAGE_FILTER_SMOOTH         10
122 #define IMAGE_FILTER_PIXELATE       11
123 #define IMAGE_FILTER_SCATTER		12
124 #define IMAGE_FILTER_MAX            12
125 #define IMAGE_FILTER_MAX_ARGS       6
126 static void php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS);
127 static void php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS);
128 static void php_image_filter_brightness(INTERNAL_FUNCTION_PARAMETERS);
129 static void php_image_filter_contrast(INTERNAL_FUNCTION_PARAMETERS);
130 static void php_image_filter_colorize(INTERNAL_FUNCTION_PARAMETERS);
131 static void php_image_filter_edgedetect(INTERNAL_FUNCTION_PARAMETERS);
132 static void php_image_filter_emboss(INTERNAL_FUNCTION_PARAMETERS);
133 static void php_image_filter_gaussian_blur(INTERNAL_FUNCTION_PARAMETERS);
134 static void php_image_filter_selective_blur(INTERNAL_FUNCTION_PARAMETERS);
135 static void php_image_filter_mean_removal(INTERNAL_FUNCTION_PARAMETERS);
136 static void php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS);
137 static void php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS);
138 static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS);
139 
140 /* End Section filters declarations */
141 static gdImagePtr _php_image_create_from_string (zval *Data, char *tn, gdImagePtr (*ioctx_func_p)());
142 static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)());
143 static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)());
144 static int _php_image_type(char data[12]);
145 static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type);
146 
147 /* {{{ arginfo */
148 ZEND_BEGIN_ARG_INFO(arginfo_gd_info, 0)
149 ZEND_END_ARG_INFO()
150 
151 ZEND_BEGIN_ARG_INFO(arginfo_imageloadfont, 0)
152 	ZEND_ARG_INFO(0, filename)
153 ZEND_END_ARG_INFO()
154 
155 ZEND_BEGIN_ARG_INFO(arginfo_imagesetstyle, 0)
156 	ZEND_ARG_INFO(0, im)
157 	ZEND_ARG_INFO(0, styles) /* ARRAY_INFO(0, styles, 0) */
158 ZEND_END_ARG_INFO()
159 
160 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatetruecolor, 0)
161 	ZEND_ARG_INFO(0, x_size)
162 	ZEND_ARG_INFO(0, y_size)
163 ZEND_END_ARG_INFO()
164 
165 ZEND_BEGIN_ARG_INFO(arginfo_imageistruecolor, 0)
166 	ZEND_ARG_INFO(0, im)
167 ZEND_END_ARG_INFO()
168 
169 ZEND_BEGIN_ARG_INFO(arginfo_imagetruecolortopalette, 0)
170 	ZEND_ARG_INFO(0, im)
171 	ZEND_ARG_INFO(0, ditherFlag)
172 	ZEND_ARG_INFO(0, colorsWanted)
173 ZEND_END_ARG_INFO()
174 
175 ZEND_BEGIN_ARG_INFO(arginfo_imagepalettetotruecolor, 0)
176 	ZEND_ARG_INFO(0, im)
177 ZEND_END_ARG_INFO()
178 
179 ZEND_BEGIN_ARG_INFO(arginfo_imagecolormatch, 0)
180 	ZEND_ARG_INFO(0, im1)
181 	ZEND_ARG_INFO(0, im2)
182 ZEND_END_ARG_INFO()
183 
184 ZEND_BEGIN_ARG_INFO(arginfo_imagesetthickness, 0)
185 	ZEND_ARG_INFO(0, im)
186 	ZEND_ARG_INFO(0, thickness)
187 ZEND_END_ARG_INFO()
188 
189 ZEND_BEGIN_ARG_INFO(arginfo_imagefilledellipse, 0)
190 	ZEND_ARG_INFO(0, im)
191 	ZEND_ARG_INFO(0, cx)
192 	ZEND_ARG_INFO(0, cy)
193 	ZEND_ARG_INFO(0, w)
194 	ZEND_ARG_INFO(0, h)
195 	ZEND_ARG_INFO(0, color)
196 ZEND_END_ARG_INFO()
197 
198 ZEND_BEGIN_ARG_INFO(arginfo_imagefilledarc, 0)
199 	ZEND_ARG_INFO(0, im)
200 	ZEND_ARG_INFO(0, cx)
201 	ZEND_ARG_INFO(0, cy)
202 	ZEND_ARG_INFO(0, w)
203 	ZEND_ARG_INFO(0, h)
204 	ZEND_ARG_INFO(0, s)
205 	ZEND_ARG_INFO(0, e)
206 	ZEND_ARG_INFO(0, col)
207 	ZEND_ARG_INFO(0, style)
208 ZEND_END_ARG_INFO()
209 
210 ZEND_BEGIN_ARG_INFO(arginfo_imagealphablending, 0)
211 	ZEND_ARG_INFO(0, im)
212 	ZEND_ARG_INFO(0, blend)
213 ZEND_END_ARG_INFO()
214 
215 ZEND_BEGIN_ARG_INFO(arginfo_imagesavealpha, 0)
216 	ZEND_ARG_INFO(0, im)
217 	ZEND_ARG_INFO(0, save)
218 ZEND_END_ARG_INFO()
219 
220 ZEND_BEGIN_ARG_INFO(arginfo_imagelayereffect, 0)
221 	ZEND_ARG_INFO(0, im)
222 	ZEND_ARG_INFO(0, effect)
223 ZEND_END_ARG_INFO()
224 
225 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorallocatealpha, 0)
226 	ZEND_ARG_INFO(0, im)
227 	ZEND_ARG_INFO(0, red)
228 	ZEND_ARG_INFO(0, green)
229 	ZEND_ARG_INFO(0, blue)
230 	ZEND_ARG_INFO(0, alpha)
231 ZEND_END_ARG_INFO()
232 
233 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorresolvealpha, 0)
234 	ZEND_ARG_INFO(0, im)
235 	ZEND_ARG_INFO(0, red)
236 	ZEND_ARG_INFO(0, green)
237 	ZEND_ARG_INFO(0, blue)
238 	ZEND_ARG_INFO(0, alpha)
239 ZEND_END_ARG_INFO()
240 
241 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorclosestalpha, 0)
242 	ZEND_ARG_INFO(0, im)
243 	ZEND_ARG_INFO(0, red)
244 	ZEND_ARG_INFO(0, green)
245 	ZEND_ARG_INFO(0, blue)
246 	ZEND_ARG_INFO(0, alpha)
247 ZEND_END_ARG_INFO()
248 
249 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorexactalpha, 0)
250 	ZEND_ARG_INFO(0, im)
251 	ZEND_ARG_INFO(0, red)
252 	ZEND_ARG_INFO(0, green)
253 	ZEND_ARG_INFO(0, blue)
254 	ZEND_ARG_INFO(0, alpha)
255 ZEND_END_ARG_INFO()
256 
257 ZEND_BEGIN_ARG_INFO(arginfo_imagecopyresampled, 0)
258 	ZEND_ARG_INFO(0, dst_im)
259 	ZEND_ARG_INFO(0, src_im)
260 	ZEND_ARG_INFO(0, dst_x)
261 	ZEND_ARG_INFO(0, dst_y)
262 	ZEND_ARG_INFO(0, src_x)
263 	ZEND_ARG_INFO(0, src_y)
264 	ZEND_ARG_INFO(0, dst_w)
265 	ZEND_ARG_INFO(0, dst_h)
266 	ZEND_ARG_INFO(0, src_w)
267 	ZEND_ARG_INFO(0, src_h)
268 ZEND_END_ARG_INFO()
269 
270 #ifdef PHP_WIN32
271 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagegrabwindow, 0, 0, 1)
272 	ZEND_ARG_INFO(0, handle)
273 	ZEND_ARG_INFO(0, client_area)
274 ZEND_END_ARG_INFO()
275 
276 ZEND_BEGIN_ARG_INFO(arginfo_imagegrabscreen, 0)
277 ZEND_END_ARG_INFO()
278 #endif
279 
280 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagerotate, 0, 0, 3)
281 	ZEND_ARG_INFO(0, im)
282 	ZEND_ARG_INFO(0, angle)
283 	ZEND_ARG_INFO(0, bgdcolor)
284 	ZEND_ARG_INFO(0, ignoretransparent)
285 ZEND_END_ARG_INFO()
286 
287 ZEND_BEGIN_ARG_INFO(arginfo_imagesettile, 0)
288 	ZEND_ARG_INFO(0, im)
289 	ZEND_ARG_INFO(0, tile)
290 ZEND_END_ARG_INFO()
291 
292 ZEND_BEGIN_ARG_INFO(arginfo_imagesetbrush, 0)
293 	ZEND_ARG_INFO(0, im)
294 	ZEND_ARG_INFO(0, brush)
295 ZEND_END_ARG_INFO()
296 
297 ZEND_BEGIN_ARG_INFO(arginfo_imagecreate, 0)
298 	ZEND_ARG_INFO(0, x_size)
299 	ZEND_ARG_INFO(0, y_size)
300 ZEND_END_ARG_INFO()
301 
302 ZEND_BEGIN_ARG_INFO(arginfo_imagetypes, 0)
303 ZEND_END_ARG_INFO()
304 
305 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromstring, 0)
306 	ZEND_ARG_INFO(0, image)
307 ZEND_END_ARG_INFO()
308 
309 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromgif, 0)
310 	ZEND_ARG_INFO(0, filename)
311 ZEND_END_ARG_INFO()
312 
313 #ifdef HAVE_GD_JPG
314 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromjpeg, 0)
315 	ZEND_ARG_INFO(0, filename)
316 ZEND_END_ARG_INFO()
317 #endif
318 
319 #ifdef HAVE_GD_PNG
320 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefrompng, 0)
321 	ZEND_ARG_INFO(0, filename)
322 ZEND_END_ARG_INFO()
323 #endif
324 
325 #ifdef HAVE_GD_WEBP
326 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromwebp, 0)
327 	ZEND_ARG_INFO(0, filename)
328 ZEND_END_ARG_INFO()
329 #endif
330 
331 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromxbm, 0)
332 	ZEND_ARG_INFO(0, filename)
333 ZEND_END_ARG_INFO()
334 
335 #if defined(HAVE_GD_XPM)
336 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromxpm, 0)
337 	ZEND_ARG_INFO(0, filename)
338 ZEND_END_ARG_INFO()
339 #endif
340 
341 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromwbmp, 0)
342 	ZEND_ARG_INFO(0, filename)
343 ZEND_END_ARG_INFO()
344 
345 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromgd, 0)
346 	ZEND_ARG_INFO(0, filename)
347 ZEND_END_ARG_INFO()
348 
349 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromgd2, 0)
350 	ZEND_ARG_INFO(0, filename)
351 ZEND_END_ARG_INFO()
352 
353 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromgd2part, 0)
354 	ZEND_ARG_INFO(0, filename)
355 	ZEND_ARG_INFO(0, srcX)
356 	ZEND_ARG_INFO(0, srcY)
357 	ZEND_ARG_INFO(0, width)
358 	ZEND_ARG_INFO(0, height)
359 ZEND_END_ARG_INFO()
360 
361 #if defined(HAVE_GD_BMP)
362 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefrombmp, 0)
363 	ZEND_ARG_INFO(0, filename)
364 ZEND_END_ARG_INFO()
365 #endif
366 
367 #if defined(HAVE_GD_TGA)
368 ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromtga, 0)
369 	ZEND_ARG_INFO(0, filename)
370 ZEND_END_ARG_INFO()
371 #endif
372 
373 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagexbm, 0, 0, 2)
374 	ZEND_ARG_INFO(0, im)
375 	ZEND_ARG_INFO(0, filename)
376 	ZEND_ARG_INFO(0, foreground)
377 ZEND_END_ARG_INFO()
378 
379 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagegif, 0, 0, 1)
380 	ZEND_ARG_INFO(0, im)
381 	ZEND_ARG_INFO(0, to)
382 ZEND_END_ARG_INFO()
383 
384 #ifdef HAVE_GD_PNG
385 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagepng, 0, 0, 1)
386 	ZEND_ARG_INFO(0, im)
387 	ZEND_ARG_INFO(0, to)
388 	ZEND_ARG_INFO(0, quality)
389 	ZEND_ARG_INFO(0, filters)
390 ZEND_END_ARG_INFO()
391 #endif
392 
393 #ifdef HAVE_GD_WEBP
394 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagewebp, 0, 0, 1)
395 	ZEND_ARG_INFO(0, im)
396 	ZEND_ARG_INFO(0, to)
397 	ZEND_ARG_INFO(0, quality)
398 ZEND_END_ARG_INFO()
399 #endif
400 
401 #ifdef HAVE_GD_JPG
402 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagejpeg, 0, 0, 1)
403 	ZEND_ARG_INFO(0, im)
404 	ZEND_ARG_INFO(0, to)
405 	ZEND_ARG_INFO(0, quality)
406 ZEND_END_ARG_INFO()
407 #endif
408 
409 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagewbmp, 0, 0, 1)
410 	ZEND_ARG_INFO(0, im)
411 	ZEND_ARG_INFO(0, to)
412 	ZEND_ARG_INFO(0, foreground)
413 ZEND_END_ARG_INFO()
414 
415 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagegd, 0, 0, 1)
416 	ZEND_ARG_INFO(0, im)
417 	ZEND_ARG_INFO(0, to)
418 ZEND_END_ARG_INFO()
419 
420 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagegd2, 0, 0, 1)
421 	ZEND_ARG_INFO(0, im)
422 	ZEND_ARG_INFO(0, to)
423 	ZEND_ARG_INFO(0, chunk_size)
424 	ZEND_ARG_INFO(0, type)
425 ZEND_END_ARG_INFO()
426 
427 #if defined(HAVE_GD_BMP)
428 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagebmp, 0, 0, 1)
429 	ZEND_ARG_INFO(0, im)
430 	ZEND_ARG_INFO(0, to)
431 	ZEND_ARG_INFO(0, compressed)
432 ZEND_END_ARG_INFO()
433 #endif
434 
435 ZEND_BEGIN_ARG_INFO(arginfo_imagedestroy, 0)
436 	ZEND_ARG_INFO(0, im)
437 ZEND_END_ARG_INFO()
438 
439 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorallocate, 0)
440 	ZEND_ARG_INFO(0, im)
441 	ZEND_ARG_INFO(0, red)
442 	ZEND_ARG_INFO(0, green)
443 	ZEND_ARG_INFO(0, blue)
444 ZEND_END_ARG_INFO()
445 
446 ZEND_BEGIN_ARG_INFO(arginfo_imagepalettecopy, 0)
447 	ZEND_ARG_INFO(0, dst)
448 	ZEND_ARG_INFO(0, src)
449 ZEND_END_ARG_INFO()
450 
451 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorat, 0)
452 	ZEND_ARG_INFO(0, im)
453 	ZEND_ARG_INFO(0, x)
454 	ZEND_ARG_INFO(0, y)
455 ZEND_END_ARG_INFO()
456 
457 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorclosest, 0)
458 	ZEND_ARG_INFO(0, im)
459 	ZEND_ARG_INFO(0, red)
460 	ZEND_ARG_INFO(0, green)
461 	ZEND_ARG_INFO(0, blue)
462 ZEND_END_ARG_INFO()
463 
464 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorclosesthwb, 0)
465 	ZEND_ARG_INFO(0, im)
466 	ZEND_ARG_INFO(0, red)
467 	ZEND_ARG_INFO(0, green)
468 	ZEND_ARG_INFO(0, blue)
469 ZEND_END_ARG_INFO()
470 
471 ZEND_BEGIN_ARG_INFO(arginfo_imagecolordeallocate, 0)
472 	ZEND_ARG_INFO(0, im)
473 	ZEND_ARG_INFO(0, index)
474 ZEND_END_ARG_INFO()
475 
476 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorresolve, 0)
477 	ZEND_ARG_INFO(0, im)
478 	ZEND_ARG_INFO(0, red)
479 	ZEND_ARG_INFO(0, green)
480 	ZEND_ARG_INFO(0, blue)
481 ZEND_END_ARG_INFO()
482 
483 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorexact, 0)
484 	ZEND_ARG_INFO(0, im)
485 	ZEND_ARG_INFO(0, red)
486 	ZEND_ARG_INFO(0, green)
487 	ZEND_ARG_INFO(0, blue)
488 ZEND_END_ARG_INFO()
489 
490 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagecolorset, 0, 0, 5)
491 	ZEND_ARG_INFO(0, im)
492 	ZEND_ARG_INFO(0, color)
493 	ZEND_ARG_INFO(0, red)
494 	ZEND_ARG_INFO(0, green)
495 	ZEND_ARG_INFO(0, blue)
496 	ZEND_ARG_INFO(0, alpha)
497 ZEND_END_ARG_INFO()
498 
499 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorsforindex, 0)
500 	ZEND_ARG_INFO(0, im)
501 	ZEND_ARG_INFO(0, index)
502 ZEND_END_ARG_INFO()
503 
504 ZEND_BEGIN_ARG_INFO(arginfo_imagegammacorrect, 0)
505 	ZEND_ARG_INFO(0, im)
506 	ZEND_ARG_INFO(0, inputgamma)
507 	ZEND_ARG_INFO(0, outputgamma)
508 ZEND_END_ARG_INFO()
509 
510 ZEND_BEGIN_ARG_INFO(arginfo_imagesetpixel, 0)
511 	ZEND_ARG_INFO(0, im)
512 	ZEND_ARG_INFO(0, x)
513 	ZEND_ARG_INFO(0, y)
514 	ZEND_ARG_INFO(0, col)
515 ZEND_END_ARG_INFO()
516 
517 ZEND_BEGIN_ARG_INFO(arginfo_imageline, 0)
518 	ZEND_ARG_INFO(0, im)
519 	ZEND_ARG_INFO(0, x1)
520 	ZEND_ARG_INFO(0, y1)
521 	ZEND_ARG_INFO(0, x2)
522 	ZEND_ARG_INFO(0, y2)
523 	ZEND_ARG_INFO(0, col)
524 ZEND_END_ARG_INFO()
525 
526 ZEND_BEGIN_ARG_INFO(arginfo_imagedashedline, 0)
527 	ZEND_ARG_INFO(0, im)
528 	ZEND_ARG_INFO(0, x1)
529 	ZEND_ARG_INFO(0, y1)
530 	ZEND_ARG_INFO(0, x2)
531 	ZEND_ARG_INFO(0, y2)
532 	ZEND_ARG_INFO(0, col)
533 ZEND_END_ARG_INFO()
534 
535 ZEND_BEGIN_ARG_INFO(arginfo_imagerectangle, 0)
536 	ZEND_ARG_INFO(0, im)
537 	ZEND_ARG_INFO(0, x1)
538 	ZEND_ARG_INFO(0, y1)
539 	ZEND_ARG_INFO(0, x2)
540 	ZEND_ARG_INFO(0, y2)
541 	ZEND_ARG_INFO(0, col)
542 ZEND_END_ARG_INFO()
543 
544 ZEND_BEGIN_ARG_INFO(arginfo_imagefilledrectangle, 0)
545 	ZEND_ARG_INFO(0, im)
546 	ZEND_ARG_INFO(0, x1)
547 	ZEND_ARG_INFO(0, y1)
548 	ZEND_ARG_INFO(0, x2)
549 	ZEND_ARG_INFO(0, y2)
550 	ZEND_ARG_INFO(0, col)
551 ZEND_END_ARG_INFO()
552 
553 ZEND_BEGIN_ARG_INFO(arginfo_imagearc, 0)
554 	ZEND_ARG_INFO(0, im)
555 	ZEND_ARG_INFO(0, cx)
556 	ZEND_ARG_INFO(0, cy)
557 	ZEND_ARG_INFO(0, w)
558 	ZEND_ARG_INFO(0, h)
559 	ZEND_ARG_INFO(0, s)
560 	ZEND_ARG_INFO(0, e)
561 	ZEND_ARG_INFO(0, col)
562 ZEND_END_ARG_INFO()
563 
564 ZEND_BEGIN_ARG_INFO(arginfo_imageellipse, 0)
565 	ZEND_ARG_INFO(0, im)
566 	ZEND_ARG_INFO(0, cx)
567 	ZEND_ARG_INFO(0, cy)
568 	ZEND_ARG_INFO(0, w)
569 	ZEND_ARG_INFO(0, h)
570 	ZEND_ARG_INFO(0, color)
571 ZEND_END_ARG_INFO()
572 
573 ZEND_BEGIN_ARG_INFO(arginfo_imagefilltoborder, 0)
574 	ZEND_ARG_INFO(0, im)
575 	ZEND_ARG_INFO(0, x)
576 	ZEND_ARG_INFO(0, y)
577 	ZEND_ARG_INFO(0, border)
578 	ZEND_ARG_INFO(0, col)
579 ZEND_END_ARG_INFO()
580 
581 ZEND_BEGIN_ARG_INFO(arginfo_imagefill, 0)
582 	ZEND_ARG_INFO(0, im)
583 	ZEND_ARG_INFO(0, x)
584 	ZEND_ARG_INFO(0, y)
585 	ZEND_ARG_INFO(0, col)
586 ZEND_END_ARG_INFO()
587 
588 ZEND_BEGIN_ARG_INFO(arginfo_imagecolorstotal, 0)
589 	ZEND_ARG_INFO(0, im)
590 ZEND_END_ARG_INFO()
591 
592 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagecolortransparent, 0, 0, 1)
593 	ZEND_ARG_INFO(0, im)
594 	ZEND_ARG_INFO(0, col)
595 ZEND_END_ARG_INFO()
596 
597 ZEND_BEGIN_ARG_INFO_EX(arginfo_imageinterlace, 0, 0, 1)
598 	ZEND_ARG_INFO(0, im)
599 	ZEND_ARG_INFO(0, interlace)
600 ZEND_END_ARG_INFO()
601 
602 ZEND_BEGIN_ARG_INFO(arginfo_imagepolygon, 0)
603 	ZEND_ARG_INFO(0, im)
604 	ZEND_ARG_INFO(0, points) /* ARRAY_INFO(0, points, 0) */
605 	ZEND_ARG_INFO(0, num_pos)
606 	ZEND_ARG_INFO(0, col)
607 ZEND_END_ARG_INFO()
608 
609 ZEND_BEGIN_ARG_INFO(arginfo_imageopenpolygon, 0)
610 	ZEND_ARG_INFO(0, im)
611 	ZEND_ARG_INFO(0, points) /* ARRAY_INFO(0, points, 0) */
612 	ZEND_ARG_INFO(0, num_pos)
613 	ZEND_ARG_INFO(0, col)
614 ZEND_END_ARG_INFO()
615 
616 ZEND_BEGIN_ARG_INFO(arginfo_imagefilledpolygon, 0)
617 	ZEND_ARG_INFO(0, im)
618 	ZEND_ARG_INFO(0, points) /* ARRAY_INFO(0, points, 0) */
619 	ZEND_ARG_INFO(0, num_pos)
620 	ZEND_ARG_INFO(0, col)
621 ZEND_END_ARG_INFO()
622 
623 ZEND_BEGIN_ARG_INFO(arginfo_imagefontwidth, 0)
624 	ZEND_ARG_INFO(0, font)
625 ZEND_END_ARG_INFO()
626 
627 ZEND_BEGIN_ARG_INFO(arginfo_imagefontheight, 0)
628 	ZEND_ARG_INFO(0, font)
629 ZEND_END_ARG_INFO()
630 
631 ZEND_BEGIN_ARG_INFO(arginfo_imagechar, 0)
632 	ZEND_ARG_INFO(0, im)
633 	ZEND_ARG_INFO(0, font)
634 	ZEND_ARG_INFO(0, x)
635 	ZEND_ARG_INFO(0, y)
636 	ZEND_ARG_INFO(0, c)
637 	ZEND_ARG_INFO(0, col)
638 ZEND_END_ARG_INFO()
639 
640 ZEND_BEGIN_ARG_INFO(arginfo_imagecharup, 0)
641 	ZEND_ARG_INFO(0, im)
642 	ZEND_ARG_INFO(0, font)
643 	ZEND_ARG_INFO(0, x)
644 	ZEND_ARG_INFO(0, y)
645 	ZEND_ARG_INFO(0, c)
646 	ZEND_ARG_INFO(0, col)
647 ZEND_END_ARG_INFO()
648 
649 ZEND_BEGIN_ARG_INFO(arginfo_imagestring, 0)
650 	ZEND_ARG_INFO(0, im)
651 	ZEND_ARG_INFO(0, font)
652 	ZEND_ARG_INFO(0, x)
653 	ZEND_ARG_INFO(0, y)
654 	ZEND_ARG_INFO(0, str)
655 	ZEND_ARG_INFO(0, col)
656 ZEND_END_ARG_INFO()
657 
658 ZEND_BEGIN_ARG_INFO(arginfo_imagestringup, 0)
659 	ZEND_ARG_INFO(0, im)
660 	ZEND_ARG_INFO(0, font)
661 	ZEND_ARG_INFO(0, x)
662 	ZEND_ARG_INFO(0, y)
663 	ZEND_ARG_INFO(0, str)
664 	ZEND_ARG_INFO(0, col)
665 ZEND_END_ARG_INFO()
666 
667 ZEND_BEGIN_ARG_INFO(arginfo_imagecopy, 0)
668 	ZEND_ARG_INFO(0, dst_im)
669 	ZEND_ARG_INFO(0, src_im)
670 	ZEND_ARG_INFO(0, dst_x)
671 	ZEND_ARG_INFO(0, dst_y)
672 	ZEND_ARG_INFO(0, src_x)
673 	ZEND_ARG_INFO(0, src_y)
674 	ZEND_ARG_INFO(0, src_w)
675 	ZEND_ARG_INFO(0, src_h)
676 ZEND_END_ARG_INFO()
677 
678 ZEND_BEGIN_ARG_INFO(arginfo_imagecopymerge, 0)
679 	ZEND_ARG_INFO(0, dst_im)
680 	ZEND_ARG_INFO(0, src_im)
681 	ZEND_ARG_INFO(0, dst_x)
682 	ZEND_ARG_INFO(0, dst_y)
683 	ZEND_ARG_INFO(0, src_x)
684 	ZEND_ARG_INFO(0, src_y)
685 	ZEND_ARG_INFO(0, src_w)
686 	ZEND_ARG_INFO(0, src_h)
687 	ZEND_ARG_INFO(0, pct)
688 ZEND_END_ARG_INFO()
689 
690 ZEND_BEGIN_ARG_INFO(arginfo_imagecopymergegray, 0)
691 	ZEND_ARG_INFO(0, dst_im)
692 	ZEND_ARG_INFO(0, src_im)
693 	ZEND_ARG_INFO(0, dst_x)
694 	ZEND_ARG_INFO(0, dst_y)
695 	ZEND_ARG_INFO(0, src_x)
696 	ZEND_ARG_INFO(0, src_y)
697 	ZEND_ARG_INFO(0, src_w)
698 	ZEND_ARG_INFO(0, src_h)
699 	ZEND_ARG_INFO(0, pct)
700 ZEND_END_ARG_INFO()
701 
702 ZEND_BEGIN_ARG_INFO(arginfo_imagecopyresized, 0)
703 	ZEND_ARG_INFO(0, dst_im)
704 	ZEND_ARG_INFO(0, src_im)
705 	ZEND_ARG_INFO(0, dst_x)
706 	ZEND_ARG_INFO(0, dst_y)
707 	ZEND_ARG_INFO(0, src_x)
708 	ZEND_ARG_INFO(0, src_y)
709 	ZEND_ARG_INFO(0, dst_w)
710 	ZEND_ARG_INFO(0, dst_h)
711 	ZEND_ARG_INFO(0, src_w)
712 	ZEND_ARG_INFO(0, src_h)
713 ZEND_END_ARG_INFO()
714 
715 ZEND_BEGIN_ARG_INFO(arginfo_imagesx, 0)
716 	ZEND_ARG_INFO(0, im)
717 ZEND_END_ARG_INFO()
718 
719 ZEND_BEGIN_ARG_INFO(arginfo_imagesy, 0)
720 	ZEND_ARG_INFO(0, im)
721 ZEND_END_ARG_INFO()
722 
723 ZEND_BEGIN_ARG_INFO(arginfo_imagesetclip, 0)
724 	ZEND_ARG_INFO(0, im)
725 	ZEND_ARG_INFO(0, x1)
726 	ZEND_ARG_INFO(0, y1)
727 	ZEND_ARG_INFO(0, x2)
728 	ZEND_ARG_INFO(0, y2)
729 ZEND_END_ARG_INFO()
730 
731 ZEND_BEGIN_ARG_INFO(arginfo_imagegetclip, 0)
732 	ZEND_ARG_INFO(0, im)
733 ZEND_END_ARG_INFO()
734 
735 #ifdef HAVE_GD_FREETYPE
736 ZEND_BEGIN_ARG_INFO_EX(arginfo_imageftbbox, 0, 0, 4)
737 	ZEND_ARG_INFO(0, size)
738 	ZEND_ARG_INFO(0, angle)
739 	ZEND_ARG_INFO(0, font_file)
740 	ZEND_ARG_INFO(0, text)
741 	ZEND_ARG_INFO(0, extrainfo) /* ARRAY_INFO(0, extrainfo, 0) */
742 ZEND_END_ARG_INFO()
743 
744 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagefttext, 0, 0, 8)
745 	ZEND_ARG_INFO(0, im)
746 	ZEND_ARG_INFO(0, size)
747 	ZEND_ARG_INFO(0, angle)
748 	ZEND_ARG_INFO(0, x)
749 	ZEND_ARG_INFO(0, y)
750 	ZEND_ARG_INFO(0, col)
751 	ZEND_ARG_INFO(0, font_file)
752 	ZEND_ARG_INFO(0, text)
753 	ZEND_ARG_INFO(0, extrainfo) /* ARRAY_INFO(0, extrainfo, 0) */
754 ZEND_END_ARG_INFO()
755 
756 ZEND_BEGIN_ARG_INFO(arginfo_imagettfbbox, 0)
757 	ZEND_ARG_INFO(0, size)
758 	ZEND_ARG_INFO(0, angle)
759 	ZEND_ARG_INFO(0, font_file)
760 	ZEND_ARG_INFO(0, text)
761 ZEND_END_ARG_INFO()
762 
763 ZEND_BEGIN_ARG_INFO(arginfo_imagettftext, 0)
764 	ZEND_ARG_INFO(0, im)
765 	ZEND_ARG_INFO(0, size)
766 	ZEND_ARG_INFO(0, angle)
767 	ZEND_ARG_INFO(0, x)
768 	ZEND_ARG_INFO(0, y)
769 	ZEND_ARG_INFO(0, col)
770 	ZEND_ARG_INFO(0, font_file)
771 	ZEND_ARG_INFO(0, text)
772 ZEND_END_ARG_INFO()
773 #endif
774 
775 ZEND_BEGIN_ARG_INFO_EX(arginfo_image2wbmp, 0, 0, 1)
776 	ZEND_ARG_INFO(0, im)
777 	ZEND_ARG_INFO(0, filename)
778 	ZEND_ARG_INFO(0, foreground)
779 ZEND_END_ARG_INFO()
780 
781 #if defined(HAVE_GD_JPG)
782 ZEND_BEGIN_ARG_INFO(arginfo_jpeg2wbmp, 0)
783 	ZEND_ARG_INFO(0, f_org)
784 	ZEND_ARG_INFO(0, f_dest)
785 	ZEND_ARG_INFO(0, d_height)
786 	ZEND_ARG_INFO(0, d_width)
787 	ZEND_ARG_INFO(0, d_threshold)
788 ZEND_END_ARG_INFO()
789 #endif
790 
791 #if defined(HAVE_GD_PNG)
792 ZEND_BEGIN_ARG_INFO(arginfo_png2wbmp, 0)
793 	ZEND_ARG_INFO(0, f_org)
794 	ZEND_ARG_INFO(0, f_dest)
795 	ZEND_ARG_INFO(0, d_height)
796 	ZEND_ARG_INFO(0, d_width)
797 	ZEND_ARG_INFO(0, d_threshold)
798 ZEND_END_ARG_INFO()
799 #endif
800 
801 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagefilter, 0, 0, 2)
802 	ZEND_ARG_INFO(0, im)
803 	ZEND_ARG_INFO(0, filtertype)
804 	ZEND_ARG_INFO(0, arg1)
805 	ZEND_ARG_INFO(0, arg2)
806 	ZEND_ARG_INFO(0, arg3)
807 	ZEND_ARG_INFO(0, arg4)
808 ZEND_END_ARG_INFO()
809 
810 ZEND_BEGIN_ARG_INFO(arginfo_imageconvolution, 0)
811 	ZEND_ARG_INFO(0, im)
812 	ZEND_ARG_INFO(0, matrix3x3) /* ARRAY_INFO(0, matrix3x3, 0) */
813 	ZEND_ARG_INFO(0, div)
814 	ZEND_ARG_INFO(0, offset)
815 ZEND_END_ARG_INFO()
816 
817 ZEND_BEGIN_ARG_INFO(arginfo_imageflip, 0)
818 	ZEND_ARG_INFO(0, im)
819 	ZEND_ARG_INFO(0, mode)
820 ZEND_END_ARG_INFO()
821 
822 ZEND_BEGIN_ARG_INFO(arginfo_imageantialias, 0)
823 	ZEND_ARG_INFO(0, im)
824 	ZEND_ARG_INFO(0, on)
825 ZEND_END_ARG_INFO()
826 
827 ZEND_BEGIN_ARG_INFO(arginfo_imagecrop, 0)
828 	ZEND_ARG_INFO(0, im)
829 	ZEND_ARG_INFO(0, rect)
830 ZEND_END_ARG_INFO()
831 
832 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagecropauto, 0, 0, 1)
833 	ZEND_ARG_INFO(0, im)
834 	ZEND_ARG_INFO(0, mode)
835 	ZEND_ARG_INFO(0, threshold)
836 	ZEND_ARG_INFO(0, color)
837 ZEND_END_ARG_INFO()
838 
839 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagescale, 0, 0, 2)
840 	ZEND_ARG_INFO(0, im)
841 	ZEND_ARG_INFO(0, new_width)
842 	ZEND_ARG_INFO(0, new_height)
843 	ZEND_ARG_INFO(0, mode)
844 ZEND_END_ARG_INFO()
845 
846 ZEND_BEGIN_ARG_INFO_EX(arginfo_imageaffine, 0, 0, 2)
847 	ZEND_ARG_INFO(0, im)
848 	ZEND_ARG_INFO(0, affine)
849 	ZEND_ARG_INFO(0, clip)
850 ZEND_END_ARG_INFO()
851 
852 ZEND_BEGIN_ARG_INFO_EX(arginfo_imageaffinematrixget, 0, 0, 1)
853 	ZEND_ARG_INFO(0, type)
854 	ZEND_ARG_INFO(0, options)
855 ZEND_END_ARG_INFO()
856 
857 ZEND_BEGIN_ARG_INFO(arginfo_imageaffinematrixconcat, 0)
858 	ZEND_ARG_INFO(0, m1)
859 	ZEND_ARG_INFO(0, m2)
860 ZEND_END_ARG_INFO()
861 
862 ZEND_BEGIN_ARG_INFO_EX(arginfo_imagesetinterpolation, 0, 0, 1)
863 	ZEND_ARG_INFO(0, im)
864 	ZEND_ARG_INFO(0, method)
865 ZEND_END_ARG_INFO()
866 
867 ZEND_BEGIN_ARG_INFO_EX(arginfo_imageresolution, 0, 0, 1)
868 	ZEND_ARG_INFO(0, im)
869 	ZEND_ARG_INFO(0, res_x)
870 	ZEND_ARG_INFO(0, res_y)
871 ZEND_END_ARG_INFO()
872 
873 /* }}} */
874 
875 /* {{{ gd_functions[]
876  */
877 static const zend_function_entry gd_functions[] = {
878 	PHP_FE(gd_info,                                 arginfo_gd_info)
879 	PHP_FE(imagearc,								arginfo_imagearc)
880 	PHP_FE(imageellipse,							arginfo_imageellipse)
881 	PHP_FE(imagechar,								arginfo_imagechar)
882 	PHP_FE(imagecharup,								arginfo_imagecharup)
883 	PHP_FE(imagecolorat,							arginfo_imagecolorat)
884 	PHP_FE(imagecolorallocate,						arginfo_imagecolorallocate)
885 	PHP_FE(imagepalettecopy,						arginfo_imagepalettecopy)
886 	PHP_FE(imagecreatefromstring,					arginfo_imagecreatefromstring)
887 	PHP_FE(imagecolorclosest,						arginfo_imagecolorclosest)
888 	PHP_FE(imagecolorclosesthwb,					arginfo_imagecolorclosesthwb)
889 	PHP_FE(imagecolordeallocate,					arginfo_imagecolordeallocate)
890 	PHP_FE(imagecolorresolve,						arginfo_imagecolorresolve)
891 	PHP_FE(imagecolorexact,							arginfo_imagecolorexact)
892 	PHP_FE(imagecolorset,							arginfo_imagecolorset)
893 	PHP_FE(imagecolortransparent,					arginfo_imagecolortransparent)
894 	PHP_FE(imagecolorstotal,						arginfo_imagecolorstotal)
895 	PHP_FE(imagecolorsforindex,						arginfo_imagecolorsforindex)
896 	PHP_FE(imagecopy,								arginfo_imagecopy)
897 	PHP_FE(imagecopymerge,							arginfo_imagecopymerge)
898 	PHP_FE(imagecopymergegray,						arginfo_imagecopymergegray)
899 	PHP_FE(imagecopyresized,						arginfo_imagecopyresized)
900 	PHP_FE(imagecreate,								arginfo_imagecreate)
901 	PHP_FE(imagecreatetruecolor,					arginfo_imagecreatetruecolor)
902 	PHP_FE(imageistruecolor,						arginfo_imageistruecolor)
903 	PHP_FE(imagetruecolortopalette,					arginfo_imagetruecolortopalette)
904 	PHP_FE(imagepalettetotruecolor,					arginfo_imagepalettetotruecolor)
905 	PHP_FE(imagesetthickness,						arginfo_imagesetthickness)
906 	PHP_FE(imagefilledarc,							arginfo_imagefilledarc)
907 	PHP_FE(imagefilledellipse,						arginfo_imagefilledellipse)
908 	PHP_FE(imagealphablending,						arginfo_imagealphablending)
909 	PHP_FE(imagesavealpha,							arginfo_imagesavealpha)
910 	PHP_FE(imagecolorallocatealpha,					arginfo_imagecolorallocatealpha)
911 	PHP_FE(imagecolorresolvealpha, 					arginfo_imagecolorresolvealpha)
912 	PHP_FE(imagecolorclosestalpha,					arginfo_imagecolorclosestalpha)
913 	PHP_FE(imagecolorexactalpha,					arginfo_imagecolorexactalpha)
914 	PHP_FE(imagecopyresampled,						arginfo_imagecopyresampled)
915 
916 #ifdef PHP_WIN32
917 	PHP_FE(imagegrabwindow,							arginfo_imagegrabwindow)
918 	PHP_FE(imagegrabscreen,							arginfo_imagegrabscreen)
919 #endif
920 
921 	PHP_FE(imagerotate,     						arginfo_imagerotate)
922 	PHP_FE(imageflip,								arginfo_imageflip)
923 
924 	PHP_FE(imageantialias,							arginfo_imageantialias)
925 	PHP_FE(imagecrop,								arginfo_imagecrop)
926 	PHP_FE(imagecropauto,							arginfo_imagecropauto)
927 	PHP_FE(imagescale,								arginfo_imagescale)
928 	PHP_FE(imageaffine,								arginfo_imageaffine)
929 	PHP_FE(imageaffinematrixconcat,					arginfo_imageaffinematrixconcat)
930 	PHP_FE(imageaffinematrixget,					arginfo_imageaffinematrixget)
931 	PHP_FE(imagesetinterpolation,                   arginfo_imagesetinterpolation)
932 	PHP_FE(imagesettile,							arginfo_imagesettile)
933 	PHP_FE(imagesetbrush,							arginfo_imagesetbrush)
934 	PHP_FE(imagesetstyle,							arginfo_imagesetstyle)
935 
936 #ifdef HAVE_GD_PNG
937 	PHP_FE(imagecreatefrompng,						arginfo_imagecreatefrompng)
938 #endif
939 #ifdef HAVE_GD_WEBP
940 	PHP_FE(imagecreatefromwebp,						arginfo_imagecreatefromwebp)
941 #endif
942 	PHP_FE(imagecreatefromgif,						arginfo_imagecreatefromgif)
943 #ifdef HAVE_GD_JPG
944 	PHP_FE(imagecreatefromjpeg,						arginfo_imagecreatefromjpeg)
945 #endif
946 	PHP_FE(imagecreatefromwbmp,						arginfo_imagecreatefromwbmp)
947 	PHP_FE(imagecreatefromxbm,						arginfo_imagecreatefromxbm)
948 #if defined(HAVE_GD_XPM)
949 	PHP_FE(imagecreatefromxpm,						arginfo_imagecreatefromxpm)
950 #endif
951 	PHP_FE(imagecreatefromgd,						arginfo_imagecreatefromgd)
952 	PHP_FE(imagecreatefromgd2,						arginfo_imagecreatefromgd2)
953 	PHP_FE(imagecreatefromgd2part,					arginfo_imagecreatefromgd2part)
954 #ifdef HAVE_GD_BMP
955 	PHP_FE(imagecreatefrombmp,						arginfo_imagecreatefrombmp)
956 #endif
957 #ifdef HAVE_GD_TGA
958 	PHP_FE(imagecreatefromtga,						arginfo_imagecreatefromtga)
959 #endif
960 #ifdef HAVE_GD_PNG
961 	PHP_FE(imagepng,								arginfo_imagepng)
962 #endif
963 #ifdef HAVE_GD_WEBP
964 	PHP_FE(imagewebp,								arginfo_imagewebp)
965 #endif
966 	PHP_FE(imagegif,								arginfo_imagegif)
967 #ifdef HAVE_GD_JPG
968 	PHP_FE(imagejpeg,								arginfo_imagejpeg)
969 #endif
970 	PHP_FE(imagewbmp,                               arginfo_imagewbmp)
971 	PHP_FE(imagegd,									arginfo_imagegd)
972 	PHP_FE(imagegd2,								arginfo_imagegd2)
973 #ifdef HAVE_GD_BMP
974 	PHP_FE(imagebmp,								arginfo_imagebmp)
975 #endif
976 
977 	PHP_FE(imagedestroy,							arginfo_imagedestroy)
978 	PHP_FE(imagegammacorrect,						arginfo_imagegammacorrect)
979 	PHP_FE(imagefill,								arginfo_imagefill)
980 	PHP_FE(imagefilledpolygon,						arginfo_imagefilledpolygon)
981 	PHP_FE(imagefilledrectangle,					arginfo_imagefilledrectangle)
982 	PHP_FE(imagefilltoborder,						arginfo_imagefilltoborder)
983 	PHP_FE(imagefontwidth,							arginfo_imagefontwidth)
984 	PHP_FE(imagefontheight,							arginfo_imagefontheight)
985 	PHP_FE(imageinterlace,							arginfo_imageinterlace)
986 	PHP_FE(imageline,								arginfo_imageline)
987 	PHP_FE(imageloadfont,							arginfo_imageloadfont)
988 	PHP_FE(imagepolygon,							arginfo_imagepolygon)
989 	PHP_FE(imageopenpolygon,						arginfo_imageopenpolygon)
990 	PHP_FE(imagerectangle,							arginfo_imagerectangle)
991 	PHP_FE(imagesetpixel,							arginfo_imagesetpixel)
992 	PHP_FE(imagestring,								arginfo_imagestring)
993 	PHP_FE(imagestringup,							arginfo_imagestringup)
994 	PHP_FE(imagesx,									arginfo_imagesx)
995 	PHP_FE(imagesy,									arginfo_imagesy)
996 	PHP_FE(imagesetclip,							arginfo_imagesetclip)
997 	PHP_FE(imagegetclip,							arginfo_imagegetclip)
998 	PHP_FE(imagedashedline,							arginfo_imagedashedline)
999 
1000 #ifdef HAVE_GD_FREETYPE
1001 	PHP_FE(imagettfbbox,							arginfo_imagettfbbox)
1002 	PHP_FE(imagettftext,							arginfo_imagettftext)
1003 	PHP_FE(imageftbbox,								arginfo_imageftbbox)
1004 	PHP_FE(imagefttext,								arginfo_imagefttext)
1005 #endif
1006 
1007 	PHP_FE(imagetypes,								arginfo_imagetypes)
1008 
1009 #if defined(HAVE_GD_JPG)
1010 	PHP_DEP_FE(jpeg2wbmp,							arginfo_jpeg2wbmp)
1011 #endif
1012 #if defined(HAVE_GD_PNG)
1013 	PHP_DEP_FE(png2wbmp,							arginfo_png2wbmp)
1014 #endif
1015 	PHP_DEP_FE(image2wbmp,							arginfo_image2wbmp)
1016 	PHP_FE(imagelayereffect,						arginfo_imagelayereffect)
1017 	PHP_FE(imagexbm,                                arginfo_imagexbm)
1018 
1019 	PHP_FE(imagecolormatch,							arginfo_imagecolormatch)
1020 
1021 /* gd filters */
1022 	PHP_FE(imagefilter,     						arginfo_imagefilter)
1023 	PHP_FE(imageconvolution,						arginfo_imageconvolution)
1024 
1025 	PHP_FE(imageresolution,							arginfo_imageresolution)
1026 
1027 	PHP_FE_END
1028 };
1029 /* }}} */
1030 
1031 zend_module_entry gd_module_entry = {
1032 	STANDARD_MODULE_HEADER,
1033 	"gd",
1034 	gd_functions,
1035 	PHP_MINIT(gd),
1036 	PHP_MSHUTDOWN(gd),
1037 	NULL,
1038 	PHP_RSHUTDOWN(gd),
1039 	PHP_MINFO(gd),
1040 	PHP_GD_VERSION,
1041 	STANDARD_MODULE_PROPERTIES
1042 };
1043 
1044 #ifdef COMPILE_DL_GD
1045 ZEND_GET_MODULE(gd)
1046 #endif
1047 
1048 /* {{{ PHP_INI_BEGIN */
PHP_INI_BEGIN()1049 PHP_INI_BEGIN()
1050 	PHP_INI_ENTRY("gd.jpeg_ignore_warning", "1", PHP_INI_ALL, NULL)
1051 PHP_INI_END()
1052 /* }}} */
1053 
1054 /* {{{ php_free_gd_image
1055  */
1056 static void php_free_gd_image(zend_resource *rsrc)
1057 {
1058 	gdImageDestroy((gdImagePtr) rsrc->ptr);
1059 }
1060 /* }}} */
1061 
1062 /* {{{ php_free_gd_font
1063  */
php_free_gd_font(zend_resource * rsrc)1064 static void php_free_gd_font(zend_resource *rsrc)
1065 {
1066 	gdFontPtr fp = (gdFontPtr) rsrc->ptr;
1067 
1068 	if (fp->data) {
1069 		efree(fp->data);
1070 	}
1071 
1072 	efree(fp);
1073 }
1074 /* }}} */
1075 
1076 /* {{{ php_gd_error_method
1077  */
php_gd_error_method(int type,const char * format,va_list args)1078 void php_gd_error_method(int type, const char *format, va_list args)
1079 {
1080 
1081 	switch (type) {
1082 #ifndef PHP_WIN32
1083 		case GD_DEBUG:
1084 		case GD_INFO:
1085 #endif
1086 		case GD_NOTICE:
1087 			type = E_NOTICE;
1088 			break;
1089 		case GD_WARNING:
1090 			type = E_WARNING;
1091 			break;
1092 		default:
1093 			type = E_ERROR;
1094 	}
1095 	php_verror(NULL, "", type, format, args);
1096 }
1097 /* }}} */
1098 
1099 /* {{{ PHP_MINIT_FUNCTION
1100  */
PHP_MINIT_FUNCTION(gd)1101 PHP_MINIT_FUNCTION(gd)
1102 {
1103 	le_gd = zend_register_list_destructors_ex(php_free_gd_image, NULL, "gd", module_number);
1104 	le_gd_font = zend_register_list_destructors_ex(php_free_gd_font, NULL, "gd font", module_number);
1105 
1106 #if defined(HAVE_GD_FREETYPE) && defined(HAVE_GD_BUNDLED)
1107 	gdFontCacheMutexSetup();
1108 #endif
1109 	gdSetErrorMethod(php_gd_error_method);
1110 
1111 	REGISTER_INI_ENTRIES();
1112 
1113 	REGISTER_LONG_CONSTANT("IMG_GIF", PHP_IMG_GIF, CONST_CS | CONST_PERSISTENT);
1114 	REGISTER_LONG_CONSTANT("IMG_JPG", PHP_IMG_JPG, CONST_CS | CONST_PERSISTENT);
1115 	REGISTER_LONG_CONSTANT("IMG_JPEG", PHP_IMG_JPEG, CONST_CS | CONST_PERSISTENT);
1116 	REGISTER_LONG_CONSTANT("IMG_PNG", PHP_IMG_PNG, CONST_CS | CONST_PERSISTENT);
1117 	REGISTER_LONG_CONSTANT("IMG_WBMP", PHP_IMG_WBMP, CONST_CS | CONST_PERSISTENT);
1118 	REGISTER_LONG_CONSTANT("IMG_XPM", PHP_IMG_XPM, CONST_CS | CONST_PERSISTENT);
1119 	REGISTER_LONG_CONSTANT("IMG_WEBP", PHP_IMG_WEBP, CONST_CS | CONST_PERSISTENT);
1120 	REGISTER_LONG_CONSTANT("IMG_BMP", PHP_IMG_BMP, CONST_CS | CONST_PERSISTENT);
1121 	REGISTER_LONG_CONSTANT("IMG_TGA", PHP_IMG_TGA, CONST_CS | CONST_PERSISTENT);
1122 
1123 	/* special colours for gd */
1124 	REGISTER_LONG_CONSTANT("IMG_COLOR_TILED", gdTiled, CONST_CS | CONST_PERSISTENT);
1125 	REGISTER_LONG_CONSTANT("IMG_COLOR_STYLED", gdStyled, CONST_CS | CONST_PERSISTENT);
1126 	REGISTER_LONG_CONSTANT("IMG_COLOR_BRUSHED", gdBrushed, CONST_CS | CONST_PERSISTENT);
1127 	REGISTER_LONG_CONSTANT("IMG_COLOR_STYLEDBRUSHED", gdStyledBrushed, CONST_CS | CONST_PERSISTENT);
1128 	REGISTER_LONG_CONSTANT("IMG_COLOR_TRANSPARENT", gdTransparent, CONST_CS | CONST_PERSISTENT);
1129 
1130 	/* for imagefilledarc */
1131 	REGISTER_LONG_CONSTANT("IMG_ARC_ROUNDED", gdArc, CONST_CS | CONST_PERSISTENT);
1132 	REGISTER_LONG_CONSTANT("IMG_ARC_PIE", gdPie, CONST_CS | CONST_PERSISTENT);
1133 	REGISTER_LONG_CONSTANT("IMG_ARC_CHORD", gdChord, CONST_CS | CONST_PERSISTENT);
1134 	REGISTER_LONG_CONSTANT("IMG_ARC_NOFILL", gdNoFill, CONST_CS | CONST_PERSISTENT);
1135 	REGISTER_LONG_CONSTANT("IMG_ARC_EDGED", gdEdged, CONST_CS | CONST_PERSISTENT);
1136 
1137     /* GD2 image format types */
1138 	REGISTER_LONG_CONSTANT("IMG_GD2_RAW", GD2_FMT_RAW, CONST_CS | CONST_PERSISTENT);
1139 	REGISTER_LONG_CONSTANT("IMG_GD2_COMPRESSED", GD2_FMT_COMPRESSED, CONST_CS | CONST_PERSISTENT);
1140 	REGISTER_LONG_CONSTANT("IMG_FLIP_HORIZONTAL", GD_FLIP_HORINZONTAL, CONST_CS | CONST_PERSISTENT);
1141 	REGISTER_LONG_CONSTANT("IMG_FLIP_VERTICAL", GD_FLIP_VERTICAL, CONST_CS | CONST_PERSISTENT);
1142 	REGISTER_LONG_CONSTANT("IMG_FLIP_BOTH", GD_FLIP_BOTH, CONST_CS | CONST_PERSISTENT);
1143 	REGISTER_LONG_CONSTANT("IMG_EFFECT_REPLACE", gdEffectReplace, CONST_CS | CONST_PERSISTENT);
1144 	REGISTER_LONG_CONSTANT("IMG_EFFECT_ALPHABLEND", gdEffectAlphaBlend, CONST_CS | CONST_PERSISTENT);
1145 	REGISTER_LONG_CONSTANT("IMG_EFFECT_NORMAL", gdEffectNormal, CONST_CS | CONST_PERSISTENT);
1146 	REGISTER_LONG_CONSTANT("IMG_EFFECT_OVERLAY", gdEffectOverlay, CONST_CS | CONST_PERSISTENT);
1147 #ifdef gdEffectMultiply
1148 	REGISTER_LONG_CONSTANT("IMG_EFFECT_MULTIPLY", gdEffectMultiply, CONST_CS | CONST_PERSISTENT);
1149 #endif
1150 
1151 	REGISTER_LONG_CONSTANT("IMG_CROP_DEFAULT", GD_CROP_DEFAULT, CONST_CS | CONST_PERSISTENT);
1152 	REGISTER_LONG_CONSTANT("IMG_CROP_TRANSPARENT", GD_CROP_TRANSPARENT, CONST_CS | CONST_PERSISTENT);
1153 	REGISTER_LONG_CONSTANT("IMG_CROP_BLACK", GD_CROP_BLACK, CONST_CS | CONST_PERSISTENT);
1154 	REGISTER_LONG_CONSTANT("IMG_CROP_WHITE", GD_CROP_WHITE, CONST_CS | CONST_PERSISTENT);
1155 	REGISTER_LONG_CONSTANT("IMG_CROP_SIDES", GD_CROP_SIDES, CONST_CS | CONST_PERSISTENT);
1156 	REGISTER_LONG_CONSTANT("IMG_CROP_THRESHOLD", GD_CROP_THRESHOLD, CONST_CS | CONST_PERSISTENT);
1157 
1158 
1159 	REGISTER_LONG_CONSTANT("IMG_BELL", GD_BELL, CONST_CS | CONST_PERSISTENT);
1160 	REGISTER_LONG_CONSTANT("IMG_BESSEL", GD_BESSEL, CONST_CS | CONST_PERSISTENT);
1161 	REGISTER_LONG_CONSTANT("IMG_BILINEAR_FIXED", GD_BILINEAR_FIXED, CONST_CS | CONST_PERSISTENT);
1162 	REGISTER_LONG_CONSTANT("IMG_BICUBIC", GD_BICUBIC, CONST_CS | CONST_PERSISTENT);
1163 	REGISTER_LONG_CONSTANT("IMG_BICUBIC_FIXED", GD_BICUBIC_FIXED, CONST_CS | CONST_PERSISTENT);
1164 	REGISTER_LONG_CONSTANT("IMG_BLACKMAN", GD_BLACKMAN, CONST_CS | CONST_PERSISTENT);
1165 	REGISTER_LONG_CONSTANT("IMG_BOX", GD_BOX, CONST_CS | CONST_PERSISTENT);
1166 	REGISTER_LONG_CONSTANT("IMG_BSPLINE", GD_BSPLINE, CONST_CS | CONST_PERSISTENT);
1167 	REGISTER_LONG_CONSTANT("IMG_CATMULLROM", GD_CATMULLROM, CONST_CS | CONST_PERSISTENT);
1168 	REGISTER_LONG_CONSTANT("IMG_GAUSSIAN", GD_GAUSSIAN, CONST_CS | CONST_PERSISTENT);
1169 	REGISTER_LONG_CONSTANT("IMG_GENERALIZED_CUBIC", GD_GENERALIZED_CUBIC, CONST_CS | CONST_PERSISTENT);
1170 	REGISTER_LONG_CONSTANT("IMG_HERMITE", GD_HERMITE, CONST_CS | CONST_PERSISTENT);
1171 	REGISTER_LONG_CONSTANT("IMG_HAMMING", GD_HAMMING, CONST_CS | CONST_PERSISTENT);
1172 	REGISTER_LONG_CONSTANT("IMG_HANNING", GD_HANNING, CONST_CS | CONST_PERSISTENT);
1173 	REGISTER_LONG_CONSTANT("IMG_MITCHELL", GD_MITCHELL, CONST_CS | CONST_PERSISTENT);
1174 	REGISTER_LONG_CONSTANT("IMG_POWER", GD_POWER, CONST_CS | CONST_PERSISTENT);
1175 	REGISTER_LONG_CONSTANT("IMG_QUADRATIC", GD_QUADRATIC, CONST_CS | CONST_PERSISTENT);
1176 	REGISTER_LONG_CONSTANT("IMG_SINC", GD_SINC, CONST_CS | CONST_PERSISTENT);
1177 	REGISTER_LONG_CONSTANT("IMG_NEAREST_NEIGHBOUR", GD_NEAREST_NEIGHBOUR, CONST_CS | CONST_PERSISTENT);
1178 	REGISTER_LONG_CONSTANT("IMG_WEIGHTED4", GD_WEIGHTED4, CONST_CS | CONST_PERSISTENT);
1179 	REGISTER_LONG_CONSTANT("IMG_TRIANGLE", GD_TRIANGLE, CONST_CS | CONST_PERSISTENT);
1180 
1181 	REGISTER_LONG_CONSTANT("IMG_AFFINE_TRANSLATE", GD_AFFINE_TRANSLATE, CONST_CS | CONST_PERSISTENT);
1182 	REGISTER_LONG_CONSTANT("IMG_AFFINE_SCALE", GD_AFFINE_SCALE, CONST_CS | CONST_PERSISTENT);
1183 	REGISTER_LONG_CONSTANT("IMG_AFFINE_ROTATE", GD_AFFINE_ROTATE, CONST_CS | CONST_PERSISTENT);
1184 	REGISTER_LONG_CONSTANT("IMG_AFFINE_SHEAR_HORIZONTAL", GD_AFFINE_SHEAR_HORIZONTAL, CONST_CS | CONST_PERSISTENT);
1185 	REGISTER_LONG_CONSTANT("IMG_AFFINE_SHEAR_VERTICAL", GD_AFFINE_SHEAR_VERTICAL, CONST_CS | CONST_PERSISTENT);
1186 
1187 #if defined(HAVE_GD_BUNDLED)
1188 	REGISTER_LONG_CONSTANT("GD_BUNDLED", 1, CONST_CS | CONST_PERSISTENT);
1189 #else
1190 	REGISTER_LONG_CONSTANT("GD_BUNDLED", 0, CONST_CS | CONST_PERSISTENT);
1191 #endif
1192 
1193 	/* Section Filters */
1194 	REGISTER_LONG_CONSTANT("IMG_FILTER_NEGATE", IMAGE_FILTER_NEGATE, CONST_CS | CONST_PERSISTENT);
1195 	REGISTER_LONG_CONSTANT("IMG_FILTER_GRAYSCALE", IMAGE_FILTER_GRAYSCALE, CONST_CS | CONST_PERSISTENT);
1196 	REGISTER_LONG_CONSTANT("IMG_FILTER_BRIGHTNESS", IMAGE_FILTER_BRIGHTNESS, CONST_CS | CONST_PERSISTENT);
1197 	REGISTER_LONG_CONSTANT("IMG_FILTER_CONTRAST", IMAGE_FILTER_CONTRAST, CONST_CS | CONST_PERSISTENT);
1198 	REGISTER_LONG_CONSTANT("IMG_FILTER_COLORIZE", IMAGE_FILTER_COLORIZE, CONST_CS | CONST_PERSISTENT);
1199 	REGISTER_LONG_CONSTANT("IMG_FILTER_EDGEDETECT", IMAGE_FILTER_EDGEDETECT, CONST_CS | CONST_PERSISTENT);
1200 	REGISTER_LONG_CONSTANT("IMG_FILTER_GAUSSIAN_BLUR", IMAGE_FILTER_GAUSSIAN_BLUR, CONST_CS | CONST_PERSISTENT);
1201 	REGISTER_LONG_CONSTANT("IMG_FILTER_SELECTIVE_BLUR", IMAGE_FILTER_SELECTIVE_BLUR, CONST_CS | CONST_PERSISTENT);
1202 	REGISTER_LONG_CONSTANT("IMG_FILTER_EMBOSS", IMAGE_FILTER_EMBOSS, CONST_CS | CONST_PERSISTENT);
1203 	REGISTER_LONG_CONSTANT("IMG_FILTER_MEAN_REMOVAL", IMAGE_FILTER_MEAN_REMOVAL, CONST_CS | CONST_PERSISTENT);
1204 	REGISTER_LONG_CONSTANT("IMG_FILTER_SMOOTH", IMAGE_FILTER_SMOOTH, CONST_CS | CONST_PERSISTENT);
1205 	REGISTER_LONG_CONSTANT("IMG_FILTER_PIXELATE", IMAGE_FILTER_PIXELATE, CONST_CS | CONST_PERSISTENT);
1206 	REGISTER_LONG_CONSTANT("IMG_FILTER_SCATTER", IMAGE_FILTER_SCATTER, CONST_CS | CONST_PERSISTENT);
1207 	/* End Section Filters */
1208 
1209 #ifdef GD_VERSION_STRING
1210 	REGISTER_STRING_CONSTANT("GD_VERSION", GD_VERSION_STRING, CONST_CS | CONST_PERSISTENT);
1211 #endif
1212 
1213 #if defined(GD_MAJOR_VERSION) && defined(GD_MINOR_VERSION) && defined(GD_RELEASE_VERSION) && defined(GD_EXTRA_VERSION)
1214 	REGISTER_LONG_CONSTANT("GD_MAJOR_VERSION", GD_MAJOR_VERSION, CONST_CS | CONST_PERSISTENT);
1215 	REGISTER_LONG_CONSTANT("GD_MINOR_VERSION", GD_MINOR_VERSION, CONST_CS | CONST_PERSISTENT);
1216 	REGISTER_LONG_CONSTANT("GD_RELEASE_VERSION", GD_RELEASE_VERSION, CONST_CS | CONST_PERSISTENT);
1217 	REGISTER_STRING_CONSTANT("GD_EXTRA_VERSION", GD_EXTRA_VERSION, CONST_CS | CONST_PERSISTENT);
1218 #endif
1219 
1220 
1221 #ifdef HAVE_GD_PNG
1222 
1223 	/*
1224 	 * cannot include #include "png.h"
1225 	 * /usr/include/pngconf.h:310:2: error: #error png.h already includes setjmp.h with some additional fixup.
1226 	 * as error, use the values for now...
1227 	 */
1228 	REGISTER_LONG_CONSTANT("PNG_NO_FILTER",	    0x00, CONST_CS | CONST_PERSISTENT);
1229 	REGISTER_LONG_CONSTANT("PNG_FILTER_NONE",   0x08, CONST_CS | CONST_PERSISTENT);
1230 	REGISTER_LONG_CONSTANT("PNG_FILTER_SUB",    0x10, CONST_CS | CONST_PERSISTENT);
1231 	REGISTER_LONG_CONSTANT("PNG_FILTER_UP",     0x20, CONST_CS | CONST_PERSISTENT);
1232 	REGISTER_LONG_CONSTANT("PNG_FILTER_AVG",    0x40, CONST_CS | CONST_PERSISTENT);
1233 	REGISTER_LONG_CONSTANT("PNG_FILTER_PAETH",  0x80, CONST_CS | CONST_PERSISTENT);
1234 	REGISTER_LONG_CONSTANT("PNG_ALL_FILTERS",   0x08 | 0x10 | 0x20 | 0x40 | 0x80, CONST_CS | CONST_PERSISTENT);
1235 #endif
1236 
1237 	return SUCCESS;
1238 }
1239 /* }}} */
1240 
1241 /* {{{ PHP_MSHUTDOWN_FUNCTION
1242  */
PHP_MSHUTDOWN_FUNCTION(gd)1243 PHP_MSHUTDOWN_FUNCTION(gd)
1244 {
1245 #if defined(HAVE_GD_FREETYPE) && defined(HAVE_GD_BUNDLED)
1246 	gdFontCacheMutexShutdown();
1247 #endif
1248 	UNREGISTER_INI_ENTRIES();
1249 	return SUCCESS;
1250 }
1251 /* }}} */
1252 
1253 /* {{{ PHP_RSHUTDOWN_FUNCTION
1254  */
PHP_RSHUTDOWN_FUNCTION(gd)1255 PHP_RSHUTDOWN_FUNCTION(gd)
1256 {
1257 #ifdef HAVE_GD_FREETYPE
1258 	gdFontCacheShutdown();
1259 #endif
1260 	return SUCCESS;
1261 }
1262 /* }}} */
1263 
1264 #if defined(HAVE_GD_BUNDLED)
1265 #define PHP_GD_VERSION_STRING "bundled (2.1.0 compatible)"
1266 #else
1267 # define PHP_GD_VERSION_STRING GD_VERSION_STRING
1268 #endif
1269 
1270 /* {{{ PHP_MINFO_FUNCTION
1271  */
PHP_MINFO_FUNCTION(gd)1272 PHP_MINFO_FUNCTION(gd)
1273 {
1274 	php_info_print_table_start();
1275 	php_info_print_table_row(2, "GD Support", "enabled");
1276 
1277 	/* need to use a PHPAPI function here because it is external module in windows */
1278 
1279 #if defined(HAVE_GD_BUNDLED)
1280 	php_info_print_table_row(2, "GD Version", PHP_GD_VERSION_STRING);
1281 #else
1282 	php_info_print_table_row(2, "GD headers Version", PHP_GD_VERSION_STRING);
1283 #if defined(HAVE_GD_LIBVERSION)
1284 	php_info_print_table_row(2, "GD library Version", gdVersionString());
1285 #endif
1286 #endif
1287 
1288 #ifdef HAVE_GD_FREETYPE
1289 	php_info_print_table_row(2, "FreeType Support", "enabled");
1290 	php_info_print_table_row(2, "FreeType Linkage", "with freetype");
1291 #ifdef HAVE_GD_BUNDLED
1292 	{
1293 		char tmp[256];
1294 
1295 #ifdef FREETYPE_PATCH
1296 		snprintf(tmp, sizeof(tmp), "%d.%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH);
1297 #elif defined(FREETYPE_MAJOR)
1298 		snprintf(tmp, sizeof(tmp), "%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR);
1299 #else
1300 		snprintf(tmp, sizeof(tmp), "1.x");
1301 #endif
1302 		php_info_print_table_row(2, "FreeType Version", tmp);
1303 	}
1304 #endif
1305 #endif
1306 
1307 	php_info_print_table_row(2, "GIF Read Support", "enabled");
1308 	php_info_print_table_row(2, "GIF Create Support", "enabled");
1309 
1310 #ifdef HAVE_GD_JPG
1311 	{
1312 		php_info_print_table_row(2, "JPEG Support", "enabled");
1313 #if defined(HAVE_GD_BUNDLED)
1314 		php_info_print_table_row(2, "libJPEG Version", gdJpegGetVersionString());
1315 #endif
1316 	}
1317 #endif
1318 
1319 #ifdef HAVE_GD_PNG
1320 	php_info_print_table_row(2, "PNG Support", "enabled");
1321 #if defined(HAVE_GD_BUNDLED)
1322 	php_info_print_table_row(2, "libPNG Version", gdPngGetVersionString());
1323 #endif
1324 #endif
1325 	php_info_print_table_row(2, "WBMP Support", "enabled");
1326 #if defined(HAVE_GD_XPM)
1327 	php_info_print_table_row(2, "XPM Support", "enabled");
1328 #if defined(HAVE_GD_BUNDLED)
1329 	{
1330 		char tmp[12];
1331 		snprintf(tmp, sizeof(tmp), "%d", XpmLibraryVersion());
1332 		php_info_print_table_row(2, "libXpm Version", tmp);
1333 	}
1334 #endif
1335 #endif
1336 	php_info_print_table_row(2, "XBM Support", "enabled");
1337 #if defined(USE_GD_JISX0208)
1338 	php_info_print_table_row(2, "JIS-mapped Japanese Font Support", "enabled");
1339 #endif
1340 #ifdef HAVE_GD_WEBP
1341 	php_info_print_table_row(2, "WebP Support", "enabled");
1342 #endif
1343 #ifdef HAVE_GD_BMP
1344 	php_info_print_table_row(2, "BMP Support", "enabled");
1345 #endif
1346 #ifdef HAVE_GD_TGA
1347 	php_info_print_table_row(2, "TGA Read Support", "enabled");
1348 #endif
1349 	php_info_print_table_end();
1350 	DISPLAY_INI_ENTRIES();
1351 }
1352 /* }}} */
1353 
1354 /* {{{ proto array gd_info()
1355  */
PHP_FUNCTION(gd_info)1356 PHP_FUNCTION(gd_info)
1357 {
1358 	if (zend_parse_parameters_none() == FAILURE) {
1359 		return;
1360 	}
1361 
1362 	array_init(return_value);
1363 
1364 	add_assoc_string(return_value, "GD Version", PHP_GD_VERSION_STRING);
1365 
1366 #ifdef HAVE_GD_FREETYPE
1367 	add_assoc_bool(return_value, "FreeType Support", 1);
1368 	add_assoc_string(return_value, "FreeType Linkage", "with freetype");
1369 #else
1370 	add_assoc_bool(return_value, "FreeType Support", 0);
1371 #endif
1372 	add_assoc_bool(return_value, "GIF Read Support", 1);
1373 	add_assoc_bool(return_value, "GIF Create Support", 1);
1374 #ifdef HAVE_GD_JPG
1375 	add_assoc_bool(return_value, "JPEG Support", 1);
1376 #else
1377 	add_assoc_bool(return_value, "JPEG Support", 0);
1378 #endif
1379 #ifdef HAVE_GD_PNG
1380 	add_assoc_bool(return_value, "PNG Support", 1);
1381 #else
1382 	add_assoc_bool(return_value, "PNG Support", 0);
1383 #endif
1384 	add_assoc_bool(return_value, "WBMP Support", 1);
1385 #if defined(HAVE_GD_XPM)
1386 	add_assoc_bool(return_value, "XPM Support", 1);
1387 #else
1388 	add_assoc_bool(return_value, "XPM Support", 0);
1389 #endif
1390 	add_assoc_bool(return_value, "XBM Support", 1);
1391 #ifdef HAVE_GD_WEBP
1392 	add_assoc_bool(return_value, "WebP Support", 1);
1393 #else
1394 	add_assoc_bool(return_value, "WebP Support", 0);
1395 #endif
1396 #ifdef HAVE_GD_BMP
1397 	add_assoc_bool(return_value, "BMP Support", 1);
1398 #else
1399 	add_assoc_bool(return_value, "BMP Support", 0);
1400 #endif
1401 #ifdef HAVE_GD_TGA
1402 	add_assoc_bool(return_value, "TGA Read Support", 1);
1403 #else
1404 	add_assoc_bool(return_value, "TGA Read Support", 0);
1405 #endif
1406 #if defined(USE_GD_JISX0208)
1407 	add_assoc_bool(return_value, "JIS-mapped Japanese Font Support", 1);
1408 #else
1409 	add_assoc_bool(return_value, "JIS-mapped Japanese Font Support", 0);
1410 #endif
1411 }
1412 /* }}} */
1413 
1414 /* Need this for cpdf. See also comment in file.c php3i_get_le_fp() */
phpi_get_le_gd(void)1415 PHP_GD_API int phpi_get_le_gd(void)
1416 {
1417 	return le_gd;
1418 }
1419 /* }}} */
1420 
1421 #define FLIPWORD(a) (((a & 0xff000000) >> 24) | ((a & 0x00ff0000) >> 8) | ((a & 0x0000ff00) << 8) | ((a & 0x000000ff) << 24))
1422 
1423 /* {{{ proto int imageloadfont(string filename)
1424    Load a new font */
PHP_FUNCTION(imageloadfont)1425 PHP_FUNCTION(imageloadfont)
1426 {
1427 	zval *ind;
1428 	zend_string *file;
1429 	int hdr_size = sizeof(gdFont) - sizeof(char *);
1430 	int body_size, n = 0, b, i, body_size_check;
1431 	gdFontPtr font;
1432 	php_stream *stream;
1433 
1434 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file) == FAILURE) {
1435 		return;
1436 	}
1437 
1438 	stream = php_stream_open_wrapper(ZSTR_VAL(file), "rb", IGNORE_PATH | IGNORE_URL_WIN | REPORT_ERRORS, NULL);
1439 	if (stream == NULL) {
1440 		RETURN_FALSE;
1441 	}
1442 
1443 	/* Only supports a architecture-dependent binary dump format
1444 	 * at the moment.
1445 	 * The file format is like this on machines with 32-byte integers:
1446 	 *
1447 	 * byte 0-3:   (int) number of characters in the font
1448 	 * byte 4-7:   (int) value of first character in the font (often 32, space)
1449 	 * byte 8-11:  (int) pixel width of each character
1450 	 * byte 12-15: (int) pixel height of each character
1451 	 * bytes 16-:  (char) array with character data, one byte per pixel
1452 	 *                    in each character, for a total of
1453 	 *                    (nchars*width*height) bytes.
1454 	 */
1455 	font = (gdFontPtr) emalloc(sizeof(gdFont));
1456 	b = 0;
1457 	while (b < hdr_size && (n = php_stream_read(stream, (char*)&font[b], hdr_size - b)) > 0) {
1458 		b += n;
1459 	}
1460 
1461 	if (n <= 0) {
1462 		efree(font);
1463 		if (php_stream_eof(stream)) {
1464 			php_error_docref(NULL, E_WARNING, "End of file while reading header");
1465 		} else {
1466 			php_error_docref(NULL, E_WARNING, "Error while reading header");
1467 		}
1468 		php_stream_close(stream);
1469 		RETURN_FALSE;
1470 	}
1471 	i = php_stream_tell(stream);
1472 	php_stream_seek(stream, 0, SEEK_END);
1473 	body_size_check = php_stream_tell(stream) - hdr_size;
1474 	php_stream_seek(stream, i, SEEK_SET);
1475 
1476 	if (overflow2(font->nchars, font->h) || overflow2(font->nchars * font->h, font->w )) {
1477 		php_error_docref(NULL, E_WARNING, "Error reading font, invalid font header");
1478 		efree(font);
1479 		php_stream_close(stream);
1480 		RETURN_FALSE;
1481 	}
1482 
1483 	body_size = font->w * font->h * font->nchars;
1484 	if (body_size != body_size_check) {
1485 		font->w = FLIPWORD(font->w);
1486 		font->h = FLIPWORD(font->h);
1487 		font->nchars = FLIPWORD(font->nchars);
1488 		if (overflow2(font->nchars, font->h) || overflow2(font->nchars * font->h, font->w )) {
1489 			php_error_docref(NULL, E_WARNING, "Error reading font, invalid font header");
1490 			efree(font);
1491 			php_stream_close(stream);
1492 			RETURN_FALSE;
1493 		}
1494 		body_size = font->w * font->h * font->nchars;
1495 	}
1496 
1497 	if (body_size != body_size_check) {
1498 		php_error_docref(NULL, E_WARNING, "Error reading font");
1499 		efree(font);
1500 		php_stream_close(stream);
1501 		RETURN_FALSE;
1502 	}
1503 
1504 	ZEND_ASSERT(body_size > 0);
1505 	font->data = emalloc(body_size);
1506 	b = 0;
1507 	while (b < body_size && (n = php_stream_read(stream, &font->data[b], body_size - b)) > 0) {
1508 		b += n;
1509 	}
1510 
1511 	if (n <= 0) {
1512 		efree(font->data);
1513 		efree(font);
1514 		if (php_stream_eof(stream)) {
1515 			php_error_docref(NULL, E_WARNING, "End of file while reading body");
1516 		} else {
1517 			php_error_docref(NULL, E_WARNING, "Error while reading body");
1518 		}
1519 		php_stream_close(stream);
1520 		RETURN_FALSE;
1521 	}
1522 	php_stream_close(stream);
1523 
1524 	ind = zend_list_insert(font, le_gd_font);
1525 
1526 	/* Adding 5 to the font index so we will never have font indices
1527 	 * that overlap with the old fonts (with indices 1-5).  The first
1528 	 * list index given out is always 1.
1529 	 */
1530 	RETURN_LONG(Z_RES_HANDLE_P(ind) + 5);
1531 }
1532 /* }}} */
1533 
1534 /* {{{ proto bool imagesetstyle(resource im, array styles)
1535    Set the line drawing styles for use with imageline and IMG_COLOR_STYLED. */
PHP_FUNCTION(imagesetstyle)1536 PHP_FUNCTION(imagesetstyle)
1537 {
1538 	zval *IM, *styles, *item;
1539 	gdImagePtr im;
1540 	int *stylearr;
1541 	int index = 0;
1542     uint32_t num_styles;
1543 
1544 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra", &IM, &styles) == FAILURE)  {
1545 		return;
1546 	}
1547 
1548 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1549 		RETURN_FALSE;
1550 	}
1551 
1552     num_styles = zend_hash_num_elements(Z_ARRVAL_P(styles));
1553     if (num_styles == 0) {
1554         php_error_docref(NULL, E_WARNING, "styles array must not be empty");
1555         RETURN_FALSE;
1556     }
1557 
1558 	/* copy the style values in the stylearr */
1559 	stylearr = safe_emalloc(sizeof(int), num_styles, 0);
1560 
1561 	ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(styles), item) {
1562 		stylearr[index++] = zval_get_long(item);
1563 	} ZEND_HASH_FOREACH_END();
1564 
1565 	gdImageSetStyle(im, stylearr, index);
1566 
1567 	efree(stylearr);
1568 
1569 	RETURN_TRUE;
1570 }
1571 /* }}} */
1572 
1573 /* {{{ proto resource imagecreatetruecolor(int x_size, int y_size)
1574    Create a new true color image */
PHP_FUNCTION(imagecreatetruecolor)1575 PHP_FUNCTION(imagecreatetruecolor)
1576 {
1577 	zend_long x_size, y_size;
1578 	gdImagePtr im;
1579 
1580 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &x_size, &y_size) == FAILURE) {
1581 		return;
1582 	}
1583 
1584 	if (x_size <= 0 || y_size <= 0 || x_size >= INT_MAX || y_size >= INT_MAX) {
1585 		php_error_docref(NULL, E_WARNING, "Invalid image dimensions");
1586 		RETURN_FALSE;
1587 	}
1588 
1589 	im = gdImageCreateTrueColor(x_size, y_size);
1590 
1591 	if (!im) {
1592 		RETURN_FALSE;
1593 	}
1594 
1595 	RETURN_RES(zend_register_resource(im, le_gd));
1596 }
1597 /* }}} */
1598 
1599 /* {{{ proto bool imageistruecolor(resource im)
1600    return true if the image uses truecolor */
PHP_FUNCTION(imageistruecolor)1601 PHP_FUNCTION(imageistruecolor)
1602 {
1603 	zval *IM;
1604 	gdImagePtr im;
1605 
1606 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE) {
1607 		return;
1608 	}
1609 
1610 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1611 		RETURN_FALSE;
1612 	}
1613 
1614 	RETURN_BOOL(im->trueColor);
1615 }
1616 /* }}} */
1617 
1618 /* {{{ proto void imagetruecolortopalette(resource im, bool ditherFlag, int colorsWanted)
1619    Convert a true color image to a palette based image with a number of colors, optionally using dithering. */
PHP_FUNCTION(imagetruecolortopalette)1620 PHP_FUNCTION(imagetruecolortopalette)
1621 {
1622 	zval *IM;
1623 	zend_bool dither;
1624 	zend_long ncolors;
1625 	gdImagePtr im;
1626 
1627 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rbl", &IM, &dither, &ncolors) == FAILURE)  {
1628 		return;
1629 	}
1630 
1631 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1632 		RETURN_FALSE;
1633 	}
1634 
1635 	if (ncolors <= 0 || ZEND_LONG_INT_OVFL(ncolors)) {
1636 		php_error_docref(NULL, E_WARNING, "Number of colors has to be greater than zero and no more than %d", INT_MAX);
1637 		RETURN_FALSE;
1638 	}
1639 	if (gdImageTrueColorToPalette(im, dither, (int)ncolors)) {
1640 		RETURN_TRUE;
1641 	} else {
1642 		php_error_docref(NULL, E_WARNING, "Couldn't convert to palette");
1643 		RETURN_FALSE;
1644 	}
1645 }
1646 /* }}} */
1647 
1648 /* {{{ proto void imagepalettetotruecolor(resource im)
1649    Convert a palette based image to a true color image. */
PHP_FUNCTION(imagepalettetotruecolor)1650 PHP_FUNCTION(imagepalettetotruecolor)
1651 {
1652 	zval *IM;
1653 	gdImagePtr im;
1654 
1655 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE)  {
1656 		return;
1657 	}
1658 
1659 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1660 		RETURN_FALSE;
1661 	}
1662 
1663 	if (gdImagePaletteToTrueColor(im) == 0) {
1664 		RETURN_FALSE;
1665 	}
1666 
1667 	RETURN_TRUE;
1668 }
1669 /* }}} */
1670 
1671 /* {{{ proto bool imagecolormatch(resource im1, resource im2)
1672    Makes the colors of the palette version of an image more closely match the true color version */
PHP_FUNCTION(imagecolormatch)1673 PHP_FUNCTION(imagecolormatch)
1674 {
1675 	zval *IM1, *IM2;
1676 	gdImagePtr im1, im2;
1677 	int result;
1678 
1679 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &IM1, &IM2) == FAILURE) {
1680 		return;
1681 	}
1682 
1683 	if ((im1 = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM1), "Image", le_gd)) == NULL) {
1684 		RETURN_FALSE;
1685 	}
1686 	if ((im2 = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM2), "Image", le_gd)) == NULL) {
1687 		RETURN_FALSE;
1688 	}
1689 
1690 	result = gdImageColorMatch(im1, im2);
1691 	switch (result) {
1692 		case -1:
1693 			php_error_docref(NULL, E_WARNING, "Image1 must be TrueColor" );
1694 			RETURN_FALSE;
1695 			break;
1696 		case -2:
1697 			php_error_docref(NULL, E_WARNING, "Image2 must be Palette" );
1698 			RETURN_FALSE;
1699 			break;
1700 		case -3:
1701 			php_error_docref(NULL, E_WARNING, "Image1 and Image2 must be the same size" );
1702 			RETURN_FALSE;
1703 			break;
1704 		case -4:
1705 			php_error_docref(NULL, E_WARNING, "Image2 must have at least one color" );
1706 			RETURN_FALSE;
1707 			break;
1708 	}
1709 
1710 	RETURN_TRUE;
1711 }
1712 /* }}} */
1713 
1714 /* {{{ proto bool imagesetthickness(resource im, int thickness)
1715    Set line thickness for drawing lines, ellipses, rectangles, polygons etc. */
PHP_FUNCTION(imagesetthickness)1716 PHP_FUNCTION(imagesetthickness)
1717 {
1718 	zval *IM;
1719 	zend_long thick;
1720 	gdImagePtr im;
1721 
1722 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &IM, &thick) == FAILURE) {
1723 		return;
1724 	}
1725 
1726 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1727 		RETURN_FALSE;
1728 	}
1729 
1730 	gdImageSetThickness(im, thick);
1731 
1732 	RETURN_TRUE;
1733 }
1734 /* }}} */
1735 
1736 /* {{{ proto bool imagefilledellipse(resource im, int cx, int cy, int w, int h, int color)
1737    Draw an ellipse */
PHP_FUNCTION(imagefilledellipse)1738 PHP_FUNCTION(imagefilledellipse)
1739 {
1740 	zval *IM;
1741 	zend_long cx, cy, w, h, color;
1742 	gdImagePtr im;
1743 
1744 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &cx, &cy, &w, &h, &color) == FAILURE) {
1745 		return;
1746 	}
1747 
1748 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1749 		RETURN_FALSE;
1750 	}
1751 
1752 	gdImageFilledEllipse(im, cx, cy, w, h, color);
1753 
1754 	RETURN_TRUE;
1755 }
1756 /* }}} */
1757 
1758 /* {{{ proto bool imagefilledarc(resource im, int cx, int cy, int w, int h, int s, int e, int col, int style)
1759    Draw a filled partial ellipse */
PHP_FUNCTION(imagefilledarc)1760 PHP_FUNCTION(imagefilledarc)
1761 {
1762 	zval *IM;
1763 	zend_long cx, cy, w, h, ST, E, col, style;
1764 	gdImagePtr im;
1765 	int e, st;
1766 
1767 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllllllll", &IM, &cx, &cy, &w, &h, &ST, &E, &col, &style) == FAILURE) {
1768 		return;
1769 	}
1770 
1771 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1772 		RETURN_FALSE;
1773 	}
1774 
1775 	e = E;
1776 	if (e < 0) {
1777 		e %= 360;
1778 	}
1779 
1780 	st = ST;
1781 	if (st < 0) {
1782 		st %= 360;
1783 	}
1784 
1785 	gdImageFilledArc(im, cx, cy, w, h, st, e, col, style);
1786 
1787 	RETURN_TRUE;
1788 }
1789 /* }}} */
1790 
1791 /* {{{ proto bool imagealphablending(resource im, bool on)
1792    Turn alpha blending mode on or off for the given image */
PHP_FUNCTION(imagealphablending)1793 PHP_FUNCTION(imagealphablending)
1794 {
1795 	zval *IM;
1796 	zend_bool blend;
1797 	gdImagePtr im;
1798 
1799 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rb", &IM, &blend) == FAILURE) {
1800 		return;
1801 	}
1802 
1803 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1804 		RETURN_FALSE;
1805 	}
1806 
1807 	gdImageAlphaBlending(im, blend);
1808 
1809 	RETURN_TRUE;
1810 }
1811 /* }}} */
1812 
1813 /* {{{ proto bool imagesavealpha(resource im, bool on)
1814    Include alpha channel to a saved image */
PHP_FUNCTION(imagesavealpha)1815 PHP_FUNCTION(imagesavealpha)
1816 {
1817 	zval *IM;
1818 	zend_bool save;
1819 	gdImagePtr im;
1820 
1821 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rb", &IM, &save) == FAILURE) {
1822 		return;
1823 	}
1824 
1825 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1826 		RETURN_FALSE;
1827 	}
1828 
1829 	gdImageSaveAlpha(im, save);
1830 
1831 	RETURN_TRUE;
1832 }
1833 /* }}} */
1834 
1835 /* {{{ proto bool imagelayereffect(resource im, int effect)
1836    Set the alpha blending flag to use the bundled libgd layering effects */
PHP_FUNCTION(imagelayereffect)1837 PHP_FUNCTION(imagelayereffect)
1838 {
1839 	zval *IM;
1840 	zend_long effect;
1841 	gdImagePtr im;
1842 
1843 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &IM, &effect) == FAILURE) {
1844 		return;
1845 	}
1846 
1847 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1848 		RETURN_FALSE;
1849 	}
1850 
1851 	gdImageAlphaBlending(im, effect);
1852 
1853 	RETURN_TRUE;
1854 }
1855 /* }}} */
1856 
1857 #define CHECK_RGBA_RANGE(component, name) \
1858 	if (component < 0 || component > gd##name##Max) { \
1859 		php_error_docref(NULL, E_WARNING, #name " component is out of range"); \
1860 		RETURN_FALSE; \
1861 	}
1862 
1863 /* {{{ proto int imagecolorallocatealpha(resource im, int red, int green, int blue, int alpha)
1864    Allocate a color with an alpha level.  Works for true color and palette based images */
PHP_FUNCTION(imagecolorallocatealpha)1865 PHP_FUNCTION(imagecolorallocatealpha)
1866 {
1867 	zval *IM;
1868 	zend_long red, green, blue, alpha;
1869 	gdImagePtr im;
1870 	int ct = (-1);
1871 
1872 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll", &IM, &red, &green, &blue, &alpha) == FAILURE) {
1873 		RETURN_FALSE;
1874 	}
1875 
1876 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1877 		RETURN_FALSE;
1878 	}
1879 
1880 	CHECK_RGBA_RANGE(red, Red);
1881 	CHECK_RGBA_RANGE(green, Green);
1882 	CHECK_RGBA_RANGE(blue, Blue);
1883 	CHECK_RGBA_RANGE(alpha, Alpha);
1884 
1885 	ct = gdImageColorAllocateAlpha(im, red, green, blue, alpha);
1886 	if (ct < 0) {
1887 		RETURN_FALSE;
1888 	}
1889 	RETURN_LONG((zend_long)ct);
1890 }
1891 /* }}} */
1892 
1893 /* {{{ proto int imagecolorresolvealpha(resource im, int red, int green, int blue, int alpha)
1894    Resolve/Allocate a colour with an alpha level.  Works for true colour and palette based images */
PHP_FUNCTION(imagecolorresolvealpha)1895 PHP_FUNCTION(imagecolorresolvealpha)
1896 {
1897 	zval *IM;
1898 	zend_long red, green, blue, alpha;
1899 	gdImagePtr im;
1900 
1901 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll", &IM, &red, &green, &blue, &alpha) == FAILURE) {
1902 		return;
1903 	}
1904 
1905 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1906 		RETURN_FALSE;
1907 	}
1908 
1909 	CHECK_RGBA_RANGE(red, Red);
1910 	CHECK_RGBA_RANGE(green, Green);
1911 	CHECK_RGBA_RANGE(blue, Blue);
1912 	CHECK_RGBA_RANGE(alpha, Alpha);
1913 
1914 	RETURN_LONG(gdImageColorResolveAlpha(im, red, green, blue, alpha));
1915 }
1916 /* }}} */
1917 
1918 /* {{{ proto int imagecolorclosestalpha(resource im, int red, int green, int blue, int alpha)
1919    Find the closest matching colour with alpha transparency */
PHP_FUNCTION(imagecolorclosestalpha)1920 PHP_FUNCTION(imagecolorclosestalpha)
1921 {
1922 	zval *IM;
1923 	zend_long red, green, blue, alpha;
1924 	gdImagePtr im;
1925 
1926 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll", &IM, &red, &green, &blue, &alpha) == FAILURE) {
1927 		return;
1928 	}
1929 
1930 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1931 		RETURN_FALSE;
1932 	}
1933 
1934 	CHECK_RGBA_RANGE(red, Red);
1935 	CHECK_RGBA_RANGE(green, Green);
1936 	CHECK_RGBA_RANGE(blue, Blue);
1937 	CHECK_RGBA_RANGE(alpha, Alpha);
1938 
1939 	RETURN_LONG(gdImageColorClosestAlpha(im, red, green, blue, alpha));
1940 }
1941 /* }}} */
1942 
1943 /* {{{ proto int imagecolorexactalpha(resource im, int red, int green, int blue, int alpha)
1944    Find exact match for colour with transparency */
PHP_FUNCTION(imagecolorexactalpha)1945 PHP_FUNCTION(imagecolorexactalpha)
1946 {
1947 	zval *IM;
1948 	zend_long red, green, blue, alpha;
1949 	gdImagePtr im;
1950 
1951 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll", &IM, &red, &green, &blue, &alpha) == FAILURE) {
1952 		return;
1953 	}
1954 
1955 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1956 		RETURN_FALSE;
1957 	}
1958 
1959 	CHECK_RGBA_RANGE(red, Red);
1960 	CHECK_RGBA_RANGE(green, Green);
1961 	CHECK_RGBA_RANGE(blue, Blue);
1962 	CHECK_RGBA_RANGE(alpha, Alpha);
1963 
1964 	RETURN_LONG(gdImageColorExactAlpha(im, red, green, blue, alpha));
1965 }
1966 /* }}} */
1967 
1968 /* {{{ proto bool imagecopyresampled(resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h)
1969    Copy and resize part of an image using resampling to help ensure clarity */
PHP_FUNCTION(imagecopyresampled)1970 PHP_FUNCTION(imagecopyresampled)
1971 {
1972 	zval *SIM, *DIM;
1973 	zend_long SX, SY, SW, SH, DX, DY, DW, DH;
1974 	gdImagePtr im_dst, im_src;
1975 	int srcH, srcW, dstH, dstW, srcY, srcX, dstY, dstX;
1976 
1977 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrllllllll", &DIM, &SIM, &DX, &DY, &SX, &SY, &DW, &DH, &SW, &SH) == FAILURE) {
1978 		return;
1979 	}
1980 
1981 	if ((im_dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(DIM), "Image", le_gd)) == NULL) {
1982 		RETURN_FALSE;
1983 	}
1984 
1985 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
1986 		RETURN_FALSE;
1987 	}
1988 
1989 	srcX = SX;
1990 	srcY = SY;
1991 	srcH = SH;
1992 	srcW = SW;
1993 	dstX = DX;
1994 	dstY = DY;
1995 	dstH = DH;
1996 	dstW = DW;
1997 
1998 	gdImageCopyResampled(im_dst, im_src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);
1999 
2000 	RETURN_TRUE;
2001 }
2002 /* }}} */
2003 
2004 #ifdef PHP_WIN32
2005 /* {{{ proto resource imagegrabwindow(int window_handle [, int client_area])
2006    Grab a window or its client area using a windows handle (HWND property in COM instance) */
PHP_FUNCTION(imagegrabwindow)2007 PHP_FUNCTION(imagegrabwindow)
2008 {
2009 	HWND window;
2010 	zend_long client_area = 0;
2011 	RECT rc = {0};
2012 	int Width, Height;
2013 	HDC		hdc;
2014 	HDC memDC;
2015 	HBITMAP memBM;
2016 	HBITMAP hOld;
2017 	zend_long lwindow_handle;
2018 	gdImagePtr im = NULL;
2019 
2020 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &lwindow_handle, &client_area) == FAILURE) {
2021 		RETURN_FALSE;
2022 	}
2023 
2024 	window = (HWND) lwindow_handle;
2025 
2026 	if (!IsWindow(window)) {
2027 		php_error_docref(NULL, E_NOTICE, "Invalid window handle");
2028 		RETURN_FALSE;
2029 	}
2030 
2031 	hdc		= GetDC(0);
2032 
2033 	if (client_area) {
2034 		GetClientRect(window, &rc);
2035 		Width = rc.right;
2036 		Height = rc.bottom;
2037 	} else {
2038 		GetWindowRect(window, &rc);
2039 		Width	= rc.right - rc.left;
2040 		Height	= rc.bottom - rc.top;
2041 	}
2042 
2043 	Width		= (Width/4)*4;
2044 
2045 	memDC	= CreateCompatibleDC(hdc);
2046 	memBM	= CreateCompatibleBitmap(hdc, Width, Height);
2047 	hOld	= (HBITMAP) SelectObject (memDC, memBM);
2048 
2049 	PrintWindow(window, memDC, (UINT) client_area);
2050 
2051 	im = gdImageCreateTrueColor(Width, Height);
2052 	if (im) {
2053 		int x,y;
2054 		for (y=0; y <= Height; y++) {
2055 			for (x=0; x <= Width; x++) {
2056 				int c = GetPixel(memDC, x,y);
2057 				gdImageSetPixel(im, x, y, gdTrueColor(GetRValue(c), GetGValue(c), GetBValue(c)));
2058 			}
2059 		}
2060 	}
2061 
2062 	SelectObject(memDC,hOld);
2063 	DeleteObject(memBM);
2064 	DeleteDC(memDC);
2065 	ReleaseDC( 0, hdc );
2066 
2067 	if (!im) {
2068 		RETURN_FALSE;
2069 	} else {
2070 		RETURN_RES(zend_register_resource(im, le_gd));
2071 	}
2072 }
2073 /* }}} */
2074 
2075 /* {{{ proto resource imagegrabscreen()
2076    Grab a screenshot */
PHP_FUNCTION(imagegrabscreen)2077 PHP_FUNCTION(imagegrabscreen)
2078 {
2079 	HWND window = GetDesktopWindow();
2080 	RECT rc = {0};
2081 	int Width, Height;
2082 	HDC		hdc;
2083 	HDC memDC;
2084 	HBITMAP memBM;
2085 	HBITMAP hOld;
2086 	gdImagePtr im;
2087 	hdc		= GetDC(0);
2088 
2089 	if (zend_parse_parameters_none() == FAILURE) {
2090 		return;
2091 	}
2092 
2093 	if (!hdc) {
2094 		RETURN_FALSE;
2095 	}
2096 
2097 	GetWindowRect(window, &rc);
2098 	Width	= rc.right - rc.left;
2099 	Height	= rc.bottom - rc.top;
2100 
2101 	Width		= (Width/4)*4;
2102 
2103 	memDC	= CreateCompatibleDC(hdc);
2104 	memBM	= CreateCompatibleBitmap(hdc, Width, Height);
2105 	hOld	= (HBITMAP) SelectObject (memDC, memBM);
2106 	BitBlt( memDC, 0, 0, Width, Height , hdc, rc.left, rc.top , SRCCOPY );
2107 
2108 	im = gdImageCreateTrueColor(Width, Height);
2109 	if (im) {
2110 		int x,y;
2111 		for (y=0; y <= Height; y++) {
2112 			for (x=0; x <= Width; x++) {
2113 				int c = GetPixel(memDC, x,y);
2114 				gdImageSetPixel(im, x, y, gdTrueColor(GetRValue(c), GetGValue(c), GetBValue(c)));
2115 			}
2116 		}
2117 	}
2118 
2119 	SelectObject(memDC,hOld);
2120 	DeleteObject(memBM);
2121 	DeleteDC(memDC);
2122 	ReleaseDC( 0, hdc );
2123 
2124 	if (!im) {
2125 		RETURN_FALSE;
2126 	} else {
2127 		RETURN_RES(zend_register_resource(im, le_gd));
2128 	}
2129 }
2130 /* }}} */
2131 #endif /* PHP_WIN32 */
2132 
2133 /* {{{ proto resource imagerotate(resource src_im, float angle, int bgdcolor [, int ignoretransparent])
2134    Rotate an image using a custom angle */
PHP_FUNCTION(imagerotate)2135 PHP_FUNCTION(imagerotate)
2136 {
2137 	zval *SIM;
2138 	gdImagePtr im_dst, im_src;
2139 	double degrees;
2140 	zend_long color;
2141 	zend_long ignoretransparent = 0;
2142 
2143 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rdl|l", &SIM, &degrees, &color, &ignoretransparent) == FAILURE) {
2144 		RETURN_FALSE;
2145 	}
2146 
2147 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
2148 		RETURN_FALSE;
2149 	}
2150 
2151 	im_dst = gdImageRotateInterpolated(im_src, (const float)degrees, color);
2152 
2153 	if (im_dst != NULL) {
2154 		RETURN_RES(zend_register_resource(im_dst, le_gd));
2155 	} else {
2156 		RETURN_FALSE;
2157 	}
2158 }
2159 /* }}} */
2160 
2161 /* {{{ proto bool imagesettile(resource image, resource tile)
2162    Set the tile image to $tile when filling $image with the "IMG_COLOR_TILED" color */
PHP_FUNCTION(imagesettile)2163 PHP_FUNCTION(imagesettile)
2164 {
2165 	zval *IM, *TILE;
2166 	gdImagePtr im, tile;
2167 
2168 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &IM, &TILE) == FAILURE) {
2169 		return;
2170 	}
2171 
2172 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2173 		RETURN_FALSE;
2174 	}
2175 
2176 	if ((tile = (gdImagePtr)zend_fetch_resource(Z_RES_P(TILE), "Image", le_gd)) == NULL) {
2177 		RETURN_FALSE;
2178 	}
2179 
2180 	gdImageSetTile(im, tile);
2181 
2182 	RETURN_TRUE;
2183 }
2184 /* }}} */
2185 
2186 /* {{{ proto bool imagesetbrush(resource image, resource brush)
2187    Set the brush image to $brush when filling $image with the "IMG_COLOR_BRUSHED" color */
PHP_FUNCTION(imagesetbrush)2188 PHP_FUNCTION(imagesetbrush)
2189 {
2190 	zval *IM, *TILE;
2191 	gdImagePtr im, tile;
2192 
2193 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &IM, &TILE) == FAILURE) {
2194 		return;
2195 	}
2196 
2197 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2198 		RETURN_FALSE;
2199 	}
2200 
2201 	if ((tile = (gdImagePtr)zend_fetch_resource(Z_RES_P(TILE), "Image", le_gd)) == NULL) {
2202 		RETURN_FALSE;
2203 	}
2204 
2205 	gdImageSetBrush(im, tile);
2206 
2207 	RETURN_TRUE;
2208 }
2209 /* }}} */
2210 
2211 /* {{{ proto resource imagecreate(int x_size, int y_size)
2212    Create a new image */
PHP_FUNCTION(imagecreate)2213 PHP_FUNCTION(imagecreate)
2214 {
2215 	zend_long x_size, y_size;
2216 	gdImagePtr im;
2217 
2218 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &x_size, &y_size) == FAILURE) {
2219 		return;
2220 	}
2221 
2222 	if (x_size <= 0 || y_size <= 0 || x_size >= INT_MAX || y_size >= INT_MAX) {
2223 		php_error_docref(NULL, E_WARNING, "Invalid image dimensions");
2224 		RETURN_FALSE;
2225 	}
2226 
2227 	im = gdImageCreate(x_size, y_size);
2228 
2229 	if (!im) {
2230 		RETURN_FALSE;
2231 	}
2232 
2233 	RETURN_RES(zend_register_resource(im, le_gd));
2234 }
2235 /* }}} */
2236 
2237 /* {{{ proto int imagetypes(void)
2238    Return the types of images supported in a bitfield - 1=GIF, 2=JPEG, 4=PNG, 8=WBMP, 16=XPM */
PHP_FUNCTION(imagetypes)2239 PHP_FUNCTION(imagetypes)
2240 {
2241 	int ret = 0;
2242 	ret = PHP_IMG_GIF;
2243 #ifdef HAVE_GD_JPG
2244 	ret |= PHP_IMG_JPG;
2245 #endif
2246 #ifdef HAVE_GD_PNG
2247 	ret |= PHP_IMG_PNG;
2248 #endif
2249 	ret |= PHP_IMG_WBMP;
2250 #if defined(HAVE_GD_XPM)
2251 	ret |= PHP_IMG_XPM;
2252 #endif
2253 #ifdef HAVE_GD_WEBP
2254 	ret |= PHP_IMG_WEBP;
2255 #endif
2256 #ifdef HAVE_GD_BMP
2257 	ret |= PHP_IMG_BMP;
2258 #endif
2259 #ifdef HAVE_GD_TGA
2260 	ret |= PHP_IMG_TGA;
2261 #endif
2262 
2263 	if (zend_parse_parameters_none() == FAILURE) {
2264 		return;
2265 	}
2266 
2267 	RETURN_LONG(ret);
2268 }
2269 /* }}} */
2270 
2271 /* {{{ _php_ctx_getmbi
2272  */
2273 
_php_ctx_getmbi(gdIOCtx * ctx)2274 static int _php_ctx_getmbi(gdIOCtx *ctx)
2275 {
2276 	int i, mbi = 0;
2277 
2278 	do {
2279 		i = (ctx->getC)(ctx);
2280 		if (i < 0) {
2281 			return -1;
2282 		}
2283 		mbi = (mbi << 7) | (i & 0x7f);
2284 	} while (i & 0x80);
2285 
2286 	return mbi;
2287 }
2288 /* }}} */
2289 
2290 /* {{{ _php_image_type
2291  */
2292 static const char php_sig_gd2[3] = {'g', 'd', '2'};
2293 
_php_image_type(char data[12])2294 static int _php_image_type (char data[12])
2295 {
2296 	/* Based on ext/standard/image.c */
2297 
2298 	if (data == NULL) {
2299 		return -1;
2300 	}
2301 
2302 	if (!memcmp(data, php_sig_gd2, sizeof(php_sig_gd2))) {
2303 		return PHP_GDIMG_TYPE_GD2;
2304 	} else if (!memcmp(data, php_sig_jpg, sizeof(php_sig_jpg))) {
2305 		return PHP_GDIMG_TYPE_JPG;
2306 	} else if (!memcmp(data, php_sig_png, sizeof(php_sig_png))) {
2307 		return PHP_GDIMG_TYPE_PNG;
2308 	} else if (!memcmp(data, php_sig_gif, sizeof(php_sig_gif))) {
2309 		return PHP_GDIMG_TYPE_GIF;
2310 	} else if (!memcmp(data, php_sig_bmp, sizeof(php_sig_bmp))) {
2311 		return PHP_GDIMG_TYPE_BMP;
2312 	} else if(!memcmp(data, php_sig_riff, sizeof(php_sig_riff)) && !memcmp(data + sizeof(php_sig_riff) + sizeof(uint32_t), php_sig_webp, sizeof(php_sig_webp))) {
2313 		return PHP_GDIMG_TYPE_WEBP;
2314 	}
2315 	else {
2316 		gdIOCtx *io_ctx;
2317 		io_ctx = gdNewDynamicCtxEx(8, data, 0);
2318 		if (io_ctx) {
2319 			if (_php_ctx_getmbi(io_ctx) == 0 && _php_ctx_getmbi(io_ctx) >= 0) {
2320 				io_ctx->gd_free(io_ctx);
2321 				return PHP_GDIMG_TYPE_WBM;
2322 			} else {
2323 				io_ctx->gd_free(io_ctx);
2324 			}
2325 		}
2326 	}
2327 	return -1;
2328 }
2329 /* }}} */
2330 
2331 /* {{{ _php_image_create_from_string
2332  */
_php_image_create_from_string(zval * data,char * tn,gdImagePtr (* ioctx_func_p)())2333 gdImagePtr _php_image_create_from_string(zval *data, char *tn, gdImagePtr (*ioctx_func_p)())
2334 {
2335 	gdImagePtr im;
2336 	gdIOCtx *io_ctx;
2337 
2338 	io_ctx = gdNewDynamicCtxEx(Z_STRLEN_P(data), Z_STRVAL_P(data), 0);
2339 
2340 	if (!io_ctx) {
2341 		return NULL;
2342 	}
2343 
2344 	im = (*ioctx_func_p)(io_ctx);
2345 	if (!im) {
2346 		php_error_docref(NULL, E_WARNING, "Passed data is not in '%s' format", tn);
2347 		io_ctx->gd_free(io_ctx);
2348 		return NULL;
2349 	}
2350 
2351 	io_ctx->gd_free(io_ctx);
2352 
2353 	return im;
2354 }
2355 /* }}} */
2356 
2357 /* {{{ proto resource imagecreatefromstring(string image)
2358    Create a new image from the image stream in the string */
PHP_FUNCTION(imagecreatefromstring)2359 PHP_FUNCTION(imagecreatefromstring)
2360 {
2361 	zval *data;
2362 	gdImagePtr im;
2363 	int imtype;
2364 	char sig[12];
2365 
2366 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &data) == FAILURE) {
2367 		return;
2368 	}
2369 
2370 	if (!try_convert_to_string(data)) {
2371 		return;
2372 	}
2373 
2374 	if (Z_STRLEN_P(data) < sizeof(sig)) {
2375 		php_error_docref(NULL, E_WARNING, "Empty string or invalid image");
2376 		RETURN_FALSE;
2377 	}
2378 
2379 	memcpy(sig, Z_STRVAL_P(data), sizeof(sig));
2380 
2381 	imtype = _php_image_type(sig);
2382 
2383 	switch (imtype) {
2384 		case PHP_GDIMG_TYPE_JPG:
2385 #ifdef HAVE_GD_JPG
2386 			im = _php_image_create_from_string(data, "JPEG", gdImageCreateFromJpegCtx);
2387 #else
2388 			php_error_docref(NULL, E_WARNING, "No JPEG support in this PHP build");
2389 			RETURN_FALSE;
2390 #endif
2391 			break;
2392 
2393 		case PHP_GDIMG_TYPE_PNG:
2394 #ifdef HAVE_GD_PNG
2395 			im = _php_image_create_from_string(data, "PNG", gdImageCreateFromPngCtx);
2396 #else
2397 			php_error_docref(NULL, E_WARNING, "No PNG support in this PHP build");
2398 			RETURN_FALSE;
2399 #endif
2400 			break;
2401 
2402 		case PHP_GDIMG_TYPE_GIF:
2403 			im = _php_image_create_from_string(data, "GIF", gdImageCreateFromGifCtx);
2404 			break;
2405 
2406 		case PHP_GDIMG_TYPE_WBM:
2407 			im = _php_image_create_from_string(data, "WBMP", gdImageCreateFromWBMPCtx);
2408 			break;
2409 
2410 		case PHP_GDIMG_TYPE_GD2:
2411 			im = _php_image_create_from_string(data, "GD2", gdImageCreateFromGd2Ctx);
2412 			break;
2413 
2414 		case PHP_GDIMG_TYPE_BMP:
2415 			im = _php_image_create_from_string(data, "BMP", gdImageCreateFromBmpCtx);
2416 			break;
2417 
2418 		case PHP_GDIMG_TYPE_WEBP:
2419 #ifdef HAVE_GD_WEBP
2420 			im = _php_image_create_from_string(data, "WEBP", gdImageCreateFromWebpCtx);
2421 			break;
2422 #else
2423 			php_error_docref(NULL, E_WARNING, "No WEBP support in this PHP build");
2424 			RETURN_FALSE;
2425 #endif
2426 
2427 		default:
2428 			php_error_docref(NULL, E_WARNING, "Data is not in a recognized format");
2429 			RETURN_FALSE;
2430 	}
2431 
2432 	if (!im) {
2433 		php_error_docref(NULL, E_WARNING, "Couldn't create GD Image Stream out of Data");
2434 		RETURN_FALSE;
2435 	}
2436 
2437 	RETURN_RES(zend_register_resource(im, le_gd));
2438 }
2439 /* }}} */
2440 
2441 /* {{{ _php_image_create_from
2442  */
_php_image_create_from(INTERNAL_FUNCTION_PARAMETERS,int image_type,char * tn,gdImagePtr (* func_p)(),gdImagePtr (* ioctx_func_p)())2443 static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)())
2444 {
2445 	char *file;
2446 	size_t file_len;
2447 	zend_long srcx, srcy, width, height;
2448 	gdImagePtr im = NULL;
2449 	php_stream *stream;
2450 	FILE * fp = NULL;
2451 #ifdef HAVE_GD_JPG
2452 	long ignore_warning;
2453 #endif
2454 
2455 	if (image_type == PHP_GDIMG_TYPE_GD2PART) {
2456 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "pllll", &file, &file_len, &srcx, &srcy, &width, &height) == FAILURE) {
2457 			return;
2458 		}
2459 		if (width < 1 || height < 1) {
2460 			php_error_docref(NULL, E_WARNING, "Zero width or height not allowed");
2461 			RETURN_FALSE;
2462 		}
2463 	} else {
2464 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &file, &file_len) == FAILURE) {
2465 			return;
2466 		}
2467 	}
2468 
2469 
2470 	stream = php_stream_open_wrapper(file, "rb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
2471 	if (stream == NULL)	{
2472 		RETURN_FALSE;
2473 	}
2474 
2475 	/* try and avoid allocating a FILE* if the stream is not naturally a FILE* */
2476 	if (php_stream_is(stream, PHP_STREAM_IS_STDIO))	{
2477 		if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)&fp, REPORT_ERRORS)) {
2478 			goto out_err;
2479 		}
2480 	} else if (ioctx_func_p) {
2481 		/* we can create an io context */
2482 		gdIOCtx* io_ctx;
2483 		zend_string *buff;
2484 		char *pstr;
2485 
2486 		buff = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0);
2487 
2488 		if (!buff) {
2489 			php_error_docref(NULL, E_WARNING,"Cannot read image data");
2490 			goto out_err;
2491 		}
2492 
2493 		/* needs to be malloc (persistent) - GD will free() it later */
2494 		pstr = pestrndup(ZSTR_VAL(buff), ZSTR_LEN(buff), 1);
2495 		io_ctx = gdNewDynamicCtxEx(ZSTR_LEN(buff), pstr, 0);
2496 		if (!io_ctx) {
2497 			pefree(pstr, 1);
2498 			zend_string_release_ex(buff, 0);
2499 			php_error_docref(NULL, E_WARNING,"Cannot allocate GD IO context");
2500 			goto out_err;
2501 		}
2502 
2503 		if (image_type == PHP_GDIMG_TYPE_GD2PART) {
2504 			im = (*ioctx_func_p)(io_ctx, srcx, srcy, width, height);
2505 		} else {
2506 			im = (*ioctx_func_p)(io_ctx);
2507 		}
2508 		io_ctx->gd_free(io_ctx);
2509 		pefree(pstr, 1);
2510 		zend_string_release_ex(buff, 0);
2511 	}
2512 	else if (php_stream_can_cast(stream, PHP_STREAM_AS_STDIO)) {
2513 		/* try and force the stream to be FILE* */
2514 		if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD, (void **) &fp, REPORT_ERRORS)) {
2515 			goto out_err;
2516 		}
2517 	}
2518 
2519 	if (!im && fp) {
2520 		switch (image_type) {
2521 			case PHP_GDIMG_TYPE_GD2PART:
2522 				im = (*func_p)(fp, srcx, srcy, width, height);
2523 				break;
2524 #if defined(HAVE_GD_XPM)
2525 			case PHP_GDIMG_TYPE_XPM:
2526 				im = gdImageCreateFromXpm(file);
2527 				break;
2528 #endif
2529 
2530 #ifdef HAVE_GD_JPG
2531 			case PHP_GDIMG_TYPE_JPG:
2532 				ignore_warning = INI_INT("gd.jpeg_ignore_warning");
2533 				im = gdImageCreateFromJpegEx(fp, ignore_warning);
2534 			break;
2535 #endif
2536 
2537 			default:
2538 				im = (*func_p)(fp);
2539 				break;
2540 		}
2541 
2542 		fflush(fp);
2543 	}
2544 
2545 /* register_im: */
2546 	if (im) {
2547 		RETVAL_RES(zend_register_resource(im, le_gd));
2548 		php_stream_close(stream);
2549 		return;
2550 	}
2551 
2552 	php_error_docref(NULL, E_WARNING, "'%s' is not a valid %s file", file, tn);
2553 out_err:
2554 	php_stream_close(stream);
2555 	RETURN_FALSE;
2556 
2557 }
2558 /* }}} */
2559 
2560 /* {{{ proto resource imagecreatefromgif(string filename)
2561    Create a new image from GIF file or URL */
PHP_FUNCTION(imagecreatefromgif)2562 PHP_FUNCTION(imagecreatefromgif)
2563 {
2564 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageCreateFromGif, gdImageCreateFromGifCtx);
2565 }
2566 /* }}} */
2567 
2568 #ifdef HAVE_GD_JPG
2569 /* {{{ proto resource imagecreatefromjpeg(string filename)
2570    Create a new image from JPEG file or URL */
PHP_FUNCTION(imagecreatefromjpeg)2571 PHP_FUNCTION(imagecreatefromjpeg)
2572 {
2573 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageCreateFromJpeg, gdImageCreateFromJpegCtx);
2574 }
2575 /* }}} */
2576 #endif /* HAVE_GD_JPG */
2577 
2578 #ifdef HAVE_GD_PNG
2579 /* {{{ proto resource imagecreatefrompng(string filename)
2580    Create a new image from PNG file or URL */
PHP_FUNCTION(imagecreatefrompng)2581 PHP_FUNCTION(imagecreatefrompng)
2582 {
2583 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImageCreateFromPng, gdImageCreateFromPngCtx);
2584 }
2585 /* }}} */
2586 #endif /* HAVE_GD_PNG */
2587 
2588 #ifdef HAVE_GD_WEBP
2589 /* {{{ proto resource imagecreatefromwebp(string filename)
2590    Create a new image from WEBP file or URL */
PHP_FUNCTION(imagecreatefromwebp)2591 PHP_FUNCTION(imagecreatefromwebp)
2592 {
2593 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "WEBP", gdImageCreateFromWebp, gdImageCreateFromWebpCtx);
2594 }
2595 /* }}} */
2596 #endif /* HAVE_GD_WEBP */
2597 
2598 /* {{{ proto resource imagecreatefromxbm(string filename)
2599    Create a new image from XBM file or URL */
PHP_FUNCTION(imagecreatefromxbm)2600 PHP_FUNCTION(imagecreatefromxbm)
2601 {
2602 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "XBM", gdImageCreateFromXbm, NULL);
2603 }
2604 /* }}} */
2605 
2606 #if defined(HAVE_GD_XPM)
2607 /* {{{ proto resource imagecreatefromxpm(string filename)
2608    Create a new image from XPM file or URL */
PHP_FUNCTION(imagecreatefromxpm)2609 PHP_FUNCTION(imagecreatefromxpm)
2610 {
2611 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XPM, "XPM", gdImageCreateFromXpm, NULL);
2612 }
2613 /* }}} */
2614 #endif
2615 
2616 /* {{{ proto resource imagecreatefromwbmp(string filename)
2617    Create a new image from WBMP file or URL */
PHP_FUNCTION(imagecreatefromwbmp)2618 PHP_FUNCTION(imagecreatefromwbmp)
2619 {
2620 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageCreateFromWBMP, gdImageCreateFromWBMPCtx);
2621 }
2622 /* }}} */
2623 
2624 /* {{{ proto resource imagecreatefromgd(string filename)
2625    Create a new image from GD file or URL */
PHP_FUNCTION(imagecreatefromgd)2626 PHP_FUNCTION(imagecreatefromgd)
2627 {
2628 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD, "GD", gdImageCreateFromGd, gdImageCreateFromGdCtx);
2629 }
2630 /* }}} */
2631 
2632 /* {{{ proto resource imagecreatefromgd2(string filename)
2633    Create a new image from GD2 file or URL */
PHP_FUNCTION(imagecreatefromgd2)2634 PHP_FUNCTION(imagecreatefromgd2)
2635 {
2636 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2, "GD2", gdImageCreateFromGd2, gdImageCreateFromGd2Ctx);
2637 }
2638 /* }}} */
2639 
2640 /* {{{ proto resource imagecreatefromgd2part(string filename, int srcX, int srcY, int width, int height)
2641    Create a new image from a given part of GD2 file or URL */
PHP_FUNCTION(imagecreatefromgd2part)2642 PHP_FUNCTION(imagecreatefromgd2part)
2643 {
2644 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2PART, "GD2", gdImageCreateFromGd2Part, gdImageCreateFromGd2PartCtx);
2645 }
2646 /* }}} */
2647 
2648 #if defined(HAVE_GD_BMP)
2649 /* {{{ proto resource imagecreatefrombmp(string filename)
2650    Create a new image from BMP file or URL */
PHP_FUNCTION(imagecreatefrombmp)2651 PHP_FUNCTION(imagecreatefrombmp)
2652 {
2653 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_BMP, "BMP", gdImageCreateFromBmp, gdImageCreateFromBmpCtx);
2654 }
2655 /* }}} */
2656 #endif
2657 
2658 #if defined(HAVE_GD_TGA)
2659 /* {{{ proto resource imagecreatefromtga(string filename)
2660    Create a new image from TGA file or URL */
PHP_FUNCTION(imagecreatefromtga)2661 PHP_FUNCTION(imagecreatefromtga)
2662 {
2663 	_php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_TGA, "TGA", gdImageCreateFromTga, gdImageCreateFromTgaCtx);
2664 }
2665 /* }}} */
2666 #endif
2667 
2668 /* {{{ _php_image_output
2669  */
_php_image_output(INTERNAL_FUNCTION_PARAMETERS,int image_type,char * tn,void (* func_p)())2670 static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)())
2671 {
2672 	zval *imgind;
2673 	char *file = NULL;
2674 	zend_long quality = 0, type = 0;
2675 	gdImagePtr im;
2676 	char *fn = NULL;
2677 	FILE *fp;
2678 	size_t file_len = 0;
2679 	int argc = ZEND_NUM_ARGS();
2680 	int q = -1, t = 1;
2681 
2682 	/* The quality parameter for Wbmp stands for the foreground when called from image2wbmp() */
2683 	/* The quality parameter for gd2 stands for chunk size */
2684 
2685 	if (zend_parse_parameters(argc, "r|pll", &imgind, &file, &file_len, &quality, &type) == FAILURE) {
2686 		return;
2687 	}
2688 
2689 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(imgind), "Image", le_gd)) == NULL) {
2690 		RETURN_FALSE;
2691 	}
2692 
2693 	if (argc > 1) {
2694 		fn = file;
2695 		if (argc >= 3) {
2696 			q = quality;
2697 			if (argc == 4) {
2698 				t = type;
2699 			}
2700 		}
2701 	}
2702 
2703 	if (argc >= 2 && file_len) {
2704 		PHP_GD_CHECK_OPEN_BASEDIR(fn, "Invalid filename");
2705 
2706 		fp = VCWD_FOPEN(fn, "wb");
2707 		if (!fp) {
2708 			php_error_docref(NULL, E_WARNING, "Unable to open '%s' for writing", fn);
2709 			RETURN_FALSE;
2710 		}
2711 
2712 		switch (image_type) {
2713 			case PHP_GDIMG_CONVERT_WBM:
2714 				if (q == -1) {
2715 					q = 0;
2716 				} else if (q < 0 || q > 255) {
2717 					php_error_docref(NULL, E_WARNING, "Invalid threshold value '%d'. It must be between 0 and 255", q);
2718 					q = 0;
2719 				}
2720 				gdImageWBMP(im, q, fp);
2721 				break;
2722 			case PHP_GDIMG_TYPE_GD:
2723 				(*func_p)(im, fp);
2724 				break;
2725 			case PHP_GDIMG_TYPE_GD2:
2726 				if (q == -1) {
2727 					q = 128;
2728 				}
2729 				(*func_p)(im, fp, q, t);
2730 				break;
2731 			default:
2732 				ZEND_ASSERT(0);
2733 		}
2734 		fflush(fp);
2735 		fclose(fp);
2736 	} else {
2737 		int   b;
2738 		FILE *tmp;
2739 		char  buf[4096];
2740 		zend_string *path;
2741 
2742 		tmp = php_open_temporary_file(NULL, NULL, &path);
2743 		if (tmp == NULL) {
2744 			php_error_docref(NULL, E_WARNING, "Unable to open temporary file");
2745 			RETURN_FALSE;
2746 		}
2747 
2748 		switch (image_type) {
2749 			case PHP_GDIMG_CONVERT_WBM:
2750  				if (q == -1) {
2751   					q = 0;
2752   				} else if (q < 0 || q > 255) {
2753   					php_error_docref(NULL, E_WARNING, "Invalid threshold value '%d'. It must be between 0 and 255", q);
2754  					q = 0;
2755   				}
2756 				gdImageWBMP(im, q, tmp);
2757 				break;
2758 			case PHP_GDIMG_TYPE_GD:
2759 				(*func_p)(im, tmp);
2760 				break;
2761 			case PHP_GDIMG_TYPE_GD2:
2762 				if (q == -1) {
2763 					q = 128;
2764 				}
2765 				(*func_p)(im, tmp, q, t);
2766 				break;
2767 			default:
2768 				ZEND_ASSERT(0);
2769 		}
2770 
2771 		fseek(tmp, 0, SEEK_SET);
2772 
2773 		while ((b = fread(buf, 1, sizeof(buf), tmp)) > 0) {
2774 			php_write(buf, b);
2775 		}
2776 
2777 		fclose(tmp);
2778 		VCWD_UNLINK((const char *)ZSTR_VAL(path)); /* make sure that the temporary file is removed */
2779 		zend_string_release_ex(path, 0);
2780 	}
2781 	RETURN_TRUE;
2782 }
2783 /* }}} */
2784 
2785 /* {{{ proto int imagexbm(int im, string filename [, int foreground])
2786    Output XBM image to browser or file */
PHP_FUNCTION(imagexbm)2787 PHP_FUNCTION(imagexbm)
2788 {
2789 	_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "XBM", gdImageXbmCtx);
2790 }
2791 /* }}} */
2792 
2793 /* {{{ proto bool imagegif(resource im [, mixed to])
2794    Output GIF image to browser or file */
PHP_FUNCTION(imagegif)2795 PHP_FUNCTION(imagegif)
2796 {
2797 	_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageGifCtx);
2798 }
2799 /* }}} */
2800 
2801 #ifdef HAVE_GD_PNG
2802 /* {{{ proto bool imagepng(resource im [, mixed to])
2803    Output PNG image to browser or file */
PHP_FUNCTION(imagepng)2804 PHP_FUNCTION(imagepng)
2805 {
2806 	_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePngCtxEx);
2807 }
2808 /* }}} */
2809 #endif /* HAVE_GD_PNG */
2810 
2811 
2812 #ifdef HAVE_GD_WEBP
2813 /* {{{ proto bool imagewebp(resource im [, mixed to[, int quality]] )
2814    Output WEBP image to browser or file */
PHP_FUNCTION(imagewebp)2815 PHP_FUNCTION(imagewebp)
2816 {
2817 	_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "WEBP", gdImageWebpCtx);
2818 }
2819 /* }}} */
2820 #endif /* HAVE_GD_WEBP */
2821 
2822 
2823 #ifdef HAVE_GD_JPG
2824 /* {{{ proto bool imagejpeg(resource im [, mixed to [, int quality]])
2825    Output JPEG image to browser or file */
PHP_FUNCTION(imagejpeg)2826 PHP_FUNCTION(imagejpeg)
2827 {
2828 	_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageJpegCtx);
2829 }
2830 /* }}} */
2831 #endif /* HAVE_GD_JPG */
2832 
2833 /* {{{ proto bool imagewbmp(resource im [, mixed to [, int foreground]])
2834    Output WBMP image to browser or file */
PHP_FUNCTION(imagewbmp)2835 PHP_FUNCTION(imagewbmp)
2836 {
2837 	_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageWBMPCtx);
2838 }
2839 /* }}} */
2840 
2841 /* {{{ proto bool imagegd(resource im [, mixed to])
2842    Output GD image to browser or file */
PHP_FUNCTION(imagegd)2843 PHP_FUNCTION(imagegd)
2844 {
2845 	_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD, "GD", gdImageGd);
2846 }
2847 /* }}} */
2848 
2849 /* {{{ proto bool imagegd2(resource im [, mixed to [, int chunk_size [, int type]]])
2850    Output GD2 image to browser or file */
PHP_FUNCTION(imagegd2)2851 PHP_FUNCTION(imagegd2)
2852 {
2853 	_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2, "GD2", gdImageGd2);
2854 }
2855 /* }}} */
2856 
2857 #ifdef HAVE_GD_BMP
2858 /* {{{ proto bool imagebmp(resource im [, mixed to [, bool compressed]])
2859    Output BMP image to browser or file */
PHP_FUNCTION(imagebmp)2860 PHP_FUNCTION(imagebmp)
2861 {
2862 	_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_BMP, "BMP", gdImageBmpCtx);
2863 }
2864 /* }}} */
2865 #endif
2866 
2867 /* {{{ proto bool imagedestroy(resource im)
2868    Destroy an image */
PHP_FUNCTION(imagedestroy)2869 PHP_FUNCTION(imagedestroy)
2870 {
2871 	zval *IM;
2872 	gdImagePtr im;
2873 
2874 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE) {
2875 		return;
2876 	}
2877 
2878 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2879 		RETURN_FALSE;
2880 	}
2881 
2882 	zend_list_close(Z_RES_P(IM));
2883 
2884 	RETURN_TRUE;
2885 }
2886 /* }}} */
2887 
2888 /* {{{ proto int imagecolorallocate(resource im, int red, int green, int blue)
2889    Allocate a color for an image */
PHP_FUNCTION(imagecolorallocate)2890 PHP_FUNCTION(imagecolorallocate)
2891 {
2892 	zval *IM;
2893 	zend_long red, green, blue;
2894 	gdImagePtr im;
2895 	int ct = (-1);
2896 
2897 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &red, &green, &blue) == FAILURE) {
2898 		return;
2899 	}
2900 
2901 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2902 		RETURN_FALSE;
2903 	}
2904 
2905 	CHECK_RGBA_RANGE(red, Red);
2906 	CHECK_RGBA_RANGE(green, Green);
2907 	CHECK_RGBA_RANGE(blue, Blue);
2908 
2909 	ct = gdImageColorAllocate(im, red, green, blue);
2910 	if (ct < 0) {
2911 		RETURN_FALSE;
2912 	}
2913 	RETURN_LONG(ct);
2914 }
2915 /* }}} */
2916 
2917 /* {{{ proto void imagepalettecopy(resource dst, resource src)
2918    Copy the palette from the src image onto the dst image */
PHP_FUNCTION(imagepalettecopy)2919 PHP_FUNCTION(imagepalettecopy)
2920 {
2921 	zval *dstim, *srcim;
2922 	gdImagePtr dst, src;
2923 
2924 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &dstim, &srcim) == FAILURE) {
2925 		return;
2926 	}
2927 
2928 	if ((dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(dstim), "Image", le_gd)) == NULL) {
2929 		RETURN_FALSE;
2930 	}
2931 
2932 	if ((src = (gdImagePtr)zend_fetch_resource(Z_RES_P(srcim), "Image", le_gd)) == NULL) {
2933 		RETURN_FALSE;
2934 	}
2935 
2936 	gdImagePaletteCopy(dst, src);
2937 }
2938 /* }}} */
2939 
2940 /* {{{ proto int imagecolorat(resource im, int x, int y)
2941    Get the index of the color of a pixel */
PHP_FUNCTION(imagecolorat)2942 PHP_FUNCTION(imagecolorat)
2943 {
2944 	zval *IM;
2945 	zend_long x, y;
2946 	gdImagePtr im;
2947 
2948 	ZEND_PARSE_PARAMETERS_START(3, 3)
2949 		Z_PARAM_RESOURCE(IM)
2950 		Z_PARAM_LONG(x)
2951 		Z_PARAM_LONG(y)
2952 	ZEND_PARSE_PARAMETERS_END();
2953 
2954 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2955 		RETURN_FALSE;
2956 	}
2957 
2958 	if (gdImageTrueColor(im)) {
2959 		if (im->tpixels && gdImageBoundsSafe(im, x, y)) {
2960 			RETURN_LONG(gdImageTrueColorPixel(im, x, y));
2961 		} else {
2962 			php_error_docref(NULL, E_NOTICE, "" ZEND_LONG_FMT "," ZEND_LONG_FMT " is out of bounds", x, y);
2963 			RETURN_FALSE;
2964 		}
2965 	} else {
2966 		if (im->pixels && gdImageBoundsSafe(im, x, y)) {
2967 			RETURN_LONG(im->pixels[y][x]);
2968 		} else {
2969 			php_error_docref(NULL, E_NOTICE, "" ZEND_LONG_FMT "," ZEND_LONG_FMT " is out of bounds", x, y);
2970 			RETURN_FALSE;
2971 		}
2972 	}
2973 }
2974 /* }}} */
2975 
2976 /* {{{ proto int imagecolorclosest(resource im, int red, int green, int blue)
2977    Get the index of the closest color to the specified color */
PHP_FUNCTION(imagecolorclosest)2978 PHP_FUNCTION(imagecolorclosest)
2979 {
2980 	zval *IM;
2981 	zend_long red, green, blue;
2982 	gdImagePtr im;
2983 
2984 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &red, &green, &blue) == FAILURE) {
2985 		return;
2986 	}
2987 
2988 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2989 		RETURN_FALSE;
2990 	}
2991 
2992 	CHECK_RGBA_RANGE(red, Red);
2993 	CHECK_RGBA_RANGE(green, Green);
2994 	CHECK_RGBA_RANGE(blue, Blue);
2995 
2996 	RETURN_LONG(gdImageColorClosest(im, red, green, blue));
2997 }
2998 /* }}} */
2999 
3000 /* {{{ proto int imagecolorclosesthwb(resource im, int red, int green, int blue)
3001    Get the index of the color which has the hue, white and blackness nearest to the given color */
PHP_FUNCTION(imagecolorclosesthwb)3002 PHP_FUNCTION(imagecolorclosesthwb)
3003 {
3004 	zval *IM;
3005 	zend_long red, green, blue;
3006 	gdImagePtr im;
3007 
3008 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &red, &green, &blue) == FAILURE) {
3009 		return;
3010 	}
3011 
3012 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3013 		RETURN_FALSE;
3014 	}
3015 
3016 	CHECK_RGBA_RANGE(red, Red);
3017 	CHECK_RGBA_RANGE(green, Green);
3018 	CHECK_RGBA_RANGE(blue, Blue);
3019 
3020 	RETURN_LONG(gdImageColorClosestHWB(im, red, green, blue));
3021 }
3022 /* }}} */
3023 
3024 /* {{{ proto bool imagecolordeallocate(resource im, int index)
3025    De-allocate a color for an image */
PHP_FUNCTION(imagecolordeallocate)3026 PHP_FUNCTION(imagecolordeallocate)
3027 {
3028 	zval *IM;
3029 	zend_long index;
3030 	int col;
3031 	gdImagePtr im;
3032 
3033 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &IM, &index) == FAILURE) {
3034 		return;
3035 	}
3036 
3037 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3038 		RETURN_FALSE;
3039 	}
3040 
3041 	/* We can return right away for a truecolor image as deallocating colours is meaningless here */
3042 	if (gdImageTrueColor(im)) {
3043 		RETURN_TRUE;
3044 	}
3045 
3046 	col = index;
3047 
3048 	if (col >= 0 && col < gdImageColorsTotal(im)) {
3049 		gdImageColorDeallocate(im, col);
3050 		RETURN_TRUE;
3051 	} else {
3052 		php_error_docref(NULL, E_WARNING, "Color index %d out of range",	col);
3053 		RETURN_FALSE;
3054 	}
3055 }
3056 /* }}} */
3057 
3058 /* {{{ proto int imagecolorresolve(resource im, int red, int green, int blue)
3059    Get the index of the specified color or its closest possible alternative */
PHP_FUNCTION(imagecolorresolve)3060 PHP_FUNCTION(imagecolorresolve)
3061 {
3062 	zval *IM;
3063 	zend_long red, green, blue;
3064 	gdImagePtr im;
3065 
3066 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &red, &green, &blue) == FAILURE) {
3067 		return;
3068 	}
3069 
3070 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3071 		RETURN_FALSE;
3072 	}
3073 
3074 	CHECK_RGBA_RANGE(red, Red);
3075 	CHECK_RGBA_RANGE(green, Green);
3076 	CHECK_RGBA_RANGE(blue, Blue);
3077 
3078 	RETURN_LONG(gdImageColorResolve(im, red, green, blue));
3079 }
3080 /* }}} */
3081 
3082 /* {{{ proto int imagecolorexact(resource im, int red, int green, int blue)
3083    Get the index of the specified color */
PHP_FUNCTION(imagecolorexact)3084 PHP_FUNCTION(imagecolorexact)
3085 {
3086 	zval *IM;
3087 	zend_long red, green, blue;
3088 	gdImagePtr im;
3089 
3090 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &red, &green, &blue) == FAILURE) {
3091 		return;
3092 	}
3093 
3094 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3095 		RETURN_FALSE;
3096 	}
3097 
3098 	CHECK_RGBA_RANGE(red, Red);
3099 	CHECK_RGBA_RANGE(green, Green);
3100 	CHECK_RGBA_RANGE(blue, Blue);
3101 
3102 	RETURN_LONG(gdImageColorExact(im, red, green, blue));
3103 }
3104 /* }}} */
3105 
3106 /* {{{ proto bool imagecolorset(resource im, int col, int red, int green, int blue)
3107    Set the color for the specified palette index */
PHP_FUNCTION(imagecolorset)3108 PHP_FUNCTION(imagecolorset)
3109 {
3110 	zval *IM;
3111 	zend_long color, red, green, blue, alpha = 0;
3112 	int col;
3113 	gdImagePtr im;
3114 
3115 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll|l", &IM, &color, &red, &green, &blue, &alpha) == FAILURE) {
3116 		return;
3117 	}
3118 
3119 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3120 		RETURN_FALSE;
3121 	}
3122 
3123 	CHECK_RGBA_RANGE(red, Red);
3124 	CHECK_RGBA_RANGE(green, Green);
3125 	CHECK_RGBA_RANGE(blue, Blue);
3126 	CHECK_RGBA_RANGE(alpha, Alpha);
3127 
3128 	col = color;
3129 
3130 	if (col >= 0 && col < gdImageColorsTotal(im)) {
3131 		im->red[col]   = red;
3132 		im->green[col] = green;
3133 		im->blue[col]  = blue;
3134 		im->alpha[col]  = alpha;
3135 	} else {
3136 		RETURN_FALSE;
3137 	}
3138 }
3139 /* }}} */
3140 
3141 /* {{{ proto array imagecolorsforindex(resource im, int col)
3142    Get the colors for an index */
PHP_FUNCTION(imagecolorsforindex)3143 PHP_FUNCTION(imagecolorsforindex)
3144 {
3145 	zval *IM;
3146 	zend_long index;
3147 	int col;
3148 	gdImagePtr im;
3149 
3150 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &IM, &index) == FAILURE) {
3151 		return;
3152 	}
3153 
3154 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3155 		RETURN_FALSE;
3156 	}
3157 
3158 	col = index;
3159 
3160 	if ((col >= 0 && gdImageTrueColor(im)) || (!gdImageTrueColor(im) && col >= 0 && col < gdImageColorsTotal(im))) {
3161 		array_init(return_value);
3162 
3163 		add_assoc_long(return_value,"red",  gdImageRed(im,col));
3164 		add_assoc_long(return_value,"green", gdImageGreen(im,col));
3165 		add_assoc_long(return_value,"blue", gdImageBlue(im,col));
3166 		add_assoc_long(return_value,"alpha", gdImageAlpha(im,col));
3167 	} else {
3168 		php_error_docref(NULL, E_WARNING, "Color index %d out of range", col);
3169 		RETURN_FALSE;
3170 	}
3171 }
3172 /* }}} */
3173 
3174 /* {{{ proto bool imagegammacorrect(resource im, float inputgamma, float outputgamma)
3175    Apply a gamma correction to a GD image */
PHP_FUNCTION(imagegammacorrect)3176 PHP_FUNCTION(imagegammacorrect)
3177 {
3178 	zval *IM;
3179 	gdImagePtr im;
3180 	int i;
3181 	double input, output, gamma;
3182 
3183 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rdd", &IM, &input, &output) == FAILURE) {
3184 		return;
3185 	}
3186 
3187 	if ( input <= 0.0 || output <= 0.0 ) {
3188 		php_error_docref(NULL, E_WARNING, "Gamma values should be positive");
3189 		RETURN_FALSE;
3190 	}
3191 
3192 	gamma = input / output;
3193 
3194 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3195 		RETURN_FALSE;
3196 	}
3197 
3198 	if (gdImageTrueColor(im))	{
3199 		int x, y, c;
3200 
3201 		for (y = 0; y < gdImageSY(im); y++)	{
3202 			for (x = 0; x < gdImageSX(im); x++)	{
3203 				c = gdImageGetPixel(im, x, y);
3204 				gdImageSetPixel(im, x, y,
3205 					gdTrueColorAlpha(
3206 						(int) ((pow((gdTrueColorGetRed(c)   / 255.0), gamma) * 255) + .5),
3207 						(int) ((pow((gdTrueColorGetGreen(c) / 255.0), gamma) * 255) + .5),
3208 						(int) ((pow((gdTrueColorGetBlue(c)  / 255.0), gamma) * 255) + .5),
3209 						gdTrueColorGetAlpha(c)
3210 					)
3211 				);
3212 			}
3213 		}
3214 		RETURN_TRUE;
3215 	}
3216 
3217 	for (i = 0; i < gdImageColorsTotal(im); i++) {
3218 		im->red[i]   = (int)((pow((im->red[i]   / 255.0), gamma) * 255) + .5);
3219 		im->green[i] = (int)((pow((im->green[i] / 255.0), gamma) * 255) + .5);
3220 		im->blue[i]  = (int)((pow((im->blue[i]  / 255.0), gamma) * 255) + .5);
3221 	}
3222 
3223 	RETURN_TRUE;
3224 }
3225 /* }}} */
3226 
3227 /* {{{ proto bool imagesetpixel(resource im, int x, int y, int col)
3228    Set a single pixel */
PHP_FUNCTION(imagesetpixel)3229 PHP_FUNCTION(imagesetpixel)
3230 {
3231 	zval *IM;
3232 	zend_long x, y, col;
3233 	gdImagePtr im;
3234 
3235 	ZEND_PARSE_PARAMETERS_START(4, 4)
3236 		Z_PARAM_RESOURCE(IM)
3237 		Z_PARAM_LONG(x)
3238 		Z_PARAM_LONG(y)
3239 		Z_PARAM_LONG(col)
3240 	ZEND_PARSE_PARAMETERS_END();
3241 
3242 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3243 		RETURN_FALSE;
3244 	}
3245 
3246 	gdImageSetPixel(im, x, y, col);
3247 	RETURN_TRUE;
3248 }
3249 /* }}} */
3250 
3251 /* {{{ proto bool imageline(resource im, int x1, int y1, int x2, int y2, int col)
3252    Draw a line */
PHP_FUNCTION(imageline)3253 PHP_FUNCTION(imageline)
3254 {
3255 	zval *IM;
3256 	zend_long x1, y1, x2, y2, col;
3257 	gdImagePtr im;
3258 
3259 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &x1, &y1, &x2, &y2, &col) == FAILURE) {
3260 		return;
3261 	}
3262 
3263 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3264 		RETURN_FALSE;
3265 	}
3266 
3267 	if (im->AA) {
3268 		gdImageSetAntiAliased(im, col);
3269 		col = gdAntiAliased;
3270 	}
3271 	gdImageLine(im, x1, y1, x2, y2, col);
3272 	RETURN_TRUE;
3273 }
3274 /* }}} */
3275 
3276 /* {{{ proto bool imagedashedline(resource im, int x1, int y1, int x2, int y2, int col)
3277    Draw a dashed line */
PHP_FUNCTION(imagedashedline)3278 PHP_FUNCTION(imagedashedline)
3279 {
3280 	zval *IM;
3281 	zend_long x1, y1, x2, y2, col;
3282 	gdImagePtr im;
3283 
3284 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &x1, &y1, &x2, &y2, &col) == FAILURE) {
3285 		return;
3286 	}
3287 
3288 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3289 		RETURN_FALSE;
3290 	}
3291 
3292 	gdImageDashedLine(im, x1, y1, x2, y2, col);
3293 	RETURN_TRUE;
3294 }
3295 /* }}} */
3296 
3297 /* {{{ proto bool imagerectangle(resource im, int x1, int y1, int x2, int y2, int col)
3298    Draw a rectangle */
PHP_FUNCTION(imagerectangle)3299 PHP_FUNCTION(imagerectangle)
3300 {
3301 	zval *IM;
3302 	zend_long x1, y1, x2, y2, col;
3303 	gdImagePtr im;
3304 
3305 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &x1, &y1, &x2, &y2, &col) == FAILURE) {
3306 		return;
3307 	}
3308 
3309 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3310 		RETURN_FALSE;
3311 	}
3312 
3313 	gdImageRectangle(im, x1, y1, x2, y2, col);
3314 	RETURN_TRUE;
3315 }
3316 /* }}} */
3317 
3318 /* {{{ proto bool imagefilledrectangle(resource im, int x1, int y1, int x2, int y2, int col)
3319    Draw a filled rectangle */
PHP_FUNCTION(imagefilledrectangle)3320 PHP_FUNCTION(imagefilledrectangle)
3321 {
3322 	zval *IM;
3323 	zend_long x1, y1, x2, y2, col;
3324 	gdImagePtr im;
3325 
3326 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &x1, &y1, &x2, &y2, &col) == FAILURE) {
3327 		return;
3328 	}
3329 
3330 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3331 		RETURN_FALSE;
3332 	}
3333 	gdImageFilledRectangle(im, x1, y1, x2, y2, col);
3334 	RETURN_TRUE;
3335 }
3336 /* }}} */
3337 
3338 /* {{{ proto bool imagearc(resource im, int cx, int cy, int w, int h, int s, int e, int col)
3339    Draw a partial ellipse */
PHP_FUNCTION(imagearc)3340 PHP_FUNCTION(imagearc)
3341 {
3342 	zval *IM;
3343 	zend_long cx, cy, w, h, ST, E, col;
3344 	gdImagePtr im;
3345 	int e, st;
3346 
3347 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllllll", &IM, &cx, &cy, &w, &h, &ST, &E, &col) == FAILURE) {
3348 		return;
3349 	}
3350 
3351 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3352 		RETURN_FALSE;
3353 	}
3354 
3355 	e = E;
3356 	if (e < 0) {
3357 		e %= 360;
3358 	}
3359 
3360 	st = ST;
3361 	if (st < 0) {
3362 		st %= 360;
3363 	}
3364 
3365 	gdImageArc(im, cx, cy, w, h, st, e, col);
3366 	RETURN_TRUE;
3367 }
3368 /* }}} */
3369 
3370 /* {{{ proto bool imageellipse(resource im, int cx, int cy, int w, int h, int color)
3371    Draw an ellipse */
PHP_FUNCTION(imageellipse)3372 PHP_FUNCTION(imageellipse)
3373 {
3374 	zval *IM;
3375 	zend_long cx, cy, w, h, color;
3376 	gdImagePtr im;
3377 
3378 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &cx, &cy, &w, &h, &color) == FAILURE) {
3379 		return;
3380 	}
3381 
3382 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3383 		RETURN_FALSE;
3384 	}
3385 
3386 	gdImageEllipse(im, cx, cy, w, h, color);
3387 	RETURN_TRUE;
3388 }
3389 /* }}} */
3390 
3391 /* {{{ proto bool imagefilltoborder(resource im, int x, int y, int border, int col)
3392    Flood fill to specific color */
PHP_FUNCTION(imagefilltoborder)3393 PHP_FUNCTION(imagefilltoborder)
3394 {
3395 	zval *IM;
3396 	zend_long x, y, border, col;
3397 	gdImagePtr im;
3398 
3399 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll", &IM, &x, &y, &border, &col) == FAILURE) {
3400 		return;
3401 	}
3402 
3403 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3404 		RETURN_FALSE;
3405 	}
3406 
3407 	gdImageFillToBorder(im, x, y, border, col);
3408 	RETURN_TRUE;
3409 }
3410 /* }}} */
3411 
3412 /* {{{ proto bool imagefill(resource im, int x, int y, int col)
3413    Flood fill */
PHP_FUNCTION(imagefill)3414 PHP_FUNCTION(imagefill)
3415 {
3416 	zval *IM;
3417 	zend_long x, y, col;
3418 	gdImagePtr im;
3419 
3420 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &x, &y, &col) == FAILURE) {
3421 		return;
3422 	}
3423 
3424 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3425 		RETURN_FALSE;
3426 	}
3427 
3428 	gdImageFill(im, x, y, col);
3429 	RETURN_TRUE;
3430 }
3431 /* }}} */
3432 
3433 /* {{{ proto int imagecolorstotal(resource im)
3434    Find out the number of colors in an image's palette */
PHP_FUNCTION(imagecolorstotal)3435 PHP_FUNCTION(imagecolorstotal)
3436 {
3437 	zval *IM;
3438 	gdImagePtr im;
3439 
3440 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE) {
3441 		return;
3442 	}
3443 
3444 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3445 		RETURN_FALSE;
3446 	}
3447 
3448 	RETURN_LONG(gdImageColorsTotal(im));
3449 }
3450 /* }}} */
3451 
3452 /* {{{ proto int imagecolortransparent(resource im [, int col])
3453    Define a color as transparent */
PHP_FUNCTION(imagecolortransparent)3454 PHP_FUNCTION(imagecolortransparent)
3455 {
3456 	zval *IM;
3457 	zend_long COL = 0;
3458 	gdImagePtr im;
3459 	int argc = ZEND_NUM_ARGS();
3460 
3461 	if (zend_parse_parameters(argc, "r|l", &IM, &COL) == FAILURE) {
3462 		return;
3463 	}
3464 
3465 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3466 		RETURN_FALSE;
3467 	}
3468 
3469 	if (argc > 1) {
3470 		gdImageColorTransparent(im, COL);
3471 	}
3472 
3473 	RETURN_LONG(gdImageGetTransparent(im));
3474 }
3475 /* }}} */
3476 
3477 /* {{{ proto int imageinterlace(resource im [, int interlace])
3478    Enable or disable interlace */
PHP_FUNCTION(imageinterlace)3479 PHP_FUNCTION(imageinterlace)
3480 {
3481 	zval *IM;
3482 	int argc = ZEND_NUM_ARGS();
3483 	zend_long INT = 0;
3484 	gdImagePtr im;
3485 
3486 	if (zend_parse_parameters(argc, "r|l", &IM, &INT) == FAILURE) {
3487 		return;
3488 	}
3489 
3490 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3491 		RETURN_FALSE;
3492 	}
3493 
3494 	if (argc > 1) {
3495 		gdImageInterlace(im, INT);
3496 	}
3497 
3498 	RETURN_LONG(gdImageGetInterlaced(im));
3499 }
3500 /* }}} */
3501 
3502 /* {{{ php_imagepolygon
3503    arg = -1 open polygon
3504    arg = 0  normal polygon
3505    arg = 1  filled polygon */
3506 /* im, points, num_points, col */
php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS,int filled)3507 static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled)
3508 {
3509 	zval *IM, *POINTS;
3510 	zend_long NPOINTS, COL;
3511 	zval *var = NULL;
3512 	gdImagePtr im;
3513 	gdPointPtr points;
3514 	int npoints, col, nelem, i;
3515 
3516 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rall", &IM, &POINTS, &NPOINTS, &COL) == FAILURE) {
3517 		return;
3518 	}
3519 
3520 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3521 		RETURN_FALSE;
3522 	}
3523 
3524 	npoints = NPOINTS;
3525 	col = COL;
3526 
3527 	nelem = zend_hash_num_elements(Z_ARRVAL_P(POINTS));
3528 	if (nelem < 6) {
3529 		php_error_docref(NULL, E_WARNING, "You must have at least 3 points in your array");
3530 		RETURN_FALSE;
3531 	}
3532 	if (npoints <= 0) {
3533 		php_error_docref(NULL, E_WARNING, "You must give a positive number of points");
3534 		RETURN_FALSE;
3535 	}
3536 	if (nelem < npoints * 2) {
3537 		php_error_docref(NULL, E_WARNING, "Trying to use %d points in array with only %d points", npoints, nelem/2);
3538 		RETURN_FALSE;
3539 	}
3540 
3541 	points = (gdPointPtr) safe_emalloc(npoints, sizeof(gdPoint), 0);
3542 
3543 	for (i = 0; i < npoints; i++) {
3544 		if ((var = zend_hash_index_find(Z_ARRVAL_P(POINTS), (i * 2))) != NULL) {
3545 			points[i].x = zval_get_long(var);
3546 		}
3547 		if ((var = zend_hash_index_find(Z_ARRVAL_P(POINTS), (i * 2) + 1)) != NULL) {
3548 			points[i].y = zval_get_long(var);
3549 		}
3550 	}
3551 
3552 	if (im->AA) {
3553 		gdImageSetAntiAliased(im, col);
3554 		col = gdAntiAliased;
3555 	}
3556 	switch (filled) {
3557 		case -1:
3558 			gdImageOpenPolygon(im, points, npoints, col);
3559 			break;
3560 		case 0:
3561 			gdImagePolygon(im, points, npoints, col);
3562 			break;
3563 		case 1:
3564 			gdImageFilledPolygon(im, points, npoints, col);
3565 			break;
3566 	}
3567 
3568 	efree(points);
3569 	RETURN_TRUE;
3570 }
3571 /* }}} */
3572 
3573 /* {{{ proto bool imagepolygon(resource im, array point, int num_points, int col)
3574    Draw a polygon */
PHP_FUNCTION(imagepolygon)3575 PHP_FUNCTION(imagepolygon)
3576 {
3577 	php_imagepolygon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3578 }
3579 /* }}} */
3580 
3581 /* {{{ proto bool imageopenpolygon(resource im, array point, int num_points, int col)
3582    Draw a polygon */
PHP_FUNCTION(imageopenpolygon)3583 PHP_FUNCTION(imageopenpolygon)
3584 {
3585 	php_imagepolygon(INTERNAL_FUNCTION_PARAM_PASSTHRU, -1);
3586 }
3587 /* }}} */
3588 
3589 /* {{{ proto bool imagefilledpolygon(resource im, array point, int num_points, int col)
3590    Draw a filled polygon */
PHP_FUNCTION(imagefilledpolygon)3591 PHP_FUNCTION(imagefilledpolygon)
3592 {
3593 	php_imagepolygon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3594 }
3595 /* }}} */
3596 
3597 /* {{{ php_find_gd_font
3598  */
php_find_gd_font(int size)3599 static gdFontPtr php_find_gd_font(int size)
3600 {
3601 	gdFontPtr font;
3602 
3603 	switch (size) {
3604 		case 1:
3605 			font = gdFontTiny;
3606 			break;
3607 		case 2:
3608 			font = gdFontSmall;
3609 			break;
3610 		case 3:
3611 			font = gdFontMediumBold;
3612 			break;
3613 		case 4:
3614 			font = gdFontLarge;
3615 			break;
3616 		case 5:
3617 			font = gdFontGiant;
3618 			break;
3619 		default: {
3620 			 zval *zv = zend_hash_index_find(&EG(regular_list), size - 5);
3621 			 if (!zv || (Z_RES_P(zv))->type != le_gd_font) {
3622 				 if (size < 1) {
3623 					 font = gdFontTiny;
3624 				 } else {
3625 					 font = gdFontGiant;
3626 				 }
3627 			 } else {
3628 				 font = (gdFontPtr)Z_RES_P(zv)->ptr;
3629 			 }
3630 		 }
3631 		 break;
3632 	}
3633 
3634 	return font;
3635 }
3636 /* }}} */
3637 
3638 /* {{{ php_imagefontsize
3639  * arg = 0  ImageFontWidth
3640  * arg = 1  ImageFontHeight
3641  */
php_imagefontsize(INTERNAL_FUNCTION_PARAMETERS,int arg)3642 static void php_imagefontsize(INTERNAL_FUNCTION_PARAMETERS, int arg)
3643 {
3644 	zend_long SIZE;
3645 	gdFontPtr font;
3646 
3647 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &SIZE) == FAILURE) {
3648 		return;
3649 	}
3650 
3651 	font = php_find_gd_font(SIZE);
3652 	RETURN_LONG(arg ? font->h : font->w);
3653 }
3654 /* }}} */
3655 
3656 /* {{{ proto int imagefontwidth(int font)
3657    Get font width */
PHP_FUNCTION(imagefontwidth)3658 PHP_FUNCTION(imagefontwidth)
3659 {
3660 	php_imagefontsize(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3661 }
3662 /* }}} */
3663 
3664 /* {{{ proto int imagefontheight(int font)
3665    Get font height */
PHP_FUNCTION(imagefontheight)3666 PHP_FUNCTION(imagefontheight)
3667 {
3668 	php_imagefontsize(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3669 }
3670 /* }}} */
3671 
3672 /* {{{ php_gdimagecharup
3673  * workaround for a bug in gd 1.2 */
php_gdimagecharup(gdImagePtr im,gdFontPtr f,int x,int y,int c,int color)3674 static void php_gdimagecharup(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
3675 {
3676 	int cx, cy, px, py, fline;
3677 	cx = 0;
3678 	cy = 0;
3679 
3680 	if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
3681 		return;
3682 	}
3683 
3684 	fline = (c - f->offset) * f->h * f->w;
3685 	for (py = y; (py > (y - f->w)); py--) {
3686 		for (px = x; (px < (x + f->h)); px++) {
3687 			if (f->data[fline + cy * f->w + cx]) {
3688 				gdImageSetPixel(im, px, py, color);
3689 			}
3690 			cy++;
3691 		}
3692 		cy = 0;
3693 		cx++;
3694 	}
3695 }
3696 /* }}} */
3697 
3698 /* {{{ php_imagechar
3699  * arg = 0  ImageChar
3700  * arg = 1  ImageCharUp
3701  * arg = 2  ImageString
3702  * arg = 3  ImageStringUp
3703  */
php_imagechar(INTERNAL_FUNCTION_PARAMETERS,int mode)3704 static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode)
3705 {
3706 	zval *IM;
3707 	zend_long SIZE, X, Y, COL;
3708 	char *C;
3709 	size_t C_len;
3710 	gdImagePtr im;
3711 	int ch = 0, col, x, y, size, i, l = 0;
3712 	unsigned char *str = NULL;
3713 	gdFontPtr font;
3714 
3715 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllsl", &IM, &SIZE, &X, &Y, &C, &C_len, &COL) == FAILURE) {
3716 		return;
3717 	}
3718 
3719 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3720 		RETURN_FALSE;
3721 	}
3722 
3723 	col = COL;
3724 
3725 	if (mode < 2) {
3726 		ch = (int)((unsigned char)*C);
3727 	} else {
3728 		str = (unsigned char *) estrndup(C, C_len);
3729 		l = strlen((char *)str);
3730 	}
3731 
3732 	y = Y;
3733 	x = X;
3734 	size = SIZE;
3735 
3736 	font = php_find_gd_font(size);
3737 
3738 	switch (mode) {
3739 		case 0:
3740 			gdImageChar(im, font, x, y, ch, col);
3741 			break;
3742 		case 1:
3743 			php_gdimagecharup(im, font, x, y, ch, col);
3744 			break;
3745 		case 2:
3746 			for (i = 0; (i < l); i++) {
3747 				gdImageChar(im, font, x, y, (int) ((unsigned char) str[i]), col);
3748 				x += font->w;
3749 			}
3750 			break;
3751 		case 3: {
3752 			for (i = 0; (i < l); i++) {
3753 				/* php_gdimagecharup(im, font, x, y, (int) str[i], col); */
3754 				gdImageCharUp(im, font, x, y, (int) str[i], col);
3755 				y -= font->w;
3756 			}
3757 			break;
3758 		}
3759 	}
3760 	if (str) {
3761 		efree(str);
3762 	}
3763 	RETURN_TRUE;
3764 }
3765 /* }}} */
3766 
3767 /* {{{ proto bool imagechar(resource im, int font, int x, int y, string c, int col)
3768    Draw a character */
PHP_FUNCTION(imagechar)3769 PHP_FUNCTION(imagechar)
3770 {
3771 	php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3772 }
3773 /* }}} */
3774 
3775 /* {{{ proto bool imagecharup(resource im, int font, int x, int y, string c, int col)
3776    Draw a character rotated 90 degrees counter-clockwise */
PHP_FUNCTION(imagecharup)3777 PHP_FUNCTION(imagecharup)
3778 {
3779 	php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3780 }
3781 /* }}} */
3782 
3783 /* {{{ proto bool imagestring(resource im, int font, int x, int y, string str, int col)
3784    Draw a string horizontally */
PHP_FUNCTION(imagestring)3785 PHP_FUNCTION(imagestring)
3786 {
3787 	php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
3788 }
3789 /* }}} */
3790 
3791 /* {{{ proto bool imagestringup(resource im, int font, int x, int y, string str, int col)
3792    Draw a string vertically - rotated 90 degrees counter-clockwise */
PHP_FUNCTION(imagestringup)3793 PHP_FUNCTION(imagestringup)
3794 {
3795 	php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
3796 }
3797 /* }}} */
3798 
3799 /* {{{ proto bool imagecopy(resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h)
3800    Copy part of an image */
PHP_FUNCTION(imagecopy)3801 PHP_FUNCTION(imagecopy)
3802 {
3803 	zval *SIM, *DIM;
3804 	zend_long SX, SY, SW, SH, DX, DY;
3805 	gdImagePtr im_dst, im_src;
3806 	int srcH, srcW, srcY, srcX, dstY, dstX;
3807 
3808 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrllllll", &DIM, &SIM, &DX, &DY, &SX, &SY, &SW, &SH) == FAILURE) {
3809 		return;
3810 	}
3811 
3812 	if ((im_dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(DIM), "Image", le_gd)) == NULL) {
3813 		RETURN_FALSE;
3814 	}
3815 
3816 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
3817 		RETURN_FALSE;
3818 	}
3819 
3820 	srcX = SX;
3821 	srcY = SY;
3822 	srcH = SH;
3823 	srcW = SW;
3824 	dstX = DX;
3825 	dstY = DY;
3826 
3827 	gdImageCopy(im_dst, im_src, dstX, dstY, srcX, srcY, srcW, srcH);
3828 	RETURN_TRUE;
3829 }
3830 /* }}} */
3831 
3832 /* {{{ proto bool imagecopymerge(resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h, int pct)
3833    Merge one part of an image with another */
PHP_FUNCTION(imagecopymerge)3834 PHP_FUNCTION(imagecopymerge)
3835 {
3836 	zval *SIM, *DIM;
3837 	zend_long SX, SY, SW, SH, DX, DY, PCT;
3838 	gdImagePtr im_dst, im_src;
3839 	int srcH, srcW, srcY, srcX, dstY, dstX, pct;
3840 
3841 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrlllllll", &DIM, &SIM, &DX, &DY, &SX, &SY, &SW, &SH, &PCT) == FAILURE) {
3842 		return;
3843 	}
3844 
3845 	if ((im_dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(DIM), "Image", le_gd)) == NULL) {
3846 		RETURN_FALSE;
3847 	}
3848 
3849 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
3850 		RETURN_FALSE;
3851 	}
3852 
3853 	srcX = SX;
3854 	srcY = SY;
3855 	srcH = SH;
3856 	srcW = SW;
3857 	dstX = DX;
3858 	dstY = DY;
3859 	pct  = PCT;
3860 
3861 	gdImageCopyMerge(im_dst, im_src, dstX, dstY, srcX, srcY, srcW, srcH, pct);
3862 	RETURN_TRUE;
3863 }
3864 /* }}} */
3865 
3866 /* {{{ proto bool imagecopymergegray(resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h, int pct)
3867    Merge one part of an image with another */
PHP_FUNCTION(imagecopymergegray)3868 PHP_FUNCTION(imagecopymergegray)
3869 {
3870 	zval *SIM, *DIM;
3871 	zend_long SX, SY, SW, SH, DX, DY, PCT;
3872 	gdImagePtr im_dst, im_src;
3873 	int srcH, srcW, srcY, srcX, dstY, dstX, pct;
3874 
3875 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrlllllll", &DIM, &SIM, &DX, &DY, &SX, &SY, &SW, &SH, &PCT) == FAILURE) {
3876 		return;
3877 	}
3878 
3879 	if ((im_dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(DIM), "Image", le_gd)) == NULL) {
3880 		RETURN_FALSE;
3881 	}
3882 
3883 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
3884 		RETURN_FALSE;
3885 	}
3886 
3887 	srcX = SX;
3888 	srcY = SY;
3889 	srcH = SH;
3890 	srcW = SW;
3891 	dstX = DX;
3892 	dstY = DY;
3893 	pct  = PCT;
3894 
3895 	gdImageCopyMergeGray(im_dst, im_src, dstX, dstY, srcX, srcY, srcW, srcH, pct);
3896 	RETURN_TRUE;
3897 }
3898 /* }}} */
3899 
3900 /* {{{ proto bool imagecopyresized(resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h)
3901    Copy and resize part of an image */
PHP_FUNCTION(imagecopyresized)3902 PHP_FUNCTION(imagecopyresized)
3903 {
3904 	zval *SIM, *DIM;
3905 	zend_long SX, SY, SW, SH, DX, DY, DW, DH;
3906 	gdImagePtr im_dst, im_src;
3907 	int srcH, srcW, dstH, dstW, srcY, srcX, dstY, dstX;
3908 
3909 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrllllllll", &DIM, &SIM, &DX, &DY, &SX, &SY, &DW, &DH, &SW, &SH) == FAILURE) {
3910 		return;
3911 	}
3912 
3913 	if ((im_dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(DIM), "Image", le_gd)) == NULL) {
3914 		RETURN_FALSE;
3915 	}
3916 
3917 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
3918 		RETURN_FALSE;
3919 	}
3920 
3921 	srcX = SX;
3922 	srcY = SY;
3923 	srcH = SH;
3924 	srcW = SW;
3925 	dstX = DX;
3926 	dstY = DY;
3927 	dstH = DH;
3928 	dstW = DW;
3929 
3930 	if (dstW <= 0 || dstH <= 0 || srcW <= 0 || srcH <= 0) {
3931 		php_error_docref(NULL, E_WARNING, "Invalid image dimensions");
3932 		RETURN_FALSE;
3933 	}
3934 
3935 	gdImageCopyResized(im_dst, im_src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);
3936 	RETURN_TRUE;
3937 }
3938 /* }}} */
3939 
3940 /* {{{ proto int imagesx(resource im)
3941    Get image width */
PHP_FUNCTION(imagesx)3942 PHP_FUNCTION(imagesx)
3943 {
3944 	zval *IM;
3945 	gdImagePtr im;
3946 
3947 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE) {
3948 		return;
3949 	}
3950 
3951 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3952 		RETURN_FALSE;
3953 	}
3954 
3955 	RETURN_LONG(gdImageSX(im));
3956 }
3957 /* }}} */
3958 
3959 /* {{{ proto int imagesy(resource im)
3960    Get image height */
PHP_FUNCTION(imagesy)3961 PHP_FUNCTION(imagesy)
3962 {
3963 	zval *IM;
3964 	gdImagePtr im;
3965 
3966 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE) {
3967 		return;
3968 	}
3969 
3970 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3971 		RETURN_FALSE;
3972 	}
3973 
3974 	RETURN_LONG(gdImageSY(im));
3975 }
3976 /* }}} */
3977 
3978 /* {{{ proto bool imagesetclip(resource im, int x1, int y1, int x2, int y2)
3979    Set the clipping rectangle. */
PHP_FUNCTION(imagesetclip)3980 PHP_FUNCTION(imagesetclip)
3981 {
3982 	zval *im_zval;
3983 	gdImagePtr im;
3984 	zend_long x1, y1, x2, y2;
3985 
3986 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll", &im_zval, &x1, &y1, &x2, &y2) == FAILURE) {
3987 		return;
3988 	}
3989 
3990 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(im_zval), "Image", le_gd)) == NULL) {
3991 		RETURN_FALSE;
3992 	}
3993 
3994 	gdImageSetClip(im, x1, y1, x2, y2);
3995 	RETURN_TRUE;
3996 }
3997 /* }}} */
3998 
3999 /* {{{ proto array imagegetclip(resource im)
4000    Get the clipping rectangle. */
PHP_FUNCTION(imagegetclip)4001 PHP_FUNCTION(imagegetclip)
4002 {
4003 	zval *im_zval;
4004 	gdImagePtr im;
4005 	int x1, y1, x2, y2;
4006 
4007 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &im_zval) == FAILURE) {
4008 		return;
4009 	}
4010 
4011 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(im_zval), "Image", le_gd)) == NULL) {
4012 		RETURN_FALSE;
4013 	}
4014 
4015 	gdImageGetClip(im, &x1, &y1, &x2, &y2);
4016 
4017 	array_init(return_value);
4018 	add_next_index_long(return_value, x1);
4019 	add_next_index_long(return_value, y1);
4020 	add_next_index_long(return_value, x2);
4021 	add_next_index_long(return_value, y2);
4022 }
4023 /* }}} */
4024 
4025 #define TTFTEXT_DRAW 0
4026 #define TTFTEXT_BBOX 1
4027 
4028 #ifdef HAVE_GD_FREETYPE
4029 /* {{{ proto array imageftbbox(float size, float angle, string font_file, string text [, array extrainfo])
4030    Give the bounding box of a text using fonts via freetype2 */
PHP_FUNCTION(imageftbbox)4031 PHP_FUNCTION(imageftbbox)
4032 {
4033 	php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_BBOX, 1);
4034 }
4035 /* }}} */
4036 
4037 /* {{{ proto array imagefttext(resource im, float size, float angle, int x, int y, int col, string font_file, string text [, array extrainfo])
4038    Write text to the image using fonts via freetype2 */
PHP_FUNCTION(imagefttext)4039 PHP_FUNCTION(imagefttext)
4040 {
4041 	php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_DRAW, 1);
4042 }
4043 /* }}} */
4044 
4045 /* {{{ proto array imagettfbbox(float size, float angle, string font_file, string text)
4046    Give the bounding box of a text using TrueType fonts */
PHP_FUNCTION(imagettfbbox)4047 PHP_FUNCTION(imagettfbbox)
4048 {
4049 	php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_BBOX, 0);
4050 }
4051 /* }}} */
4052 
4053 /* {{{ proto array imagettftext(resource im, float size, float angle, int x, int y, int col, string font_file, string text)
4054    Write text to the image using a TrueType font */
PHP_FUNCTION(imagettftext)4055 PHP_FUNCTION(imagettftext)
4056 {
4057 	php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_DRAW, 0);
4058 }
4059 /* }}} */
4060 
4061 /* {{{ php_imagettftext_common
4062  */
php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS,int mode,int extended)4063 static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int extended)
4064 {
4065 	zval *IM, *EXT = NULL;
4066 	gdImagePtr im=NULL;
4067 	zend_long col = -1, x = 0, y = 0;
4068 	size_t str_len, fontname_len;
4069 	int i, brect[8];
4070 	double ptsize, angle;
4071 	char *str = NULL, *fontname = NULL;
4072 	char *error = NULL;
4073 	int argc = ZEND_NUM_ARGS();
4074 	gdFTStringExtra strex = {0};
4075 
4076 	if (mode == TTFTEXT_BBOX) {
4077 		if (argc < 4 || argc > ((extended) ? 5 : 4)) {
4078 			ZEND_WRONG_PARAM_COUNT();
4079 		} else if (zend_parse_parameters(argc, "ddss|a", &ptsize, &angle, &fontname, &fontname_len, &str, &str_len, &EXT) == FAILURE) {
4080 			RETURN_FALSE;
4081 		}
4082 	} else {
4083 		if (argc < 8 || argc > ((extended) ? 9 : 8)) {
4084 			ZEND_WRONG_PARAM_COUNT();
4085 		} else if (zend_parse_parameters(argc, "rddlllss|a", &IM, &ptsize, &angle, &x, &y, &col, &fontname, &fontname_len, &str, &str_len, &EXT) == FAILURE) {
4086 			RETURN_FALSE;
4087 		}
4088 		if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4089 			RETURN_FALSE;
4090 		}
4091 	}
4092 
4093 	/* convert angle to radians */
4094 	angle = angle * (M_PI/180);
4095 
4096 	if (extended && EXT) {	/* parse extended info */
4097 		zval *item;
4098 		zend_string *key;
4099 
4100 		/* walk the assoc array */
4101 		ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(EXT), key, item) {
4102 			if (key == NULL) {
4103 				continue;
4104 			}
4105 			if (strcmp("linespacing", ZSTR_VAL(key)) == 0) {
4106 				strex.flags |= gdFTEX_LINESPACE;
4107 				strex.linespacing = zval_get_double(item);
4108 			}
4109 		} ZEND_HASH_FOREACH_END();
4110 	}
4111 
4112 #ifdef VIRTUAL_DIR
4113 	{
4114 		char tmp_font_path[MAXPATHLEN];
4115 
4116 		if (!VCWD_REALPATH(fontname, tmp_font_path)) {
4117 			fontname = NULL;
4118 		}
4119 	}
4120 #endif /* VIRTUAL_DIR */
4121 
4122 	PHP_GD_CHECK_OPEN_BASEDIR(fontname, "Invalid font filename");
4123 
4124 	if (extended) {
4125 		error = gdImageStringFTEx(im, brect, col, fontname, ptsize, angle, x, y, str, &strex);
4126 	} else {
4127 		error = gdImageStringFT(im, brect, col, fontname, ptsize, angle, x, y, str);
4128 	}
4129 
4130 	if (error) {
4131 		php_error_docref(NULL, E_WARNING, "%s", error);
4132 		RETURN_FALSE;
4133 	}
4134 
4135 	array_init(return_value);
4136 
4137 	/* return array with the text's bounding box */
4138 	for (i = 0; i < 8; i++) {
4139 		add_next_index_long(return_value, brect[i]);
4140 	}
4141 }
4142 /* }}} */
4143 #endif /* HAVE_GD_FREETYPE */
4144 
4145 /* {{{ proto bool image2wbmp(resource im [, string filename [, int foreground]])
4146    Output WBMP image to browser or file */
PHP_FUNCTION(image2wbmp)4147 PHP_FUNCTION(image2wbmp)
4148 {
4149 	_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_CONVERT_WBM, "WBMP", NULL);
4150 }
4151 /* }}} */
4152 
4153 #if defined(HAVE_GD_JPG)
4154 /* {{{ proto bool jpeg2wbmp(string f_org, string f_dest, int d_height, int d_width, int threshold)
4155    Convert JPEG image to WBMP image */
PHP_FUNCTION(jpeg2wbmp)4156 PHP_FUNCTION(jpeg2wbmp)
4157 {
4158 	_php_image_convert(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG);
4159 }
4160 /* }}} */
4161 #endif
4162 
4163 #if defined(HAVE_GD_PNG)
4164 /* {{{ proto bool png2wbmp(string f_org, string f_dest, int d_height, int d_width, int threshold)
4165    Convert PNG image to WBMP image */
PHP_FUNCTION(png2wbmp)4166 PHP_FUNCTION(png2wbmp)
4167 {
4168 	_php_image_convert(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG);
4169 }
4170 /* }}} */
4171 #endif
4172 
4173 /* {{{ _php_image_convert
4174  * _php_image_convert converts jpeg/png images to wbmp and resizes them as needed  */
_php_image_convert(INTERNAL_FUNCTION_PARAMETERS,int image_type)4175 static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type )
4176 {
4177 	char *f_org, *f_dest;
4178 	size_t f_org_len, f_dest_len;
4179 	zend_long height, width, threshold;
4180 	gdImagePtr im_org, im_dest, im_tmp;
4181 	char *fn_org = NULL;
4182 	char *fn_dest = NULL;
4183 	FILE *org, *dest;
4184 	int dest_height = -1;
4185 	int dest_width = -1;
4186 	int org_height, org_width;
4187 	int white, black;
4188 	int color, color_org, median;
4189 	int int_threshold;
4190 	int x, y;
4191 	float x_ratio, y_ratio;
4192 #ifdef HAVE_GD_JPG
4193     zend_long ignore_warning;
4194 #endif
4195 
4196 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "pplll", &f_org, &f_org_len, &f_dest, &f_dest_len, &height, &width, &threshold) == FAILURE) {
4197 		return;
4198 	}
4199 
4200 	fn_org  = f_org;
4201 	fn_dest = f_dest;
4202 	dest_height = height;
4203 	dest_width = width;
4204 	int_threshold = threshold;
4205 
4206 	/* Check threshold value */
4207 	if (int_threshold < 0 || int_threshold > 8) {
4208 		php_error_docref(NULL, E_WARNING, "Invalid threshold value '%d'", int_threshold);
4209 		RETURN_FALSE;
4210 	}
4211 
4212 	/* Check origin file */
4213 	PHP_GD_CHECK_OPEN_BASEDIR(fn_org, "Invalid origin filename");
4214 
4215 	/* Check destination file */
4216 	PHP_GD_CHECK_OPEN_BASEDIR(fn_dest, "Invalid destination filename");
4217 
4218 	/* Open origin file */
4219 	org = VCWD_FOPEN(fn_org, "rb");
4220 	if (!org) {
4221 		php_error_docref(NULL, E_WARNING, "Unable to open '%s' for reading", fn_org);
4222 		RETURN_FALSE;
4223 	}
4224 
4225 	/* Open destination file */
4226 	dest = VCWD_FOPEN(fn_dest, "wb");
4227 	if (!dest) {
4228 		php_error_docref(NULL, E_WARNING, "Unable to open '%s' for writing", fn_dest);
4229         fclose(org);
4230 		RETURN_FALSE;
4231 	}
4232 
4233 	switch (image_type) {
4234 
4235 #ifdef HAVE_GD_JPG
4236 		case PHP_GDIMG_TYPE_JPG:
4237 			ignore_warning = INI_INT("gd.jpeg_ignore_warning");
4238 			im_org = gdImageCreateFromJpegEx(org, ignore_warning);
4239 			if (im_org == NULL) {
4240 				php_error_docref(NULL, E_WARNING, "Unable to open '%s' Not a valid JPEG file", fn_dest);
4241                 fclose(org);
4242                 fclose(dest);
4243 				RETURN_FALSE;
4244 			}
4245 			break;
4246 #endif /* HAVE_GD_JPG */
4247 
4248 #ifdef HAVE_GD_PNG
4249 		case PHP_GDIMG_TYPE_PNG:
4250 			im_org = gdImageCreateFromPng(org);
4251 			if (im_org == NULL) {
4252 				php_error_docref(NULL, E_WARNING, "Unable to open '%s' Not a valid PNG file", fn_dest);
4253                 fclose(org);
4254                 fclose(dest);
4255 				RETURN_FALSE;
4256 			}
4257 			break;
4258 #endif /* HAVE_GD_PNG */
4259 
4260 		default:
4261 			php_error_docref(NULL, E_WARNING, "Format not supported");
4262             fclose(org);
4263             fclose(dest);
4264 			RETURN_FALSE;
4265 			break;
4266 	}
4267 
4268 	fclose(org);
4269 
4270 	org_width  = gdImageSX (im_org);
4271 	org_height = gdImageSY (im_org);
4272 
4273 	x_ratio = (float) org_width / (float) dest_width;
4274 	y_ratio = (float) org_height / (float) dest_height;
4275 
4276 	if (x_ratio > 1 && y_ratio > 1) {
4277 		if (y_ratio > x_ratio) {
4278 			x_ratio = y_ratio;
4279 		} else {
4280 			y_ratio = x_ratio;
4281 		}
4282 		dest_width = (int) (org_width / x_ratio);
4283 		dest_height = (int) (org_height / y_ratio);
4284 	} else {
4285 		x_ratio = (float) dest_width / (float) org_width;
4286 		y_ratio = (float) dest_height / (float) org_height;
4287 
4288 		if (y_ratio < x_ratio) {
4289 			x_ratio = y_ratio;
4290 		} else {
4291 			y_ratio = x_ratio;
4292 		}
4293 		dest_width = (int) (org_width * x_ratio);
4294 		dest_height = (int) (org_height * y_ratio);
4295 	}
4296 
4297 	im_tmp = gdImageCreate (dest_width, dest_height);
4298 	if (im_tmp == NULL ) {
4299 		php_error_docref(NULL, E_WARNING, "Unable to allocate temporary buffer");
4300         fclose(dest);
4301         gdImageDestroy(im_org);
4302 		RETURN_FALSE;
4303 	}
4304 
4305 	gdImageCopyResized (im_tmp, im_org, 0, 0, 0, 0, dest_width, dest_height, org_width, org_height);
4306 
4307 	gdImageDestroy(im_org);
4308 
4309 	im_dest = gdImageCreate(dest_width, dest_height);
4310 	if (im_dest == NULL) {
4311 		php_error_docref(NULL, E_WARNING, "Unable to allocate destination buffer");
4312         fclose(dest);
4313         gdImageDestroy(im_tmp);
4314 		RETURN_FALSE;
4315 	}
4316 
4317 	white = gdImageColorAllocate(im_dest, 255, 255, 255);
4318 	if (white == -1) {
4319 		php_error_docref(NULL, E_WARNING, "Unable to allocate the colors for the destination buffer");
4320         fclose(dest);
4321         gdImageDestroy(im_tmp);
4322         gdImageDestroy(im_dest);
4323 		RETURN_FALSE;
4324 	}
4325 
4326 	black = gdImageColorAllocate(im_dest, 0, 0, 0);
4327 	if (black == -1) {
4328 		php_error_docref(NULL, E_WARNING, "Unable to allocate the colors for the destination buffer");
4329         fclose(dest);
4330         gdImageDestroy(im_tmp);
4331         gdImageDestroy(im_dest);
4332 		RETURN_FALSE;
4333 	}
4334 
4335 	int_threshold = int_threshold * 32;
4336 
4337 	for (y = 0; y < dest_height; y++) {
4338 		for (x = 0; x < dest_width; x++) {
4339 			color_org = gdImageGetPixel (im_tmp, x, y);
4340 			median = (im_tmp->red[color_org] + im_tmp->green[color_org] + im_tmp->blue[color_org]) / 3;
4341 			if (median < int_threshold) {
4342 				color = black;
4343 			} else {
4344 				color = white;
4345 			}
4346 			gdImageSetPixel (im_dest, x, y, color);
4347 		}
4348 	}
4349 
4350 	gdImageDestroy (im_tmp );
4351 
4352 	gdImageWBMP(im_dest, black , dest);
4353 
4354 	fflush(dest);
4355 	fclose(dest);
4356 
4357 	gdImageDestroy(im_dest);
4358 
4359 	RETURN_TRUE;
4360 }
4361 /* }}} */
4362 
4363 /* Section Filters */
4364 #define PHP_GD_SINGLE_RES	\
4365 	zval *SIM;	\
4366 	gdImagePtr im_src;	\
4367 	if (zend_parse_parameters(1, "r", &SIM) == FAILURE) {	\
4368 		RETURN_FALSE;	\
4369 	}	\
4370 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {	\
4371 		RETURN_FALSE;	\
4372 	}
4373 
php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS)4374 static void php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS)
4375 {
4376 	PHP_GD_SINGLE_RES
4377 
4378 	if (gdImageNegate(im_src) == 1) {
4379 		RETURN_TRUE;
4380 	}
4381 
4382 	RETURN_FALSE;
4383 }
4384 
php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS)4385 static void php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS)
4386 {
4387 	PHP_GD_SINGLE_RES
4388 
4389 	if (gdImageGrayScale(im_src) == 1) {
4390 		RETURN_TRUE;
4391 	}
4392 
4393 	RETURN_FALSE;
4394 }
4395 
php_image_filter_brightness(INTERNAL_FUNCTION_PARAMETERS)4396 static void php_image_filter_brightness(INTERNAL_FUNCTION_PARAMETERS)
4397 {
4398 	zval *SIM;
4399 	gdImagePtr im_src;
4400 	zend_long brightness, tmp;
4401 
4402 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "zll", &SIM, &tmp, &brightness) == FAILURE) {
4403 		RETURN_FALSE;
4404 	}
4405 
4406 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
4407 		RETURN_FALSE;
4408 	}
4409 
4410 	if (gdImageBrightness(im_src, (int)brightness) == 1) {
4411 		RETURN_TRUE;
4412 	}
4413 
4414 	RETURN_FALSE;
4415 }
4416 
php_image_filter_contrast(INTERNAL_FUNCTION_PARAMETERS)4417 static void php_image_filter_contrast(INTERNAL_FUNCTION_PARAMETERS)
4418 {
4419 	zval *SIM;
4420 	gdImagePtr im_src;
4421 	zend_long contrast, tmp;
4422 
4423 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rll", &SIM, &tmp, &contrast) == FAILURE) {
4424 		RETURN_FALSE;
4425 	}
4426 
4427 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
4428 		RETURN_FALSE;
4429 	}
4430 
4431 	if (gdImageContrast(im_src, (int)contrast) == 1) {
4432 		RETURN_TRUE;
4433 	}
4434 
4435 	RETURN_FALSE;
4436 }
4437 
php_image_filter_colorize(INTERNAL_FUNCTION_PARAMETERS)4438 static void php_image_filter_colorize(INTERNAL_FUNCTION_PARAMETERS)
4439 {
4440 	zval *SIM;
4441 	gdImagePtr im_src;
4442 	zend_long r,g,b,tmp;
4443 	zend_long a = 0;
4444 
4445 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll|l", &SIM, &tmp, &r, &g, &b, &a) == FAILURE) {
4446 		RETURN_FALSE;
4447 	}
4448 
4449 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
4450 		RETURN_FALSE;
4451 	}
4452 
4453 	if (gdImageColor(im_src, (int) r, (int) g, (int) b, (int) a) == 1) {
4454 		RETURN_TRUE;
4455 	}
4456 
4457 	RETURN_FALSE;
4458 }
4459 
php_image_filter_edgedetect(INTERNAL_FUNCTION_PARAMETERS)4460 static void php_image_filter_edgedetect(INTERNAL_FUNCTION_PARAMETERS)
4461 {
4462 	PHP_GD_SINGLE_RES
4463 
4464 	if (gdImageEdgeDetectQuick(im_src) == 1) {
4465 		RETURN_TRUE;
4466 	}
4467 
4468 	RETURN_FALSE;
4469 }
4470 
php_image_filter_emboss(INTERNAL_FUNCTION_PARAMETERS)4471 static void php_image_filter_emboss(INTERNAL_FUNCTION_PARAMETERS)
4472 {
4473 	PHP_GD_SINGLE_RES
4474 
4475 	if (gdImageEmboss(im_src) == 1) {
4476 		RETURN_TRUE;
4477 	}
4478 
4479 	RETURN_FALSE;
4480 }
4481 
php_image_filter_gaussian_blur(INTERNAL_FUNCTION_PARAMETERS)4482 static void php_image_filter_gaussian_blur(INTERNAL_FUNCTION_PARAMETERS)
4483 {
4484 	PHP_GD_SINGLE_RES
4485 
4486 	if (gdImageGaussianBlur(im_src) == 1) {
4487 		RETURN_TRUE;
4488 	}
4489 
4490 	RETURN_FALSE;
4491 }
4492 
php_image_filter_selective_blur(INTERNAL_FUNCTION_PARAMETERS)4493 static void php_image_filter_selective_blur(INTERNAL_FUNCTION_PARAMETERS)
4494 {
4495 	PHP_GD_SINGLE_RES
4496 
4497 	if (gdImageSelectiveBlur(im_src) == 1) {
4498 		RETURN_TRUE;
4499 	}
4500 
4501 	RETURN_FALSE;
4502 }
4503 
php_image_filter_mean_removal(INTERNAL_FUNCTION_PARAMETERS)4504 static void php_image_filter_mean_removal(INTERNAL_FUNCTION_PARAMETERS)
4505 {
4506 	PHP_GD_SINGLE_RES
4507 
4508 	if (gdImageMeanRemoval(im_src) == 1) {
4509 		RETURN_TRUE;
4510 	}
4511 
4512 	RETURN_FALSE;
4513 }
4514 
php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS)4515 static void php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS)
4516 {
4517 	zval *SIM;
4518 	zend_long tmp;
4519 	gdImagePtr im_src;
4520 	double weight;
4521 
4522 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rld", &SIM, &tmp, &weight) == FAILURE) {
4523 		RETURN_FALSE;
4524 	}
4525 
4526 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
4527 		RETURN_FALSE;
4528 	}
4529 
4530 	if (gdImageSmooth(im_src, (float)weight)==1) {
4531 		RETURN_TRUE;
4532 	}
4533 
4534 	RETURN_FALSE;
4535 }
4536 
php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS)4537 static void php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS)
4538 {
4539 	zval *IM;
4540 	gdImagePtr im;
4541 	zend_long tmp, blocksize;
4542 	zend_bool mode = 0;
4543 
4544 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rll|b", &IM, &tmp, &blocksize, &mode) == FAILURE) {
4545 		RETURN_FALSE;
4546 	}
4547 
4548 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4549 		RETURN_FALSE;
4550 	}
4551 
4552 	if (gdImagePixelate(im, (int) blocksize, (const unsigned int) mode)) {
4553 		RETURN_TRUE;
4554 	}
4555 
4556 	RETURN_FALSE;
4557 }
4558 
php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS)4559 static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS)
4560 {
4561 	zval *IM;
4562 	zval *hash_colors = NULL;
4563 	gdImagePtr im;
4564 	zend_long tmp;
4565 	zend_long scatter_sub, scatter_plus;
4566 
4567 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll|a", &IM, &tmp, &scatter_sub, &scatter_plus, &hash_colors) == FAILURE) {
4568 		RETURN_FALSE;
4569 	}
4570 
4571 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4572 		RETURN_FALSE;
4573 	}
4574 
4575 	if (hash_colors) {
4576 		uint32_t i = 0;
4577 		uint32_t num_colors = zend_hash_num_elements(Z_ARRVAL_P(hash_colors));
4578 		zval *color;
4579 		int *colors;
4580 
4581 		if (num_colors == 0) {
4582 			RETURN_BOOL(gdImageScatter(im, (int)scatter_sub, (int)scatter_plus));
4583 		}
4584 
4585 		colors = emalloc(num_colors * sizeof(int));
4586 
4587 		ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(hash_colors), color) {
4588 			*(colors + i++) = (int) zval_get_long(color);
4589 		} ZEND_HASH_FOREACH_END();
4590 
4591 		RETVAL_BOOL(gdImageScatterColor(im, (int)scatter_sub, (int)scatter_plus, colors, num_colors));
4592 
4593 		efree(colors);
4594 	} else {
4595 		RETURN_BOOL(gdImageScatter(im, (int) scatter_sub, (int) scatter_plus))
4596 	}
4597 }
4598 
4599 /* {{{ proto bool imagefilter(resource src_im, int filtertype[, int arg1 [, int arg2 [, int arg3 [, int arg4 ]]]] )
4600    Applies Filter an image using a custom angle */
PHP_FUNCTION(imagefilter)4601 PHP_FUNCTION(imagefilter)
4602 {
4603 	zval *tmp;
4604 
4605 	typedef void (*image_filter)(INTERNAL_FUNCTION_PARAMETERS);
4606 	zend_long filtertype;
4607 	image_filter filters[] =
4608 	{
4609 		php_image_filter_negate ,
4610 		php_image_filter_grayscale,
4611 		php_image_filter_brightness,
4612 		php_image_filter_contrast,
4613 		php_image_filter_colorize,
4614 		php_image_filter_edgedetect,
4615 		php_image_filter_emboss,
4616 		php_image_filter_gaussian_blur,
4617 		php_image_filter_selective_blur,
4618 		php_image_filter_mean_removal,
4619 		php_image_filter_smooth,
4620 		php_image_filter_pixelate,
4621 		php_image_filter_scatter
4622 	};
4623 
4624 	if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > IMAGE_FILTER_MAX_ARGS) {
4625 		WRONG_PARAM_COUNT;
4626 	} else if (zend_parse_parameters(2, "rl", &tmp, &filtertype) == FAILURE) {
4627 		return;
4628 	}
4629 
4630 	if (filtertype >= 0 && filtertype <= IMAGE_FILTER_MAX) {
4631 		filters[filtertype](INTERNAL_FUNCTION_PARAM_PASSTHRU);
4632 	}
4633 }
4634 /* }}} */
4635 
4636 /* {{{ proto resource imageconvolution(resource src_im, array matrix3x3, double div, double offset)
4637    Apply a 3x3 convolution matrix, using coefficient div and offset */
PHP_FUNCTION(imageconvolution)4638 PHP_FUNCTION(imageconvolution)
4639 {
4640 	zval *SIM, *hash_matrix;
4641 	zval *var = NULL, *var2 = NULL;
4642 	gdImagePtr im_src = NULL;
4643 	double div, offset;
4644 	int nelem, i, j, res;
4645 	float matrix[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}};
4646 
4647 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "radd", &SIM, &hash_matrix, &div, &offset) == FAILURE) {
4648 		RETURN_FALSE;
4649 	}
4650 
4651 	if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
4652 		RETURN_FALSE;
4653 	}
4654 
4655 	nelem = zend_hash_num_elements(Z_ARRVAL_P(hash_matrix));
4656 	if (nelem != 3) {
4657 		php_error_docref(NULL, E_WARNING, "You must have 3x3 array");
4658 		RETURN_FALSE;
4659 	}
4660 
4661 	for (i=0; i<3; i++) {
4662 		if ((var = zend_hash_index_find(Z_ARRVAL_P(hash_matrix), (i))) != NULL && Z_TYPE_P(var) == IS_ARRAY) {
4663 			if (zend_hash_num_elements(Z_ARRVAL_P(var)) != 3 ) {
4664 				php_error_docref(NULL, E_WARNING, "You must have 3x3 array");
4665 				RETURN_FALSE;
4666 			}
4667 
4668 			for (j=0; j<3; j++) {
4669 				if ((var2 = zend_hash_index_find(Z_ARRVAL_P(var), j)) != NULL) {
4670 					matrix[i][j] = (float) zval_get_double(var2);
4671 				} else {
4672 					php_error_docref(NULL, E_WARNING, "You must have a 3x3 matrix");
4673 					RETURN_FALSE;
4674 				}
4675 			}
4676 		}
4677 	}
4678 	res = gdImageConvolution(im_src, matrix, (float)div, (float)offset);
4679 
4680 	if (res) {
4681 		RETURN_TRUE;
4682 	} else {
4683 		RETURN_FALSE;
4684 	}
4685 }
4686 /* }}} */
4687 /* End section: Filters */
4688 
4689 /* {{{ proto bool imageflip(resource im, int mode)
4690    Flip an image (in place) horizontally, vertically or both directions. */
PHP_FUNCTION(imageflip)4691 PHP_FUNCTION(imageflip)
4692 {
4693 	zval *IM;
4694 	zend_long mode;
4695 	gdImagePtr im;
4696 
4697 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &IM, &mode) == FAILURE)  {
4698 		return;
4699 	}
4700 
4701 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4702 		RETURN_FALSE;
4703 	}
4704 
4705 	switch (mode) {
4706 		case GD_FLIP_VERTICAL:
4707 			gdImageFlipVertical(im);
4708 			break;
4709 
4710 		case GD_FLIP_HORINZONTAL:
4711 			gdImageFlipHorizontal(im);
4712 			break;
4713 
4714 		case GD_FLIP_BOTH:
4715 			gdImageFlipBoth(im);
4716 			break;
4717 
4718 		default:
4719 			php_error_docref(NULL, E_WARNING, "Unknown flip mode");
4720 			RETURN_FALSE;
4721 	}
4722 
4723 	RETURN_TRUE;
4724 }
4725 /* }}} */
4726 
4727 /* {{{ proto bool imageantialias(resource im, bool on)
4728    Should antialiased functions used or not*/
PHP_FUNCTION(imageantialias)4729 PHP_FUNCTION(imageantialias)
4730 {
4731 	zval *IM;
4732 	zend_bool alias;
4733 	gdImagePtr im;
4734 
4735 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rb", &IM, &alias) == FAILURE) {
4736 		return;
4737 	}
4738 
4739 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4740 		RETURN_FALSE;
4741 	}
4742 
4743 	if (im->trueColor) {
4744 		im->AA = alias;
4745 	}
4746 
4747 	RETURN_TRUE;
4748 }
4749 /* }}} */
4750 
4751 /* {{{ proto resource imagecrop(resource im, array rect)
4752    Crop an image using the given coordinates and size, x, y, width and height. */
PHP_FUNCTION(imagecrop)4753 PHP_FUNCTION(imagecrop)
4754 {
4755 	zval *IM;
4756 	gdImagePtr im;
4757 	gdImagePtr im_crop;
4758 	gdRect rect;
4759 	zval *z_rect;
4760 	zval *tmp;
4761 
4762 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra", &IM, &z_rect) == FAILURE)  {
4763 		return;
4764 	}
4765 
4766 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4767 		RETURN_FALSE;
4768 	}
4769 
4770 	if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "x", sizeof("x") -1)) != NULL) {
4771 		rect.x = zval_get_long(tmp);
4772 	} else {
4773 		php_error_docref(NULL, E_WARNING, "Missing x position");
4774 		RETURN_FALSE;
4775 	}
4776 
4777 	if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "y", sizeof("y") - 1)) != NULL) {
4778 		rect.y = zval_get_long(tmp);
4779 	} else {
4780 		php_error_docref(NULL, E_WARNING, "Missing y position");
4781 		RETURN_FALSE;
4782 	}
4783 
4784 	if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "width", sizeof("width") - 1)) != NULL) {
4785 		rect.width = zval_get_long(tmp);
4786 	} else {
4787 		php_error_docref(NULL, E_WARNING, "Missing width");
4788 		RETURN_FALSE;
4789 	}
4790 
4791 	if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "height", sizeof("height") - 1)) != NULL) {
4792 		rect.height = zval_get_long(tmp);
4793 	} else {
4794 		php_error_docref(NULL, E_WARNING, "Missing height");
4795 		RETURN_FALSE;
4796 	}
4797 
4798 	im_crop = gdImageCrop(im, &rect);
4799 
4800 	if (im_crop == NULL) {
4801 		RETURN_FALSE;
4802 	} else {
4803 		RETURN_RES(zend_register_resource(im_crop, le_gd));
4804 	}
4805 }
4806 /* }}} */
4807 
4808 /* {{{ proto resource imagecropauto(resource im [, int mode = GD_CROP_DEFAULT [, float threshold [, int color]]])
4809    Crop an image automatically using one of the available modes. */
PHP_FUNCTION(imagecropauto)4810 PHP_FUNCTION(imagecropauto)
4811 {
4812 	zval *IM;
4813 	zend_long mode = GD_CROP_DEFAULT;
4814 	zend_long color = -1;
4815 	double threshold = 0.5f;
4816 	gdImagePtr im;
4817 	gdImagePtr im_crop;
4818 
4819 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|ldl", &IM, &mode, &threshold, &color) == FAILURE)  {
4820 		return;
4821 	}
4822 
4823 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4824 		RETURN_FALSE;
4825 	}
4826 
4827 	switch (mode) {
4828 		case -1:
4829 			php_error_docref(NULL, E_DEPRECATED, "Crop mode -1 is deprecated. Use IMG_CROP_DEFAULT instead.");
4830 			mode = GD_CROP_DEFAULT;
4831 			/* FALLTHRU */
4832 		case GD_CROP_DEFAULT:
4833 		case GD_CROP_TRANSPARENT:
4834 		case GD_CROP_BLACK:
4835 		case GD_CROP_WHITE:
4836 		case GD_CROP_SIDES:
4837 			im_crop = gdImageCropAuto(im, mode);
4838 			break;
4839 
4840 		case GD_CROP_THRESHOLD:
4841 			if (color < 0 || (!gdImageTrueColor(im) && color >= gdImageColorsTotal(im))) {
4842 				php_error_docref(NULL, E_WARNING, "Color argument missing with threshold mode");
4843 				RETURN_FALSE;
4844 			}
4845 			im_crop = gdImageCropThreshold(im, color, (float) threshold);
4846 			break;
4847 
4848 		default:
4849 			php_error_docref(NULL, E_WARNING, "Unknown crop mode");
4850 			RETURN_FALSE;
4851 	}
4852 	if (im_crop == NULL) {
4853 		RETURN_FALSE;
4854 	} else {
4855 		RETURN_RES(zend_register_resource(im_crop, le_gd));
4856 	}
4857 }
4858 /* }}} */
4859 
4860 /* {{{ proto resource imagescale(resource im, int new_width[, int new_height[, int method]])
4861    Scale an image using the given new width and height. */
PHP_FUNCTION(imagescale)4862 PHP_FUNCTION(imagescale)
4863 {
4864 	zval *IM;
4865 	gdImagePtr im;
4866 	gdImagePtr im_scaled = NULL;
4867 	int new_width, new_height;
4868 	zend_long tmp_w, tmp_h=-1, tmp_m = GD_BILINEAR_FIXED;
4869 	gdInterpolationMethod method, old_method;
4870 
4871 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|ll", &IM, &tmp_w, &tmp_h, &tmp_m) == FAILURE)  {
4872 		return;
4873 	}
4874 	method = tmp_m;
4875 
4876 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4877 		RETURN_FALSE;
4878 	}
4879 
4880 	if (tmp_h < 0 || tmp_w < 0) {
4881 		/* preserve ratio */
4882 		long src_x, src_y;
4883 
4884 		src_x = gdImageSX(im);
4885 		src_y = gdImageSY(im);
4886 
4887 		if (src_x && tmp_h < 0) {
4888 			tmp_h = tmp_w * src_y / src_x;
4889 		}
4890 		if (src_y && tmp_w < 0) {
4891 			tmp_w = tmp_h * src_x / src_y;
4892 		}
4893 	}
4894 
4895 	if (tmp_h <= 0 || tmp_h > INT_MAX || tmp_w <= 0 || tmp_w > INT_MAX) {
4896 		RETURN_FALSE;
4897 	}
4898 
4899 	new_width = tmp_w;
4900 	new_height = tmp_h;
4901 
4902 	/* gdImageGetInterpolationMethod() is only available as of GD 2.1.1 */
4903 	old_method = im->interpolation_id;
4904 	if (gdImageSetInterpolationMethod(im, method)) {
4905 		im_scaled = gdImageScale(im, new_width, new_height);
4906 	}
4907 	gdImageSetInterpolationMethod(im, old_method);
4908 
4909 	if (im_scaled == NULL) {
4910 		RETURN_FALSE;
4911 	} else {
4912 		RETURN_RES(zend_register_resource(im_scaled, le_gd));
4913 	}
4914 }
4915 /* }}} */
4916 
4917 /* {{{ proto resource imageaffine(resource src, array affine[, array clip])
4918    Return an image containing the affine tramsformed src image, using an optional clipping area */
PHP_FUNCTION(imageaffine)4919 PHP_FUNCTION(imageaffine)
4920 {
4921 	zval *IM;
4922 	gdImagePtr src;
4923 	gdImagePtr dst;
4924 	gdRect rect;
4925 	gdRectPtr pRect = NULL;
4926 	zval *z_rect = NULL;
4927 	zval *z_affine;
4928 	zval *tmp;
4929 	double affine[6];
4930 	int i, nelems;
4931 	zval *zval_affine_elem = NULL;
4932 
4933 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra|a", &IM, &z_affine, &z_rect) == FAILURE)  {
4934 		return;
4935 	}
4936 
4937 	if ((src = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4938 		RETURN_FALSE;
4939 	}
4940 
4941 	if ((nelems = zend_hash_num_elements(Z_ARRVAL_P(z_affine))) != 6) {
4942 		php_error_docref(NULL, E_WARNING, "Affine array must have six elements");
4943 		RETURN_FALSE;
4944 	}
4945 
4946 	for (i = 0; i < nelems; i++) {
4947 		if ((zval_affine_elem = zend_hash_index_find(Z_ARRVAL_P(z_affine), i)) != NULL) {
4948 			switch (Z_TYPE_P(zval_affine_elem)) {
4949 				case IS_LONG:
4950 					affine[i]  = Z_LVAL_P(zval_affine_elem);
4951 					break;
4952 				case IS_DOUBLE:
4953 					affine[i] = Z_DVAL_P(zval_affine_elem);
4954 					break;
4955 				case IS_STRING:
4956 					affine[i] = zval_get_double(zval_affine_elem);
4957 					break;
4958 				default:
4959 					php_error_docref(NULL, E_WARNING, "Invalid type for element %i", i);
4960 					RETURN_FALSE;
4961 			}
4962 		}
4963 	}
4964 
4965 	if (z_rect != NULL) {
4966 		if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "x", sizeof("x") - 1)) != NULL) {
4967 			rect.x = zval_get_long(tmp);
4968 		} else {
4969 			php_error_docref(NULL, E_WARNING, "Missing x position");
4970 			RETURN_FALSE;
4971 		}
4972 
4973 		if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "y", sizeof("y") - 1)) != NULL) {
4974 			rect.y = zval_get_long(tmp);
4975 		} else {
4976 			php_error_docref(NULL, E_WARNING, "Missing y position");
4977 			RETURN_FALSE;
4978 		}
4979 
4980 		if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "width", sizeof("width") - 1)) != NULL) {
4981 			rect.width = zval_get_long(tmp);
4982 		} else {
4983 			php_error_docref(NULL, E_WARNING, "Missing width");
4984 			RETURN_FALSE;
4985 		}
4986 
4987 		if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "height", sizeof("height") - 1)) != NULL) {
4988 			rect.height = zval_get_long(tmp);
4989 		} else {
4990 			php_error_docref(NULL, E_WARNING, "Missing height");
4991 			RETURN_FALSE;
4992 		}
4993 		pRect = &rect;
4994 	} else {
4995 		rect.x = -1;
4996 		rect.y = -1;
4997 		rect.width = gdImageSX(src);
4998 		rect.height = gdImageSY(src);
4999 		pRect = NULL;
5000 	}
5001 
5002 	if (gdTransformAffineGetImage(&dst, src, pRect, affine) != GD_TRUE) {
5003 		RETURN_FALSE;
5004 	}
5005 
5006 	if (dst == NULL) {
5007 		RETURN_FALSE;
5008 	} else {
5009 		RETURN_RES(zend_register_resource(dst, le_gd));
5010 	}
5011 }
5012 /* }}} */
5013 
5014 /* {{{ proto array imageaffinematrixget(int type[, array options])
5015    Return an image containing the affine tramsformed src image, using an optional clipping area */
PHP_FUNCTION(imageaffinematrixget)5016 PHP_FUNCTION(imageaffinematrixget)
5017 {
5018 	double affine[6];
5019 	zend_long type;
5020 	zval *options = NULL;
5021 	zval *tmp;
5022 	int res = GD_FALSE, i;
5023 
5024 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|z", &type, &options) == FAILURE)  {
5025 		return;
5026 	}
5027 
5028 	switch((gdAffineStandardMatrix)type) {
5029 		case GD_AFFINE_TRANSLATE:
5030 		case GD_AFFINE_SCALE: {
5031 			double x, y;
5032 			if (!options || Z_TYPE_P(options) != IS_ARRAY) {
5033 				php_error_docref(NULL, E_WARNING, "Array expected as options");
5034 				RETURN_FALSE;
5035 			}
5036 			if ((tmp = zend_hash_str_find(Z_ARRVAL_P(options), "x", sizeof("x") - 1)) != NULL) {
5037 				x = zval_get_double(tmp);
5038 			} else {
5039 				php_error_docref(NULL, E_WARNING, "Missing x position");
5040 				RETURN_FALSE;
5041 			}
5042 
5043 			if ((tmp = zend_hash_str_find(Z_ARRVAL_P(options), "y", sizeof("y") - 1)) != NULL) {
5044 				y = zval_get_double(tmp);
5045 			} else {
5046 				php_error_docref(NULL, E_WARNING, "Missing y position");
5047 				RETURN_FALSE;
5048 			}
5049 
5050 			if (type == GD_AFFINE_TRANSLATE) {
5051 				res = gdAffineTranslate(affine, x, y);
5052 			} else {
5053 				res = gdAffineScale(affine, x, y);
5054 			}
5055 			break;
5056 		}
5057 
5058 		case GD_AFFINE_ROTATE:
5059 		case GD_AFFINE_SHEAR_HORIZONTAL:
5060 		case GD_AFFINE_SHEAR_VERTICAL: {
5061 			double angle;
5062 
5063 			if (!options) {
5064 				php_error_docref(NULL, E_WARNING, "Number is expected as option");
5065 				RETURN_FALSE;
5066 			}
5067 
5068 			angle = zval_get_double(options);
5069 
5070 			if (type == GD_AFFINE_SHEAR_HORIZONTAL) {
5071 				res = gdAffineShearHorizontal(affine, angle);
5072 			} else if (type == GD_AFFINE_SHEAR_VERTICAL) {
5073 				res = gdAffineShearVertical(affine, angle);
5074 			} else {
5075 				res = gdAffineRotate(affine, angle);
5076 			}
5077 			break;
5078 		}
5079 
5080 		default:
5081 			php_error_docref(NULL, E_WARNING, "Invalid type for element " ZEND_LONG_FMT, type);
5082 			RETURN_FALSE;
5083 	}
5084 
5085 	if (res == GD_FALSE) {
5086 		RETURN_FALSE;
5087 	} else {
5088 		array_init(return_value);
5089 		for (i = 0; i < 6; i++) {
5090 			add_index_double(return_value, i, affine[i]);
5091 		}
5092 	}
5093 } /* }}} */
5094 
5095 /* {{{ proto array imageaffineconcat(array m1, array m2)
5096    Concat two matrices (as in doing many ops in one go) */
PHP_FUNCTION(imageaffinematrixconcat)5097 PHP_FUNCTION(imageaffinematrixconcat)
5098 {
5099 	double m1[6];
5100 	double m2[6];
5101 	double mr[6];
5102 
5103 	zval *tmp;
5104 	zval *z_m1;
5105 	zval *z_m2;
5106 	int i, nelems;
5107 
5108 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "aa", &z_m1, &z_m2) == FAILURE)  {
5109 		return;
5110 	}
5111 
5112 	if (((nelems = zend_hash_num_elements(Z_ARRVAL_P(z_m1))) != 6) || (nelems = zend_hash_num_elements(Z_ARRVAL_P(z_m2))) != 6) {
5113 		php_error_docref(NULL, E_WARNING, "Affine arrays must have six elements");
5114 		RETURN_FALSE;
5115 	}
5116 
5117 	for (i = 0; i < 6; i++) {
5118 		if ((tmp = zend_hash_index_find(Z_ARRVAL_P(z_m1), i)) != NULL) {
5119 			switch (Z_TYPE_P(tmp)) {
5120 				case IS_LONG:
5121 					m1[i]  = Z_LVAL_P(tmp);
5122 					break;
5123 				case IS_DOUBLE:
5124 					m1[i] = Z_DVAL_P(tmp);
5125 					break;
5126 				case IS_STRING:
5127 					m1[i] = zval_get_double(tmp);
5128 					break;
5129 				default:
5130 					php_error_docref(NULL, E_WARNING, "Invalid type for element %i", i);
5131 					RETURN_FALSE;
5132 			}
5133 		}
5134 		if ((tmp = zend_hash_index_find(Z_ARRVAL_P(z_m2), i)) != NULL) {
5135 			switch (Z_TYPE_P(tmp)) {
5136 				case IS_LONG:
5137 					m2[i]  = Z_LVAL_P(tmp);
5138 					break;
5139 				case IS_DOUBLE:
5140 					m2[i] = Z_DVAL_P(tmp);
5141 					break;
5142 				case IS_STRING:
5143 					m2[i] = zval_get_double(tmp);
5144 					break;
5145 				default:
5146 					php_error_docref(NULL, E_WARNING, "Invalid type for element %i", i);
5147 					RETURN_FALSE;
5148 			}
5149 		}
5150 	}
5151 
5152 	if (gdAffineConcat (mr, m1, m2) != GD_TRUE) {
5153 		RETURN_FALSE;
5154 	}
5155 
5156 	array_init(return_value);
5157 	for (i = 0; i < 6; i++) {
5158 		add_index_double(return_value, i, mr[i]);
5159 	}
5160 } /* }}} */
5161 
5162 /* {{{ proto resource imagesetinterpolation(resource im [, int method]])
5163    Set the default interpolation method, passing -1 or 0 sets it to the libgd default (bilinear). */
PHP_FUNCTION(imagesetinterpolation)5164 PHP_FUNCTION(imagesetinterpolation)
5165 {
5166 	zval *IM;
5167 	gdImagePtr im;
5168 	zend_long method = GD_BILINEAR_FIXED;
5169 
5170 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &IM, &method) == FAILURE)  {
5171 		return;
5172 	}
5173 
5174 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
5175 		RETURN_FALSE;
5176 	}
5177 
5178 	if (method == -1) {
5179 		 method = GD_BILINEAR_FIXED;
5180 	}
5181 	RETURN_BOOL(gdImageSetInterpolationMethod(im, (gdInterpolationMethod) method));
5182 }
5183 /* }}} */
5184 
5185 /* {{{ proto array imageresolution(resource im [, res_x, [res_y]])
5186    Get or set the resolution of the image in DPI. */
PHP_FUNCTION(imageresolution)5187 PHP_FUNCTION(imageresolution)
5188 {
5189 	zval *IM;
5190 	gdImagePtr im;
5191 	zend_long res_x = GD_RESOLUTION, res_y = GD_RESOLUTION;
5192 
5193 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|ll", &IM, &res_x, &res_y) == FAILURE)  {
5194 		return;
5195 	}
5196 
5197 	if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
5198 		RETURN_FALSE;
5199 	}
5200 
5201 	switch (ZEND_NUM_ARGS()) {
5202 		case 3:
5203 			gdImageSetResolution(im, res_x, res_y);
5204 			RETURN_TRUE;
5205 		case 2:
5206 			gdImageSetResolution(im, res_x, res_x);
5207 			RETURN_TRUE;
5208 		default:
5209 			array_init(return_value);
5210 			add_next_index_long(return_value, gdImageResolutionX(im));
5211 			add_next_index_long(return_value, gdImageResolutionY(im));
5212 	}
5213 }
5214 /* }}} */
5215