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