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