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#if defined(USE_GD_JISX0208)
1298    add_assoc_bool(return_value, "JIS-mapped Japanese Font Support", 1);
1299#else
1300    add_assoc_bool(return_value, "JIS-mapped Japanese Font Support", 0);
1301#endif
1302}
1303/* }}} */
1304
1305/* Need this for cpdf. See also comment in file.c php3i_get_le_fp() */
1306PHP_GD_API int phpi_get_le_gd(void)
1307{
1308    return le_gd;
1309}
1310/* }}} */
1311
1312#define FLIPWORD(a) (((a & 0xff000000) >> 24) | ((a & 0x00ff0000) >> 8) | ((a & 0x0000ff00) << 8) | ((a & 0x000000ff) << 24))
1313
1314/* {{{ proto int imageloadfont(string filename)
1315   Load a new font */
1316PHP_FUNCTION(imageloadfont)
1317{
1318    zval *ind;
1319    zend_string *file;
1320    int hdr_size = sizeof(gdFont) - sizeof(char *);
1321    int body_size, n = 0, b, i, body_size_check;
1322    gdFontPtr font;
1323    php_stream *stream;
1324
1325    if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file) == FAILURE) {
1326        return;
1327    }
1328
1329    stream = php_stream_open_wrapper(ZSTR_VAL(file), "rb", IGNORE_PATH | IGNORE_URL_WIN | REPORT_ERRORS, NULL);
1330    if (stream == NULL) {
1331        RETURN_FALSE;
1332    }
1333
1334    /* Only supports a architecture-dependent binary dump format
1335     * at the moment.
1336     * The file format is like this on machines with 32-byte integers:
1337     *
1338     * byte 0-3:   (int) number of characters in the font
1339     * byte 4-7:   (int) value of first character in the font (often 32, space)
1340     * byte 8-11:  (int) pixel width of each character
1341     * byte 12-15: (int) pixel height of each character
1342     * bytes 16-:  (char) array with character data, one byte per pixel
1343     *                    in each character, for a total of
1344     *                    (nchars*width*height) bytes.
1345     */
1346    font = (gdFontPtr) emalloc(sizeof(gdFont));
1347    b = 0;
1348    while (b < hdr_size && (n = php_stream_read(stream, (char*)&font[b], hdr_size - b))) {
1349        b += n;
1350    }
1351
1352    if (!n) {
1353        efree(font);
1354        if (php_stream_eof(stream)) {
1355            php_error_docref(NULL, E_WARNING, "End of file while reading header");
1356        } else {
1357            php_error_docref(NULL, E_WARNING, "Error while reading header");
1358        }
1359        php_stream_close(stream);
1360        RETURN_FALSE;
1361    }
1362    i = php_stream_tell(stream);
1363    php_stream_seek(stream, 0, SEEK_END);
1364    body_size_check = php_stream_tell(stream) - hdr_size;
1365    php_stream_seek(stream, i, SEEK_SET);
1366
1367    body_size = font->w * font->h * font->nchars;
1368    if (body_size != body_size_check) {
1369        font->w = FLIPWORD(font->w);
1370        font->h = FLIPWORD(font->h);
1371        font->nchars = FLIPWORD(font->nchars);
1372        body_size = font->w * font->h * font->nchars;
1373    }
1374
1375    if (overflow2(font->nchars, font->h) || overflow2(font->nchars * font->h, font->w )) {
1376        php_error_docref(NULL, E_WARNING, "Error reading font, invalid font header");
1377        efree(font);
1378        php_stream_close(stream);
1379        RETURN_FALSE;
1380    }
1381
1382    if (body_size != body_size_check) {
1383        php_error_docref(NULL, E_WARNING, "Error reading font");
1384        efree(font);
1385        php_stream_close(stream);
1386        RETURN_FALSE;
1387    }
1388
1389    font->data = emalloc(body_size);
1390    b = 0;
1391    while (b < body_size && (n = php_stream_read(stream, &font->data[b], body_size - b))) {
1392        b += n;
1393    }
1394
1395    if (!n) {
1396        efree(font->data);
1397        efree(font);
1398        if (php_stream_eof(stream)) {
1399            php_error_docref(NULL, E_WARNING, "End of file while reading body");
1400        } else {
1401            php_error_docref(NULL, E_WARNING, "Error while reading body");
1402        }
1403        php_stream_close(stream);
1404        RETURN_FALSE;
1405    }
1406    php_stream_close(stream);
1407
1408    ind = zend_list_insert(font, le_gd_font);
1409
1410    /* Adding 5 to the font index so we will never have font indices
1411     * that overlap with the old fonts (with indices 1-5).  The first
1412     * list index given out is always 1.
1413     */
1414    RETURN_LONG(Z_RES_HANDLE_P(ind) + 5);
1415}
1416/* }}} */
1417
1418/* {{{ proto bool imagesetstyle(resource im, array styles)
1419   Set the line drawing styles for use with imageline and IMG_COLOR_STYLED. */
1420PHP_FUNCTION(imagesetstyle)
1421{
1422    zval *IM, *styles, *item;
1423    gdImagePtr im;
1424    int *stylearr;
1425    int index = 0;
1426
1427    if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra", &IM, &styles) == FAILURE)  {
1428        return;
1429    }
1430
1431    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1432        RETURN_FALSE;
1433    }
1434
1435    /* copy the style values in the stylearr */
1436    stylearr = safe_emalloc(sizeof(int), zend_hash_num_elements(HASH_OF(styles)), 0);
1437
1438    ZEND_HASH_FOREACH_VAL(HASH_OF(styles), item) {
1439        stylearr[index++] = zval_get_long(item);
1440    } ZEND_HASH_FOREACH_END();
1441
1442    gdImageSetStyle(im, stylearr, index);
1443
1444    efree(stylearr);
1445
1446    RETURN_TRUE;
1447}
1448/* }}} */
1449
1450/* {{{ proto resource imagecreatetruecolor(int x_size, int y_size)
1451   Create a new true color image */
1452PHP_FUNCTION(imagecreatetruecolor)
1453{
1454    zend_long x_size, y_size;
1455    gdImagePtr im;
1456
1457    if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &x_size, &y_size) == FAILURE) {
1458        return;
1459    }
1460
1461    if (x_size <= 0 || y_size <= 0 || x_size >= INT_MAX || y_size >= INT_MAX) {
1462        php_error_docref(NULL, E_WARNING, "Invalid image dimensions");
1463        RETURN_FALSE;
1464    }
1465
1466    im = gdImageCreateTrueColor(x_size, y_size);
1467
1468    if (!im) {
1469        RETURN_FALSE;
1470    }
1471
1472    RETURN_RES(zend_register_resource(im, le_gd));
1473}
1474/* }}} */
1475
1476/* {{{ proto bool imageistruecolor(resource im)
1477   return true if the image uses truecolor */
1478PHP_FUNCTION(imageistruecolor)
1479{
1480    zval *IM;
1481    gdImagePtr im;
1482
1483    if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE) {
1484        return;
1485    }
1486
1487    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1488        RETURN_FALSE;
1489    }
1490
1491    RETURN_BOOL(im->trueColor);
1492}
1493/* }}} */
1494
1495/* {{{ proto void imagetruecolortopalette(resource im, bool ditherFlag, int colorsWanted)
1496   Convert a true colour image to a palette based image with a number of colours, optionally using dithering. */
1497PHP_FUNCTION(imagetruecolortopalette)
1498{
1499    zval *IM;
1500    zend_bool dither;
1501    zend_long ncolors;
1502    gdImagePtr im;
1503
1504    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rbl", &IM, &dither, &ncolors) == FAILURE)  {
1505        return;
1506    }
1507
1508    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1509        RETURN_FALSE;
1510    }
1511
1512    if (ncolors <= 0) {
1513        php_error_docref(NULL, E_WARNING, "Number of colors has to be greater than zero");
1514        RETURN_FALSE;
1515    }
1516    gdImageTrueColorToPalette(im, dither, ncolors);
1517
1518    RETURN_TRUE;
1519}
1520/* }}} */
1521
1522/* {{{ proto void imagetruecolortopalette(resource im, bool ditherFlag, int colorsWanted)
1523   Convert a true colour image to a palette based image with a number of colours, optionally using dithering. */
1524PHP_FUNCTION(imagepalettetotruecolor)
1525{
1526    zval *IM;
1527    gdImagePtr im;
1528
1529    if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE)  {
1530        return;
1531    }
1532
1533    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1534        RETURN_FALSE;
1535    }
1536
1537    if (gdImagePaletteToTrueColor(im) == 0) {
1538        RETURN_FALSE;
1539    }
1540
1541    RETURN_TRUE;
1542}
1543/* }}} */
1544
1545/* {{{ proto bool imagecolormatch(resource im1, resource im2)
1546   Makes the colors of the palette version of an image more closely match the true color version */
1547PHP_FUNCTION(imagecolormatch)
1548{
1549    zval *IM1, *IM2;
1550    gdImagePtr im1, im2;
1551    int result;
1552
1553    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &IM1, &IM2) == FAILURE) {
1554        return;
1555    }
1556
1557    if ((im1 = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM1), "Image", le_gd)) == NULL) {
1558        RETURN_FALSE;
1559    }
1560    if ((im2 = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM2), "Image", le_gd)) == NULL) {
1561        RETURN_FALSE;
1562    }
1563
1564    result = gdImageColorMatch(im1, im2);
1565    switch (result) {
1566        case -1:
1567            php_error_docref(NULL, E_WARNING, "Image1 must be TrueColor" );
1568            RETURN_FALSE;
1569            break;
1570        case -2:
1571            php_error_docref(NULL, E_WARNING, "Image2 must be Palette" );
1572            RETURN_FALSE;
1573            break;
1574        case -3:
1575            php_error_docref(NULL, E_WARNING, "Image1 and Image2 must be the same size" );
1576            RETURN_FALSE;
1577            break;
1578        case -4:
1579            php_error_docref(NULL, E_WARNING, "Image2 must have at least one color" );
1580            RETURN_FALSE;
1581            break;
1582    }
1583
1584    RETURN_TRUE;
1585}
1586/* }}} */
1587
1588/* {{{ proto bool imagesetthickness(resource im, int thickness)
1589   Set line thickness for drawing lines, ellipses, rectangles, polygons etc. */
1590PHP_FUNCTION(imagesetthickness)
1591{
1592    zval *IM;
1593    zend_long thick;
1594    gdImagePtr im;
1595
1596    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &IM, &thick) == FAILURE) {
1597        return;
1598    }
1599
1600    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1601        RETURN_FALSE;
1602    }
1603
1604    gdImageSetThickness(im, thick);
1605
1606    RETURN_TRUE;
1607}
1608/* }}} */
1609
1610/* {{{ proto bool imagefilledellipse(resource im, int cx, int cy, int w, int h, int color)
1611   Draw an ellipse */
1612PHP_FUNCTION(imagefilledellipse)
1613{
1614    zval *IM;
1615    zend_long cx, cy, w, h, color;
1616    gdImagePtr im;
1617
1618    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &cx, &cy, &w, &h, &color) == FAILURE) {
1619        return;
1620    }
1621
1622    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1623        RETURN_FALSE;
1624    }
1625
1626    gdImageFilledEllipse(im, cx, cy, w, h, color);
1627
1628    RETURN_TRUE;
1629}
1630/* }}} */
1631
1632/* {{{ proto bool imagefilledarc(resource im, int cx, int cy, int w, int h, int s, int e, int col, int style)
1633   Draw a filled partial ellipse */
1634PHP_FUNCTION(imagefilledarc)
1635{
1636    zval *IM;
1637    zend_long cx, cy, w, h, ST, E, col, style;
1638    gdImagePtr im;
1639    int e, st;
1640
1641    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllllllll", &IM, &cx, &cy, &w, &h, &ST, &E, &col, &style) == FAILURE) {
1642        return;
1643    }
1644
1645    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1646        RETURN_FALSE;
1647    }
1648
1649    e = E;
1650    if (e < 0) {
1651        e %= 360;
1652    }
1653
1654    st = ST;
1655    if (st < 0) {
1656        st %= 360;
1657    }
1658
1659    gdImageFilledArc(im, cx, cy, w, h, st, e, col, style);
1660
1661    RETURN_TRUE;
1662}
1663/* }}} */
1664
1665/* {{{ proto bool imagealphablending(resource im, bool on)
1666   Turn alpha blending mode on or off for the given image */
1667PHP_FUNCTION(imagealphablending)
1668{
1669    zval *IM;
1670    zend_bool blend;
1671    gdImagePtr im;
1672
1673    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rb", &IM, &blend) == FAILURE) {
1674        return;
1675    }
1676
1677    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1678        RETURN_FALSE;
1679    }
1680
1681    gdImageAlphaBlending(im, blend);
1682
1683    RETURN_TRUE;
1684}
1685/* }}} */
1686
1687/* {{{ proto bool imagesavealpha(resource im, bool on)
1688   Include alpha channel to a saved image */
1689PHP_FUNCTION(imagesavealpha)
1690{
1691    zval *IM;
1692    zend_bool save;
1693    gdImagePtr im;
1694
1695    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rb", &IM, &save) == FAILURE) {
1696        return;
1697    }
1698
1699    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1700        RETURN_FALSE;
1701    }
1702
1703    gdImageSaveAlpha(im, save);
1704
1705    RETURN_TRUE;
1706}
1707/* }}} */
1708
1709/* {{{ proto bool imagelayereffect(resource im, int effect)
1710   Set the alpha blending flag to use the bundled libgd layering effects */
1711PHP_FUNCTION(imagelayereffect)
1712{
1713    zval *IM;
1714    zend_long effect;
1715    gdImagePtr im;
1716
1717    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &IM, &effect) == FAILURE) {
1718        return;
1719    }
1720
1721    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1722        RETURN_FALSE;
1723    }
1724
1725    gdImageAlphaBlending(im, effect);
1726
1727    RETURN_TRUE;
1728}
1729/* }}} */
1730
1731/* {{{ proto int imagecolorallocatealpha(resource im, int red, int green, int blue, int alpha)
1732   Allocate a color with an alpha level.  Works for true color and palette based images */
1733PHP_FUNCTION(imagecolorallocatealpha)
1734{
1735    zval *IM;
1736    zend_long red, green, blue, alpha;
1737    gdImagePtr im;
1738    int ct = (-1);
1739
1740    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll", &IM, &red, &green, &blue, &alpha) == FAILURE) {
1741        RETURN_FALSE;
1742    }
1743
1744    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1745        RETURN_FALSE;
1746    }
1747
1748    ct = gdImageColorAllocateAlpha(im, red, green, blue, alpha);
1749    if (ct < 0) {
1750        RETURN_FALSE;
1751    }
1752    RETURN_LONG((zend_long)ct);
1753}
1754/* }}} */
1755
1756/* {{{ proto int imagecolorresolvealpha(resource im, int red, int green, int blue, int alpha)
1757   Resolve/Allocate a colour with an alpha level.  Works for true colour and palette based images */
1758PHP_FUNCTION(imagecolorresolvealpha)
1759{
1760    zval *IM;
1761    zend_long red, green, blue, alpha;
1762    gdImagePtr im;
1763
1764    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll", &IM, &red, &green, &blue, &alpha) == FAILURE) {
1765        return;
1766    }
1767
1768    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1769        RETURN_FALSE;
1770    }
1771
1772    RETURN_LONG(gdImageColorResolveAlpha(im, red, green, blue, alpha));
1773}
1774/* }}} */
1775
1776/* {{{ proto int imagecolorclosestalpha(resource im, int red, int green, int blue, int alpha)
1777   Find the closest matching colour with alpha transparency */
1778PHP_FUNCTION(imagecolorclosestalpha)
1779{
1780    zval *IM;
1781    zend_long red, green, blue, alpha;
1782    gdImagePtr im;
1783
1784    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll", &IM, &red, &green, &blue, &alpha) == FAILURE) {
1785        return;
1786    }
1787
1788    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1789        RETURN_FALSE;
1790    }
1791
1792    RETURN_LONG(gdImageColorClosestAlpha(im, red, green, blue, alpha));
1793}
1794/* }}} */
1795
1796/* {{{ proto int imagecolorexactalpha(resource im, int red, int green, int blue, int alpha)
1797   Find exact match for colour with transparency */
1798PHP_FUNCTION(imagecolorexactalpha)
1799{
1800    zval *IM;
1801    zend_long red, green, blue, alpha;
1802    gdImagePtr im;
1803
1804    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll", &IM, &red, &green, &blue, &alpha) == FAILURE) {
1805        return;
1806    }
1807
1808    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
1809        RETURN_FALSE;
1810    }
1811
1812    RETURN_LONG(gdImageColorExactAlpha(im, red, green, blue, alpha));
1813}
1814/* }}} */
1815
1816/* {{{ 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)
1817   Copy and resize part of an image using resampling to help ensure clarity */
1818PHP_FUNCTION(imagecopyresampled)
1819{
1820    zval *SIM, *DIM;
1821    zend_long SX, SY, SW, SH, DX, DY, DW, DH;
1822    gdImagePtr im_dst, im_src;
1823    int srcH, srcW, dstH, dstW, srcY, srcX, dstY, dstX;
1824
1825    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrllllllll", &DIM, &SIM, &DX, &DY, &SX, &SY, &DW, &DH, &SW, &SH) == FAILURE) {
1826        return;
1827    }
1828
1829    if ((im_dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(DIM), "Image", le_gd)) == NULL) {
1830        RETURN_FALSE;
1831    }
1832
1833    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
1834        RETURN_FALSE;
1835    }
1836
1837    srcX = SX;
1838    srcY = SY;
1839    srcH = SH;
1840    srcW = SW;
1841    dstX = DX;
1842    dstY = DY;
1843    dstH = DH;
1844    dstW = DW;
1845
1846    gdImageCopyResampled(im_dst, im_src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);
1847
1848    RETURN_TRUE;
1849}
1850/* }}} */
1851
1852#ifdef PHP_WIN32
1853/* {{{ proto resource imagegrabwindow(int window_handle [, int client_area])
1854   Grab a window or its client area using a windows handle (HWND property in COM instance) */
1855PHP_FUNCTION(imagegrabwindow)
1856{
1857    HWND window;
1858    zend_long client_area = 0;
1859    RECT rc = {0};
1860    RECT rc_win = {0};
1861    int Width, Height;
1862    HDC     hdc;
1863    HDC memDC;
1864    HBITMAP memBM;
1865    HBITMAP hOld;
1866    HINSTANCE handle;
1867    zend_long lwindow_handle;
1868    typedef BOOL (WINAPI *tPrintWindow)(HWND, HDC,UINT);
1869    tPrintWindow pPrintWindow = 0;
1870    gdImagePtr im = NULL;
1871
1872    if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &lwindow_handle, &client_area) == FAILURE) {
1873        RETURN_FALSE;
1874    }
1875
1876    window = (HWND) lwindow_handle;
1877
1878    if (!IsWindow(window)) {
1879        php_error_docref(NULL, E_NOTICE, "Invalid window handle");
1880        RETURN_FALSE;
1881    }
1882
1883    hdc     = GetDC(0);
1884
1885    if (client_area) {
1886        GetClientRect(window, &rc);
1887        Width = rc.right;
1888        Height = rc.bottom;
1889    } else {
1890        GetWindowRect(window, &rc);
1891        Width   = rc.right - rc.left;
1892        Height  = rc.bottom - rc.top;
1893    }
1894
1895    Width       = (Width/4)*4;
1896
1897    memDC   = CreateCompatibleDC(hdc);
1898    memBM   = CreateCompatibleBitmap(hdc, Width, Height);
1899    hOld    = (HBITMAP) SelectObject (memDC, memBM);
1900
1901
1902    handle = LoadLibrary("User32.dll");
1903    if ( handle == 0 ) {
1904        goto clean;
1905    }
1906    pPrintWindow = (tPrintWindow) GetProcAddress(handle, "PrintWindow");
1907
1908    if ( pPrintWindow )  {
1909        pPrintWindow(window, memDC, (UINT) client_area);
1910    } else {
1911        php_error_docref(NULL, E_WARNING, "Windows API too old");
1912        goto clean;
1913    }
1914
1915    FreeLibrary(handle);
1916
1917    im = gdImageCreateTrueColor(Width, Height);
1918    if (im) {
1919        int x,y;
1920        for (y=0; y <= Height; y++) {
1921            for (x=0; x <= Width; x++) {
1922                int c = GetPixel(memDC, x,y);
1923                gdImageSetPixel(im, x, y, gdTrueColor(GetRValue(c), GetGValue(c), GetBValue(c)));
1924            }
1925        }
1926    }
1927
1928clean:
1929    SelectObject(memDC,hOld);
1930    DeleteObject(memBM);
1931    DeleteDC(memDC);
1932    ReleaseDC( 0, hdc );
1933
1934    if (!im) {
1935        RETURN_FALSE;
1936    } else {
1937        RETURN_RES(zend_register_resource(im, le_gd));
1938    }
1939}
1940/* }}} */
1941
1942/* {{{ proto resource imagegrabscreen()
1943   Grab a screenshot */
1944PHP_FUNCTION(imagegrabscreen)
1945{
1946    HWND window = GetDesktopWindow();
1947    RECT rc = {0};
1948    int Width, Height;
1949    HDC     hdc;
1950    HDC memDC;
1951    HBITMAP memBM;
1952    HBITMAP hOld;
1953    typedef BOOL (WINAPI *tPrintWindow)(HWND, HDC,UINT);
1954    tPrintWindow pPrintWindow = 0;
1955    gdImagePtr im;
1956    hdc     = GetDC(0);
1957
1958    if (zend_parse_parameters_none() == FAILURE) {
1959        return;
1960    }
1961
1962    if (!hdc) {
1963        RETURN_FALSE;
1964    }
1965
1966    GetWindowRect(window, &rc);
1967    Width   = rc.right - rc.left;
1968    Height  = rc.bottom - rc.top;
1969
1970    Width       = (Width/4)*4;
1971
1972    memDC   = CreateCompatibleDC(hdc);
1973    memBM   = CreateCompatibleBitmap(hdc, Width, Height);
1974    hOld    = (HBITMAP) SelectObject (memDC, memBM);
1975    BitBlt( memDC, 0, 0, Width, Height , hdc, rc.left, rc.top , SRCCOPY );
1976
1977    im = gdImageCreateTrueColor(Width, Height);
1978    if (im) {
1979        int x,y;
1980        for (y=0; y <= Height; y++) {
1981            for (x=0; x <= Width; x++) {
1982                int c = GetPixel(memDC, x,y);
1983                gdImageSetPixel(im, x, y, gdTrueColor(GetRValue(c), GetGValue(c), GetBValue(c)));
1984            }
1985        }
1986    }
1987
1988    SelectObject(memDC,hOld);
1989    DeleteObject(memBM);
1990    DeleteDC(memDC);
1991    ReleaseDC( 0, hdc );
1992
1993    if (!im) {
1994        RETURN_FALSE;
1995    } else {
1996        RETURN_RES(zend_register_resource(im, le_gd));
1997    }
1998}
1999/* }}} */
2000#endif /* PHP_WIN32 */
2001
2002/* {{{ proto resource imagerotate(resource src_im, float angle, int bgdcolor [, int ignoretransparent])
2003   Rotate an image using a custom angle */
2004PHP_FUNCTION(imagerotate)
2005{
2006    zval *SIM;
2007    gdImagePtr im_dst, im_src;
2008    double degrees;
2009    zend_long color;
2010    zend_long ignoretransparent = 0;
2011
2012    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rdl|l", &SIM, &degrees, &color, &ignoretransparent) == FAILURE) {
2013        RETURN_FALSE;
2014    }
2015
2016    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
2017        RETURN_FALSE;
2018    }
2019
2020    im_dst = gdImageRotateInterpolated(im_src, (const float)degrees, color);
2021
2022    if (im_dst != NULL) {
2023        RETURN_RES(zend_register_resource(im_dst, le_gd));
2024    } else {
2025        RETURN_FALSE;
2026    }
2027}
2028/* }}} */
2029
2030/* {{{ proto bool imagesettile(resource image, resource tile)
2031   Set the tile image to $tile when filling $image with the "IMG_COLOR_TILED" color */
2032PHP_FUNCTION(imagesettile)
2033{
2034    zval *IM, *TILE;
2035    gdImagePtr im, tile;
2036
2037    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &IM, &TILE) == FAILURE) {
2038        return;
2039    }
2040
2041    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2042        RETURN_FALSE;
2043    }
2044
2045    if ((tile = (gdImagePtr)zend_fetch_resource(Z_RES_P(TILE), "Image", le_gd)) == NULL) {
2046        RETURN_FALSE;
2047    }
2048
2049    gdImageSetTile(im, tile);
2050
2051    RETURN_TRUE;
2052}
2053/* }}} */
2054
2055/* {{{ proto bool imagesetbrush(resource image, resource brush)
2056   Set the brush image to $brush when filling $image with the "IMG_COLOR_BRUSHED" color */
2057PHP_FUNCTION(imagesetbrush)
2058{
2059    zval *IM, *TILE;
2060    gdImagePtr im, tile;
2061
2062    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &IM, &TILE) == FAILURE) {
2063        return;
2064    }
2065
2066    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2067        RETURN_FALSE;
2068    }
2069
2070    if ((tile = (gdImagePtr)zend_fetch_resource(Z_RES_P(TILE), "Image", le_gd)) == NULL) {
2071        RETURN_FALSE;
2072    }
2073
2074    gdImageSetBrush(im, tile);
2075
2076    RETURN_TRUE;
2077}
2078/* }}} */
2079
2080/* {{{ proto resource imagecreate(int x_size, int y_size)
2081   Create a new image */
2082PHP_FUNCTION(imagecreate)
2083{
2084    zend_long x_size, y_size;
2085    gdImagePtr im;
2086
2087    if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &x_size, &y_size) == FAILURE) {
2088        return;
2089    }
2090
2091    if (x_size <= 0 || y_size <= 0 || x_size >= INT_MAX || y_size >= INT_MAX) {
2092        php_error_docref(NULL, E_WARNING, "Invalid image dimensions");
2093        RETURN_FALSE;
2094    }
2095
2096    im = gdImageCreate(x_size, y_size);
2097
2098    if (!im) {
2099        RETURN_FALSE;
2100    }
2101
2102    RETURN_RES(zend_register_resource(im, le_gd));
2103}
2104/* }}} */
2105
2106/* {{{ proto int imagetypes(void)
2107   Return the types of images supported in a bitfield - 1=GIF, 2=JPEG, 4=PNG, 8=WBMP, 16=XPM */
2108PHP_FUNCTION(imagetypes)
2109{
2110    int ret=0;
2111    ret = 1;
2112#ifdef HAVE_GD_JPG
2113    ret |= 2;
2114#endif
2115#ifdef HAVE_GD_PNG
2116    ret |= 4;
2117#endif
2118    ret |= 8;
2119#if defined(HAVE_GD_XPM)
2120    ret |= 16;
2121#endif
2122
2123    if (zend_parse_parameters_none() == FAILURE) {
2124        return;
2125    }
2126
2127    RETURN_LONG(ret);
2128}
2129/* }}} */
2130
2131/* {{{ _php_ctx_getmbi
2132 */
2133
2134static int _php_ctx_getmbi(gdIOCtx *ctx)
2135{
2136    int i, mbi = 0;
2137
2138    do {
2139        i = (ctx->getC)(ctx);
2140        if (i < 0) {
2141            return -1;
2142        }
2143        mbi = (mbi << 7) | (i & 0x7f);
2144    } while (i & 0x80);
2145
2146    return mbi;
2147}
2148/* }}} */
2149
2150/* {{{ _php_image_type
2151 */
2152static const char php_sig_gd2[3] = {'g', 'd', '2'};
2153
2154static int _php_image_type (char data[8])
2155{
2156    /* Based on ext/standard/image.c */
2157
2158    if (data == NULL) {
2159        return -1;
2160    }
2161
2162    if (!memcmp(data, php_sig_gd2, 3)) {
2163        return PHP_GDIMG_TYPE_GD2;
2164    } else if (!memcmp(data, php_sig_jpg, 3)) {
2165        return PHP_GDIMG_TYPE_JPG;
2166    } else if (!memcmp(data, php_sig_png, 3)) {
2167        if (!memcmp(data, php_sig_png, 8)) {
2168            return PHP_GDIMG_TYPE_PNG;
2169        }
2170    } else if (!memcmp(data, php_sig_gif, 3)) {
2171        return PHP_GDIMG_TYPE_GIF;
2172    }
2173    else {
2174        gdIOCtx *io_ctx;
2175        io_ctx = gdNewDynamicCtxEx(8, data, 0);
2176        if (io_ctx) {
2177            if (_php_ctx_getmbi(io_ctx) == 0 && _php_ctx_getmbi(io_ctx) >= 0) {
2178                io_ctx->gd_free(io_ctx);
2179                return PHP_GDIMG_TYPE_WBM;
2180            } else {
2181                io_ctx->gd_free(io_ctx);
2182            }
2183        }
2184    }
2185    return -1;
2186}
2187/* }}} */
2188
2189/* {{{ _php_image_create_from_string
2190 */
2191gdImagePtr _php_image_create_from_string(zval *data, char *tn, gdImagePtr (*ioctx_func_p)())
2192{
2193    gdImagePtr im;
2194    gdIOCtx *io_ctx;
2195
2196    io_ctx = gdNewDynamicCtxEx(Z_STRLEN_P(data), Z_STRVAL_P(data), 0);
2197
2198    if (!io_ctx) {
2199        return NULL;
2200    }
2201
2202    im = (*ioctx_func_p)(io_ctx);
2203    if (!im) {
2204        php_error_docref(NULL, E_WARNING, "Passed data is not in '%s' format", tn);
2205        io_ctx->gd_free(io_ctx);
2206        return NULL;
2207    }
2208
2209    io_ctx->gd_free(io_ctx);
2210
2211    return im;
2212}
2213/* }}} */
2214
2215/* {{{ proto resource imagecreatefromstring(string image)
2216   Create a new image from the image stream in the string */
2217PHP_FUNCTION(imagecreatefromstring)
2218{
2219    zval *data;
2220    gdImagePtr im;
2221    int imtype;
2222    char sig[8];
2223
2224    if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &data) == FAILURE) {
2225        return;
2226    }
2227
2228    convert_to_string_ex(data);
2229    if (Z_STRLEN_P(data) < 8) {
2230        php_error_docref(NULL, E_WARNING, "Empty string or invalid image");
2231        RETURN_FALSE;
2232    }
2233
2234    memcpy(sig, Z_STRVAL_P(data), 8);
2235
2236    imtype = _php_image_type(sig);
2237
2238    switch (imtype) {
2239        case PHP_GDIMG_TYPE_JPG:
2240#ifdef HAVE_GD_JPG
2241            im = _php_image_create_from_string(data, "JPEG", gdImageCreateFromJpegCtx);
2242#else
2243            php_error_docref(NULL, E_WARNING, "No JPEG support in this PHP build");
2244            RETURN_FALSE;
2245#endif
2246            break;
2247
2248        case PHP_GDIMG_TYPE_PNG:
2249#ifdef HAVE_GD_PNG
2250            im = _php_image_create_from_string(data, "PNG", gdImageCreateFromPngCtx);
2251#else
2252            php_error_docref(NULL, E_WARNING, "No PNG support in this PHP build");
2253            RETURN_FALSE;
2254#endif
2255            break;
2256
2257        case PHP_GDIMG_TYPE_GIF:
2258            im = _php_image_create_from_string(data, "GIF", gdImageCreateFromGifCtx);
2259            break;
2260
2261        case PHP_GDIMG_TYPE_WBM:
2262            im = _php_image_create_from_string(data, "WBMP", gdImageCreateFromWBMPCtx);
2263            break;
2264
2265        case PHP_GDIMG_TYPE_GD2:
2266            im = _php_image_create_from_string(data, "GD2", gdImageCreateFromGd2Ctx);
2267            break;
2268
2269        default:
2270            php_error_docref(NULL, E_WARNING, "Data is not in a recognized format");
2271            RETURN_FALSE;
2272    }
2273
2274    if (!im) {
2275        php_error_docref(NULL, E_WARNING, "Couldn't create GD Image Stream out of Data");
2276        RETURN_FALSE;
2277    }
2278
2279    RETURN_RES(zend_register_resource(im, le_gd));
2280}
2281/* }}} */
2282
2283/* {{{ _php_image_create_from
2284 */
2285static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)())
2286{
2287    char *file;
2288    size_t file_len;
2289    zend_long srcx, srcy, width, height;
2290    gdImagePtr im = NULL;
2291    php_stream *stream;
2292    FILE * fp = NULL;
2293#ifdef HAVE_GD_JPG
2294    long ignore_warning;
2295#endif
2296
2297    if (image_type == PHP_GDIMG_TYPE_GD2PART) {
2298        if (zend_parse_parameters(ZEND_NUM_ARGS(), "pllll", &file, &file_len, &srcx, &srcy, &width, &height) == FAILURE) {
2299            return;
2300        }
2301        if (width < 1 || height < 1) {
2302            php_error_docref(NULL, E_WARNING, "Zero width or height not allowed");
2303            RETURN_FALSE;
2304        }
2305    } else {
2306        if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &file, &file_len) == FAILURE) {
2307            return;
2308        }
2309    }
2310
2311
2312    stream = php_stream_open_wrapper(file, "rb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL);
2313    if (stream == NULL) {
2314        RETURN_FALSE;
2315    }
2316
2317    /* try and avoid allocating a FILE* if the stream is not naturally a FILE* */
2318    if (php_stream_is(stream, PHP_STREAM_IS_STDIO)) {
2319        if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)&fp, REPORT_ERRORS)) {
2320            goto out_err;
2321        }
2322    } else if (ioctx_func_p) {
2323        /* we can create an io context */
2324        gdIOCtx* io_ctx;
2325        zend_string *buff;
2326        char *pstr;
2327
2328        buff = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0);
2329
2330        if (!buff) {
2331            php_error_docref(NULL, E_WARNING,"Cannot read image data");
2332            goto out_err;
2333        }
2334
2335        /* needs to be malloc (persistent) - GD will free() it later */
2336        pstr = pestrndup(ZSTR_VAL(buff), ZSTR_LEN(buff), 1);
2337        io_ctx = gdNewDynamicCtxEx(ZSTR_LEN(buff), pstr, 0);
2338        if (!io_ctx) {
2339            pefree(pstr, 1);
2340            zend_string_release(buff);
2341            php_error_docref(NULL, E_WARNING,"Cannot allocate GD IO context");
2342            goto out_err;
2343        }
2344
2345        if (image_type == PHP_GDIMG_TYPE_GD2PART) {
2346            im = (*ioctx_func_p)(io_ctx, srcx, srcy, width, height);
2347        } else {
2348            im = (*ioctx_func_p)(io_ctx);
2349        }
2350        io_ctx->gd_free(io_ctx);
2351        pefree(pstr, 1);
2352        zend_string_release(buff);
2353    }
2354    else if (php_stream_can_cast(stream, PHP_STREAM_AS_STDIO)) {
2355        /* try and force the stream to be FILE* */
2356        if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD, (void **) &fp, REPORT_ERRORS)) {
2357            goto out_err;
2358        }
2359    }
2360
2361    if (!im && fp) {
2362        switch (image_type) {
2363            case PHP_GDIMG_TYPE_GD2PART:
2364                im = (*func_p)(fp, srcx, srcy, width, height);
2365                break;
2366#if defined(HAVE_GD_XPM)
2367            case PHP_GDIMG_TYPE_XPM:
2368                im = gdImageCreateFromXpm(file);
2369                break;
2370#endif
2371
2372#ifdef HAVE_GD_JPG
2373            case PHP_GDIMG_TYPE_JPG:
2374                ignore_warning = INI_INT("gd.jpeg_ignore_warning");
2375                im = gdImageCreateFromJpegEx(fp, ignore_warning);
2376            break;
2377#endif
2378
2379            default:
2380                im = (*func_p)(fp);
2381                break;
2382        }
2383
2384        fflush(fp);
2385    }
2386
2387/* register_im: */
2388    if (im) {
2389        RETVAL_RES(zend_register_resource(im, le_gd));
2390        php_stream_close(stream);
2391        return;
2392    }
2393
2394    php_error_docref(NULL, E_WARNING, "'%s' is not a valid %s file", file, tn);
2395out_err:
2396    php_stream_close(stream);
2397    RETURN_FALSE;
2398
2399}
2400/* }}} */
2401
2402/* {{{ proto resource imagecreatefromgif(string filename)
2403   Create a new image from GIF file or URL */
2404PHP_FUNCTION(imagecreatefromgif)
2405{
2406    _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageCreateFromGif, gdImageCreateFromGifCtx);
2407}
2408/* }}} */
2409
2410#ifdef HAVE_GD_JPG
2411/* {{{ proto resource imagecreatefromjpeg(string filename)
2412   Create a new image from JPEG file or URL */
2413PHP_FUNCTION(imagecreatefromjpeg)
2414{
2415    _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageCreateFromJpeg, gdImageCreateFromJpegCtx);
2416}
2417/* }}} */
2418#endif /* HAVE_GD_JPG */
2419
2420#ifdef HAVE_GD_PNG
2421/* {{{ proto resource imagecreatefrompng(string filename)
2422   Create a new image from PNG file or URL */
2423PHP_FUNCTION(imagecreatefrompng)
2424{
2425    _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImageCreateFromPng, gdImageCreateFromPngCtx);
2426}
2427/* }}} */
2428#endif /* HAVE_GD_PNG */
2429
2430#ifdef HAVE_GD_WEBP
2431/* {{{ proto resource imagecreatefromwebp(string filename)
2432   Create a new image from WEBP file or URL */
2433PHP_FUNCTION(imagecreatefromwebp)
2434{
2435    _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "WEBP", gdImageCreateFromWebp, gdImageCreateFromWebpCtx);
2436}
2437/* }}} */
2438#endif /* HAVE_GD_VPX */
2439
2440/* {{{ proto resource imagecreatefromxbm(string filename)
2441   Create a new image from XBM file or URL */
2442PHP_FUNCTION(imagecreatefromxbm)
2443{
2444    _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "XBM", gdImageCreateFromXbm, NULL);
2445}
2446/* }}} */
2447
2448#if defined(HAVE_GD_XPM)
2449/* {{{ proto resource imagecreatefromxpm(string filename)
2450   Create a new image from XPM file or URL */
2451PHP_FUNCTION(imagecreatefromxpm)
2452{
2453    _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XPM, "XPM", gdImageCreateFromXpm, NULL);
2454}
2455/* }}} */
2456#endif
2457
2458/* {{{ proto resource imagecreatefromwbmp(string filename)
2459   Create a new image from WBMP file or URL */
2460PHP_FUNCTION(imagecreatefromwbmp)
2461{
2462    _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageCreateFromWBMP, gdImageCreateFromWBMPCtx);
2463}
2464/* }}} */
2465
2466/* {{{ proto resource imagecreatefromgd(string filename)
2467   Create a new image from GD file or URL */
2468PHP_FUNCTION(imagecreatefromgd)
2469{
2470    _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD, "GD", gdImageCreateFromGd, gdImageCreateFromGdCtx);
2471}
2472/* }}} */
2473
2474/* {{{ proto resource imagecreatefromgd2(string filename)
2475   Create a new image from GD2 file or URL */
2476PHP_FUNCTION(imagecreatefromgd2)
2477{
2478    _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2, "GD2", gdImageCreateFromGd2, gdImageCreateFromGd2Ctx);
2479}
2480/* }}} */
2481
2482/* {{{ proto resource imagecreatefromgd2part(string filename, int srcX, int srcY, int width, int height)
2483   Create a new image from a given part of GD2 file or URL */
2484PHP_FUNCTION(imagecreatefromgd2part)
2485{
2486    _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2PART, "GD2", gdImageCreateFromGd2Part, gdImageCreateFromGd2PartCtx);
2487}
2488/* }}} */
2489
2490/* {{{ _php_image_output
2491 */
2492static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)())
2493{
2494    zval *imgind;
2495    char *file = NULL;
2496    zend_long quality = 0, type = 0;
2497    gdImagePtr im;
2498    char *fn = NULL;
2499    FILE *fp;
2500    size_t file_len = 0;
2501    int argc = ZEND_NUM_ARGS();
2502    int q = -1, i, t = 1;
2503
2504    /* The quality parameter for Wbmp stands for the threshold when called from image2wbmp() */
2505    /* When called from imagewbmp() the quality parameter stands for the foreground color. Default: black. */
2506    /* The quality parameter for gd2 stands for chunk size */
2507
2508    if (zend_parse_parameters(argc, "r|pll", &imgind, &file, &file_len, &quality, &type) == FAILURE) {
2509        return;
2510    }
2511
2512    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(imgind), "Image", le_gd)) == NULL) {
2513        RETURN_FALSE;
2514    }
2515
2516    if (argc > 1) {
2517        fn = file;
2518        if (argc == 3) {
2519            q = quality;
2520        }
2521        if (argc == 4) {
2522            t = type;
2523        }
2524    }
2525
2526    if (argc >= 2 && file_len) {
2527        PHP_GD_CHECK_OPEN_BASEDIR(fn, "Invalid filename");
2528
2529        fp = VCWD_FOPEN(fn, "wb");
2530        if (!fp) {
2531            php_error_docref(NULL, E_WARNING, "Unable to open '%s' for writing", fn);
2532            RETURN_FALSE;
2533        }
2534
2535        switch (image_type) {
2536            case PHP_GDIMG_CONVERT_WBM:
2537                if (q == -1) {
2538                    q = 0;
2539                } else if (q < 0 || q > 255) {
2540                    php_error_docref(NULL, E_WARNING, "Invalid threshold value '%d'. It must be between 0 and 255", q);
2541                    q = 0;
2542                }
2543                gdImageWBMP(im, q, fp);
2544                break;
2545            case PHP_GDIMG_TYPE_JPG:
2546                (*func_p)(im, fp, q);
2547                break;
2548            case PHP_GDIMG_TYPE_WBM:
2549                for (i = 0; i < gdImageColorsTotal(im); i++) {
2550                    if (gdImageRed(im, i) == 0) break;
2551                }
2552                (*func_p)(im, i, fp);
2553                break;
2554            case PHP_GDIMG_TYPE_GD:
2555                if (im->trueColor){
2556                    gdImageTrueColorToPalette(im,1,256);
2557                }
2558                (*func_p)(im, fp);
2559                break;
2560            case PHP_GDIMG_TYPE_GD2:
2561                if (q == -1) {
2562                    q = 128;
2563                }
2564                (*func_p)(im, fp, q, t);
2565                break;
2566            default:
2567                if (q == -1) {
2568                    q = 128;
2569                }
2570                (*func_p)(im, fp, q, t);
2571                break;
2572        }
2573        fflush(fp);
2574        fclose(fp);
2575    } else {
2576        int   b;
2577        FILE *tmp;
2578        char  buf[4096];
2579        zend_string *path;
2580
2581        tmp = php_open_temporary_file(NULL, NULL, &path);
2582        if (tmp == NULL) {
2583            php_error_docref(NULL, E_WARNING, "Unable to open temporary file");
2584            RETURN_FALSE;
2585        }
2586
2587        switch (image_type) {
2588            case PHP_GDIMG_CONVERT_WBM:
2589                if (q == -1) {
2590                    q = 0;
2591                } else if (q < 0 || q > 255) {
2592                    php_error_docref(NULL, E_WARNING, "Invalid threshold value '%d'. It must be between 0 and 255", q);
2593                    q = 0;
2594                }
2595                gdImageWBMP(im, q, tmp);
2596                break;
2597            case PHP_GDIMG_TYPE_JPG:
2598                (*func_p)(im, tmp, q);
2599                break;
2600            case PHP_GDIMG_TYPE_WBM:
2601                for (i = 0; i < gdImageColorsTotal(im); i++) {
2602                    if (gdImageRed(im, i) == 0) {
2603                        break;
2604                    }
2605                }
2606                (*func_p)(im, q, tmp);
2607                break;
2608            case PHP_GDIMG_TYPE_GD:
2609                if (im->trueColor) {
2610                    gdImageTrueColorToPalette(im,1,256);
2611                }
2612                (*func_p)(im, tmp);
2613                break;
2614            case PHP_GDIMG_TYPE_GD2:
2615                if (q == -1) {
2616                    q = 128;
2617                }
2618                (*func_p)(im, tmp, q, t);
2619                break;
2620            default:
2621                (*func_p)(im, tmp);
2622                break;
2623        }
2624
2625        fseek(tmp, 0, SEEK_SET);
2626
2627#if APACHE && defined(CHARSET_EBCDIC)
2628        /* XXX this is unlikely to work any more thies@thieso.net */
2629
2630        /* This is a binary file already: avoid EBCDIC->ASCII conversion */
2631        ap_bsetflag(php3_rqst->connection->client, B_EBCDIC2ASCII, 0);
2632#endif
2633        while ((b = fread(buf, 1, sizeof(buf), tmp)) > 0) {
2634            php_write(buf, b);
2635        }
2636
2637        fclose(tmp);
2638        VCWD_UNLINK((const char *)ZSTR_VAL(path)); /* make sure that the temporary file is removed */
2639        zend_string_release(path);
2640    }
2641    RETURN_TRUE;
2642}
2643/* }}} */
2644
2645/* {{{ proto int imagexbm(int im, string filename [, int foreground])
2646   Output XBM image to browser or file */
2647PHP_FUNCTION(imagexbm)
2648{
2649    _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "XBM", gdImageXbmCtx);
2650}
2651/* }}} */
2652
2653/* {{{ proto bool imagegif(resource im [, string filename])
2654   Output GIF image to browser or file */
2655PHP_FUNCTION(imagegif)
2656{
2657    _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageGifCtx);
2658}
2659/* }}} */
2660
2661#ifdef HAVE_GD_PNG
2662/* {{{ proto bool imagepng(resource im [, string filename])
2663   Output PNG image to browser or file */
2664PHP_FUNCTION(imagepng)
2665{
2666    _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePngCtxEx);
2667}
2668/* }}} */
2669#endif /* HAVE_GD_PNG */
2670
2671
2672#ifdef HAVE_GD_WEBP
2673/* {{{ proto bool imagewebp(resource im [, string filename[, int quality]] )
2674   Output WEBP image to browser or file */
2675PHP_FUNCTION(imagewebp)
2676{
2677    _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "WEBP", gdImageWebpCtx);
2678}
2679/* }}} */
2680#endif /* HAVE_GD_WEBP */
2681
2682
2683#ifdef HAVE_GD_JPG
2684/* {{{ proto bool imagejpeg(resource im [, string filename [, int quality]])
2685   Output JPEG image to browser or file */
2686PHP_FUNCTION(imagejpeg)
2687{
2688    _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageJpegCtx);
2689}
2690/* }}} */
2691#endif /* HAVE_GD_JPG */
2692
2693/* {{{ proto bool imagewbmp(resource im [, string filename [, int foreground]])
2694   Output WBMP image to browser or file */
2695PHP_FUNCTION(imagewbmp)
2696{
2697    _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageWBMPCtx);
2698}
2699/* }}} */
2700
2701/* {{{ proto bool imagegd(resource im [, string filename])
2702   Output GD image to browser or file */
2703PHP_FUNCTION(imagegd)
2704{
2705    _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD, "GD", gdImageGd);
2706}
2707/* }}} */
2708
2709/* {{{ proto bool imagegd2(resource im [, string filename [, int chunk_size [, int type]]])
2710   Output GD2 image to browser or file */
2711PHP_FUNCTION(imagegd2)
2712{
2713    _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2, "GD2", gdImageGd2);
2714}
2715/* }}} */
2716
2717/* {{{ proto bool imagedestroy(resource im)
2718   Destroy an image */
2719PHP_FUNCTION(imagedestroy)
2720{
2721    zval *IM;
2722    gdImagePtr im;
2723
2724    if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE) {
2725        return;
2726    }
2727
2728    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2729        RETURN_FALSE;
2730    }
2731
2732    zend_list_close(Z_RES_P(IM));
2733
2734    RETURN_TRUE;
2735}
2736/* }}} */
2737
2738
2739/* {{{ proto int imagecolorallocate(resource im, int red, int green, int blue)
2740   Allocate a color for an image */
2741PHP_FUNCTION(imagecolorallocate)
2742{
2743    zval *IM;
2744    zend_long red, green, blue;
2745    gdImagePtr im;
2746    int ct = (-1);
2747
2748    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &red, &green, &blue) == FAILURE) {
2749        return;
2750    }
2751
2752    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2753        RETURN_FALSE;
2754    }
2755
2756    ct = gdImageColorAllocate(im, red, green, blue);
2757    if (ct < 0) {
2758        RETURN_FALSE;
2759    }
2760    RETURN_LONG(ct);
2761}
2762/* }}} */
2763
2764/* {{{ proto void imagepalettecopy(resource dst, resource src)
2765   Copy the palette from the src image onto the dst image */
2766PHP_FUNCTION(imagepalettecopy)
2767{
2768    zval *dstim, *srcim;
2769    gdImagePtr dst, src;
2770
2771    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &dstim, &srcim) == FAILURE) {
2772        return;
2773    }
2774
2775    if ((dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(dstim), "Image", le_gd)) == NULL) {
2776        RETURN_FALSE;
2777    }
2778
2779    if ((src = (gdImagePtr)zend_fetch_resource(Z_RES_P(srcim), "Image", le_gd)) == NULL) {
2780        RETURN_FALSE;
2781    }
2782
2783    gdImagePaletteCopy(dst, src);
2784}
2785/* }}} */
2786
2787/* {{{ proto int imagecolorat(resource im, int x, int y)
2788   Get the index of the color of a pixel */
2789PHP_FUNCTION(imagecolorat)
2790{
2791    zval *IM;
2792    zend_long x, y;
2793    gdImagePtr im;
2794
2795    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rll", &IM, &x, &y) == FAILURE) {
2796        return;
2797    }
2798
2799    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2800        RETURN_FALSE;
2801    }
2802
2803    if (gdImageTrueColor(im)) {
2804        if (im->tpixels && gdImageBoundsSafe(im, x, y)) {
2805            RETURN_LONG(gdImageTrueColorPixel(im, x, y));
2806        } else {
2807            php_error_docref(NULL, E_NOTICE, "%pd,%pd is out of bounds", x, y);
2808            RETURN_FALSE;
2809        }
2810    } else {
2811        if (im->pixels && gdImageBoundsSafe(im, x, y)) {
2812            RETURN_LONG(im->pixels[y][x]);
2813        } else {
2814            php_error_docref(NULL, E_NOTICE, "%pd,%pd is out of bounds", x, y);
2815            RETURN_FALSE;
2816        }
2817    }
2818}
2819/* }}} */
2820
2821/* {{{ proto int imagecolorclosest(resource im, int red, int green, int blue)
2822   Get the index of the closest color to the specified color */
2823PHP_FUNCTION(imagecolorclosest)
2824{
2825    zval *IM;
2826    zend_long red, green, blue;
2827    gdImagePtr im;
2828
2829    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &red, &green, &blue) == FAILURE) {
2830        return;
2831    }
2832
2833    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2834        RETURN_FALSE;
2835    }
2836
2837    RETURN_LONG(gdImageColorClosest(im, red, green, blue));
2838}
2839/* }}} */
2840
2841/* {{{ proto int imagecolorclosesthwb(resource im, int red, int green, int blue)
2842   Get the index of the color which has the hue, white and blackness nearest to the given color */
2843PHP_FUNCTION(imagecolorclosesthwb)
2844{
2845    zval *IM;
2846    zend_long red, green, blue;
2847    gdImagePtr im;
2848
2849    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &red, &green, &blue) == FAILURE) {
2850        return;
2851    }
2852
2853    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2854        RETURN_FALSE;
2855    }
2856
2857    RETURN_LONG(gdImageColorClosestHWB(im, red, green, blue));
2858}
2859/* }}} */
2860
2861/* {{{ proto bool imagecolordeallocate(resource im, int index)
2862   De-allocate a color for an image */
2863PHP_FUNCTION(imagecolordeallocate)
2864{
2865    zval *IM;
2866    zend_long index;
2867    int col;
2868    gdImagePtr im;
2869
2870    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &IM, &index) == FAILURE) {
2871        return;
2872    }
2873
2874    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2875        RETURN_FALSE;
2876    }
2877
2878    /* We can return right away for a truecolor image as deallocating colours is meaningless here */
2879    if (gdImageTrueColor(im)) {
2880        RETURN_TRUE;
2881    }
2882
2883    col = index;
2884
2885    if (col >= 0 && col < gdImageColorsTotal(im)) {
2886        gdImageColorDeallocate(im, col);
2887        RETURN_TRUE;
2888    } else {
2889        php_error_docref(NULL, E_WARNING, "Color index %d out of range",    col);
2890        RETURN_FALSE;
2891    }
2892}
2893/* }}} */
2894
2895/* {{{ proto int imagecolorresolve(resource im, int red, int green, int blue)
2896   Get the index of the specified color or its closest possible alternative */
2897PHP_FUNCTION(imagecolorresolve)
2898{
2899    zval *IM;
2900    zend_long red, green, blue;
2901    gdImagePtr im;
2902
2903    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &red, &green, &blue) == FAILURE) {
2904        return;
2905    }
2906
2907    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2908        RETURN_FALSE;
2909    }
2910
2911    RETURN_LONG(gdImageColorResolve(im, red, green, blue));
2912}
2913/* }}} */
2914
2915/* {{{ proto int imagecolorexact(resource im, int red, int green, int blue)
2916   Get the index of the specified color */
2917PHP_FUNCTION(imagecolorexact)
2918{
2919    zval *IM;
2920    zend_long red, green, blue;
2921    gdImagePtr im;
2922
2923    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &red, &green, &blue) == FAILURE) {
2924        return;
2925    }
2926
2927    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2928        RETURN_FALSE;
2929    }
2930
2931    RETURN_LONG(gdImageColorExact(im, red, green, blue));
2932}
2933/* }}} */
2934
2935/* {{{ proto void imagecolorset(resource im, int col, int red, int green, int blue)
2936   Set the color for the specified palette index */
2937PHP_FUNCTION(imagecolorset)
2938{
2939    zval *IM;
2940    zend_long color, red, green, blue, alpha = 0;
2941    int col;
2942    gdImagePtr im;
2943
2944    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll|l", &IM, &color, &red, &green, &blue, &alpha) == FAILURE) {
2945        return;
2946    }
2947
2948    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2949        RETURN_FALSE;
2950    }
2951
2952    col = color;
2953
2954    if (col >= 0 && col < gdImageColorsTotal(im)) {
2955        im->red[col]   = red;
2956        im->green[col] = green;
2957        im->blue[col]  = blue;
2958        im->alpha[col]  = alpha;
2959    } else {
2960        RETURN_FALSE;
2961    }
2962}
2963/* }}} */
2964
2965/* {{{ proto array imagecolorsforindex(resource im, int col)
2966   Get the colors for an index */
2967PHP_FUNCTION(imagecolorsforindex)
2968{
2969    zval *IM;
2970    zend_long index;
2971    int col;
2972    gdImagePtr im;
2973
2974    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &IM, &index) == FAILURE) {
2975        return;
2976    }
2977
2978    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
2979        RETURN_FALSE;
2980    }
2981
2982    col = index;
2983
2984    if ((col >= 0 && gdImageTrueColor(im)) || (!gdImageTrueColor(im) && col >= 0 && col < gdImageColorsTotal(im))) {
2985        array_init(return_value);
2986
2987        add_assoc_long(return_value,"red",  gdImageRed(im,col));
2988        add_assoc_long(return_value,"green", gdImageGreen(im,col));
2989        add_assoc_long(return_value,"blue", gdImageBlue(im,col));
2990        add_assoc_long(return_value,"alpha", gdImageAlpha(im,col));
2991    } else {
2992        php_error_docref(NULL, E_WARNING, "Color index %d out of range", col);
2993        RETURN_FALSE;
2994    }
2995}
2996/* }}} */
2997
2998/* {{{ proto bool imagegammacorrect(resource im, float inputgamma, float outputgamma)
2999   Apply a gamma correction to a GD image */
3000PHP_FUNCTION(imagegammacorrect)
3001{
3002    zval *IM;
3003    gdImagePtr im;
3004    int i;
3005    double input, output;
3006
3007    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rdd", &IM, &input, &output) == FAILURE) {
3008        return;
3009    }
3010
3011    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3012        RETURN_FALSE;
3013    }
3014
3015    if (gdImageTrueColor(im))   {
3016        int x, y, c;
3017
3018        for (y = 0; y < gdImageSY(im); y++) {
3019            for (x = 0; x < gdImageSX(im); x++) {
3020                c = gdImageGetPixel(im, x, y);
3021                gdImageSetPixel(im, x, y,
3022                    gdTrueColorAlpha(
3023                        (int) ((pow((pow((gdTrueColorGetRed(c)   / 255.0), input)), 1.0 / output) * 255) + .5),
3024                        (int) ((pow((pow((gdTrueColorGetGreen(c) / 255.0), input)), 1.0 / output) * 255) + .5),
3025                        (int) ((pow((pow((gdTrueColorGetBlue(c)  / 255.0), input)), 1.0 / output) * 255) + .5),
3026                        gdTrueColorGetAlpha(c)
3027                    )
3028                );
3029            }
3030        }
3031        RETURN_TRUE;
3032    }
3033
3034    for (i = 0; i < gdImageColorsTotal(im); i++) {
3035        im->red[i]   = (int)((pow((pow((im->red[i]   / 255.0), input)), 1.0 / output) * 255) + .5);
3036        im->green[i] = (int)((pow((pow((im->green[i] / 255.0), input)), 1.0 / output) * 255) + .5);
3037        im->blue[i]  = (int)((pow((pow((im->blue[i]  / 255.0), input)), 1.0 / output) * 255) + .5);
3038    }
3039
3040    RETURN_TRUE;
3041}
3042/* }}} */
3043
3044/* {{{ proto bool imagesetpixel(resource im, int x, int y, int col)
3045   Set a single pixel */
3046PHP_FUNCTION(imagesetpixel)
3047{
3048    zval *IM;
3049    zend_long x, y, col;
3050    gdImagePtr im;
3051
3052    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &x, &y, &col) == FAILURE) {
3053        return;
3054    }
3055
3056    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3057        RETURN_FALSE;
3058    }
3059
3060    gdImageSetPixel(im, x, y, col);
3061    RETURN_TRUE;
3062}
3063/* }}} */
3064
3065/* {{{ proto bool imageline(resource im, int x1, int y1, int x2, int y2, int col)
3066   Draw a line */
3067PHP_FUNCTION(imageline)
3068{
3069    zval *IM;
3070    zend_long x1, y1, x2, y2, col;
3071    gdImagePtr im;
3072
3073    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &x1, &y1, &x2, &y2, &col) == FAILURE) {
3074        return;
3075    }
3076
3077    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3078        RETURN_FALSE;
3079    }
3080
3081#ifdef HAVE_GD_BUNDLED
3082    if (im->antialias) {
3083        gdImageAALine(im, x1, y1, x2, y2, col);
3084    } else
3085#endif
3086    {
3087        gdImageLine(im, x1, y1, x2, y2, col);
3088    }
3089    RETURN_TRUE;
3090}
3091/* }}} */
3092
3093/* {{{ proto bool imagedashedline(resource im, int x1, int y1, int x2, int y2, int col)
3094   Draw a dashed line */
3095PHP_FUNCTION(imagedashedline)
3096{
3097    zval *IM;
3098    zend_long x1, y1, x2, y2, col;
3099    gdImagePtr im;
3100
3101    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &x1, &y1, &x2, &y2, &col) == FAILURE) {
3102        return;
3103    }
3104
3105    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3106        RETURN_FALSE;
3107    }
3108
3109    gdImageDashedLine(im, x1, y1, x2, y2, col);
3110    RETURN_TRUE;
3111}
3112/* }}} */
3113
3114/* {{{ proto bool imagerectangle(resource im, int x1, int y1, int x2, int y2, int col)
3115   Draw a rectangle */
3116PHP_FUNCTION(imagerectangle)
3117{
3118    zval *IM;
3119    zend_long x1, y1, x2, y2, col;
3120    gdImagePtr im;
3121
3122    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &x1, &y1, &x2, &y2, &col) == FAILURE) {
3123        return;
3124    }
3125
3126    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3127        RETURN_FALSE;
3128    }
3129
3130    gdImageRectangle(im, x1, y1, x2, y2, col);
3131    RETURN_TRUE;
3132}
3133/* }}} */
3134
3135/* {{{ proto bool imagefilledrectangle(resource im, int x1, int y1, int x2, int y2, int col)
3136   Draw a filled rectangle */
3137PHP_FUNCTION(imagefilledrectangle)
3138{
3139    zval *IM;
3140    zend_long x1, y1, x2, y2, col;
3141    gdImagePtr im;
3142
3143    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &x1, &y1, &x2, &y2, &col) == FAILURE) {
3144        return;
3145    }
3146
3147    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3148        RETURN_FALSE;
3149    }
3150    gdImageFilledRectangle(im, x1, y1, x2, y2, col);
3151    RETURN_TRUE;
3152}
3153/* }}} */
3154
3155/* {{{ proto bool imagearc(resource im, int cx, int cy, int w, int h, int s, int e, int col)
3156   Draw a partial ellipse */
3157PHP_FUNCTION(imagearc)
3158{
3159    zval *IM;
3160    zend_long cx, cy, w, h, ST, E, col;
3161    gdImagePtr im;
3162    int e, st;
3163
3164    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllllll", &IM, &cx, &cy, &w, &h, &ST, &E, &col) == FAILURE) {
3165        return;
3166    }
3167
3168    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3169        RETURN_FALSE;
3170    }
3171
3172    e = E;
3173    if (e < 0) {
3174        e %= 360;
3175    }
3176
3177    st = ST;
3178    if (st < 0) {
3179        st %= 360;
3180    }
3181
3182    gdImageArc(im, cx, cy, w, h, st, e, col);
3183    RETURN_TRUE;
3184}
3185/* }}} */
3186
3187/* {{{ proto bool imageellipse(resource im, int cx, int cy, int w, int h, int color)
3188   Draw an ellipse */
3189PHP_FUNCTION(imageellipse)
3190{
3191    zval *IM;
3192    zend_long cx, cy, w, h, color;
3193    gdImagePtr im;
3194
3195    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllll", &IM, &cx, &cy, &w, &h, &color) == FAILURE) {
3196        return;
3197    }
3198
3199    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3200        RETURN_FALSE;
3201    }
3202
3203    gdImageEllipse(im, cx, cy, w, h, color);
3204    RETURN_TRUE;
3205}
3206/* }}} */
3207
3208/* {{{ proto bool imagefilltoborder(resource im, int x, int y, int border, int col)
3209   Flood fill to specific color */
3210PHP_FUNCTION(imagefilltoborder)
3211{
3212    zval *IM;
3213    zend_long x, y, border, col;
3214    gdImagePtr im;
3215
3216    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll", &IM, &x, &y, &border, &col) == FAILURE) {
3217        return;
3218    }
3219
3220    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3221        RETURN_FALSE;
3222    }
3223
3224    gdImageFillToBorder(im, x, y, border, col);
3225    RETURN_TRUE;
3226}
3227/* }}} */
3228
3229/* {{{ proto bool imagefill(resource im, int x, int y, int col)
3230   Flood fill */
3231PHP_FUNCTION(imagefill)
3232{
3233    zval *IM;
3234    zend_long x, y, col;
3235    gdImagePtr im;
3236
3237    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlll", &IM, &x, &y, &col) == FAILURE) {
3238        return;
3239    }
3240
3241    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3242        RETURN_FALSE;
3243    }
3244
3245    gdImageFill(im, x, y, col);
3246    RETURN_TRUE;
3247}
3248/* }}} */
3249
3250/* {{{ proto int imagecolorstotal(resource im)
3251   Find out the number of colors in an image's palette */
3252PHP_FUNCTION(imagecolorstotal)
3253{
3254    zval *IM;
3255    gdImagePtr im;
3256
3257    if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE) {
3258        return;
3259    }
3260
3261    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3262        RETURN_FALSE;
3263    }
3264
3265    RETURN_LONG(gdImageColorsTotal(im));
3266}
3267/* }}} */
3268
3269/* {{{ proto int imagecolortransparent(resource im [, int col])
3270   Define a color as transparent */
3271PHP_FUNCTION(imagecolortransparent)
3272{
3273    zval *IM;
3274    zend_long COL = 0;
3275    gdImagePtr im;
3276    int argc = ZEND_NUM_ARGS();
3277
3278    if (zend_parse_parameters(argc, "r|l", &IM, &COL) == FAILURE) {
3279        return;
3280    }
3281
3282    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3283        RETURN_FALSE;
3284    }
3285
3286    if (argc > 1) {
3287        gdImageColorTransparent(im, COL);
3288    }
3289
3290    RETURN_LONG(gdImageGetTransparent(im));
3291}
3292/* }}} */
3293
3294/* {{{ proto int imageinterlace(resource im [, int interlace])
3295   Enable or disable interlace */
3296PHP_FUNCTION(imageinterlace)
3297{
3298    zval *IM;
3299    int argc = ZEND_NUM_ARGS();
3300    zend_long INT = 0;
3301    gdImagePtr im;
3302
3303    if (zend_parse_parameters(argc, "r|l", &IM, &INT) == FAILURE) {
3304        return;
3305    }
3306
3307    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3308        RETURN_FALSE;
3309    }
3310
3311    if (argc > 1) {
3312        gdImageInterlace(im, INT);
3313    }
3314
3315    RETURN_LONG(gdImageGetInterlaced(im));
3316}
3317/* }}} */
3318
3319/* {{{ php_imagepolygon
3320   arg = 0  normal polygon
3321   arg = 1  filled polygon */
3322/* im, points, num_points, col */
3323static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled)
3324{
3325    zval *IM, *POINTS;
3326    zend_long NPOINTS, COL;
3327    zval *var = NULL;
3328    gdImagePtr im;
3329    gdPointPtr points;
3330    int npoints, col, nelem, i;
3331
3332    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rall", &IM, &POINTS, &NPOINTS, &COL) == FAILURE) {
3333        return;
3334    }
3335
3336    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3337        RETURN_FALSE;
3338    }
3339
3340    npoints = NPOINTS;
3341    col = COL;
3342
3343    nelem = zend_hash_num_elements(Z_ARRVAL_P(POINTS));
3344    if (nelem < 6) {
3345        php_error_docref(NULL, E_WARNING, "You must have at least 3 points in your array");
3346        RETURN_FALSE;
3347    }
3348    if (npoints <= 0) {
3349        php_error_docref(NULL, E_WARNING, "You must give a positive number of points");
3350        RETURN_FALSE;
3351    }
3352    if (nelem < npoints * 2) {
3353        php_error_docref(NULL, E_WARNING, "Trying to use %d points in array with only %d points", npoints, nelem/2);
3354        RETURN_FALSE;
3355    }
3356
3357    points = (gdPointPtr) safe_emalloc(npoints, sizeof(gdPoint), 0);
3358
3359    for (i = 0; i < npoints; i++) {
3360        if ((var = zend_hash_index_find(Z_ARRVAL_P(POINTS), (i * 2))) != NULL) {
3361            points[i].x = zval_get_long(var);
3362        }
3363        if ((var = zend_hash_index_find(Z_ARRVAL_P(POINTS), (i * 2) + 1)) != NULL) {
3364            points[i].y = zval_get_long(var);
3365        }
3366    }
3367
3368    if (filled) {
3369        gdImageFilledPolygon(im, points, npoints, col);
3370    } else {
3371        gdImagePolygon(im, points, npoints, col);
3372    }
3373
3374    efree(points);
3375    RETURN_TRUE;
3376}
3377/* }}} */
3378
3379/* {{{ proto bool imagepolygon(resource im, array point, int num_points, int col)
3380   Draw a polygon */
3381PHP_FUNCTION(imagepolygon)
3382{
3383    php_imagepolygon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3384}
3385/* }}} */
3386
3387/* {{{ proto bool imagefilledpolygon(resource im, array point, int num_points, int col)
3388   Draw a filled polygon */
3389PHP_FUNCTION(imagefilledpolygon)
3390{
3391    php_imagepolygon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3392}
3393/* }}} */
3394
3395/* {{{ php_find_gd_font
3396 */
3397static gdFontPtr php_find_gd_font(int size)
3398{
3399    gdFontPtr font;
3400
3401    switch (size) {
3402        case 1:
3403            font = gdFontTiny;
3404            break;
3405        case 2:
3406            font = gdFontSmall;
3407            break;
3408        case 3:
3409            font = gdFontMediumBold;
3410            break;
3411        case 4:
3412            font = gdFontLarge;
3413            break;
3414        case 5:
3415            font = gdFontGiant;
3416            break;
3417        default: {
3418             zval *zv = zend_hash_index_find(&EG(regular_list), size - 5);
3419             if (!zv || (Z_RES_P(zv))->type != le_gd_font) {
3420                 if (size < 1) {
3421                     font = gdFontTiny;
3422                 } else {
3423                     font = gdFontGiant;
3424                 }
3425             } else {
3426                 font = (gdFontPtr)Z_RES_P(zv)->ptr;
3427             }
3428         }
3429         break;
3430    }
3431
3432    return font;
3433}
3434/* }}} */
3435
3436/* {{{ php_imagefontsize
3437 * arg = 0  ImageFontWidth
3438 * arg = 1  ImageFontHeight
3439 */
3440static void php_imagefontsize(INTERNAL_FUNCTION_PARAMETERS, int arg)
3441{
3442    zend_long SIZE;
3443    gdFontPtr font;
3444
3445    if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &SIZE) == FAILURE) {
3446        return;
3447    }
3448
3449    font = php_find_gd_font(SIZE);
3450    RETURN_LONG(arg ? font->h : font->w);
3451}
3452/* }}} */
3453
3454/* {{{ proto int imagefontwidth(int font)
3455   Get font width */
3456PHP_FUNCTION(imagefontwidth)
3457{
3458    php_imagefontsize(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3459}
3460/* }}} */
3461
3462/* {{{ proto int imagefontheight(int font)
3463   Get font height */
3464PHP_FUNCTION(imagefontheight)
3465{
3466    php_imagefontsize(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3467}
3468/* }}} */
3469
3470/* {{{ php_gdimagecharup
3471 * workaround for a bug in gd 1.2 */
3472static void php_gdimagecharup(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
3473{
3474    int cx, cy, px, py, fline;
3475    cx = 0;
3476    cy = 0;
3477
3478    if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
3479        return;
3480    }
3481
3482    fline = (c - f->offset) * f->h * f->w;
3483    for (py = y; (py > (y - f->w)); py--) {
3484        for (px = x; (px < (x + f->h)); px++) {
3485            if (f->data[fline + cy * f->w + cx]) {
3486                gdImageSetPixel(im, px, py, color);
3487            }
3488            cy++;
3489        }
3490        cy = 0;
3491        cx++;
3492    }
3493}
3494/* }}} */
3495
3496/* {{{ php_imagechar
3497 * arg = 0  ImageChar
3498 * arg = 1  ImageCharUp
3499 * arg = 2  ImageString
3500 * arg = 3  ImageStringUp
3501 */
3502static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode)
3503{
3504    zval *IM;
3505    zend_long SIZE, X, Y, COL;
3506    char *C;
3507    size_t C_len;
3508    gdImagePtr im;
3509    int ch = 0, col, x, y, size, i, l = 0;
3510    unsigned char *str = NULL;
3511    gdFontPtr font;
3512
3513    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlllsl", &IM, &SIZE, &X, &Y, &C, &C_len, &COL) == FAILURE) {
3514        return;
3515    }
3516
3517    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3518        RETURN_FALSE;
3519    }
3520
3521    col = COL;
3522
3523    if (mode < 2) {
3524        ch = (int)((unsigned char)*C);
3525    } else {
3526        str = (unsigned char *) estrndup(C, C_len);
3527        l = strlen((char *)str);
3528    }
3529
3530    y = Y;
3531    x = X;
3532    size = SIZE;
3533
3534    font = php_find_gd_font(size);
3535
3536    switch (mode) {
3537        case 0:
3538            gdImageChar(im, font, x, y, ch, col);
3539            break;
3540        case 1:
3541            php_gdimagecharup(im, font, x, y, ch, col);
3542            break;
3543        case 2:
3544            for (i = 0; (i < l); i++) {
3545                gdImageChar(im, font, x, y, (int) ((unsigned char) str[i]), col);
3546                x += font->w;
3547            }
3548            break;
3549        case 3: {
3550            for (i = 0; (i < l); i++) {
3551                /* php_gdimagecharup(im, font, x, y, (int) str[i], col); */
3552                gdImageCharUp(im, font, x, y, (int) str[i], col);
3553                y -= font->w;
3554            }
3555            break;
3556        }
3557    }
3558    if (str) {
3559        efree(str);
3560    }
3561    RETURN_TRUE;
3562}
3563/* }}} */
3564
3565/* {{{ proto bool imagechar(resource im, int font, int x, int y, string c, int col)
3566   Draw a character */
3567PHP_FUNCTION(imagechar)
3568{
3569    php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3570}
3571/* }}} */
3572
3573/* {{{ proto bool imagecharup(resource im, int font, int x, int y, string c, int col)
3574   Draw a character rotated 90 degrees counter-clockwise */
3575PHP_FUNCTION(imagecharup)
3576{
3577    php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3578}
3579/* }}} */
3580
3581/* {{{ proto bool imagestring(resource im, int font, int x, int y, string str, int col)
3582   Draw a string horizontally */
3583PHP_FUNCTION(imagestring)
3584{
3585    php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
3586}
3587/* }}} */
3588
3589/* {{{ proto bool imagestringup(resource im, int font, int x, int y, string str, int col)
3590   Draw a string vertically - rotated 90 degrees counter-clockwise */
3591PHP_FUNCTION(imagestringup)
3592{
3593    php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
3594}
3595/* }}} */
3596
3597/* {{{ 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)
3598   Copy part of an image */
3599PHP_FUNCTION(imagecopy)
3600{
3601    zval *SIM, *DIM;
3602    zend_long SX, SY, SW, SH, DX, DY;
3603    gdImagePtr im_dst, im_src;
3604    int srcH, srcW, srcY, srcX, dstY, dstX;
3605
3606    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrllllll", &DIM, &SIM, &DX, &DY, &SX, &SY, &SW, &SH) == FAILURE) {
3607        return;
3608    }
3609
3610    if ((im_dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(DIM), "Image", le_gd)) == NULL) {
3611        RETURN_FALSE;
3612    }
3613
3614    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
3615        RETURN_FALSE;
3616    }
3617
3618    srcX = SX;
3619    srcY = SY;
3620    srcH = SH;
3621    srcW = SW;
3622    dstX = DX;
3623    dstY = DY;
3624
3625    gdImageCopy(im_dst, im_src, dstX, dstY, srcX, srcY, srcW, srcH);
3626    RETURN_TRUE;
3627}
3628/* }}} */
3629
3630/* {{{ 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)
3631   Merge one part of an image with another */
3632PHP_FUNCTION(imagecopymerge)
3633{
3634    zval *SIM, *DIM;
3635    zend_long SX, SY, SW, SH, DX, DY, PCT;
3636    gdImagePtr im_dst, im_src;
3637    int srcH, srcW, srcY, srcX, dstY, dstX, pct;
3638
3639    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrlllllll", &DIM, &SIM, &DX, &DY, &SX, &SY, &SW, &SH, &PCT) == FAILURE) {
3640        return;
3641    }
3642
3643    if ((im_dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(DIM), "Image", le_gd)) == NULL) {
3644        RETURN_FALSE;
3645    }
3646
3647    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
3648        RETURN_FALSE;
3649    }
3650
3651    srcX = SX;
3652    srcY = SY;
3653    srcH = SH;
3654    srcW = SW;
3655    dstX = DX;
3656    dstY = DY;
3657    pct  = PCT;
3658
3659    gdImageCopyMerge(im_dst, im_src, dstX, dstY, srcX, srcY, srcW, srcH, pct);
3660    RETURN_TRUE;
3661}
3662/* }}} */
3663
3664/* {{{ 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)
3665   Merge one part of an image with another */
3666PHP_FUNCTION(imagecopymergegray)
3667{
3668    zval *SIM, *DIM;
3669    zend_long SX, SY, SW, SH, DX, DY, PCT;
3670    gdImagePtr im_dst, im_src;
3671    int srcH, srcW, srcY, srcX, dstY, dstX, pct;
3672
3673    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrlllllll", &DIM, &SIM, &DX, &DY, &SX, &SY, &SW, &SH, &PCT) == FAILURE) {
3674        return;
3675    }
3676
3677    if ((im_dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(DIM), "Image", le_gd)) == NULL) {
3678        RETURN_FALSE;
3679    }
3680
3681    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
3682        RETURN_FALSE;
3683    }
3684
3685    srcX = SX;
3686    srcY = SY;
3687    srcH = SH;
3688    srcW = SW;
3689    dstX = DX;
3690    dstY = DY;
3691    pct  = PCT;
3692
3693    gdImageCopyMergeGray(im_dst, im_src, dstX, dstY, srcX, srcY, srcW, srcH, pct);
3694    RETURN_TRUE;
3695}
3696/* }}} */
3697
3698/* {{{ 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)
3699   Copy and resize part of an image */
3700PHP_FUNCTION(imagecopyresized)
3701{
3702    zval *SIM, *DIM;
3703    zend_long SX, SY, SW, SH, DX, DY, DW, DH;
3704    gdImagePtr im_dst, im_src;
3705    int srcH, srcW, dstH, dstW, srcY, srcX, dstY, dstX;
3706
3707    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrllllllll", &DIM, &SIM, &DX, &DY, &SX, &SY, &DW, &DH, &SW, &SH) == FAILURE) {
3708        return;
3709    }
3710
3711    if ((im_dst = (gdImagePtr)zend_fetch_resource(Z_RES_P(DIM), "Image", le_gd)) == NULL) {
3712        RETURN_FALSE;
3713    }
3714
3715    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
3716        RETURN_FALSE;
3717    }
3718
3719    srcX = SX;
3720    srcY = SY;
3721    srcH = SH;
3722    srcW = SW;
3723    dstX = DX;
3724    dstY = DY;
3725    dstH = DH;
3726    dstW = DW;
3727
3728    if (dstW <= 0 || dstH <= 0 || srcW <= 0 || srcH <= 0) {
3729        php_error_docref(NULL, E_WARNING, "Invalid image dimensions");
3730        RETURN_FALSE;
3731    }
3732
3733    gdImageCopyResized(im_dst, im_src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);
3734    RETURN_TRUE;
3735}
3736/* }}} */
3737
3738/* {{{ proto int imagesx(resource im)
3739   Get image width */
3740PHP_FUNCTION(imagesx)
3741{
3742    zval *IM;
3743    gdImagePtr im;
3744
3745    if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE) {
3746        return;
3747    }
3748
3749    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3750        RETURN_FALSE;
3751    }
3752
3753    RETURN_LONG(gdImageSX(im));
3754}
3755/* }}} */
3756
3757/* {{{ proto int imagesy(resource im)
3758   Get image height */
3759PHP_FUNCTION(imagesy)
3760{
3761    zval *IM;
3762    gdImagePtr im;
3763
3764    if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &IM) == FAILURE) {
3765        return;
3766    }
3767
3768    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3769        RETURN_FALSE;
3770    }
3771
3772    RETURN_LONG(gdImageSY(im));
3773}
3774/* }}} */
3775
3776#ifdef ENABLE_GD_TTF
3777#define TTFTEXT_DRAW 0
3778#define TTFTEXT_BBOX 1
3779#endif
3780
3781#ifdef ENABLE_GD_TTF
3782
3783#if HAVE_GD_FREETYPE && HAVE_LIBFREETYPE
3784/* {{{ proto array imageftbbox(float size, float angle, string font_file, string text [, array extrainfo])
3785   Give the bounding box of a text using fonts via freetype2 */
3786PHP_FUNCTION(imageftbbox)
3787{
3788    php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_BBOX, 1);
3789}
3790/* }}} */
3791
3792/* {{{ proto array imagefttext(resource im, float size, float angle, int x, int y, int col, string font_file, string text [, array extrainfo])
3793   Write text to the image using fonts via freetype2 */
3794PHP_FUNCTION(imagefttext)
3795{
3796    php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_DRAW, 1);
3797}
3798/* }}} */
3799#endif /* HAVE_GD_FREETYPE && HAVE_LIBFREETYPE */
3800
3801/* {{{ proto array imagettfbbox(float size, float angle, string font_file, string text)
3802   Give the bounding box of a text using TrueType fonts */
3803PHP_FUNCTION(imagettfbbox)
3804{
3805    php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_BBOX, 0);
3806}
3807/* }}} */
3808
3809/* {{{ proto array imagettftext(resource im, float size, float angle, int x, int y, int col, string font_file, string text)
3810   Write text to the image using a TrueType font */
3811PHP_FUNCTION(imagettftext)
3812{
3813    php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_DRAW, 0);
3814}
3815/* }}} */
3816
3817/* {{{ php_imagettftext_common
3818 */
3819static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int extended)
3820{
3821    zval *IM, *EXT = NULL;
3822    gdImagePtr im=NULL;
3823    zend_long col = -1, x = -1, y = -1;
3824    size_t str_len, fontname_len;
3825    int i, brect[8];
3826    double ptsize, angle;
3827    char *str = NULL, *fontname = NULL;
3828    char *error = NULL;
3829    int argc = ZEND_NUM_ARGS();
3830    gdFTStringExtra strex = {0};
3831
3832    if (mode == TTFTEXT_BBOX) {
3833        if (argc < 4 || argc > ((extended) ? 5 : 4)) {
3834            ZEND_WRONG_PARAM_COUNT();
3835        } else if (zend_parse_parameters(argc, "ddss|a", &ptsize, &angle, &fontname, &fontname_len, &str, &str_len, &EXT) == FAILURE) {
3836            RETURN_FALSE;
3837        }
3838    } else {
3839        if (argc < 8 || argc > ((extended) ? 9 : 8)) {
3840            ZEND_WRONG_PARAM_COUNT();
3841        } else if (zend_parse_parameters(argc, "rddlllss|a", &IM, &ptsize, &angle, &x, &y, &col, &fontname, &fontname_len, &str, &str_len, &EXT) == FAILURE) {
3842            RETURN_FALSE;
3843        }
3844        if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
3845            RETURN_FALSE;
3846        }
3847    }
3848
3849    /* convert angle to radians */
3850    angle = angle * (M_PI/180);
3851
3852    if (extended && EXT) {  /* parse extended info */
3853        zval *item;
3854        zend_string *key;
3855        zend_ulong num_key;
3856
3857        /* walk the assoc array */
3858        ZEND_HASH_FOREACH_KEY_VAL(HASH_OF(EXT), num_key, key, item) {
3859            if (key == NULL) {
3860                continue;
3861            }
3862            if (strcmp("linespacing", ZSTR_VAL(key)) == 0) {
3863                strex.flags |= gdFTEX_LINESPACE;
3864                strex.linespacing = zval_get_double(item);
3865            }
3866        } ZEND_HASH_FOREACH_END();
3867    }
3868
3869#ifdef VIRTUAL_DIR
3870    {
3871        char tmp_font_path[MAXPATHLEN];
3872
3873        if (!VCWD_REALPATH(fontname, tmp_font_path)) {
3874            fontname = NULL;
3875        }
3876    }
3877#endif /* VIRTUAL_DIR */
3878
3879    PHP_GD_CHECK_OPEN_BASEDIR(fontname, "Invalid font filename");
3880
3881#ifdef HAVE_GD_FREETYPE
3882    if (extended) {
3883        error = gdImageStringFTEx(im, brect, col, fontname, ptsize, angle, x, y, str, &strex);
3884    }
3885    else
3886        error = gdImageStringFT(im, brect, col, fontname, ptsize, angle, x, y, str);
3887
3888#endif /* HAVE_GD_FREETYPE */
3889
3890    if (error) {
3891        php_error_docref(NULL, E_WARNING, "%s", error);
3892        RETURN_FALSE;
3893    }
3894
3895    array_init(return_value);
3896
3897    /* return array with the text's bounding box */
3898    for (i = 0; i < 8; i++) {
3899        add_next_index_long(return_value, brect[i]);
3900    }
3901}
3902/* }}} */
3903#endif  /* ENABLE_GD_TTF */
3904
3905/* {{{ proto bool image2wbmp(resource im [, string filename [, int threshold]])
3906   Output WBMP image to browser or file */
3907PHP_FUNCTION(image2wbmp)
3908{
3909    _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_CONVERT_WBM, "WBMP", _php_image_bw_convert);
3910}
3911/* }}} */
3912
3913#if defined(HAVE_GD_JPG)
3914/* {{{ proto bool jpeg2wbmp (string f_org, string f_dest, int d_height, int d_width, int threshold)
3915   Convert JPEG image to WBMP image */
3916PHP_FUNCTION(jpeg2wbmp)
3917{
3918    _php_image_convert(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG);
3919}
3920/* }}} */
3921#endif
3922
3923#if defined(HAVE_GD_PNG)
3924/* {{{ proto bool png2wbmp (string f_org, string f_dest, int d_height, int d_width, int threshold)
3925   Convert PNG image to WBMP image */
3926PHP_FUNCTION(png2wbmp)
3927{
3928    _php_image_convert(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG);
3929}
3930/* }}} */
3931#endif
3932
3933/* {{{ _php_image_bw_convert
3934 * It converts a gd Image to bw using a threshold value */
3935static void _php_image_bw_convert(gdImagePtr im_org, gdIOCtx *out, int threshold)
3936{
3937    gdImagePtr im_dest;
3938    int white, black;
3939    int color, color_org, median;
3940    int dest_height = gdImageSY(im_org);
3941    int dest_width = gdImageSX(im_org);
3942    int x, y;
3943
3944    im_dest = gdImageCreate(dest_width, dest_height);
3945    if (im_dest == NULL) {
3946        php_error_docref(NULL, E_WARNING, "Unable to allocate temporary buffer");
3947        return;
3948    }
3949
3950    white = gdImageColorAllocate(im_dest, 255, 255, 255);
3951    if (white == -1) {
3952        php_error_docref(NULL, E_WARNING, "Unable to allocate the colors for the destination buffer");
3953        return;
3954    }
3955
3956    black = gdImageColorAllocate(im_dest, 0, 0, 0);
3957    if (black == -1) {
3958        php_error_docref(NULL, E_WARNING, "Unable to allocate the colors for the destination buffer");
3959        return;
3960    }
3961
3962    if (im_org->trueColor) {
3963        gdImageTrueColorToPalette(im_org, 1, 256);
3964    }
3965
3966    for (y = 0; y < dest_height; y++) {
3967        for (x = 0; x < dest_width; x++) {
3968            color_org = gdImageGetPixel(im_org, x, y);
3969            median = (im_org->red[color_org] + im_org->green[color_org] + im_org->blue[color_org]) / 3;
3970            if (median < threshold) {
3971                color = black;
3972            } else {
3973                color = white;
3974            }
3975            gdImageSetPixel (im_dest, x, y, color);
3976        }
3977    }
3978    gdImageWBMPCtx (im_dest, black, out);
3979
3980}
3981/* }}} */
3982
3983/* {{{ _php_image_convert
3984 * _php_image_convert converts jpeg/png images to wbmp and resizes them as needed  */
3985static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type )
3986{
3987    char *f_org, *f_dest;
3988    size_t f_org_len, f_dest_len;
3989    zend_long height, width, threshold;
3990    gdImagePtr im_org, im_dest, im_tmp;
3991    char *fn_org = NULL;
3992    char *fn_dest = NULL;
3993    FILE *org, *dest;
3994    int dest_height = -1;
3995    int dest_width = -1;
3996    int org_height, org_width;
3997    int white, black;
3998    int color, color_org, median;
3999    int int_threshold;
4000    int x, y;
4001    float x_ratio, y_ratio;
4002#ifdef HAVE_GD_JPG
4003    zend_long ignore_warning;
4004#endif
4005
4006    if (zend_parse_parameters(ZEND_NUM_ARGS(), "pplll", &f_org, &f_org_len, &f_dest, &f_dest_len, &height, &width, &threshold) == FAILURE) {
4007        return;
4008    }
4009
4010    fn_org  = f_org;
4011    fn_dest = f_dest;
4012    dest_height = height;
4013    dest_width = width;
4014    int_threshold = threshold;
4015
4016    /* Check threshold value */
4017    if (int_threshold < 0 || int_threshold > 8) {
4018        php_error_docref(NULL, E_WARNING, "Invalid threshold value '%d'", int_threshold);
4019        RETURN_FALSE;
4020    }
4021
4022    /* Check origin file */
4023    PHP_GD_CHECK_OPEN_BASEDIR(fn_org, "Invalid origin filename");
4024
4025    /* Check destination file */
4026    PHP_GD_CHECK_OPEN_BASEDIR(fn_dest, "Invalid destination filename");
4027
4028    /* Open origin file */
4029    org = VCWD_FOPEN(fn_org, "rb");
4030    if (!org) {
4031        php_error_docref(NULL, E_WARNING, "Unable to open '%s' for reading", fn_org);
4032        RETURN_FALSE;
4033    }
4034
4035    /* Open destination file */
4036    dest = VCWD_FOPEN(fn_dest, "wb");
4037    if (!dest) {
4038        php_error_docref(NULL, E_WARNING, "Unable to open '%s' for writing", fn_dest);
4039        RETURN_FALSE;
4040    }
4041
4042    switch (image_type) {
4043        case PHP_GDIMG_TYPE_GIF:
4044            im_org = gdImageCreateFromGif(org);
4045            if (im_org == NULL) {
4046                php_error_docref(NULL, E_WARNING, "Unable to open '%s' Not a valid GIF file", fn_dest);
4047                RETURN_FALSE;
4048            }
4049            break;
4050
4051#ifdef HAVE_GD_JPG
4052        case PHP_GDIMG_TYPE_JPG:
4053            ignore_warning = INI_INT("gd.jpeg_ignore_warning");
4054            im_org = gdImageCreateFromJpegEx(org, ignore_warning);
4055            if (im_org == NULL) {
4056                php_error_docref(NULL, E_WARNING, "Unable to open '%s' Not a valid JPEG file", fn_dest);
4057                RETURN_FALSE;
4058            }
4059            break;
4060#endif /* HAVE_GD_JPG */
4061
4062#ifdef HAVE_GD_PNG
4063        case PHP_GDIMG_TYPE_PNG:
4064            im_org = gdImageCreateFromPng(org);
4065            if (im_org == NULL) {
4066                php_error_docref(NULL, E_WARNING, "Unable to open '%s' Not a valid PNG file", fn_dest);
4067                RETURN_FALSE;
4068            }
4069            break;
4070#endif /* HAVE_GD_PNG */
4071
4072        default:
4073            php_error_docref(NULL, E_WARNING, "Format not supported");
4074            RETURN_FALSE;
4075            break;
4076    }
4077
4078    org_width  = gdImageSX (im_org);
4079    org_height = gdImageSY (im_org);
4080
4081    x_ratio = (float) org_width / (float) dest_width;
4082    y_ratio = (float) org_height / (float) dest_height;
4083
4084    if (x_ratio > 1 && y_ratio > 1) {
4085        if (y_ratio > x_ratio) {
4086            x_ratio = y_ratio;
4087        } else {
4088            y_ratio = x_ratio;
4089        }
4090        dest_width = (int) (org_width / x_ratio);
4091        dest_height = (int) (org_height / y_ratio);
4092    } else {
4093        x_ratio = (float) dest_width / (float) org_width;
4094        y_ratio = (float) dest_height / (float) org_height;
4095
4096        if (y_ratio < x_ratio) {
4097            x_ratio = y_ratio;
4098        } else {
4099            y_ratio = x_ratio;
4100        }
4101        dest_width = (int) (org_width * x_ratio);
4102        dest_height = (int) (org_height * y_ratio);
4103    }
4104
4105    im_tmp = gdImageCreate (dest_width, dest_height);
4106    if (im_tmp == NULL ) {
4107        php_error_docref(NULL, E_WARNING, "Unable to allocate temporary buffer");
4108        RETURN_FALSE;
4109    }
4110
4111    gdImageCopyResized (im_tmp, im_org, 0, 0, 0, 0, dest_width, dest_height, org_width, org_height);
4112
4113    gdImageDestroy(im_org);
4114
4115    fclose(org);
4116
4117    im_dest = gdImageCreate(dest_width, dest_height);
4118    if (im_dest == NULL) {
4119        php_error_docref(NULL, E_WARNING, "Unable to allocate destination buffer");
4120        RETURN_FALSE;
4121    }
4122
4123    white = gdImageColorAllocate(im_dest, 255, 255, 255);
4124    if (white == -1) {
4125        php_error_docref(NULL, E_WARNING, "Unable to allocate the colors for the destination buffer");
4126        RETURN_FALSE;
4127    }
4128
4129    black = gdImageColorAllocate(im_dest, 0, 0, 0);
4130    if (black == -1) {
4131        php_error_docref(NULL, E_WARNING, "Unable to allocate the colors for the destination buffer");
4132        RETURN_FALSE;
4133    }
4134
4135    int_threshold = int_threshold * 32;
4136
4137    for (y = 0; y < dest_height; y++) {
4138        for (x = 0; x < dest_width; x++) {
4139            color_org = gdImageGetPixel (im_tmp, x, y);
4140            median = (im_tmp->red[color_org] + im_tmp->green[color_org] + im_tmp->blue[color_org]) / 3;
4141            if (median < int_threshold) {
4142                color = black;
4143            } else {
4144                color = white;
4145            }
4146            gdImageSetPixel (im_dest, x, y, color);
4147        }
4148    }
4149
4150    gdImageDestroy (im_tmp );
4151
4152    gdImageWBMP(im_dest, black , dest);
4153
4154    fflush(dest);
4155    fclose(dest);
4156
4157    gdImageDestroy(im_dest);
4158
4159    RETURN_TRUE;
4160}
4161/* }}} */
4162
4163/* Section Filters */
4164#define PHP_GD_SINGLE_RES   \
4165    zval *SIM;  \
4166    gdImagePtr im_src;  \
4167    if (zend_parse_parameters(1, "r", &SIM) == FAILURE) {   \
4168        RETURN_FALSE;   \
4169    }   \
4170    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) { \
4171        RETURN_FALSE;   \
4172    }
4173
4174static void php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS)
4175{
4176    PHP_GD_SINGLE_RES
4177
4178    if (gdImageNegate(im_src) == 1) {
4179        RETURN_TRUE;
4180    }
4181
4182    RETURN_FALSE;
4183}
4184
4185static void php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS)
4186{
4187    PHP_GD_SINGLE_RES
4188
4189    if (gdImageGrayScale(im_src) == 1) {
4190        RETURN_TRUE;
4191    }
4192
4193    RETURN_FALSE;
4194}
4195
4196static void php_image_filter_brightness(INTERNAL_FUNCTION_PARAMETERS)
4197{
4198    zval *SIM;
4199    gdImagePtr im_src;
4200    zend_long brightness, tmp;
4201
4202    if (zend_parse_parameters(ZEND_NUM_ARGS(), "zll", &SIM, &tmp, &brightness) == FAILURE) {
4203        RETURN_FALSE;
4204    }
4205
4206    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
4207        RETURN_FALSE;
4208    }
4209
4210    if (im_src == NULL) {
4211        RETURN_FALSE;
4212    }
4213
4214    if (gdImageBrightness(im_src, (int)brightness) == 1) {
4215        RETURN_TRUE;
4216    }
4217
4218    RETURN_FALSE;
4219}
4220
4221static void php_image_filter_contrast(INTERNAL_FUNCTION_PARAMETERS)
4222{
4223    zval *SIM;
4224    gdImagePtr im_src;
4225    zend_long contrast, tmp;
4226
4227    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rll", &SIM, &tmp, &contrast) == FAILURE) {
4228        RETURN_FALSE;
4229    }
4230
4231    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
4232        RETURN_FALSE;
4233    }
4234
4235    if (im_src == NULL) {
4236        RETURN_FALSE;
4237    }
4238
4239    if (gdImageContrast(im_src, (int)contrast) == 1) {
4240        RETURN_TRUE;
4241    }
4242
4243    RETURN_FALSE;
4244}
4245
4246static void php_image_filter_colorize(INTERNAL_FUNCTION_PARAMETERS)
4247{
4248    zval *SIM;
4249    gdImagePtr im_src;
4250    zend_long r,g,b,tmp;
4251    zend_long a = 0;
4252
4253    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllll|l", &SIM, &tmp, &r, &g, &b, &a) == FAILURE) {
4254        RETURN_FALSE;
4255    }
4256
4257    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
4258        RETURN_FALSE;
4259    }
4260
4261    if (im_src == NULL) {
4262        RETURN_FALSE;
4263    }
4264
4265    if (gdImageColor(im_src, (int) r, (int) g, (int) b, (int) a) == 1) {
4266        RETURN_TRUE;
4267    }
4268
4269    RETURN_FALSE;
4270}
4271
4272static void php_image_filter_edgedetect(INTERNAL_FUNCTION_PARAMETERS)
4273{
4274    PHP_GD_SINGLE_RES
4275
4276    if (gdImageEdgeDetectQuick(im_src) == 1) {
4277        RETURN_TRUE;
4278    }
4279
4280    RETURN_FALSE;
4281}
4282
4283static void php_image_filter_emboss(INTERNAL_FUNCTION_PARAMETERS)
4284{
4285    PHP_GD_SINGLE_RES
4286
4287    if (gdImageEmboss(im_src) == 1) {
4288        RETURN_TRUE;
4289    }
4290
4291    RETURN_FALSE;
4292}
4293
4294static void php_image_filter_gaussian_blur(INTERNAL_FUNCTION_PARAMETERS)
4295{
4296    PHP_GD_SINGLE_RES
4297
4298    if (gdImageGaussianBlur(im_src) == 1) {
4299        RETURN_TRUE;
4300    }
4301
4302    RETURN_FALSE;
4303}
4304
4305static void php_image_filter_selective_blur(INTERNAL_FUNCTION_PARAMETERS)
4306{
4307    PHP_GD_SINGLE_RES
4308
4309    if (gdImageSelectiveBlur(im_src) == 1) {
4310        RETURN_TRUE;
4311    }
4312
4313    RETURN_FALSE;
4314}
4315
4316static void php_image_filter_mean_removal(INTERNAL_FUNCTION_PARAMETERS)
4317{
4318    PHP_GD_SINGLE_RES
4319
4320    if (gdImageMeanRemoval(im_src) == 1) {
4321        RETURN_TRUE;
4322    }
4323
4324    RETURN_FALSE;
4325}
4326
4327static void php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS)
4328{
4329    zval *SIM;
4330    zend_long tmp;
4331    gdImagePtr im_src;
4332    double weight;
4333
4334    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rld", &SIM, &tmp, &weight) == FAILURE) {
4335        RETURN_FALSE;
4336    }
4337
4338    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
4339        RETURN_FALSE;
4340    }
4341
4342    if (im_src == NULL) {
4343        RETURN_FALSE;
4344    }
4345
4346    if (gdImageSmooth(im_src, (float)weight)==1) {
4347        RETURN_TRUE;
4348    }
4349
4350    RETURN_FALSE;
4351}
4352
4353static void php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS)
4354{
4355    zval *IM;
4356    gdImagePtr im;
4357    zend_long tmp, blocksize;
4358    zend_bool mode = 0;
4359
4360    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rll|b", &IM, &tmp, &blocksize, &mode) == FAILURE) {
4361        RETURN_FALSE;
4362    }
4363
4364    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4365        RETURN_FALSE;
4366    }
4367
4368    if (im == NULL) {
4369        RETURN_FALSE;
4370    }
4371
4372    if (gdImagePixelate(im, (int) blocksize, (const unsigned int) mode)) {
4373        RETURN_TRUE;
4374    }
4375
4376    RETURN_FALSE;
4377}
4378
4379/* {{{ proto bool imagefilter(resource src_im, int filtertype[, int arg1 [, int arg2 [, int arg3 [, int arg4 ]]]] )
4380   Applies Filter an image using a custom angle */
4381PHP_FUNCTION(imagefilter)
4382{
4383    zval *tmp;
4384
4385    typedef void (*image_filter)(INTERNAL_FUNCTION_PARAMETERS);
4386    zend_long filtertype;
4387    image_filter filters[] =
4388    {
4389        php_image_filter_negate ,
4390        php_image_filter_grayscale,
4391        php_image_filter_brightness,
4392        php_image_filter_contrast,
4393        php_image_filter_colorize,
4394        php_image_filter_edgedetect,
4395        php_image_filter_emboss,
4396        php_image_filter_gaussian_blur,
4397        php_image_filter_selective_blur,
4398        php_image_filter_mean_removal,
4399        php_image_filter_smooth,
4400        php_image_filter_pixelate
4401    };
4402
4403    if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > IMAGE_FILTER_MAX_ARGS) {
4404        WRONG_PARAM_COUNT;
4405    } else if (zend_parse_parameters(2, "rl", &tmp, &filtertype) == FAILURE) {
4406        return;
4407    }
4408
4409    if (filtertype >= 0 && filtertype <= IMAGE_FILTER_MAX) {
4410        filters[filtertype](INTERNAL_FUNCTION_PARAM_PASSTHRU);
4411    }
4412}
4413/* }}} */
4414
4415/* {{{ proto resource imageconvolution(resource src_im, array matrix3x3, double div, double offset)
4416   Apply a 3x3 convolution matrix, using coefficient div and offset */
4417PHP_FUNCTION(imageconvolution)
4418{
4419    zval *SIM, *hash_matrix;
4420    zval *var = NULL, *var2 = NULL;
4421    gdImagePtr im_src = NULL;
4422    double div, offset;
4423    int nelem, i, j, res;
4424    float matrix[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}};
4425
4426    if (zend_parse_parameters(ZEND_NUM_ARGS(), "radd", &SIM, &hash_matrix, &div, &offset) == FAILURE) {
4427        RETURN_FALSE;
4428    }
4429
4430    if ((im_src = (gdImagePtr)zend_fetch_resource(Z_RES_P(SIM), "Image", le_gd)) == NULL) {
4431        RETURN_FALSE;
4432    }
4433
4434    nelem = zend_hash_num_elements(Z_ARRVAL_P(hash_matrix));
4435    if (nelem != 3) {
4436        php_error_docref(NULL, E_WARNING, "You must have 3x3 array");
4437        RETURN_FALSE;
4438    }
4439
4440    for (i=0; i<3; i++) {
4441        if ((var = zend_hash_index_find(Z_ARRVAL_P(hash_matrix), (i))) != NULL && Z_TYPE_P(var) == IS_ARRAY) {
4442            if (zend_hash_num_elements(Z_ARRVAL_P(var)) != 3 ) {
4443                php_error_docref(NULL, E_WARNING, "You must have 3x3 array");
4444                RETURN_FALSE;
4445            }
4446
4447            for (j=0; j<3; j++) {
4448                if ((var2 = zend_hash_index_find(Z_ARRVAL_P(var), j)) != NULL) {
4449                    matrix[i][j] = (float) zval_get_double(var2);
4450                } else {
4451                    php_error_docref(NULL, E_WARNING, "You must have a 3x3 matrix");
4452                    RETURN_FALSE;
4453                }
4454            }
4455        }
4456    }
4457    res = gdImageConvolution(im_src, matrix, (float)div, (float)offset);
4458
4459    if (res) {
4460        RETURN_TRUE;
4461    } else {
4462        RETURN_FALSE;
4463    }
4464}
4465/* }}} */
4466/* End section: Filters */
4467
4468/* {{{ proto void imageflip(resource im, int mode)
4469   Flip an image (in place) horizontally, vertically or both directions. */
4470PHP_FUNCTION(imageflip)
4471{
4472    zval *IM;
4473    zend_long mode;
4474    gdImagePtr im;
4475
4476    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &IM, &mode) == FAILURE)  {
4477        return;
4478    }
4479
4480    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4481        RETURN_FALSE;
4482    }
4483
4484    switch (mode) {
4485        case GD_FLIP_VERTICAL:
4486            gdImageFlipVertical(im);
4487            break;
4488
4489        case GD_FLIP_HORINZONTAL:
4490            gdImageFlipHorizontal(im);
4491            break;
4492
4493        case GD_FLIP_BOTH:
4494            gdImageFlipBoth(im);
4495            break;
4496
4497        default:
4498            php_error_docref(NULL, E_WARNING, "Unknown flip mode");
4499            RETURN_FALSE;
4500    }
4501
4502    RETURN_TRUE;
4503}
4504/* }}} */
4505
4506#ifdef HAVE_GD_BUNDLED
4507/* {{{ proto bool imageantialias(resource im, bool on)
4508   Should antialiased functions used or not*/
4509PHP_FUNCTION(imageantialias)
4510{
4511    zval *IM;
4512    zend_bool alias;
4513    gdImagePtr im;
4514
4515    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rb", &IM, &alias) == FAILURE) {
4516        return;
4517    }
4518
4519    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4520        RETURN_FALSE;
4521    }
4522    gdImageAntialias(im, alias);
4523    RETURN_TRUE;
4524}
4525/* }}} */
4526#endif
4527
4528/* {{{ proto void imagecrop(resource im, array rect)
4529   Crop an image using the given coordinates and size, x, y, width and height. */
4530PHP_FUNCTION(imagecrop)
4531{
4532    zval *IM;
4533    gdImagePtr im;
4534    gdImagePtr im_crop;
4535    gdRect rect;
4536    zval *z_rect;
4537    zval *tmp;
4538
4539    if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra", &IM, &z_rect) == FAILURE)  {
4540        return;
4541    }
4542
4543    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4544        RETURN_FALSE;
4545    }
4546
4547    if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "x", sizeof("x") -1)) != NULL) {
4548        rect.x = zval_get_long(tmp);
4549    } else {
4550        php_error_docref(NULL, E_WARNING, "Missing x position");
4551        RETURN_FALSE;
4552    }
4553
4554    if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "y", sizeof("y") - 1)) != NULL) {
4555        rect.y = zval_get_long(tmp);
4556    } else {
4557        php_error_docref(NULL, E_WARNING, "Missing y position");
4558        RETURN_FALSE;
4559    }
4560
4561    if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "width", sizeof("width") - 1)) != NULL) {
4562        rect.width = zval_get_long(tmp);
4563    } else {
4564        php_error_docref(NULL, E_WARNING, "Missing width");
4565        RETURN_FALSE;
4566    }
4567
4568    if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "height", sizeof("height") - 1)) != NULL) {
4569        rect.height = zval_get_long(tmp);
4570    } else {
4571        php_error_docref(NULL, E_WARNING, "Missing height");
4572        RETURN_FALSE;
4573    }
4574
4575    im_crop = gdImageCrop(im, &rect);
4576
4577    if (im_crop == NULL) {
4578        RETURN_FALSE;
4579    } else {
4580        RETURN_RES(zend_register_resource(im_crop, le_gd));
4581    }
4582}
4583/* }}} */
4584
4585/* {{{ proto void imagecropauto(resource im [, int mode [, float threshold [, int color]]])
4586   Crop an image automatically using one of the available modes. */
4587PHP_FUNCTION(imagecropauto)
4588{
4589    zval *IM;
4590    zend_long mode = -1;
4591    zend_long color = -1;
4592    double threshold = 0.5f;
4593    gdImagePtr im;
4594    gdImagePtr im_crop;
4595
4596    if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|ldl", &IM, &mode, &threshold, &color) == FAILURE)  {
4597        return;
4598    }
4599
4600    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4601        RETURN_FALSE;
4602    }
4603
4604    switch (mode) {
4605        case -1:
4606            mode = GD_CROP_DEFAULT;
4607        case GD_CROP_DEFAULT:
4608        case GD_CROP_TRANSPARENT:
4609        case GD_CROP_BLACK:
4610        case GD_CROP_WHITE:
4611        case GD_CROP_SIDES:
4612            im_crop = gdImageCropAuto(im, mode);
4613            break;
4614
4615        case GD_CROP_THRESHOLD:
4616            if (color < 0) {
4617                php_error_docref(NULL, E_WARNING, "Color argument missing with threshold mode");
4618                RETURN_FALSE;
4619            }
4620            im_crop = gdImageCropThreshold(im, color, (float) threshold);
4621            break;
4622
4623        default:
4624            php_error_docref(NULL, E_WARNING, "Unknown crop mode");
4625            RETURN_FALSE;
4626    }
4627    if (im_crop == NULL) {
4628        RETURN_FALSE;
4629    } else {
4630        RETURN_RES(zend_register_resource(im_crop, le_gd));
4631    }
4632}
4633/* }}} */
4634
4635/* {{{ proto resource imagescale(resource im, int new_width[, int new_height[, int method]])
4636   Scale an image using the given new width and height. */
4637PHP_FUNCTION(imagescale)
4638{
4639    zval *IM;
4640    gdImagePtr im;
4641    gdImagePtr im_scaled = NULL;
4642    int new_width, new_height;
4643    zend_long tmp_w, tmp_h=-1, tmp_m = GD_BILINEAR_FIXED;
4644    gdInterpolationMethod method;
4645
4646    if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|ll", &IM, &tmp_w, &tmp_h, &tmp_m) == FAILURE)  {
4647        return;
4648    }
4649    method = tmp_m;
4650
4651    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4652        RETURN_FALSE;
4653    }
4654
4655    if (tmp_h < 0) {
4656        /* preserve ratio */
4657        long src_x, src_y;
4658
4659        src_x = gdImageSX(im);
4660        src_y = gdImageSY(im);
4661        if (src_x) {
4662            tmp_h = tmp_w * src_y / src_x;
4663        }
4664    }
4665
4666    new_width = tmp_w;
4667    new_height = tmp_h;
4668
4669    if (gdImageSetInterpolationMethod(im, method)) {
4670        im_scaled = gdImageScale(im, new_width, new_height);
4671    }
4672
4673    if (im_scaled == NULL) {
4674        RETURN_FALSE;
4675    } else {
4676        RETURN_RES(zend_register_resource(im_scaled, le_gd));
4677    }
4678}
4679/* }}} */
4680
4681/* {{{ proto resource imageaffine(resource src, array affine[, array clip])
4682   Return an image containing the affine tramsformed src image, using an optional clipping area */
4683PHP_FUNCTION(imageaffine)
4684{
4685    zval *IM;
4686    gdImagePtr src;
4687    gdImagePtr dst;
4688    gdRect rect;
4689    gdRectPtr pRect = NULL;
4690    zval *z_rect = NULL;
4691    zval *z_affine;
4692    zval *tmp;
4693    double affine[6];
4694    int i, nelems;
4695    zval *zval_affine_elem = NULL;
4696
4697    if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra|a", &IM, &z_affine, &z_rect) == FAILURE)  {
4698        return;
4699    }
4700
4701    if ((src = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4702        RETURN_FALSE;
4703    }
4704
4705    if ((nelems = zend_hash_num_elements(Z_ARRVAL_P(z_affine))) != 6) {
4706        php_error_docref(NULL, E_WARNING, "Affine array must have six elements");
4707        RETURN_FALSE;
4708    }
4709
4710    for (i = 0; i < nelems; i++) {
4711        if ((zval_affine_elem = zend_hash_index_find(Z_ARRVAL_P(z_affine), i)) != NULL) {
4712            switch (Z_TYPE_P(zval_affine_elem)) {
4713                case IS_LONG:
4714                    affine[i]  = Z_LVAL_P(zval_affine_elem);
4715                    break;
4716                case IS_DOUBLE:
4717                    affine[i] = Z_DVAL_P(zval_affine_elem);
4718                    break;
4719                case IS_STRING:
4720                    affine[i] = zval_get_double(zval_affine_elem);
4721                    break;
4722                default:
4723                    php_error_docref(NULL, E_WARNING, "Invalid type for element %i", i);
4724                    RETURN_FALSE;
4725            }
4726        }
4727    }
4728
4729    if (z_rect != NULL) {
4730        if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "x", sizeof("x") - 1)) != NULL) {
4731            rect.x = zval_get_long(tmp);
4732        } else {
4733            php_error_docref(NULL, E_WARNING, "Missing x position");
4734            RETURN_FALSE;
4735        }
4736
4737        if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "y", sizeof("y") - 1)) != NULL) {
4738            rect.y = zval_get_long(tmp);
4739        } else {
4740            php_error_docref(NULL, E_WARNING, "Missing y position");
4741            RETURN_FALSE;
4742        }
4743
4744        if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "width", sizeof("width") - 1)) != NULL) {
4745            rect.width = zval_get_long(tmp);
4746        } else {
4747            php_error_docref(NULL, E_WARNING, "Missing width");
4748            RETURN_FALSE;
4749        }
4750
4751        if ((tmp = zend_hash_str_find(HASH_OF(z_rect), "height", sizeof("height") - 1)) != NULL) {
4752            rect.height = zval_get_long(tmp);
4753        } else {
4754            php_error_docref(NULL, E_WARNING, "Missing height");
4755            RETURN_FALSE;
4756        }
4757        pRect = &rect;
4758    } else {
4759        rect.x = -1;
4760        rect.y = -1;
4761        rect.width = gdImageSX(src);
4762        rect.height = gdImageSY(src);
4763        pRect = NULL;
4764    }
4765
4766    if (gdTransformAffineGetImage(&dst, src, pRect, affine) != GD_TRUE) {
4767        RETURN_FALSE;
4768    }
4769
4770    if (dst == NULL) {
4771        RETURN_FALSE;
4772    } else {
4773        RETURN_RES(zend_register_resource(dst, le_gd));
4774    }
4775}
4776/* }}} */
4777
4778/* {{{ proto array imageaffinematrixget(int type[, array options])
4779   Return an image containing the affine tramsformed src image, using an optional clipping area */
4780PHP_FUNCTION(imageaffinematrixget)
4781{
4782    double affine[6];
4783    zend_long type;
4784    zval *options = NULL;
4785    zval *tmp;
4786    int res = GD_FALSE, i;
4787
4788    if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|z", &type, &options) == FAILURE)  {
4789        return;
4790    }
4791
4792    switch((gdAffineStandardMatrix)type) {
4793        case GD_AFFINE_TRANSLATE:
4794        case GD_AFFINE_SCALE: {
4795            double x, y;
4796            if (!options || Z_TYPE_P(options) != IS_ARRAY) {
4797                php_error_docref(NULL, E_WARNING, "Array expected as options");
4798                RETURN_FALSE;
4799            }
4800            if ((tmp = zend_hash_str_find(HASH_OF(options), "x", sizeof("x") - 1)) != NULL) {
4801                x = zval_get_double(tmp);
4802            } else {
4803                php_error_docref(NULL, E_WARNING, "Missing x position");
4804                RETURN_FALSE;
4805            }
4806
4807            if ((tmp = zend_hash_str_find(HASH_OF(options), "y", sizeof("y") - 1)) != NULL) {
4808                y = zval_get_double(tmp);
4809            } else {
4810                php_error_docref(NULL, E_WARNING, "Missing y position");
4811                RETURN_FALSE;
4812            }
4813
4814            if (type == GD_AFFINE_TRANSLATE) {
4815                res = gdAffineTranslate(affine, x, y);
4816            } else {
4817                res = gdAffineScale(affine, x, y);
4818            }
4819            break;
4820        }
4821
4822        case GD_AFFINE_ROTATE:
4823        case GD_AFFINE_SHEAR_HORIZONTAL:
4824        case GD_AFFINE_SHEAR_VERTICAL: {
4825            double angle;
4826
4827            if (!options) {
4828                php_error_docref(NULL, E_WARNING, "Number is expected as option");
4829                RETURN_FALSE;
4830            }
4831
4832            angle = zval_get_double(options);
4833
4834            if (type == GD_AFFINE_SHEAR_HORIZONTAL) {
4835                res = gdAffineShearHorizontal(affine, angle);
4836            } else if (type == GD_AFFINE_SHEAR_VERTICAL) {
4837                res = gdAffineShearVertical(affine, angle);
4838            } else {
4839                res = gdAffineRotate(affine, angle);
4840            }
4841            break;
4842        }
4843
4844        default:
4845            php_error_docref(NULL, E_WARNING, "Invalid type for element %li", type);
4846            RETURN_FALSE;
4847    }
4848
4849    if (res == GD_FALSE) {
4850        RETURN_FALSE;
4851    } else {
4852        array_init(return_value);
4853        for (i = 0; i < 6; i++) {
4854            add_index_double(return_value, i, affine[i]);
4855        }
4856    }
4857} /* }}} */
4858
4859/* {{{ proto array imageaffineconcat(array m1, array m2)
4860   Concat two matrices (as in doing many ops in one go) */
4861PHP_FUNCTION(imageaffinematrixconcat)
4862{
4863    double m1[6];
4864    double m2[6];
4865    double mr[6];
4866
4867    zval *tmp;
4868    zval *z_m1;
4869    zval *z_m2;
4870    int i, nelems;
4871
4872    if (zend_parse_parameters(ZEND_NUM_ARGS(), "aa", &z_m1, &z_m2) == FAILURE)  {
4873        return;
4874    }
4875
4876    if (((nelems = zend_hash_num_elements(Z_ARRVAL_P(z_m1))) != 6) || (nelems = zend_hash_num_elements(Z_ARRVAL_P(z_m2))) != 6) {
4877        php_error_docref(NULL, E_WARNING, "Affine arrays must have six elements");
4878        RETURN_FALSE;
4879    }
4880
4881    for (i = 0; i < 6; i++) {
4882        if ((tmp = zend_hash_index_find(Z_ARRVAL_P(z_m1), i)) != NULL) {
4883            switch (Z_TYPE_P(tmp)) {
4884                case IS_LONG:
4885                    m1[i]  = Z_LVAL_P(tmp);
4886                    break;
4887                case IS_DOUBLE:
4888                    m1[i] = Z_DVAL_P(tmp);
4889                    break;
4890                case IS_STRING:
4891                    m1[i] = zval_get_double(tmp);
4892                    break;
4893                default:
4894                    php_error_docref(NULL, E_WARNING, "Invalid type for element %i", i);
4895                    RETURN_FALSE;
4896            }
4897        }
4898        if ((tmp = zend_hash_index_find(Z_ARRVAL_P(z_m2), i)) != NULL) {
4899            switch (Z_TYPE_P(tmp)) {
4900                case IS_LONG:
4901                    m2[i]  = Z_LVAL_P(tmp);
4902                    break;
4903                case IS_DOUBLE:
4904                    m2[i] = Z_DVAL_P(tmp);
4905                    break;
4906                case IS_STRING:
4907                    m2[i] = zval_get_double(tmp);
4908                    break;
4909                default:
4910                    php_error_docref(NULL, E_WARNING, "Invalid type for element %i", i);
4911                    RETURN_FALSE;
4912            }
4913        }
4914    }
4915
4916    if (gdAffineConcat (mr, m1, m2) != GD_TRUE) {
4917        RETURN_FALSE;
4918    }
4919
4920    array_init(return_value);
4921    for (i = 0; i < 6; i++) {
4922        add_index_double(return_value, i, mr[i]);
4923    }
4924} /* }}} */
4925
4926/* {{{ proto resource imagesetinterpolation(resource im [, int method]])
4927   Set the default interpolation method, passing -1 or 0 sets it to the libgd default (bilinear). */
4928PHP_FUNCTION(imagesetinterpolation)
4929{
4930    zval *IM;
4931    gdImagePtr im;
4932    zend_long method = GD_BILINEAR_FIXED;
4933
4934    if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &IM, &method) == FAILURE)  {
4935        return;
4936    }
4937
4938    if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
4939        RETURN_FALSE;
4940    }
4941
4942    if (method == -1) {
4943         method = GD_BILINEAR_FIXED;
4944    }
4945    RETURN_BOOL(gdImageSetInterpolationMethod(im, (gdInterpolationMethod) method));
4946}
4947/* }}} */
4948
4949/*
4950 * Local variables:
4951 * tab-width: 4
4952 * c-basic-offset: 4
4953 * End:
4954 * vim600: sw=4 ts=4 fdm=marker
4955 * vim<600: sw=4 ts=4
4956 */
4957