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