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