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