1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Rasmus Lerdorf <rasmus@php.net> |
14 | Stig Bakken <ssb@php.net> |
15 | Jim Winstead <jimw@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* gd 1.2 is copyright 1994, 1995, Quest Protein Database Center,
20 Cold Spring Harbor Labs. */
21
22 /* Note that there is no code from the gd package in this file */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include "php.h"
29 #include "php_ini.h"
30 #include "ext/standard/head.h"
31 #include <math.h>
32 #include "SAPI.h"
33 #include "php_gd.h"
34 #include "ext/standard/php_image.h"
35 #include "ext/standard/info.h"
36 #include "php_open_temporary_file.h"
37 #include "php_memory_streams.h"
38 #include "zend_object_handlers.h"
39
40 #ifdef HAVE_SYS_WAIT_H
41 # include <sys/wait.h>
42 #endif
43 #ifdef HAVE_UNISTD_H
44 # include <unistd.h>
45 #endif
46 #ifdef PHP_WIN32
47 # include <io.h>
48 # include <fcntl.h>
49 # include <windows.h>
50 # include <Winuser.h>
51 # include <Wingdi.h>
52 #endif
53
54 #if defined(HAVE_GD_XPM) && defined(HAVE_GD_BUNDLED)
55 # include <X11/xpm.h>
56 #endif
57
58 #include "gd_compat.h"
59
60 #ifdef HAVE_GD_BUNDLED
61 # include "libgd/gd.h"
62 # include "libgd/gd_errors.h"
63 # include "libgd/gdfontt.h" /* 1 Tiny font */
64 # include "libgd/gdfonts.h" /* 2 Small font */
65 # include "libgd/gdfontmb.h" /* 3 Medium bold font */
66 # include "libgd/gdfontl.h" /* 4 Large font */
67 # include "libgd/gdfontg.h" /* 5 Giant font */
68 #else
69 # include <gd.h>
70 # include <gd_errors.h>
71 # include <gdfontt.h> /* 1 Tiny font */
72 # include <gdfonts.h> /* 2 Small font */
73 # include <gdfontmb.h> /* 3 Medium bold font */
74 # include <gdfontl.h> /* 4 Large font */
75 # include <gdfontg.h> /* 5 Giant font */
76 #endif
77
78 #if defined(HAVE_GD_FREETYPE) && defined(HAVE_GD_BUNDLED)
79 # include <ft2build.h>
80 # include FT_FREETYPE_H
81 #endif
82
83 #if defined(HAVE_GD_XPM) && defined(HAVE_GD_BUNDLED)
84 # include "X11/xpm.h"
85 #endif
86
87 #ifndef M_PI
88 #define M_PI 3.14159265358979323846
89 #endif
90
91 /* don't used libgd constants, not used, so going to be removed */
92 #define PHP_GD_FLIP_HORIZONTAL 1
93 #define PHP_GD_FLIP_VERTICAL 2
94 #define PHP_GD_FLIP_BOTH 3
95
96 #ifdef HAVE_GD_FREETYPE
97 static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int);
98 #endif
99
100 #include "gd_arginfo.h"
101
102 /* as it is not really public, duplicate declaration here to avoid
103 pointless warnings */
104 int overflow2(int a, int b);
105
106 static void php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS);
107 static void php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS);
108 static void php_image_filter_brightness(INTERNAL_FUNCTION_PARAMETERS);
109 static void php_image_filter_contrast(INTERNAL_FUNCTION_PARAMETERS);
110 static void php_image_filter_colorize(INTERNAL_FUNCTION_PARAMETERS);
111 static void php_image_filter_edgedetect(INTERNAL_FUNCTION_PARAMETERS);
112 static void php_image_filter_emboss(INTERNAL_FUNCTION_PARAMETERS);
113 static void php_image_filter_gaussian_blur(INTERNAL_FUNCTION_PARAMETERS);
114 static void php_image_filter_selective_blur(INTERNAL_FUNCTION_PARAMETERS);
115 static void php_image_filter_mean_removal(INTERNAL_FUNCTION_PARAMETERS);
116 static void php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS);
117 static void php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS);
118 static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS);
119
120 /* End Section filters declarations */
121 static gdImagePtr _php_image_create_from_string(zend_string *Data, const char *tn, gdImagePtr (*ioctx_func_p)(gdIOCtxPtr));
122 static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, const char *tn, gdImagePtr (*func_p)(FILE *), gdImagePtr (*ioctx_func_p)(gdIOCtxPtr));
123 static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, const char *tn);
124 static gdIOCtx *create_stream_context(php_stream *stream, int close_stream);
125 static gdIOCtx *create_output_context(zval *to_zval, uint32_t arg_num);
126 static int _php_image_type(zend_string *data);
127
128 /*********************************************************
129 *
130 * GD Object Representation
131 *
132 ********************************************************/
133
134 zend_class_entry *gd_image_ce;
135
136 typedef struct _gd_ext_image_object {
137 gdImagePtr image;
138 zend_object std;
139 } php_gd_image_object;
140
141 static zend_object_handlers php_gd_image_object_handlers;
142
php_gd_image_object_get_constructor(zend_object * object)143 static zend_function *php_gd_image_object_get_constructor(zend_object *object)
144 {
145 zend_throw_error(NULL, "You cannot initialize a GdImage object except through helper functions");
146 return NULL;
147 }
148
149 /**
150 * Returns the underlying php_gd_image_object from a zend_object
151 */
152
php_gd_exgdimage_from_zobj_p(zend_object * obj)153 static zend_always_inline php_gd_image_object* php_gd_exgdimage_from_zobj_p(zend_object* obj)
154 {
155 return (php_gd_image_object *) ((char *) (obj) - XtOffsetOf(php_gd_image_object, std));
156 }
157
158 /**
159 * Converts an extension GdImage instance contained within a zval into the gdImagePtr
160 * for use with library APIs
161 */
php_gd_libgdimageptr_from_zval_p(zval * zp)162 PHP_GD_API gdImagePtr php_gd_libgdimageptr_from_zval_p(zval* zp)
163 {
164 return php_gd_exgdimage_from_zobj_p(Z_OBJ_P(zp))->image;
165 }
166
167
php_gd_image_object_create(zend_class_entry * class_type)168 zend_object *php_gd_image_object_create(zend_class_entry *class_type)
169 {
170 size_t block_len = sizeof(php_gd_image_object) + zend_object_properties_size(class_type);
171 php_gd_image_object *intern = emalloc(block_len);
172 memset(intern, 0, block_len);
173
174 zend_object_std_init(&intern->std, class_type);
175 object_properties_init(&intern->std, class_type);
176
177 return &intern->std;
178 }
179
php_gd_image_object_free(zend_object * intern)180 static void php_gd_image_object_free(zend_object *intern)
181 {
182 php_gd_image_object *img_obj_ptr = php_gd_exgdimage_from_zobj_p(intern);
183 if (img_obj_ptr->image) {
184 gdImageDestroy(img_obj_ptr->image);
185 }
186 zend_object_std_dtor(intern);
187 }
188
189 /**
190 * Creates a new GdImage object wrapping the gdImagePtr and attaches it
191 * to the zval (usually return_value).
192 *
193 * This function must only be called once per valid gdImagePtr
194 */
php_gd_assign_libgdimageptr_as_extgdimage(zval * val,gdImagePtr image)195 void php_gd_assign_libgdimageptr_as_extgdimage(zval *val, gdImagePtr image)
196 {
197 object_init_ex(val, gd_image_ce);
198 php_gd_exgdimage_from_zobj_p(Z_OBJ_P(val))->image = image;
199 }
200
php_gd_object_minit_helper(void)201 static void php_gd_object_minit_helper(void)
202 {
203 gd_image_ce = register_class_GdImage();
204 gd_image_ce->create_object = php_gd_image_object_create;
205 gd_image_ce->default_object_handlers = &php_gd_image_object_handlers;
206
207 /* setting up the object handlers for the GdImage class */
208 memcpy(&php_gd_image_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
209 php_gd_image_object_handlers.clone_obj = NULL;
210 php_gd_image_object_handlers.free_obj = php_gd_image_object_free;
211 php_gd_image_object_handlers.get_constructor = php_gd_image_object_get_constructor;
212 php_gd_image_object_handlers.compare = zend_objects_not_comparable;
213 php_gd_image_object_handlers.offset = XtOffsetOf(php_gd_image_object, std);
214 }
215
216 static zend_class_entry *gd_font_ce = NULL;
217 static zend_object_handlers php_gd_font_object_handlers;
218
219 typedef struct _php_gd_font_object {
220 gdFontPtr font;
221 zend_object std;
222 } php_gd_font_object;
223
php_gd_font_object_from_zend_object(zend_object * zobj)224 static php_gd_font_object *php_gd_font_object_from_zend_object(zend_object *zobj)
225 {
226 return ((php_gd_font_object*)(zobj + 1)) - 1;
227 }
228
php_gd_font_object_to_zend_object(php_gd_font_object * obj)229 static zend_object *php_gd_font_object_to_zend_object(php_gd_font_object *obj)
230 {
231 return ((zend_object*)(obj + 1)) - 1;
232 }
233
php_gd_font_object_create(zend_class_entry * ce)234 static zend_object *php_gd_font_object_create(zend_class_entry *ce)
235 {
236 php_gd_font_object *obj = zend_object_alloc(sizeof(php_gd_font_object), ce);
237 zend_object *zobj = php_gd_font_object_to_zend_object(obj);
238
239 obj->font = NULL;
240 zend_object_std_init(zobj, ce);
241 object_properties_init(zobj, ce);
242 zobj->handlers = &php_gd_font_object_handlers;
243
244 return zobj;
245 }
246
php_gd_font_object_free(zend_object * zobj)247 static void php_gd_font_object_free(zend_object *zobj)
248 {
249 php_gd_font_object *obj = php_gd_font_object_from_zend_object(zobj);
250
251 if (obj->font) {
252 if (obj->font->data) {
253 efree(obj->font->data);
254 }
255 efree(obj->font);
256 obj->font = NULL;
257 }
258
259 zend_object_std_dtor(zobj);
260 }
261
php_gd_font_object_get_constructor(zend_object * object)262 static zend_function *php_gd_font_object_get_constructor(zend_object *object)
263 {
264 zend_throw_error(NULL, "You cannot initialize a GdFont object except through helper functions");
265 return NULL;
266 }
267
php_gd_font_minit_helper(void)268 static void php_gd_font_minit_helper(void)
269 {
270 gd_font_ce = register_class_GdFont();
271 gd_font_ce->create_object = php_gd_font_object_create;
272
273 /* setting up the object handlers for the GdFont class */
274 memcpy(&php_gd_font_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
275 php_gd_font_object_handlers.clone_obj = NULL;
276 php_gd_font_object_handlers.free_obj = php_gd_font_object_free;
277 php_gd_font_object_handlers.get_constructor = php_gd_font_object_get_constructor;
278 php_gd_font_object_handlers.offset = XtOffsetOf(php_gd_font_object, std);
279 }
280
281 /*********************************************************
282 *
283 * Extension Implementation
284 *
285 ********************************************************/
286
287 zend_module_entry gd_module_entry = {
288 STANDARD_MODULE_HEADER,
289 "gd",
290 ext_functions,
291 PHP_MINIT(gd),
292 PHP_MSHUTDOWN(gd),
293 NULL,
294 PHP_RSHUTDOWN(gd),
295 PHP_MINFO(gd),
296 PHP_GD_VERSION,
297 STANDARD_MODULE_PROPERTIES
298 };
299
300 #ifdef COMPILE_DL_GD
301 ZEND_GET_MODULE(gd)
302 #endif
303
304 /* {{{ PHP_INI_BEGIN */
PHP_INI_BEGIN()305 PHP_INI_BEGIN()
306 PHP_INI_ENTRY_EX("gd.jpeg_ignore_warning", "1", PHP_INI_ALL, NULL, zend_ini_boolean_displayer_cb)
307 PHP_INI_END()
308 /* }}} */
309
310 /* {{{ php_gd_error_method */
311 void php_gd_error_method(int type, const char *format, va_list args)
312 {
313 switch (type) {
314 #ifndef PHP_WIN32
315 case GD_DEBUG:
316 case GD_INFO:
317 #endif
318 case GD_NOTICE:
319 type = E_NOTICE;
320 break;
321 case GD_WARNING:
322 type = E_WARNING;
323 break;
324 default:
325 type = E_ERROR;
326 }
327 php_verror(NULL, "", type, format, args);
328 }
329 /* }}} */
330
331 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(gd)332 PHP_MINIT_FUNCTION(gd)
333 {
334 php_gd_object_minit_helper();
335 php_gd_font_minit_helper();
336
337 #if defined(HAVE_GD_FREETYPE) && defined(HAVE_GD_BUNDLED)
338 gdFontCacheMutexSetup();
339 #endif
340 gdSetErrorMethod(php_gd_error_method);
341
342 REGISTER_INI_ENTRIES();
343
344 register_gd_symbols(module_number);
345
346 return SUCCESS;
347 }
348 /* }}} */
349
350 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(gd)351 PHP_MSHUTDOWN_FUNCTION(gd)
352 {
353 #if defined(HAVE_GD_FREETYPE) && defined(HAVE_GD_BUNDLED)
354 gdFontCacheMutexShutdown();
355 #endif
356 UNREGISTER_INI_ENTRIES();
357 return SUCCESS;
358 }
359 /* }}} */
360
361 /* {{{ PHP_RSHUTDOWN_FUNCTION */
PHP_RSHUTDOWN_FUNCTION(gd)362 PHP_RSHUTDOWN_FUNCTION(gd)
363 {
364 #ifdef HAVE_GD_FREETYPE
365 gdFontCacheShutdown();
366 #endif
367 return SUCCESS;
368 }
369 /* }}} */
370
371 #ifdef HAVE_GD_BUNDLED
372 #define PHP_GD_VERSION_STRING "bundled (2.1.0 compatible)"
373 #else
374 # define PHP_GD_VERSION_STRING GD_VERSION_STRING
375 #endif
376
377 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(gd)378 PHP_MINFO_FUNCTION(gd)
379 {
380 php_info_print_table_start();
381 php_info_print_table_row(2, "GD Support", "enabled");
382
383 /* need to use a PHPAPI function here because it is external module in windows */
384
385 #ifdef HAVE_GD_BUNDLED
386 php_info_print_table_row(2, "GD Version", PHP_GD_VERSION_STRING);
387 #else
388 php_info_print_table_row(2, "GD headers Version", PHP_GD_VERSION_STRING);
389 #ifdef HAVE_GD_LIBVERSION
390 php_info_print_table_row(2, "GD library Version", gdVersionString());
391 #endif
392 #endif
393
394 #ifdef HAVE_GD_FREETYPE
395 php_info_print_table_row(2, "FreeType Support", "enabled");
396 php_info_print_table_row(2, "FreeType Linkage", "with freetype");
397 #ifdef HAVE_GD_BUNDLED
398 {
399 char tmp[256];
400
401 #ifdef FREETYPE_PATCH
402 snprintf(tmp, sizeof(tmp), "%d.%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH);
403 #elif defined(FREETYPE_MAJOR)
404 snprintf(tmp, sizeof(tmp), "%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR);
405 #else
406 snprintf(tmp, sizeof(tmp), "1.x");
407 #endif
408 php_info_print_table_row(2, "FreeType Version", tmp);
409 }
410 #endif
411 #endif
412
413 php_info_print_table_row(2, "GIF Read Support", "enabled");
414 php_info_print_table_row(2, "GIF Create Support", "enabled");
415
416 #ifdef HAVE_GD_JPG
417 {
418 php_info_print_table_row(2, "JPEG Support", "enabled");
419 #ifdef HAVE_GD_BUNDLED
420 php_info_print_table_row(2, "libJPEG Version", gdJpegGetVersionString());
421 #endif
422 }
423 #endif
424
425 #ifdef HAVE_GD_PNG
426 php_info_print_table_row(2, "PNG Support", "enabled");
427 #ifdef HAVE_GD_BUNDLED
428 php_info_print_table_row(2, "libPNG Version", gdPngGetVersionString());
429 #endif
430 #endif
431 php_info_print_table_row(2, "WBMP Support", "enabled");
432 #ifdef HAVE_GD_XPM
433 php_info_print_table_row(2, "XPM Support", "enabled");
434 #ifdef HAVE_GD_BUNDLED
435 {
436 char tmp[12];
437 snprintf(tmp, sizeof(tmp), "%d", XpmLibraryVersion());
438 php_info_print_table_row(2, "libXpm Version", tmp);
439 }
440 #endif
441 #endif
442 php_info_print_table_row(2, "XBM Support", "enabled");
443 #ifdef USE_GD_JISX0208
444 php_info_print_table_row(2, "JIS-mapped Japanese Font Support", "enabled");
445 #endif
446 #ifdef HAVE_GD_WEBP
447 php_info_print_table_row(2, "WebP Support", "enabled");
448 #endif
449 #ifdef HAVE_GD_BMP
450 php_info_print_table_row(2, "BMP Support", "enabled");
451 #endif
452 #ifdef HAVE_GD_AVIF
453 php_info_print_table_row(2, "AVIF Support", "enabled");
454 #endif
455 #ifdef HAVE_GD_TGA
456 php_info_print_table_row(2, "TGA Read Support", "enabled");
457 #endif
458 php_info_print_table_end();
459 DISPLAY_INI_ENTRIES();
460 }
461 /* }}} */
462
463 /* {{{ */
PHP_FUNCTION(gd_info)464 PHP_FUNCTION(gd_info)
465 {
466 ZEND_PARSE_PARAMETERS_NONE();
467
468 array_init(return_value);
469
470 add_assoc_string(return_value, "GD Version", PHP_GD_VERSION_STRING);
471
472 #ifdef HAVE_GD_FREETYPE
473 add_assoc_bool(return_value, "FreeType Support", 1);
474 add_assoc_string(return_value, "FreeType Linkage", "with freetype");
475 #else
476 add_assoc_bool(return_value, "FreeType Support", 0);
477 #endif
478 add_assoc_bool(return_value, "GIF Read Support", 1);
479 add_assoc_bool(return_value, "GIF Create Support", 1);
480 #ifdef HAVE_GD_JPG
481 add_assoc_bool(return_value, "JPEG Support", 1);
482 #else
483 add_assoc_bool(return_value, "JPEG Support", 0);
484 #endif
485 #ifdef HAVE_GD_PNG
486 add_assoc_bool(return_value, "PNG Support", 1);
487 #else
488 add_assoc_bool(return_value, "PNG Support", 0);
489 #endif
490 add_assoc_bool(return_value, "WBMP Support", 1);
491 #ifdef HAVE_GD_XPM
492 add_assoc_bool(return_value, "XPM Support", 1);
493 #else
494 add_assoc_bool(return_value, "XPM Support", 0);
495 #endif
496 add_assoc_bool(return_value, "XBM Support", 1);
497 #ifdef HAVE_GD_WEBP
498 add_assoc_bool(return_value, "WebP Support", 1);
499 #else
500 add_assoc_bool(return_value, "WebP Support", 0);
501 #endif
502 #ifdef HAVE_GD_BMP
503 add_assoc_bool(return_value, "BMP Support", 1);
504 #else
505 add_assoc_bool(return_value, "BMP Support", 0);
506 #endif
507 #ifdef HAVE_GD_AVIF
508 add_assoc_bool(return_value, "AVIF Support", 1);
509 #else
510 add_assoc_bool(return_value, "AVIF Support", 0);
511 #endif
512 #ifdef HAVE_GD_TGA
513 add_assoc_bool(return_value, "TGA Read Support", 1);
514 #else
515 add_assoc_bool(return_value, "TGA Read Support", 0);
516 #endif
517 #ifdef USE_GD_JISX0208
518 add_assoc_bool(return_value, "JIS-mapped Japanese Font Support", 1);
519 #else
520 add_assoc_bool(return_value, "JIS-mapped Japanese Font Support", 0);
521 #endif
522 }
523 /* }}} */
524
525 #define FLIPWORD(a) (((a & 0xff000000) >> 24) | ((a & 0x00ff0000) >> 8) | ((a & 0x0000ff00) << 8) | ((a & 0x000000ff) << 24))
526
527 /* {{{ Load a new font */
PHP_FUNCTION(imageloadfont)528 PHP_FUNCTION(imageloadfont)
529 {
530 zend_string *file;
531 int hdr_size = sizeof(gdFont) - sizeof(char *);
532 int body_size, n = 0, b, i, body_size_check;
533 gdFontPtr font;
534 php_stream *stream;
535
536 ZEND_PARSE_PARAMETERS_START(1, 1)
537 Z_PARAM_PATH_STR(file)
538 ZEND_PARSE_PARAMETERS_END();
539
540 stream = php_stream_open_wrapper(ZSTR_VAL(file), "rb", IGNORE_PATH | REPORT_ERRORS, NULL);
541 if (stream == NULL) {
542 RETURN_FALSE;
543 }
544
545 /* Only supports a architecture-dependent binary dump format
546 * at the moment.
547 * The file format is like this on machines with 32-byte integers:
548 *
549 * byte 0-3: (int) number of characters in the font
550 * byte 4-7: (int) value of first character in the font (often 32, space)
551 * byte 8-11: (int) pixel width of each character
552 * byte 12-15: (int) pixel height of each character
553 * bytes 16-: (char) array with character data, one byte per pixel
554 * in each character, for a total of
555 * (nchars*width*height) bytes.
556 */
557 font = (gdFontPtr) emalloc(sizeof(gdFont));
558 b = 0;
559 while (b < hdr_size && (n = php_stream_read(stream, (char*)&font[b], hdr_size - b)) > 0) {
560 b += n;
561 }
562
563 if (n <= 0) {
564 efree(font);
565 if (php_stream_eof(stream)) {
566 php_error_docref(NULL, E_WARNING, "End of file while reading header");
567 } else {
568 php_error_docref(NULL, E_WARNING, "Error while reading header");
569 }
570 php_stream_close(stream);
571 RETURN_FALSE;
572 }
573 i = php_stream_tell(stream);
574 php_stream_seek(stream, 0, SEEK_END);
575 body_size_check = php_stream_tell(stream) - hdr_size;
576 php_stream_seek(stream, i, SEEK_SET);
577
578 if (overflow2(font->nchars, font->h) || overflow2(font->nchars * font->h, font->w )) {
579 php_error_docref(NULL, E_WARNING, "Error reading font, invalid font header");
580 efree(font);
581 php_stream_close(stream);
582 RETURN_FALSE;
583 }
584
585 body_size = font->w * font->h * font->nchars;
586 if (body_size != body_size_check) {
587 font->w = FLIPWORD(font->w);
588 font->h = FLIPWORD(font->h);
589 font->nchars = FLIPWORD(font->nchars);
590 if (overflow2(font->nchars, font->h) || overflow2(font->nchars * font->h, font->w )) {
591 php_error_docref(NULL, E_WARNING, "Error reading font, invalid font header");
592 efree(font);
593 php_stream_close(stream);
594 RETURN_FALSE;
595 }
596 body_size = font->w * font->h * font->nchars;
597 }
598
599 if (body_size != body_size_check) {
600 php_error_docref(NULL, E_WARNING, "Error reading font");
601 efree(font);
602 php_stream_close(stream);
603 RETURN_FALSE;
604 }
605
606 ZEND_ASSERT(body_size > 0);
607 font->data = emalloc(body_size);
608 b = 0;
609 while (b < body_size && (n = php_stream_read(stream, &font->data[b], body_size - b)) > 0) {
610 b += n;
611 }
612
613 if (n <= 0) {
614 efree(font->data);
615 efree(font);
616 if (php_stream_eof(stream)) {
617 php_error_docref(NULL, E_WARNING, "End of file while reading body");
618 } else {
619 php_error_docref(NULL, E_WARNING, "Error while reading body");
620 }
621 php_stream_close(stream);
622 RETURN_FALSE;
623 }
624 php_stream_close(stream);
625
626 object_init_ex(return_value, gd_font_ce);
627 php_gd_font_object_from_zend_object(Z_OBJ_P(return_value))->font = font;
628 }
629 /* }}} */
630
631 /* {{{ Set the line drawing styles for use with imageline and IMG_COLOR_STYLED. */
PHP_FUNCTION(imagesetstyle)632 PHP_FUNCTION(imagesetstyle)
633 {
634 zval *IM, *styles, *item;
635 gdImagePtr im;
636 int *stylearr;
637 int index = 0;
638 uint32_t num_styles;
639
640 ZEND_PARSE_PARAMETERS_START(2, 2)
641 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
642 Z_PARAM_ARRAY(styles)
643 ZEND_PARSE_PARAMETERS_END();
644
645 im = php_gd_libgdimageptr_from_zval_p(IM);
646
647 num_styles = zend_hash_num_elements(Z_ARRVAL_P(styles));
648 if (num_styles == 0) {
649 zend_argument_must_not_be_empty_error(2);
650 RETURN_THROWS();
651 }
652
653 /* copy the style values in the stylearr */
654 stylearr = safe_emalloc(sizeof(int), num_styles, 0);
655
656 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(styles), item) {
657 stylearr[index++] = zval_get_long(item);
658 } ZEND_HASH_FOREACH_END();
659
660 gdImageSetStyle(im, stylearr, index);
661
662 efree(stylearr);
663
664 RETURN_TRUE;
665 }
666 /* }}} */
667
668 /* {{{ Create a new true color image */
PHP_FUNCTION(imagecreatetruecolor)669 PHP_FUNCTION(imagecreatetruecolor)
670 {
671 zend_long x_size, y_size;
672 gdImagePtr im;
673
674 ZEND_PARSE_PARAMETERS_START(2, 2)
675 Z_PARAM_LONG(x_size)
676 Z_PARAM_LONG(y_size)
677 ZEND_PARSE_PARAMETERS_END();
678
679 if (x_size <= 0 || x_size >= INT_MAX) {
680 zend_argument_value_error(1, "must be greater than 0");
681 RETURN_THROWS();
682 }
683
684 if (y_size <= 0 || y_size >= INT_MAX) {
685 zend_argument_value_error(2, "must be greater than 0");
686 RETURN_THROWS();
687 }
688
689 im = gdImageCreateTrueColor(x_size, y_size);
690
691 if (!im) {
692 RETURN_FALSE;
693 }
694
695 php_gd_assign_libgdimageptr_as_extgdimage(return_value, im);
696 }
697 /* }}} */
698
699 /* {{{ return true if the image uses truecolor */
PHP_FUNCTION(imageistruecolor)700 PHP_FUNCTION(imageistruecolor)
701 {
702 zval *IM;
703 gdImagePtr im;
704
705 ZEND_PARSE_PARAMETERS_START(1, 1)
706 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
707 ZEND_PARSE_PARAMETERS_END();
708
709 im = php_gd_libgdimageptr_from_zval_p(IM);
710
711 RETURN_BOOL(im->trueColor);
712 }
713 /* }}} */
714
715 /* {{{ Convert a true color image to a palette based image with a number of colors, optionally using dithering. */
PHP_FUNCTION(imagetruecolortopalette)716 PHP_FUNCTION(imagetruecolortopalette)
717 {
718 zval *IM;
719 bool dither;
720 zend_long ncolors;
721 gdImagePtr im;
722
723 ZEND_PARSE_PARAMETERS_START(3, 3)
724 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
725 Z_PARAM_BOOL(dither)
726 Z_PARAM_LONG(ncolors)
727 ZEND_PARSE_PARAMETERS_END();
728
729 im = php_gd_libgdimageptr_from_zval_p(IM);
730
731 if (ncolors <= 0 || ZEND_LONG_INT_OVFL(ncolors)) {
732 zend_argument_value_error(3, "must be greater than 0 and less than %d", INT_MAX);
733 RETURN_THROWS();
734 }
735
736 if (gdImageTrueColorToPalette(im, dither, (int)ncolors)) {
737 RETURN_TRUE;
738 } else {
739 php_error_docref(NULL, E_WARNING, "Couldn't convert to palette");
740 RETURN_FALSE;
741 }
742 }
743 /* }}} */
744
745 /* {{{ Convert a palette based image to a true color image. */
PHP_FUNCTION(imagepalettetotruecolor)746 PHP_FUNCTION(imagepalettetotruecolor)
747 {
748 zval *IM;
749 gdImagePtr im;
750
751 ZEND_PARSE_PARAMETERS_START(1, 1)
752 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
753 ZEND_PARSE_PARAMETERS_END();
754
755 im = php_gd_libgdimageptr_from_zval_p(IM);
756
757 if (gdImagePaletteToTrueColor(im) == 0) {
758 RETURN_FALSE;
759 }
760
761 RETURN_TRUE;
762 }
763 /* }}} */
764
765 /* {{{ Makes the colors of the palette version of an image more closely match the true color version */
PHP_FUNCTION(imagecolormatch)766 PHP_FUNCTION(imagecolormatch)
767 {
768 zval *IM1, *IM2;
769 gdImagePtr im1, im2;
770 int result;
771
772 ZEND_PARSE_PARAMETERS_START(2, 2)
773 Z_PARAM_OBJECT_OF_CLASS(IM1, gd_image_ce)
774 Z_PARAM_OBJECT_OF_CLASS(IM2, gd_image_ce)
775 ZEND_PARSE_PARAMETERS_END();
776
777 im1 = php_gd_libgdimageptr_from_zval_p(IM1);
778 im2 = php_gd_libgdimageptr_from_zval_p(IM2);
779
780 result = gdImageColorMatch(im1, im2);
781 switch (result) {
782 case -1:
783 zend_argument_value_error(1, "must be TrueColor");
784 RETURN_THROWS();
785 break;
786 case -2:
787 zend_argument_value_error(2, "must be Palette");
788 RETURN_THROWS();
789 break;
790 case -3:
791 zend_argument_value_error(2, "must be the same size as argument #1 ($im1)");
792 RETURN_THROWS();
793 break;
794 case -4:
795 zend_argument_value_error(2, "must have at least one color");
796 RETURN_THROWS();
797 break;
798 }
799
800 RETURN_TRUE;
801 }
802 /* }}} */
803
804 /* {{{ Set line thickness for drawing lines, ellipses, rectangles, polygons etc. */
PHP_FUNCTION(imagesetthickness)805 PHP_FUNCTION(imagesetthickness)
806 {
807 zval *IM;
808 zend_long thick;
809 gdImagePtr im;
810
811 ZEND_PARSE_PARAMETERS_START(2, 2)
812 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
813 Z_PARAM_LONG(thick)
814 ZEND_PARSE_PARAMETERS_END();
815
816 im = php_gd_libgdimageptr_from_zval_p(IM);
817
818 gdImageSetThickness(im, thick);
819
820 RETURN_TRUE;
821 }
822 /* }}} */
823
824 /* {{{ Draw an ellipse */
PHP_FUNCTION(imagefilledellipse)825 PHP_FUNCTION(imagefilledellipse)
826 {
827 zval *IM;
828 zend_long cx, cy, w, h, color;
829 gdImagePtr im;
830
831 ZEND_PARSE_PARAMETERS_START(6, 6)
832 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
833 Z_PARAM_LONG(cx)
834 Z_PARAM_LONG(cy)
835 Z_PARAM_LONG(w)
836 Z_PARAM_LONG(h)
837 Z_PARAM_LONG(color)
838 ZEND_PARSE_PARAMETERS_END();
839
840 im = php_gd_libgdimageptr_from_zval_p(IM);
841
842 gdImageFilledEllipse(im, cx, cy, w, h, color);
843 RETURN_TRUE;
844 }
845 /* }}} */
846
847 /* {{{ Draw a filled partial ellipse */
PHP_FUNCTION(imagefilledarc)848 PHP_FUNCTION(imagefilledarc)
849 {
850 zval *IM;
851 zend_long cx, cy, w, h, ST, E, col, style;
852 gdImagePtr im;
853 int e, st;
854
855 ZEND_PARSE_PARAMETERS_START(9, 9)
856 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
857 Z_PARAM_LONG(cx)
858 Z_PARAM_LONG(cy)
859 Z_PARAM_LONG(w)
860 Z_PARAM_LONG(h)
861 Z_PARAM_LONG(ST)
862 Z_PARAM_LONG(E)
863 Z_PARAM_LONG(col)
864 Z_PARAM_LONG(style)
865 ZEND_PARSE_PARAMETERS_END();
866
867 im = php_gd_libgdimageptr_from_zval_p(IM);
868
869 e = E;
870 if (e < 0) {
871 e %= 360;
872 }
873
874 st = ST;
875 if (st < 0) {
876 st %= 360;
877 }
878
879 gdImageFilledArc(im, cx, cy, w, h, st, e, col, style);
880
881 RETURN_TRUE;
882 }
883 /* }}} */
884
885 /* {{{ Turn alpha blending mode on or off for the given image */
PHP_FUNCTION(imagealphablending)886 PHP_FUNCTION(imagealphablending)
887 {
888 zval *IM;
889 bool blend;
890 gdImagePtr im;
891
892 ZEND_PARSE_PARAMETERS_START(2, 2)
893 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
894 Z_PARAM_BOOL(blend)
895 ZEND_PARSE_PARAMETERS_END();
896
897 im = php_gd_libgdimageptr_from_zval_p(IM);
898
899 gdImageAlphaBlending(im, blend);
900
901 RETURN_TRUE;
902 }
903 /* }}} */
904
905 /* {{{ Include alpha channel to a saved image */
PHP_FUNCTION(imagesavealpha)906 PHP_FUNCTION(imagesavealpha)
907 {
908 zval *IM;
909 bool save;
910 gdImagePtr im;
911
912 ZEND_PARSE_PARAMETERS_START(2, 2)
913 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
914 Z_PARAM_BOOL(save)
915 ZEND_PARSE_PARAMETERS_END();
916
917 im = php_gd_libgdimageptr_from_zval_p(IM);
918
919 gdImageSaveAlpha(im, save);
920
921 RETURN_TRUE;
922 }
923 /* }}} */
924
925 /* {{{ Set the alpha blending flag to use the bundled libgd layering effects */
PHP_FUNCTION(imagelayereffect)926 PHP_FUNCTION(imagelayereffect)
927 {
928 zval *IM;
929 zend_long effect;
930 gdImagePtr im;
931
932 ZEND_PARSE_PARAMETERS_START(2, 2)
933 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
934 Z_PARAM_LONG(effect)
935 ZEND_PARSE_PARAMETERS_END();
936
937 im = php_gd_libgdimageptr_from_zval_p(IM);
938
939 gdImageAlphaBlending(im, effect);
940
941 RETURN_TRUE;
942 }
943 /* }}} */
944
945 #define CHECK_RGBA_RANGE(component, name, argument_number) \
946 if (component < 0 || component > gd##name##Max) { \
947 zend_argument_value_error(argument_number, "must be between 0 and %d (inclusive)", gd##name##Max); \
948 RETURN_THROWS(); \
949 }
950
951 /* {{{ Allocate a color with an alpha level. Works for true color and palette based images */
PHP_FUNCTION(imagecolorallocatealpha)952 PHP_FUNCTION(imagecolorallocatealpha)
953 {
954 zval *IM;
955 zend_long red, green, blue, alpha;
956 gdImagePtr im;
957 int ct = (-1);
958
959 ZEND_PARSE_PARAMETERS_START(5, 5)
960 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
961 Z_PARAM_LONG(red)
962 Z_PARAM_LONG(green)
963 Z_PARAM_LONG(blue)
964 Z_PARAM_LONG(alpha)
965 ZEND_PARSE_PARAMETERS_END();
966
967 im = php_gd_libgdimageptr_from_zval_p(IM);
968
969 CHECK_RGBA_RANGE(red, Red, 2);
970 CHECK_RGBA_RANGE(green, Green, 3);
971 CHECK_RGBA_RANGE(blue, Blue, 4);
972 CHECK_RGBA_RANGE(alpha, Alpha, 5);
973
974 ct = gdImageColorAllocateAlpha(im, red, green, blue, alpha);
975 if (ct < 0) {
976 RETURN_FALSE;
977 }
978 RETURN_LONG((zend_long)ct);
979 }
980 /* }}} */
981
982 /* {{{ Resolve/Allocate a colour with an alpha level. Works for true colour and palette based images */
PHP_FUNCTION(imagecolorresolvealpha)983 PHP_FUNCTION(imagecolorresolvealpha)
984 {
985 zval *IM;
986 zend_long red, green, blue, alpha;
987 gdImagePtr im;
988
989 ZEND_PARSE_PARAMETERS_START(5, 5)
990 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
991 Z_PARAM_LONG(red)
992 Z_PARAM_LONG(green)
993 Z_PARAM_LONG(blue)
994 Z_PARAM_LONG(alpha)
995 ZEND_PARSE_PARAMETERS_END();
996
997 im = php_gd_libgdimageptr_from_zval_p(IM);
998
999 CHECK_RGBA_RANGE(red, Red, 2);
1000 CHECK_RGBA_RANGE(green, Green, 3);
1001 CHECK_RGBA_RANGE(blue, Blue, 4);
1002 CHECK_RGBA_RANGE(alpha, Alpha, 5);
1003
1004 RETURN_LONG(gdImageColorResolveAlpha(im, red, green, blue, alpha));
1005 }
1006 /* }}} */
1007
1008 /* {{{ Find the closest matching colour with alpha transparency */
PHP_FUNCTION(imagecolorclosestalpha)1009 PHP_FUNCTION(imagecolorclosestalpha)
1010 {
1011 zval *IM;
1012 zend_long red, green, blue, alpha;
1013 gdImagePtr im;
1014
1015 ZEND_PARSE_PARAMETERS_START(5, 5)
1016 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
1017 Z_PARAM_LONG(red)
1018 Z_PARAM_LONG(green)
1019 Z_PARAM_LONG(blue)
1020 Z_PARAM_LONG(alpha)
1021 ZEND_PARSE_PARAMETERS_END();
1022
1023 im = php_gd_libgdimageptr_from_zval_p(IM);
1024
1025 CHECK_RGBA_RANGE(red, Red, 2);
1026 CHECK_RGBA_RANGE(green, Green, 3);
1027 CHECK_RGBA_RANGE(blue, Blue, 4);
1028 CHECK_RGBA_RANGE(alpha, Alpha, 5);
1029
1030 RETURN_LONG(gdImageColorClosestAlpha(im, red, green, blue, alpha));
1031 }
1032 /* }}} */
1033
1034 /* {{{ Find exact match for colour with transparency */
PHP_FUNCTION(imagecolorexactalpha)1035 PHP_FUNCTION(imagecolorexactalpha)
1036 {
1037 zval *IM;
1038 zend_long red, green, blue, alpha;
1039 gdImagePtr im;
1040
1041 ZEND_PARSE_PARAMETERS_START(5, 5)
1042 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
1043 Z_PARAM_LONG(red)
1044 Z_PARAM_LONG(green)
1045 Z_PARAM_LONG(blue)
1046 Z_PARAM_LONG(alpha)
1047 ZEND_PARSE_PARAMETERS_END();
1048
1049 im = php_gd_libgdimageptr_from_zval_p(IM);
1050
1051 CHECK_RGBA_RANGE(red, Red, 2);
1052 CHECK_RGBA_RANGE(green, Green, 3);
1053 CHECK_RGBA_RANGE(blue, Blue, 4);
1054 CHECK_RGBA_RANGE(alpha, Alpha, 5);
1055
1056 RETURN_LONG(gdImageColorExactAlpha(im, red, green, blue, alpha));
1057 }
1058 /* }}} */
1059
1060 /* {{{ Copy and resize part of an image using resampling to help ensure clarity */
PHP_FUNCTION(imagecopyresampled)1061 PHP_FUNCTION(imagecopyresampled)
1062 {
1063 zval *SIM, *DIM;
1064 zend_long SX, SY, SW, SH, DX, DY, DW, DH;
1065 gdImagePtr im_dst, im_src;
1066 int srcH, srcW, dstH, dstW, srcY, srcX, dstY, dstX;
1067
1068 ZEND_PARSE_PARAMETERS_START(10, 10)
1069 Z_PARAM_OBJECT_OF_CLASS(DIM, gd_image_ce)
1070 Z_PARAM_OBJECT_OF_CLASS(SIM, gd_image_ce)
1071 Z_PARAM_LONG(DX)
1072 Z_PARAM_LONG(DY)
1073 Z_PARAM_LONG(SX)
1074 Z_PARAM_LONG(SY)
1075 Z_PARAM_LONG(DW)
1076 Z_PARAM_LONG(DH)
1077 Z_PARAM_LONG(SW)
1078 Z_PARAM_LONG(SH)
1079 ZEND_PARSE_PARAMETERS_END();
1080
1081 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
1082 im_dst = php_gd_libgdimageptr_from_zval_p(DIM);
1083
1084 srcX = SX;
1085 srcY = SY;
1086 srcH = SH;
1087 srcW = SW;
1088 dstX = DX;
1089 dstY = DY;
1090 dstH = DH;
1091 dstW = DW;
1092
1093 gdImageCopyResampled(im_dst, im_src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);
1094
1095 RETURN_TRUE;
1096 }
1097 /* }}} */
1098
1099 #ifdef PHP_WIN32
1100 /* {{{ Grab a window or its client area using a windows handle (HWND property in COM instance) */
PHP_FUNCTION(imagegrabwindow)1101 PHP_FUNCTION(imagegrabwindow)
1102 {
1103 HWND window;
1104 bool client_area = false;
1105 RECT rc = {0};
1106 int Width, Height;
1107 HDC hdc;
1108 HDC memDC;
1109 HBITMAP memBM;
1110 HBITMAP hOld;
1111 zend_long lwindow_handle;
1112 gdImagePtr im = NULL;
1113
1114 ZEND_PARSE_PARAMETERS_START(1, 2)
1115 Z_PARAM_LONG(lwindow_handle)
1116 Z_PARAM_OPTIONAL
1117 Z_PARAM_BOOL(client_area)
1118 ZEND_PARSE_PARAMETERS_END();
1119
1120 window = (HWND) lwindow_handle;
1121
1122 if (!IsWindow(window)) {
1123 php_error_docref(NULL, E_NOTICE, "Invalid window handle");
1124 RETURN_FALSE;
1125 }
1126
1127 hdc = GetDC(0);
1128
1129 if (client_area) {
1130 GetClientRect(window, &rc);
1131 Width = rc.right;
1132 Height = rc.bottom;
1133 } else {
1134 GetWindowRect(window, &rc);
1135 Width = rc.right - rc.left;
1136 Height = rc.bottom - rc.top;
1137 }
1138
1139 Width = (Width/4)*4;
1140
1141 memDC = CreateCompatibleDC(hdc);
1142 memBM = CreateCompatibleBitmap(hdc, Width, Height);
1143 hOld = (HBITMAP) SelectObject (memDC, memBM);
1144
1145 PrintWindow(window, memDC, (UINT) client_area);
1146
1147 im = gdImageCreateTrueColor(Width, Height);
1148 if (im) {
1149 int x,y;
1150 for (y=0; y <= Height; y++) {
1151 for (x=0; x <= Width; x++) {
1152 int c = GetPixel(memDC, x,y);
1153 gdImageSetPixel(im, x, y, gdTrueColor(GetRValue(c), GetGValue(c), GetBValue(c)));
1154 }
1155 }
1156 }
1157
1158 SelectObject(memDC,hOld);
1159 DeleteObject(memBM);
1160 DeleteDC(memDC);
1161 ReleaseDC( 0, hdc );
1162
1163 if (!im) {
1164 RETURN_FALSE;
1165 }
1166
1167 php_gd_assign_libgdimageptr_as_extgdimage(return_value, im);
1168 }
1169 /* }}} */
1170
1171 /* {{{ Grab a screenshot */
PHP_FUNCTION(imagegrabscreen)1172 PHP_FUNCTION(imagegrabscreen)
1173 {
1174 HWND window = GetDesktopWindow();
1175 RECT rc = {0};
1176 int Width, Height;
1177 HDC hdc;
1178 HDC memDC;
1179 HBITMAP memBM;
1180 HBITMAP hOld;
1181 gdImagePtr im;
1182 hdc = GetDC(0);
1183
1184 ZEND_PARSE_PARAMETERS_NONE();
1185
1186 if (!hdc) {
1187 RETURN_FALSE;
1188 }
1189
1190 GetWindowRect(window, &rc);
1191 Width = rc.right - rc.left;
1192 Height = rc.bottom - rc.top;
1193
1194 Width = (Width/4)*4;
1195
1196 memDC = CreateCompatibleDC(hdc);
1197 memBM = CreateCompatibleBitmap(hdc, Width, Height);
1198 hOld = (HBITMAP) SelectObject (memDC, memBM);
1199 BitBlt( memDC, 0, 0, Width, Height , hdc, rc.left, rc.top , SRCCOPY );
1200
1201 im = gdImageCreateTrueColor(Width, Height);
1202 if (im) {
1203 int x,y;
1204 for (y=0; y <= Height; y++) {
1205 for (x=0; x <= Width; x++) {
1206 int c = GetPixel(memDC, x,y);
1207 gdImageSetPixel(im, x, y, gdTrueColor(GetRValue(c), GetGValue(c), GetBValue(c)));
1208 }
1209 }
1210 }
1211
1212 SelectObject(memDC,hOld);
1213 DeleteObject(memBM);
1214 DeleteDC(memDC);
1215 ReleaseDC( 0, hdc );
1216
1217 if (!im) {
1218 RETURN_FALSE;
1219 }
1220
1221 php_gd_assign_libgdimageptr_as_extgdimage(return_value, im);
1222 }
1223 /* }}} */
1224 #endif /* PHP_WIN32 */
1225
1226 /* {{{ Rotate an image using a custom angle */
PHP_FUNCTION(imagerotate)1227 PHP_FUNCTION(imagerotate)
1228 {
1229 zval *SIM;
1230 gdImagePtr im_dst, im_src;
1231 double degrees;
1232 zend_long color;
1233
1234 ZEND_PARSE_PARAMETERS_START(3, 3)
1235 Z_PARAM_OBJECT_OF_CLASS(SIM, gd_image_ce)
1236 Z_PARAM_DOUBLE(degrees)
1237 Z_PARAM_LONG(color)
1238 ZEND_PARSE_PARAMETERS_END();
1239
1240 if (degrees < (double)(INT_MIN / 100) || degrees > (double)(INT_MAX / 100)) {
1241 zend_argument_value_error(2, "must be between %d and %d", (INT_MIN / 100), (INT_MAX / 100));
1242 RETURN_THROWS();
1243 }
1244
1245 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
1246 im_dst = gdImageRotateInterpolated(im_src, (const float)degrees, color);
1247
1248 if (im_dst == NULL) {
1249 RETURN_FALSE;
1250 }
1251
1252 php_gd_assign_libgdimageptr_as_extgdimage(return_value, im_dst);
1253 }
1254 /* }}} */
1255
1256 /* {{{ Set the tile image to $tile when filling $image with the "IMG_COLOR_TILED" color */
PHP_FUNCTION(imagesettile)1257 PHP_FUNCTION(imagesettile)
1258 {
1259 zval *IM, *TILE;
1260 gdImagePtr im, tile;
1261
1262 ZEND_PARSE_PARAMETERS_START(2, 2)
1263 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
1264 Z_PARAM_OBJECT_OF_CLASS(TILE, gd_image_ce)
1265 ZEND_PARSE_PARAMETERS_END();
1266
1267 im = php_gd_libgdimageptr_from_zval_p(IM);
1268 tile = php_gd_libgdimageptr_from_zval_p(TILE);
1269
1270 gdImageSetTile(im, tile);
1271
1272 RETURN_TRUE;
1273 }
1274 /* }}} */
1275
1276 /* {{{ Set the brush image to $brush when filling $image with the "IMG_COLOR_BRUSHED" color */
PHP_FUNCTION(imagesetbrush)1277 PHP_FUNCTION(imagesetbrush)
1278 {
1279 zval *IM, *TILE;
1280 gdImagePtr im, tile;
1281
1282 ZEND_PARSE_PARAMETERS_START(2, 2)
1283 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
1284 Z_PARAM_OBJECT_OF_CLASS(TILE, gd_image_ce)
1285 ZEND_PARSE_PARAMETERS_END();
1286
1287 im = php_gd_libgdimageptr_from_zval_p(IM);
1288 tile = php_gd_libgdimageptr_from_zval_p(TILE);
1289
1290 gdImageSetBrush(im, tile);
1291
1292 RETURN_TRUE;
1293 }
1294 /* }}} */
1295
1296 /* {{{ Create a new image */
PHP_FUNCTION(imagecreate)1297 PHP_FUNCTION(imagecreate)
1298 {
1299 zend_long x_size, y_size;
1300 gdImagePtr im;
1301
1302 ZEND_PARSE_PARAMETERS_START(2, 2)
1303 Z_PARAM_LONG(x_size)
1304 Z_PARAM_LONG(y_size)
1305 ZEND_PARSE_PARAMETERS_END();
1306
1307 if (x_size <= 0 || x_size >= INT_MAX) {
1308 zend_argument_value_error(1, "must be greater than 0");
1309 RETURN_THROWS();
1310 }
1311
1312 if (y_size <= 0 || y_size >= INT_MAX) {
1313 zend_argument_value_error(2, "must be greater than 0");
1314 RETURN_THROWS();
1315 }
1316
1317 im = gdImageCreate(x_size, y_size);
1318
1319 if (!im) {
1320 RETURN_FALSE;
1321 }
1322
1323 php_gd_assign_libgdimageptr_as_extgdimage(return_value, im);
1324 }
1325 /* }}} */
1326
1327 /* {{{ Return the types of images supported in a bitfield - 1=GIF, 2=JPEG, 4=PNG, 8=WBMP, 16=XPM, etc */
PHP_FUNCTION(imagetypes)1328 PHP_FUNCTION(imagetypes)
1329 {
1330 int ret = 0;
1331 ret = PHP_IMG_GIF;
1332 #ifdef HAVE_GD_JPG
1333 ret |= PHP_IMG_JPG;
1334 #endif
1335 #ifdef HAVE_GD_PNG
1336 ret |= PHP_IMG_PNG;
1337 #endif
1338 ret |= PHP_IMG_WBMP;
1339 #ifdef HAVE_GD_XPM
1340 ret |= PHP_IMG_XPM;
1341 #endif
1342 #ifdef HAVE_GD_WEBP
1343 ret |= PHP_IMG_WEBP;
1344 #endif
1345 #ifdef HAVE_GD_BMP
1346 ret |= PHP_IMG_BMP;
1347 #endif
1348 #ifdef HAVE_GD_TGA
1349 ret |= PHP_IMG_TGA;
1350 #endif
1351 #ifdef HAVE_GD_AVIF
1352 ret |= PHP_IMG_AVIF;
1353 #endif
1354
1355 ZEND_PARSE_PARAMETERS_NONE();
1356
1357 RETURN_LONG(ret);
1358 }
1359 /* }}} */
1360
1361 /* {{{ _php_image_type
1362 * Based on ext/standard/image.c
1363 */
1364 static const char php_sig_gd2[3] = {'g', 'd', '2'};
1365
_php_image_type(zend_string * data)1366 static int _php_image_type(zend_string *data)
1367 {
1368 if (ZSTR_LEN(data) < 12) {
1369 /* Handle this the same way as an unknown image type. */
1370 return -1;
1371 }
1372
1373 if (!memcmp(ZSTR_VAL(data), php_sig_gd2, sizeof(php_sig_gd2))) {
1374 return PHP_GDIMG_TYPE_GD2;
1375 } else if (!memcmp(ZSTR_VAL(data), php_sig_jpg, sizeof(php_sig_jpg))) {
1376 return PHP_GDIMG_TYPE_JPG;
1377 } else if (!memcmp(ZSTR_VAL(data), php_sig_png, sizeof(php_sig_png))) {
1378 return PHP_GDIMG_TYPE_PNG;
1379 } else if (!memcmp(ZSTR_VAL(data), php_sig_gif, sizeof(php_sig_gif))) {
1380 return PHP_GDIMG_TYPE_GIF;
1381 } else if (!memcmp(ZSTR_VAL(data), php_sig_bmp, sizeof(php_sig_bmp))) {
1382 return PHP_GDIMG_TYPE_BMP;
1383 } else if(!memcmp(ZSTR_VAL(data), php_sig_riff, sizeof(php_sig_riff)) && !memcmp(ZSTR_VAL(data) + sizeof(php_sig_riff) + sizeof(uint32_t), php_sig_webp, sizeof(php_sig_webp))) {
1384 return PHP_GDIMG_TYPE_WEBP;
1385 }
1386
1387 php_stream *image_stream = php_stream_memory_open(TEMP_STREAM_READONLY, data);
1388
1389 if (image_stream != NULL) {
1390 bool is_avif = php_is_image_avif(image_stream);
1391 php_stream_close(image_stream);
1392
1393 if (is_avif) {
1394 return PHP_GDIMG_TYPE_AVIF;
1395 }
1396 }
1397
1398 if (ZSTR_VAL(data)[0] == 0) {
1399 return PHP_GDIMG_TYPE_WBM;
1400 }
1401
1402 return -1;
1403 }
1404 /* }}} */
1405
1406 /* {{{ _php_image_create_from_string */
_php_image_create_from_string(zend_string * data,const char * tn,gdImagePtr (* ioctx_func_p)(gdIOCtxPtr))1407 gdImagePtr _php_image_create_from_string(zend_string *data, const char *tn, gdImagePtr (*ioctx_func_p)(gdIOCtxPtr))
1408 {
1409 gdImagePtr im;
1410 gdIOCtx *io_ctx;
1411
1412 io_ctx = gdNewDynamicCtxEx(ZSTR_LEN(data), ZSTR_VAL(data), 0);
1413
1414 if (!io_ctx) {
1415 return NULL;
1416 }
1417
1418 im = (*ioctx_func_p)(io_ctx);
1419 if (!im) {
1420 php_error_docref(NULL, E_WARNING, "Passed data is not in \"%s\" format", tn);
1421 io_ctx->gd_free(io_ctx);
1422 return NULL;
1423 }
1424
1425 io_ctx->gd_free(io_ctx);
1426
1427 return im;
1428 }
1429 /* }}} */
1430
1431 /* {{{ Create a new image from the image stream in the string */
PHP_FUNCTION(imagecreatefromstring)1432 PHP_FUNCTION(imagecreatefromstring)
1433 {
1434 zend_string *data;
1435 gdImagePtr im;
1436 int imtype;
1437
1438 ZEND_PARSE_PARAMETERS_START(1, 1)
1439 Z_PARAM_STR(data)
1440 ZEND_PARSE_PARAMETERS_END();
1441
1442 imtype = _php_image_type(data);
1443
1444 switch (imtype) {
1445 case PHP_GDIMG_TYPE_JPG:
1446 #ifdef HAVE_GD_JPG
1447 im = _php_image_create_from_string(data, "JPEG", gdImageCreateFromJpegCtx);
1448 #else
1449 php_error_docref(NULL, E_WARNING, "No JPEG support in this PHP build");
1450 RETURN_FALSE;
1451 #endif
1452 break;
1453
1454 case PHP_GDIMG_TYPE_PNG:
1455 #ifdef HAVE_GD_PNG
1456 im = _php_image_create_from_string(data, "PNG", gdImageCreateFromPngCtx);
1457 #else
1458 php_error_docref(NULL, E_WARNING, "No PNG support in this PHP build");
1459 RETURN_FALSE;
1460 #endif
1461 break;
1462
1463 case PHP_GDIMG_TYPE_GIF:
1464 im = _php_image_create_from_string(data, "GIF", gdImageCreateFromGifCtx);
1465 break;
1466
1467 case PHP_GDIMG_TYPE_WBM:
1468 im = _php_image_create_from_string(data, "WBMP", gdImageCreateFromWBMPCtx);
1469 break;
1470
1471 case PHP_GDIMG_TYPE_GD2:
1472 im = _php_image_create_from_string(data, "GD2", gdImageCreateFromGd2Ctx);
1473 break;
1474
1475 case PHP_GDIMG_TYPE_BMP:
1476 im = _php_image_create_from_string(data, "BMP", gdImageCreateFromBmpCtx);
1477 break;
1478
1479 case PHP_GDIMG_TYPE_WEBP:
1480 #ifdef HAVE_GD_WEBP
1481 im = _php_image_create_from_string(data, "WEBP", gdImageCreateFromWebpCtx);
1482 break;
1483 #else
1484 php_error_docref(NULL, E_WARNING, "No WEBP support in this PHP build");
1485 RETURN_FALSE;
1486 #endif
1487
1488 case PHP_GDIMG_TYPE_AVIF:
1489 #ifdef HAVE_GD_AVIF
1490 im = _php_image_create_from_string(data, "AVIF", gdImageCreateFromAvifCtx);
1491 break;
1492 #else
1493 php_error_docref(NULL, E_WARNING, "No AVIF support in this PHP build");
1494 RETURN_FALSE;
1495 #endif
1496
1497 default:
1498 php_error_docref(NULL, E_WARNING, "Data is not in a recognized format");
1499 RETURN_FALSE;
1500 }
1501
1502 if (!im) {
1503 php_error_docref(NULL, E_WARNING, "Couldn't create GD Image Stream out of Data");
1504 RETURN_FALSE;
1505 }
1506
1507 php_gd_assign_libgdimageptr_as_extgdimage(return_value, im);
1508 }
1509 /* }}} */
1510
1511 /* {{{ _php_image_create_from */
_php_image_create_from(INTERNAL_FUNCTION_PARAMETERS,int image_type,const char * tn,gdImagePtr (* func_p)(FILE *),gdImagePtr (* ioctx_func_p)(gdIOCtxPtr))1512 static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, const char *tn, gdImagePtr (*func_p)(FILE *), gdImagePtr (*ioctx_func_p)(gdIOCtxPtr))
1513 {
1514 char *file;
1515 size_t file_len;
1516 zend_long srcx, srcy, width, height;
1517 gdImagePtr im = NULL;
1518 php_stream *stream;
1519 FILE * fp = NULL;
1520 #ifdef HAVE_GD_JPG
1521 long ignore_warning;
1522 #endif
1523
1524 if (image_type == PHP_GDIMG_TYPE_GD2PART) {
1525 if (zend_parse_parameters(ZEND_NUM_ARGS(), "pllll", &file, &file_len, &srcx, &srcy, &width, &height) == FAILURE) {
1526 RETURN_THROWS();
1527 }
1528
1529 if (width < 1) {
1530 zend_argument_value_error(4, "must be greater than or equal to 1");
1531 RETURN_THROWS();
1532 }
1533
1534 if (height < 1) {
1535 zend_argument_value_error(5, "must be greater than or equal to 1");
1536 RETURN_THROWS();
1537 }
1538
1539 } else {
1540 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &file, &file_len) == FAILURE) {
1541 RETURN_THROWS();
1542 }
1543 }
1544
1545
1546 stream = php_stream_open_wrapper(file, "rb", REPORT_ERRORS|IGNORE_PATH, NULL);
1547 if (stream == NULL) {
1548 RETURN_FALSE;
1549 }
1550
1551 /* try and avoid allocating a FILE* if the stream is not naturally a FILE* */
1552 if (php_stream_is(stream, PHP_STREAM_IS_STDIO)) {
1553 if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)&fp, REPORT_ERRORS)) {
1554 goto out_err;
1555 }
1556 } else if (ioctx_func_p || image_type == PHP_GDIMG_TYPE_GD2PART) {
1557 /* we can create an io context */
1558 gdIOCtx* io_ctx;
1559 zend_string *buff;
1560 char *pstr;
1561
1562 buff = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0);
1563
1564 if (!buff) {
1565 php_error_docref(NULL, E_WARNING,"Cannot read image data");
1566 goto out_err;
1567 }
1568
1569 /* needs to be malloc (persistent) - GD will free() it later */
1570 pstr = pestrndup(ZSTR_VAL(buff), ZSTR_LEN(buff), 1);
1571 io_ctx = gdNewDynamicCtxEx(ZSTR_LEN(buff), pstr, 0);
1572 if (!io_ctx) {
1573 pefree(pstr, 1);
1574 zend_string_release_ex(buff, 0);
1575 php_error_docref(NULL, E_WARNING,"Cannot allocate GD IO context");
1576 goto out_err;
1577 }
1578
1579 if (image_type == PHP_GDIMG_TYPE_GD2PART) {
1580 im = gdImageCreateFromGd2PartCtx(io_ctx, srcx, srcy, width, height);
1581 } else {
1582 im = (*ioctx_func_p)(io_ctx);
1583 }
1584 io_ctx->gd_free(io_ctx);
1585 pefree(pstr, 1);
1586 zend_string_release_ex(buff, 0);
1587 }
1588 else if (php_stream_can_cast(stream, PHP_STREAM_AS_STDIO)) {
1589 /* try and force the stream to be FILE* */
1590 if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD, (void **) &fp, REPORT_ERRORS)) {
1591 goto out_err;
1592 }
1593 }
1594
1595 if (!im && fp) {
1596 switch (image_type) {
1597 case PHP_GDIMG_TYPE_GD2PART:
1598 im = gdImageCreateFromGd2Part(fp, srcx, srcy, width, height);
1599 break;
1600 #ifdef HAVE_GD_XPM
1601 case PHP_GDIMG_TYPE_XPM:
1602 im = gdImageCreateFromXpm(file);
1603 break;
1604 #endif
1605
1606 #ifdef HAVE_GD_JPG
1607 case PHP_GDIMG_TYPE_JPG:
1608 ignore_warning = INI_INT("gd.jpeg_ignore_warning");
1609 im = gdImageCreateFromJpegEx(fp, ignore_warning);
1610 break;
1611 #endif
1612
1613 default:
1614 im = (*func_p)(fp);
1615 break;
1616 }
1617
1618 fflush(fp);
1619 }
1620
1621 /* register_im: */
1622 if (im) {
1623 php_stream_close(stream);
1624 php_gd_assign_libgdimageptr_as_extgdimage(return_value, im);
1625 return;
1626 }
1627
1628 php_error_docref(NULL, E_WARNING, "\"%s\" is not a valid %s file", file, tn);
1629 out_err:
1630 php_stream_close(stream);
1631 RETURN_FALSE;
1632
1633 }
1634 /* }}} */
1635
1636 /* {{{ Create a new image from GIF file or URL */
PHP_FUNCTION(imagecreatefromgif)1637 PHP_FUNCTION(imagecreatefromgif)
1638 {
1639 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageCreateFromGif, gdImageCreateFromGifCtx);
1640 }
1641 /* }}} */
1642
1643 #ifdef HAVE_GD_JPG
1644 /* {{{ Create a new image from JPEG file or URL */
PHP_FUNCTION(imagecreatefromjpeg)1645 PHP_FUNCTION(imagecreatefromjpeg)
1646 {
1647 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageCreateFromJpeg, gdImageCreateFromJpegCtx);
1648 }
1649 /* }}} */
1650 #endif /* HAVE_GD_JPG */
1651
1652 #ifdef HAVE_GD_PNG
1653 /* {{{ Create a new image from PNG file or URL */
PHP_FUNCTION(imagecreatefrompng)1654 PHP_FUNCTION(imagecreatefrompng)
1655 {
1656 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImageCreateFromPng, gdImageCreateFromPngCtx);
1657 }
1658 /* }}} */
1659 #endif /* HAVE_GD_PNG */
1660
1661 #ifdef HAVE_GD_WEBP
1662 /* {{{ Create a new image from WEBP file or URL */
PHP_FUNCTION(imagecreatefromwebp)1663 PHP_FUNCTION(imagecreatefromwebp)
1664 {
1665 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "WEBP", gdImageCreateFromWebp, gdImageCreateFromWebpCtx);
1666 }
1667 /* }}} */
1668 #endif /* HAVE_GD_WEBP */
1669
1670 /* {{{ Create a new image from XBM file or URL */
PHP_FUNCTION(imagecreatefromxbm)1671 PHP_FUNCTION(imagecreatefromxbm)
1672 {
1673 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "XBM", gdImageCreateFromXbm, NULL);
1674 }
1675 /* }}} */
1676
1677 #ifdef HAVE_GD_AVIF
1678 /* {{{ Create a new image from AVIF file or URL */
PHP_FUNCTION(imagecreatefromavif)1679 PHP_FUNCTION(imagecreatefromavif)
1680 {
1681 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_AVIF, "AVIF", gdImageCreateFromAvif, gdImageCreateFromAvifCtx);
1682 }
1683 /* }}} */
1684 #endif /* HAVE_GD_AVIF */
1685
1686 #ifdef HAVE_GD_XPM
1687 /* {{{ Create a new image from XPM file or URL */
PHP_FUNCTION(imagecreatefromxpm)1688 PHP_FUNCTION(imagecreatefromxpm)
1689 {
1690 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XPM, "XPM", NULL, NULL);
1691 }
1692 /* }}} */
1693 #endif
1694
1695 /* {{{ Create a new image from WBMP file or URL */
PHP_FUNCTION(imagecreatefromwbmp)1696 PHP_FUNCTION(imagecreatefromwbmp)
1697 {
1698 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageCreateFromWBMP, gdImageCreateFromWBMPCtx);
1699 }
1700 /* }}} */
1701
1702 /* {{{ Create a new image from GD file or URL */
PHP_FUNCTION(imagecreatefromgd)1703 PHP_FUNCTION(imagecreatefromgd)
1704 {
1705 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD, "GD", gdImageCreateFromGd, gdImageCreateFromGdCtx);
1706 }
1707 /* }}} */
1708
1709 /* {{{ Create a new image from GD2 file or URL */
PHP_FUNCTION(imagecreatefromgd2)1710 PHP_FUNCTION(imagecreatefromgd2)
1711 {
1712 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2, "GD2", gdImageCreateFromGd2, gdImageCreateFromGd2Ctx);
1713 }
1714 /* }}} */
1715
1716 /* {{{ Create a new image from a given part of GD2 file or URL */
PHP_FUNCTION(imagecreatefromgd2part)1717 PHP_FUNCTION(imagecreatefromgd2part)
1718 {
1719 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2PART, "GD2", NULL, NULL);
1720 }
1721 /* }}} */
1722
1723 #ifdef HAVE_GD_BMP
1724 /* {{{ Create a new image from BMP file or URL */
PHP_FUNCTION(imagecreatefrombmp)1725 PHP_FUNCTION(imagecreatefrombmp)
1726 {
1727 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_BMP, "BMP", gdImageCreateFromBmp, gdImageCreateFromBmpCtx);
1728 }
1729 /* }}} */
1730 #endif
1731
1732 #ifdef HAVE_GD_TGA
1733 /* {{{ Create a new image from TGA file or URL */
PHP_FUNCTION(imagecreatefromtga)1734 PHP_FUNCTION(imagecreatefromtga)
1735 {
1736 _php_image_create_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_TGA, "TGA", gdImageCreateFromTga, gdImageCreateFromTgaCtx);
1737 }
1738 /* }}} */
1739 #endif
1740
1741 /* {{{ _php_image_output */
_php_image_output(INTERNAL_FUNCTION_PARAMETERS,int image_type,const char * tn)1742 static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, const char *tn)
1743 {
1744 zval *imgind;
1745 char *file = NULL;
1746 zend_long quality = 128, type = 1;
1747 gdImagePtr im;
1748 FILE *fp;
1749 size_t file_len = 0;
1750
1751 /* The quality parameter for gd2 stands for chunk size */
1752
1753 switch (image_type) {
1754 case PHP_GDIMG_TYPE_GD:
1755 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|p!", &imgind, gd_image_ce, &file, &file_len) == FAILURE) {
1756 RETURN_THROWS();
1757 }
1758 break;
1759 case PHP_GDIMG_TYPE_GD2:
1760 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|p!ll", &imgind, gd_image_ce, &file, &file_len, &quality, &type) == FAILURE) {
1761 RETURN_THROWS();
1762 }
1763 break;
1764 EMPTY_SWITCH_DEFAULT_CASE()
1765 }
1766
1767 /* quality must fit in an int */
1768 if (quality < INT_MIN || quality > INT_MAX) {
1769 php_error_docref(NULL, E_WARNING, "Argument #3 ($chunk_size) must be between %d and %d", INT_MIN, INT_MAX);
1770 RETURN_FALSE;
1771 }
1772
1773 im = php_gd_libgdimageptr_from_zval_p(imgind);
1774
1775 if (file_len) {
1776 PHP_GD_CHECK_OPEN_BASEDIR(file, "Invalid filename");
1777
1778 fp = VCWD_FOPEN(file, "wb");
1779 if (!fp) {
1780 php_error_docref(NULL, E_WARNING, "Unable to open \"%s\" for writing", file);
1781 RETURN_FALSE;
1782 }
1783
1784 switch (image_type) {
1785 case PHP_GDIMG_TYPE_GD:
1786 gdImageGd(im, fp);
1787 break;
1788 case PHP_GDIMG_TYPE_GD2:
1789 if (quality == -1) {
1790 quality = 128;
1791 }
1792 gdImageGd2(im, fp, quality, type);
1793 break;
1794 EMPTY_SWITCH_DEFAULT_CASE()
1795 }
1796 fflush(fp);
1797 fclose(fp);
1798 } else {
1799 int b;
1800 FILE *tmp;
1801 char buf[4096];
1802 zend_string *path;
1803
1804 tmp = php_open_temporary_file(NULL, NULL, &path);
1805 if (tmp == NULL) {
1806 php_error_docref(NULL, E_WARNING, "Unable to open temporary file");
1807 RETURN_FALSE;
1808 }
1809
1810 switch (image_type) {
1811 case PHP_GDIMG_TYPE_GD:
1812 gdImageGd(im, tmp);
1813 break;
1814 case PHP_GDIMG_TYPE_GD2:
1815 if (quality == -1) {
1816 quality = 128;
1817 }
1818 gdImageGd2(im, tmp, quality, type);
1819 break;
1820 EMPTY_SWITCH_DEFAULT_CASE()
1821 }
1822
1823 fseek(tmp, 0, SEEK_SET);
1824
1825 while ((b = fread(buf, 1, sizeof(buf), tmp)) > 0) {
1826 php_write(buf, b);
1827 }
1828
1829 fclose(tmp);
1830 VCWD_UNLINK((const char *)ZSTR_VAL(path)); /* make sure that the temporary file is removed */
1831 zend_string_release_ex(path, 0);
1832 }
1833 RETURN_TRUE;
1834 }
1835 /* }}} */
1836
1837 /* {{{ Output XBM image to browser or file */
PHP_FUNCTION(imagexbm)1838 PHP_FUNCTION(imagexbm)
1839 {
1840 zval *imgind;
1841 char *file = NULL;
1842 size_t file_len = 0;
1843 zend_long foreground_color;
1844 bool foreground_color_is_null = true;
1845 gdImagePtr im;
1846 int i;
1847 gdIOCtx *ctx = NULL;
1848 php_stream *stream;
1849
1850 ZEND_PARSE_PARAMETERS_START(2, 3)
1851 Z_PARAM_OBJECT_OF_CLASS(imgind, gd_image_ce)
1852 Z_PARAM_PATH_OR_NULL(file, file_len)
1853 Z_PARAM_OPTIONAL
1854 Z_PARAM_LONG_OR_NULL(foreground_color, foreground_color_is_null)
1855 ZEND_PARSE_PARAMETERS_END();
1856
1857 im = php_gd_libgdimageptr_from_zval_p(imgind);
1858
1859 if (file != NULL) {
1860 stream = php_stream_open_wrapper(file, "wb", REPORT_ERRORS|IGNORE_PATH, NULL);
1861 if (stream == NULL) {
1862 RETURN_FALSE;
1863 }
1864
1865 ctx = create_stream_context(stream, 1);
1866 } else {
1867 ctx = create_output_context(NULL, 0);
1868 }
1869
1870 if (foreground_color_is_null) {
1871 for (i = 0; i < gdImageColorsTotal(im); i++) {
1872 if (!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) {
1873 break;
1874 }
1875 }
1876
1877 foreground_color = i;
1878 }
1879
1880 gdImageXbmCtx(im, file ? file : "", (int) foreground_color, ctx);
1881
1882 ctx->gd_free(ctx);
1883
1884 RETURN_TRUE;
1885 }
1886 /* }}} */
1887
1888 /* {{{ Output GIF image to browser or file */
PHP_FUNCTION(imagegif)1889 PHP_FUNCTION(imagegif)
1890 {
1891 zval *imgind;
1892 gdImagePtr im;
1893 gdIOCtx *ctx;
1894 zval *to_zval = NULL;
1895
1896 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!", &imgind, gd_image_ce, &to_zval) == FAILURE) {
1897 RETURN_THROWS();
1898 }
1899
1900 im = php_gd_libgdimageptr_from_zval_p(imgind);
1901
1902 ctx = create_output_context(to_zval, 2);
1903 if (!ctx) {
1904 RETURN_FALSE;
1905 }
1906
1907 gdImageGifCtx(im, ctx);
1908
1909 ctx->gd_free(ctx);
1910
1911 RETURN_TRUE;
1912 }
1913 /* }}} */
1914
1915 #ifdef HAVE_GD_PNG
1916 /* {{{ Output PNG image to browser or file */
PHP_FUNCTION(imagepng)1917 PHP_FUNCTION(imagepng)
1918 {
1919 zval *imgind;
1920 zend_long quality = -1, basefilter = -1;
1921 gdImagePtr im;
1922 gdIOCtx *ctx;
1923 zval *to_zval = NULL;
1924
1925 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!ll", &imgind, gd_image_ce, &to_zval, &quality, &basefilter) == FAILURE) {
1926 RETURN_THROWS();
1927 }
1928
1929 im = php_gd_libgdimageptr_from_zval_p(imgind);
1930
1931 ctx = create_output_context(to_zval, 2);
1932 if (!ctx) {
1933 RETURN_FALSE;
1934 }
1935
1936 if (quality < -1 || quality > 9) {
1937 zend_argument_value_error(3, "must be between -1 and 9");
1938 ctx->gd_free(ctx);
1939 RETURN_THROWS();
1940 }
1941
1942 #ifdef HAVE_GD_BUNDLED
1943 gdImagePngCtxEx(im, ctx, (int) quality, (int) basefilter);
1944 #else
1945 gdImagePngCtxEx(im, ctx, (int) quality);
1946 #endif
1947
1948 ctx->gd_free(ctx);
1949
1950 RETURN_TRUE;
1951 }
1952 /* }}} */
1953 #endif /* HAVE_GD_PNG */
1954
1955 #ifdef HAVE_GD_WEBP
1956 /* {{{ Output WEBP image to browser or file */
PHP_FUNCTION(imagewebp)1957 PHP_FUNCTION(imagewebp)
1958 {
1959 zval *imgind;
1960 zend_long quality = -1;
1961 gdImagePtr im;
1962 gdIOCtx *ctx;
1963 zval *to_zval = NULL;
1964
1965 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!l", &imgind, gd_image_ce, &to_zval, &quality) == FAILURE) {
1966 RETURN_THROWS();
1967 }
1968
1969 im = php_gd_libgdimageptr_from_zval_p(imgind);
1970
1971 ctx = create_output_context(to_zval, 2);
1972 if (!ctx) {
1973 RETURN_FALSE;
1974 }
1975
1976 if (quality < -1) {
1977 zend_argument_value_error(3, "must be greater than or equal to -1");
1978 ctx->gd_free(ctx);
1979 RETURN_THROWS();
1980 }
1981
1982 gdImageWebpCtx(im, ctx, (int) quality);
1983
1984 ctx->gd_free(ctx);
1985
1986 RETURN_TRUE;
1987 }
1988 /* }}} */
1989 #endif /* HAVE_GD_WEBP */
1990
1991 #ifdef HAVE_GD_AVIF
1992 /* {{{ Output AVIF image to browser or file */
PHP_FUNCTION(imageavif)1993 PHP_FUNCTION(imageavif)
1994 {
1995 zval *imgind;
1996 zend_long quality = -1, speed = -1;
1997 gdImagePtr im;
1998 gdIOCtx *ctx;
1999 zval *to_zval = NULL;
2000
2001 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!ll", &imgind, gd_image_ce, &to_zval, &quality, &speed) == FAILURE) {
2002 RETURN_THROWS();
2003 }
2004
2005 im = php_gd_libgdimageptr_from_zval_p(imgind);
2006
2007 ctx = create_output_context(to_zval, 2);
2008 if (!ctx) {
2009 RETURN_FALSE;
2010 }
2011
2012 if (quality < -1 || quality > 100) {
2013 zend_argument_value_error(3, "must be between -1 and 100");
2014 ctx->gd_free(ctx);
2015 RETURN_THROWS();
2016 }
2017
2018 if (speed < -1 || speed > 10) {
2019 zend_argument_value_error(4, "must be between -1 and 10");
2020 ctx->gd_free(ctx);
2021 RETURN_THROWS();
2022 } else if (speed == -1) {
2023 speed = 6;
2024 }
2025
2026 gdImageAvifCtx(im, ctx, (int) quality, (int) speed);
2027
2028 ctx->gd_free(ctx);
2029
2030 RETURN_TRUE;
2031 }
2032 /* }}} */
2033 #endif /* HAVE_GD_AVIF */
2034
2035 #ifdef HAVE_GD_JPG
2036 /* {{{ Output JPEG image to browser or file */
PHP_FUNCTION(imagejpeg)2037 PHP_FUNCTION(imagejpeg)
2038 {
2039 zval *imgind;
2040 zend_long quality = -1;
2041 gdImagePtr im;
2042 gdIOCtx *ctx;
2043 zval *to_zval = NULL;
2044
2045 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|z!l", &imgind, gd_image_ce, &to_zval, &quality) == FAILURE) {
2046 RETURN_THROWS();
2047 }
2048
2049 im = php_gd_libgdimageptr_from_zval_p(imgind);
2050
2051 ctx = create_output_context(to_zval, 2);
2052 if (!ctx) {
2053 RETURN_FALSE;
2054 }
2055
2056 if (quality < -1 || quality > 100) {
2057 zend_argument_value_error(3, "must be at between -1 and 100");
2058 ctx->gd_free(ctx);
2059 RETURN_THROWS();
2060 }
2061
2062 gdImageJpegCtx(im, ctx, (int) quality);
2063
2064 ctx->gd_free(ctx);
2065
2066 RETURN_TRUE;
2067 }
2068 /* }}} */
2069 #endif /* HAVE_GD_JPG */
2070
2071 /* {{{ Output WBMP image to browser or file */
PHP_FUNCTION(imagewbmp)2072 PHP_FUNCTION(imagewbmp)
2073 {
2074 zval *imgind;
2075 zend_long foreground_color;
2076 bool foreground_color_is_null = true;
2077 gdImagePtr im;
2078 int i;
2079 gdIOCtx *ctx;
2080 zval *to_zval = NULL;
2081
2082 ZEND_PARSE_PARAMETERS_START(1, 3)
2083 Z_PARAM_OBJECT_OF_CLASS(imgind, gd_image_ce)
2084 Z_PARAM_OPTIONAL
2085 Z_PARAM_ZVAL_OR_NULL(to_zval)
2086 Z_PARAM_LONG_OR_NULL(foreground_color, foreground_color_is_null)
2087 ZEND_PARSE_PARAMETERS_END();
2088
2089 im = php_gd_libgdimageptr_from_zval_p(imgind);
2090
2091 ctx = create_output_context(to_zval, 2);
2092 if (!ctx) {
2093 RETURN_FALSE;
2094 }
2095
2096 if (foreground_color_is_null) {
2097 for (i = 0; i < gdImageColorsTotal(im); i++) {
2098 if (!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) {
2099 break;
2100 }
2101 }
2102
2103 foreground_color = i;
2104 }
2105
2106 gdImageWBMPCtx(im, foreground_color, ctx);
2107
2108 ctx->gd_free(ctx);
2109
2110 RETURN_TRUE;
2111 }
2112 /* }}} */
2113
2114 /* {{{ Output GD image to browser or file */
PHP_FUNCTION(imagegd)2115 PHP_FUNCTION(imagegd)
2116 {
2117 _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD, "GD");
2118 }
2119 /* }}} */
2120
2121 /* {{{ Output GD2 image to browser or file */
PHP_FUNCTION(imagegd2)2122 PHP_FUNCTION(imagegd2)
2123 {
2124 _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GD2, "GD2");
2125 }
2126 /* }}} */
2127
2128 #ifdef HAVE_GD_BMP
2129 /* {{{ Output BMP image to browser or file */
PHP_FUNCTION(imagebmp)2130 PHP_FUNCTION(imagebmp)
2131 {
2132 zval *imgind;
2133 bool compressed = true;
2134 gdImagePtr im;
2135 gdIOCtx *ctx;
2136 zval *to_zval = NULL;
2137
2138 ZEND_PARSE_PARAMETERS_START(1, 3)
2139 Z_PARAM_OBJECT_OF_CLASS(imgind, gd_image_ce)
2140 Z_PARAM_OPTIONAL
2141 Z_PARAM_ZVAL_OR_NULL(to_zval)
2142 Z_PARAM_BOOL(compressed)
2143 ZEND_PARSE_PARAMETERS_END();
2144
2145 im = php_gd_libgdimageptr_from_zval_p(imgind);
2146
2147 ctx = create_output_context(to_zval, 2);
2148 if (!ctx) {
2149 RETURN_FALSE;
2150 }
2151
2152 gdImageBmpCtx(im, ctx, (int) compressed);
2153
2154 ctx->gd_free(ctx);
2155
2156 RETURN_TRUE;
2157 }
2158 /* }}} */
2159 #endif
2160
2161 /* {{{ Destroy an image - No effect as of PHP 8.0 */
PHP_FUNCTION(imagedestroy)2162 PHP_FUNCTION(imagedestroy)
2163 {
2164 /* This function used to free the resource, as resources are no longer used, it does nothing */
2165 zval *IM;
2166
2167 ZEND_PARSE_PARAMETERS_START(1, 1)
2168 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2169 ZEND_PARSE_PARAMETERS_END();
2170
2171 RETURN_TRUE;
2172 }
2173 /* }}} */
2174
2175 /* {{{ Allocate a color for an image */
PHP_FUNCTION(imagecolorallocate)2176 PHP_FUNCTION(imagecolorallocate)
2177 {
2178 zval *IM;
2179 zend_long red, green, blue;
2180 gdImagePtr im;
2181 int ct = -1;
2182
2183 ZEND_PARSE_PARAMETERS_START(4, 4)
2184 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2185 Z_PARAM_LONG(red)
2186 Z_PARAM_LONG(green)
2187 Z_PARAM_LONG(blue)
2188 ZEND_PARSE_PARAMETERS_END();
2189
2190 im = php_gd_libgdimageptr_from_zval_p(IM);
2191
2192 CHECK_RGBA_RANGE(red, Red, 2);
2193 CHECK_RGBA_RANGE(green, Green, 3);
2194 CHECK_RGBA_RANGE(blue, Blue, 4);
2195
2196 ct = gdImageColorAllocate(im, red, green, blue);
2197 if (ct < 0) {
2198 RETURN_FALSE;
2199 }
2200 RETURN_LONG(ct);
2201 }
2202 /* }}} */
2203
2204 /* {{{ Copy the palette from the src image onto the dst image */
PHP_FUNCTION(imagepalettecopy)2205 PHP_FUNCTION(imagepalettecopy)
2206 {
2207 zval *dstim, *srcim;
2208 gdImagePtr dst, src;
2209
2210 ZEND_PARSE_PARAMETERS_START(2, 2)
2211 Z_PARAM_OBJECT_OF_CLASS(dstim, gd_image_ce)
2212 Z_PARAM_OBJECT_OF_CLASS(srcim, gd_image_ce)
2213 ZEND_PARSE_PARAMETERS_END();
2214
2215 src = php_gd_libgdimageptr_from_zval_p(srcim);
2216 dst = php_gd_libgdimageptr_from_zval_p(dstim);
2217
2218 gdImagePaletteCopy(dst, src);
2219 }
2220 /* }}} */
2221
2222 /* {{{ Get the index of the color of a pixel */
PHP_FUNCTION(imagecolorat)2223 PHP_FUNCTION(imagecolorat)
2224 {
2225 zval *IM;
2226 zend_long x, y;
2227 gdImagePtr im;
2228
2229 ZEND_PARSE_PARAMETERS_START(3, 3)
2230 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2231 Z_PARAM_LONG(x)
2232 Z_PARAM_LONG(y)
2233 ZEND_PARSE_PARAMETERS_END();
2234
2235 im = php_gd_libgdimageptr_from_zval_p(IM);
2236
2237 if (gdImageTrueColor(im)) {
2238 if (im->tpixels && gdImageBoundsSafe(im, x, y)) {
2239 RETURN_LONG(gdImageTrueColorPixel(im, x, y));
2240 } else {
2241 php_error_docref(NULL, E_NOTICE, "" ZEND_LONG_FMT "," ZEND_LONG_FMT " is out of bounds", x, y);
2242 RETURN_FALSE;
2243 }
2244 } else {
2245 if (im->pixels && gdImageBoundsSafe(im, x, y)) {
2246 RETURN_LONG(im->pixels[y][x]);
2247 } else {
2248 php_error_docref(NULL, E_NOTICE, "" ZEND_LONG_FMT "," ZEND_LONG_FMT " is out of bounds", x, y);
2249 RETURN_FALSE;
2250 }
2251 }
2252 }
2253 /* }}} */
2254
2255 /* {{{ Get the index of the closest color to the specified color */
PHP_FUNCTION(imagecolorclosest)2256 PHP_FUNCTION(imagecolorclosest)
2257 {
2258 zval *IM;
2259 zend_long red, green, blue;
2260 gdImagePtr im;
2261
2262 ZEND_PARSE_PARAMETERS_START(4, 4)
2263 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2264 Z_PARAM_LONG(red)
2265 Z_PARAM_LONG(green)
2266 Z_PARAM_LONG(blue)
2267 ZEND_PARSE_PARAMETERS_END();
2268
2269 im = php_gd_libgdimageptr_from_zval_p(IM);
2270
2271 CHECK_RGBA_RANGE(red, Red, 2);
2272 CHECK_RGBA_RANGE(green, Green, 3);
2273 CHECK_RGBA_RANGE(blue, Blue, 4);
2274
2275 RETURN_LONG(gdImageColorClosest(im, red, green, blue));
2276 }
2277 /* }}} */
2278
2279 /* {{{ Get the index of the color which has the hue, white and blackness nearest to the given color */
PHP_FUNCTION(imagecolorclosesthwb)2280 PHP_FUNCTION(imagecolorclosesthwb)
2281 {
2282 zval *IM;
2283 zend_long red, green, blue;
2284 gdImagePtr im;
2285
2286 ZEND_PARSE_PARAMETERS_START(4, 4)
2287 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2288 Z_PARAM_LONG(red)
2289 Z_PARAM_LONG(green)
2290 Z_PARAM_LONG(blue)
2291 ZEND_PARSE_PARAMETERS_END();
2292
2293 im = php_gd_libgdimageptr_from_zval_p(IM);
2294
2295 CHECK_RGBA_RANGE(red, Red, 2);
2296 CHECK_RGBA_RANGE(green, Green, 3);
2297 CHECK_RGBA_RANGE(blue, Blue, 4);
2298
2299 RETURN_LONG(gdImageColorClosestHWB(im, red, green, blue));
2300 }
2301 /* }}} */
2302
2303 /* {{{ De-allocate a color for an image */
PHP_FUNCTION(imagecolordeallocate)2304 PHP_FUNCTION(imagecolordeallocate)
2305 {
2306 zval *IM;
2307 zend_long index;
2308 int col;
2309 gdImagePtr im;
2310
2311 ZEND_PARSE_PARAMETERS_START(2, 2)
2312 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2313 Z_PARAM_LONG(index)
2314 ZEND_PARSE_PARAMETERS_END();
2315
2316 im = php_gd_libgdimageptr_from_zval_p(IM);
2317
2318 /* We can return right away for a truecolor image as deallocating colours is meaningless here */
2319 if (gdImageTrueColor(im)) {
2320 RETURN_TRUE;
2321 }
2322
2323 col = index;
2324
2325 if (col >= 0 && col < gdImageColorsTotal(im)) {
2326 gdImageColorDeallocate(im, col);
2327 RETURN_TRUE;
2328 } else {
2329 zend_argument_value_error(2, "must be between 0 and %d", gdImageColorsTotal(im));
2330 RETURN_THROWS();
2331 }
2332 }
2333 /* }}} */
2334
2335 /* {{{ Get the index of the specified color or its closest possible alternative */
PHP_FUNCTION(imagecolorresolve)2336 PHP_FUNCTION(imagecolorresolve)
2337 {
2338 zval *IM;
2339 zend_long red, green, blue;
2340 gdImagePtr im;
2341
2342 ZEND_PARSE_PARAMETERS_START(4, 4)
2343 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2344 Z_PARAM_LONG(red)
2345 Z_PARAM_LONG(green)
2346 Z_PARAM_LONG(blue)
2347 ZEND_PARSE_PARAMETERS_END();
2348
2349 im = php_gd_libgdimageptr_from_zval_p(IM);
2350
2351 CHECK_RGBA_RANGE(red, Red, 2);
2352 CHECK_RGBA_RANGE(green, Green, 3);
2353 CHECK_RGBA_RANGE(blue, Blue, 4);
2354
2355 RETURN_LONG(gdImageColorResolve(im, red, green, blue));
2356 }
2357 /* }}} */
2358
2359 /* {{{ Get the index of the specified color */
PHP_FUNCTION(imagecolorexact)2360 PHP_FUNCTION(imagecolorexact)
2361 {
2362 zval *IM;
2363 zend_long red, green, blue;
2364 gdImagePtr im;
2365
2366 ZEND_PARSE_PARAMETERS_START(4, 4)
2367 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2368 Z_PARAM_LONG(red)
2369 Z_PARAM_LONG(green)
2370 Z_PARAM_LONG(blue)
2371 ZEND_PARSE_PARAMETERS_END();
2372
2373 im = php_gd_libgdimageptr_from_zval_p(IM);
2374
2375 CHECK_RGBA_RANGE(red, Red, 2);
2376 CHECK_RGBA_RANGE(green, Green, 3);
2377 CHECK_RGBA_RANGE(blue, Blue, 4);
2378
2379 RETURN_LONG(gdImageColorExact(im, red, green, blue));
2380 }
2381 /* }}} */
2382
2383 /* {{{ Set the color for the specified palette index */
PHP_FUNCTION(imagecolorset)2384 PHP_FUNCTION(imagecolorset)
2385 {
2386 zval *IM;
2387 zend_long color, red, green, blue, alpha = 0;
2388 int col;
2389 gdImagePtr im;
2390
2391 ZEND_PARSE_PARAMETERS_START(5, 6)
2392 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2393 Z_PARAM_LONG(color)
2394 Z_PARAM_LONG(red)
2395 Z_PARAM_LONG(green)
2396 Z_PARAM_LONG(blue)
2397 Z_PARAM_OPTIONAL
2398 Z_PARAM_LONG(alpha)
2399 ZEND_PARSE_PARAMETERS_END();
2400
2401 im = php_gd_libgdimageptr_from_zval_p(IM);
2402
2403 CHECK_RGBA_RANGE(red, Red, 3);
2404 CHECK_RGBA_RANGE(green, Green, 4);
2405 CHECK_RGBA_RANGE(blue, Blue, 5);
2406 CHECK_RGBA_RANGE(alpha, Alpha, 6);
2407
2408 col = color;
2409
2410 if (col >= 0 && col < gdImageColorsTotal(im)) {
2411 im->red[col] = red;
2412 im->green[col] = green;
2413 im->blue[col] = blue;
2414 im->alpha[col] = alpha;
2415 } else {
2416 RETURN_FALSE;
2417 }
2418 }
2419 /* }}} */
2420
2421 /* {{{ Get the colors for an index */
PHP_FUNCTION(imagecolorsforindex)2422 PHP_FUNCTION(imagecolorsforindex)
2423 {
2424 zval *IM;
2425 zend_long index;
2426 int col;
2427 gdImagePtr im;
2428
2429 ZEND_PARSE_PARAMETERS_START(2, 2)
2430 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2431 Z_PARAM_LONG(index)
2432 ZEND_PARSE_PARAMETERS_END();
2433
2434 im = php_gd_libgdimageptr_from_zval_p(IM);
2435
2436 col = index;
2437
2438 if ((col >= 0 && gdImageTrueColor(im)) || (!gdImageTrueColor(im) && col >= 0 && col < gdImageColorsTotal(im))) {
2439 array_init(return_value);
2440
2441 add_assoc_long(return_value,"red", gdImageRed(im,col));
2442 add_assoc_long(return_value,"green", gdImageGreen(im,col));
2443 add_assoc_long(return_value,"blue", gdImageBlue(im,col));
2444 add_assoc_long(return_value,"alpha", gdImageAlpha(im,col));
2445 } else {
2446 zend_argument_value_error(2, "is out of range");
2447 RETURN_THROWS();
2448 }
2449 }
2450 /* }}} */
2451
2452 /* {{{ Apply a gamma correction to a GD image */
PHP_FUNCTION(imagegammacorrect)2453 PHP_FUNCTION(imagegammacorrect)
2454 {
2455 zval *IM;
2456 gdImagePtr im;
2457 int i;
2458 double input, output, gamma;
2459
2460 ZEND_PARSE_PARAMETERS_START(3, 3)
2461 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2462 Z_PARAM_DOUBLE(input)
2463 Z_PARAM_DOUBLE(output)
2464 ZEND_PARSE_PARAMETERS_END();
2465
2466 if (input <= 0.0) {
2467 zend_argument_value_error(2, "must be greater than 0");
2468 RETURN_THROWS();
2469 }
2470
2471 if (output <= 0.0) {
2472 zend_argument_value_error(3, "must be greater than 0");
2473 RETURN_THROWS();
2474 }
2475
2476 gamma = input / output;
2477
2478 im = php_gd_libgdimageptr_from_zval_p(IM);
2479
2480 if (gdImageTrueColor(im)) {
2481 int x, y, c;
2482
2483 for (y = 0; y < gdImageSY(im); y++) {
2484 for (x = 0; x < gdImageSX(im); x++) {
2485 c = gdImageGetPixel(im, x, y);
2486 gdImageSetPixel(im, x, y,
2487 gdTrueColorAlpha(
2488 (int) ((pow((gdTrueColorGetRed(c) / 255.0), gamma) * 255) + .5),
2489 (int) ((pow((gdTrueColorGetGreen(c) / 255.0), gamma) * 255) + .5),
2490 (int) ((pow((gdTrueColorGetBlue(c) / 255.0), gamma) * 255) + .5),
2491 gdTrueColorGetAlpha(c)
2492 )
2493 );
2494 }
2495 }
2496 RETURN_TRUE;
2497 }
2498
2499 for (i = 0; i < gdImageColorsTotal(im); i++) {
2500 im->red[i] = (int)((pow((im->red[i] / 255.0), gamma) * 255) + .5);
2501 im->green[i] = (int)((pow((im->green[i] / 255.0), gamma) * 255) + .5);
2502 im->blue[i] = (int)((pow((im->blue[i] / 255.0), gamma) * 255) + .5);
2503 }
2504
2505 RETURN_TRUE;
2506 }
2507 /* }}} */
2508
2509 /* {{{ Set a single pixel */
PHP_FUNCTION(imagesetpixel)2510 PHP_FUNCTION(imagesetpixel)
2511 {
2512 zval *IM;
2513 zend_long x, y, col;
2514 gdImagePtr im;
2515
2516 ZEND_PARSE_PARAMETERS_START(4, 4)
2517 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2518 Z_PARAM_LONG(x)
2519 Z_PARAM_LONG(y)
2520 Z_PARAM_LONG(col)
2521 ZEND_PARSE_PARAMETERS_END();
2522
2523 im = php_gd_libgdimageptr_from_zval_p(IM);
2524
2525 gdImageSetPixel(im, x, y, col);
2526 RETURN_TRUE;
2527 }
2528 /* }}} */
2529
2530 /* {{{ Draw a line */
PHP_FUNCTION(imageline)2531 PHP_FUNCTION(imageline)
2532 {
2533 zval *IM;
2534 zend_long x1, y1, x2, y2, col;
2535 gdImagePtr im;
2536
2537 ZEND_PARSE_PARAMETERS_START(6, 6)
2538 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2539 Z_PARAM_LONG(x1)
2540 Z_PARAM_LONG(y1)
2541 Z_PARAM_LONG(x2)
2542 Z_PARAM_LONG(y2)
2543 Z_PARAM_LONG(col)
2544 ZEND_PARSE_PARAMETERS_END();
2545
2546
2547 im = php_gd_libgdimageptr_from_zval_p(IM);
2548
2549 if (im->AA) {
2550 gdImageSetAntiAliased(im, col);
2551 col = gdAntiAliased;
2552 }
2553 gdImageLine(im, x1, y1, x2, y2, col);
2554 RETURN_TRUE;
2555 }
2556 /* }}} */
2557
2558 /* {{{ Draw a dashed line */
PHP_FUNCTION(imagedashedline)2559 PHP_FUNCTION(imagedashedline)
2560 {
2561 zval *IM;
2562 zend_long x1, y1, x2, y2, col;
2563 gdImagePtr im;
2564
2565 ZEND_PARSE_PARAMETERS_START(6, 6)
2566 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2567 Z_PARAM_LONG(x1)
2568 Z_PARAM_LONG(y1)
2569 Z_PARAM_LONG(x2)
2570 Z_PARAM_LONG(y2)
2571 Z_PARAM_LONG(col)
2572 ZEND_PARSE_PARAMETERS_END();
2573
2574 im = php_gd_libgdimageptr_from_zval_p(IM);
2575
2576 gdImageDashedLine(im, x1, y1, x2, y2, col);
2577 RETURN_TRUE;
2578 }
2579 /* }}} */
2580
2581 /* {{{ Draw a rectangle */
PHP_FUNCTION(imagerectangle)2582 PHP_FUNCTION(imagerectangle)
2583 {
2584 zval *IM;
2585 zend_long x1, y1, x2, y2, col;
2586 gdImagePtr im;
2587
2588 ZEND_PARSE_PARAMETERS_START(6, 6)
2589 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2590 Z_PARAM_LONG(x1)
2591 Z_PARAM_LONG(y1)
2592 Z_PARAM_LONG(x2)
2593 Z_PARAM_LONG(y2)
2594 Z_PARAM_LONG(col)
2595 ZEND_PARSE_PARAMETERS_END();
2596
2597 im = php_gd_libgdimageptr_from_zval_p(IM);
2598
2599 gdImageRectangle(im, x1, y1, x2, y2, col);
2600 RETURN_TRUE;
2601 }
2602 /* }}} */
2603
2604 /* {{{ Draw a filled rectangle */
PHP_FUNCTION(imagefilledrectangle)2605 PHP_FUNCTION(imagefilledrectangle)
2606 {
2607 zval *IM;
2608 zend_long x1, y1, x2, y2, col;
2609 gdImagePtr im;
2610
2611 ZEND_PARSE_PARAMETERS_START(6, 6)
2612 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2613 Z_PARAM_LONG(x1)
2614 Z_PARAM_LONG(y1)
2615 Z_PARAM_LONG(x2)
2616 Z_PARAM_LONG(y2)
2617 Z_PARAM_LONG(col)
2618 ZEND_PARSE_PARAMETERS_END();
2619
2620 im = php_gd_libgdimageptr_from_zval_p(IM);
2621 gdImageFilledRectangle(im, x1, y1, x2, y2, col);
2622 RETURN_TRUE;
2623 }
2624 /* }}} */
2625
2626 /* {{{ Draw a partial ellipse */
PHP_FUNCTION(imagearc)2627 PHP_FUNCTION(imagearc)
2628 {
2629 zval *IM;
2630 zend_long cx, cy, w, h, ST, E, col;
2631 gdImagePtr im;
2632 int e, st;
2633
2634 ZEND_PARSE_PARAMETERS_START(8, 8)
2635 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2636 Z_PARAM_LONG(cx)
2637 Z_PARAM_LONG(cy)
2638 Z_PARAM_LONG(w)
2639 Z_PARAM_LONG(h)
2640 Z_PARAM_LONG(ST)
2641 Z_PARAM_LONG(E)
2642 Z_PARAM_LONG(col)
2643 ZEND_PARSE_PARAMETERS_END();
2644
2645 im = php_gd_libgdimageptr_from_zval_p(IM);
2646
2647 e = E;
2648 if (e < 0) {
2649 e %= 360;
2650 }
2651
2652 st = ST;
2653 if (st < 0) {
2654 st %= 360;
2655 }
2656
2657 gdImageArc(im, cx, cy, w, h, st, e, col);
2658 RETURN_TRUE;
2659 }
2660 /* }}} */
2661
2662 /* {{{ Draw an ellipse */
PHP_FUNCTION(imageellipse)2663 PHP_FUNCTION(imageellipse)
2664 {
2665 zval *IM;
2666 zend_long cx, cy, w, h, color;
2667 gdImagePtr im;
2668
2669 ZEND_PARSE_PARAMETERS_START(6, 6)
2670 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2671 Z_PARAM_LONG(cx)
2672 Z_PARAM_LONG(cy)
2673 Z_PARAM_LONG(w)
2674 Z_PARAM_LONG(h)
2675 Z_PARAM_LONG(color)
2676 ZEND_PARSE_PARAMETERS_END();
2677
2678 im = php_gd_libgdimageptr_from_zval_p(IM);
2679
2680 gdImageEllipse(im, cx, cy, w, h, color);
2681 RETURN_TRUE;
2682 }
2683 /* }}} */
2684
2685 /* {{{ Flood fill to specific color */
PHP_FUNCTION(imagefilltoborder)2686 PHP_FUNCTION(imagefilltoborder)
2687 {
2688 zval *IM;
2689 zend_long x, y, border, col;
2690 gdImagePtr im;
2691
2692 ZEND_PARSE_PARAMETERS_START(5, 5)
2693 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2694 Z_PARAM_LONG(x)
2695 Z_PARAM_LONG(y)
2696 Z_PARAM_LONG(border)
2697 Z_PARAM_LONG(col)
2698 ZEND_PARSE_PARAMETERS_END();
2699
2700 im = php_gd_libgdimageptr_from_zval_p(IM);
2701
2702 gdImageFillToBorder(im, x, y, border, col);
2703 RETURN_TRUE;
2704 }
2705 /* }}} */
2706
2707 /* {{{ Flood fill */
PHP_FUNCTION(imagefill)2708 PHP_FUNCTION(imagefill)
2709 {
2710 zval *IM;
2711 zend_long x, y, col;
2712 gdImagePtr im;
2713
2714 ZEND_PARSE_PARAMETERS_START(4, 4)
2715 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2716 Z_PARAM_LONG(x)
2717 Z_PARAM_LONG(y)
2718 Z_PARAM_LONG(col)
2719 ZEND_PARSE_PARAMETERS_END();
2720
2721 im = php_gd_libgdimageptr_from_zval_p(IM);
2722
2723 gdImageFill(im, x, y, col);
2724 RETURN_TRUE;
2725 }
2726 /* }}} */
2727
2728 /* {{{ Find out the number of colors in an image's palette */
PHP_FUNCTION(imagecolorstotal)2729 PHP_FUNCTION(imagecolorstotal)
2730 {
2731 zval *IM;
2732 gdImagePtr im;
2733
2734 ZEND_PARSE_PARAMETERS_START(1, 1)
2735 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2736 ZEND_PARSE_PARAMETERS_END();
2737
2738 im = php_gd_libgdimageptr_from_zval_p(IM);
2739
2740 RETURN_LONG(gdImageColorsTotal(im));
2741 }
2742 /* }}} */
2743
2744 /* {{{ Define a color as transparent */
PHP_FUNCTION(imagecolortransparent)2745 PHP_FUNCTION(imagecolortransparent)
2746 {
2747 zval *IM;
2748 zend_long COL = 0;
2749 bool COL_IS_NULL = true;
2750 gdImagePtr im;
2751
2752 ZEND_PARSE_PARAMETERS_START(1, 2)
2753 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2754 Z_PARAM_OPTIONAL
2755 Z_PARAM_LONG_OR_NULL(COL, COL_IS_NULL)
2756 ZEND_PARSE_PARAMETERS_END();
2757
2758 im = php_gd_libgdimageptr_from_zval_p(IM);
2759
2760 if (!COL_IS_NULL) {
2761 gdImageColorTransparent(im, COL);
2762 }
2763
2764 RETURN_LONG(gdImageGetTransparent(im));
2765 }
2766 /* }}} */
2767
2768 /* {{{ Enable or disable interlace */
PHP_FUNCTION(imageinterlace)2769 PHP_FUNCTION(imageinterlace)
2770 {
2771 zval *IM;
2772 bool INT = false;
2773 bool INT_IS_NULL = true;
2774 gdImagePtr im;
2775
2776 ZEND_PARSE_PARAMETERS_START(1, 2)
2777 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2778 Z_PARAM_OPTIONAL
2779 Z_PARAM_BOOL_OR_NULL(INT, INT_IS_NULL)
2780 ZEND_PARSE_PARAMETERS_END();
2781
2782 im = php_gd_libgdimageptr_from_zval_p(IM);
2783
2784 if (!INT_IS_NULL) {
2785 gdImageInterlace(im, INT);
2786 }
2787
2788 RETURN_BOOL(gdImageGetInterlaced(im));
2789 }
2790 /* }}} */
2791
2792 /* {{{ php_imagepolygon
2793 arg = -1 open polygon
2794 arg = 0 normal polygon
2795 arg = 1 filled polygon */
2796 /* im, points, num_points, col */
php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS,int filled)2797 static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled)
2798 {
2799 zval *IM, *POINTS;
2800 zend_long NPOINTS, COL;
2801 bool COL_IS_NULL = true;
2802 zval *var = NULL;
2803 gdImagePtr im;
2804 gdPointPtr points;
2805 int npoints, col, nelem, i;
2806
2807 ZEND_PARSE_PARAMETERS_START(3, 4)
2808 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2809 Z_PARAM_ARRAY(POINTS)
2810 Z_PARAM_LONG(NPOINTS)
2811 Z_PARAM_OPTIONAL
2812 Z_PARAM_LONG_OR_NULL(COL, COL_IS_NULL)
2813 ZEND_PARSE_PARAMETERS_END();
2814
2815 if (COL_IS_NULL) {
2816 COL = NPOINTS;
2817 NPOINTS = zend_hash_num_elements(Z_ARRVAL_P(POINTS));
2818 if (NPOINTS % 2 != 0) {
2819 zend_argument_value_error(2, "must have an even number of elements");
2820 RETURN_THROWS();
2821 }
2822 NPOINTS /= 2;
2823 } else {
2824 php_error_docref(NULL, E_DEPRECATED, "Using the $num_points parameter is deprecated");
2825 }
2826
2827 im = php_gd_libgdimageptr_from_zval_p(IM);
2828
2829 npoints = NPOINTS;
2830 col = COL;
2831
2832 nelem = zend_hash_num_elements(Z_ARRVAL_P(POINTS));
2833 if (npoints < 3) {
2834 zend_argument_value_error(3, "must be greater than or equal to 3");
2835 RETURN_THROWS();
2836 }
2837
2838 if (nelem < npoints * 2) {
2839 zend_value_error("Trying to use %d points in array with only %d points", npoints, nelem/2);
2840 RETURN_THROWS();
2841 }
2842
2843 points = (gdPointPtr) safe_emalloc(npoints, sizeof(gdPoint), 0);
2844
2845 for (i = 0; i < npoints; i++) {
2846 if ((var = zend_hash_index_find(Z_ARRVAL_P(POINTS), (i * 2))) != NULL) {
2847 points[i].x = zval_get_long(var);
2848 }
2849 if ((var = zend_hash_index_find(Z_ARRVAL_P(POINTS), (i * 2) + 1)) != NULL) {
2850 points[i].y = zval_get_long(var);
2851 }
2852 }
2853
2854 if (im->AA) {
2855 gdImageSetAntiAliased(im, col);
2856 col = gdAntiAliased;
2857 }
2858 switch (filled) {
2859 case -1:
2860 gdImageOpenPolygon(im, points, npoints, col);
2861 break;
2862 case 0:
2863 gdImagePolygon(im, points, npoints, col);
2864 break;
2865 case 1:
2866 gdImageFilledPolygon(im, points, npoints, col);
2867 break;
2868 }
2869
2870 efree(points);
2871 RETURN_TRUE;
2872 }
2873 /* }}} */
2874
2875 /* {{{ Draw a polygon */
PHP_FUNCTION(imagepolygon)2876 PHP_FUNCTION(imagepolygon)
2877 {
2878 php_imagepolygon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2879 }
2880 /* }}} */
2881
2882 /* {{{ Draw a polygon */
PHP_FUNCTION(imageopenpolygon)2883 PHP_FUNCTION(imageopenpolygon)
2884 {
2885 php_imagepolygon(INTERNAL_FUNCTION_PARAM_PASSTHRU, -1);
2886 }
2887 /* }}} */
2888
2889 /* {{{ Draw a filled polygon */
PHP_FUNCTION(imagefilledpolygon)2890 PHP_FUNCTION(imagefilledpolygon)
2891 {
2892 php_imagepolygon(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2893 }
2894 /* }}} */
2895
2896 /* {{{ php_find_gd_font */
php_find_gd_font(zend_object * font_obj,zend_long font_int)2897 static gdFontPtr php_find_gd_font(zend_object *font_obj, zend_long font_int)
2898 {
2899 if (font_obj) {
2900 return php_gd_font_object_from_zend_object(font_obj)->font;
2901 }
2902
2903 switch (font_int) {
2904 case 1: return gdFontTiny;
2905 case 2: return gdFontSmall;
2906 case 3: return gdFontMediumBold;
2907 case 4: return gdFontLarge;
2908 case 5: return gdFontGiant;
2909 }
2910
2911 return font_int < 1 ? gdFontTiny : gdFontGiant;
2912 }
2913 /* }}} */
2914
2915 /* {{{ php_imagefontsize
2916 * arg = 0 ImageFontWidth
2917 * arg = 1 ImageFontHeight
2918 */
php_imagefontsize(INTERNAL_FUNCTION_PARAMETERS,int arg)2919 static void php_imagefontsize(INTERNAL_FUNCTION_PARAMETERS, int arg)
2920 {
2921 zend_object *font_obj = NULL;
2922 zend_long font_int = 0;
2923 gdFontPtr font;
2924
2925 ZEND_PARSE_PARAMETERS_START(1, 1)
2926 Z_PARAM_OBJ_OF_CLASS_OR_LONG(font_obj, gd_font_ce, font_int)
2927 ZEND_PARSE_PARAMETERS_END();
2928
2929 font = php_find_gd_font(font_obj, font_int);
2930 RETURN_LONG(arg ? font->h : font->w);
2931 }
2932 /* }}} */
2933
2934 /* {{{ Get font width */
PHP_FUNCTION(imagefontwidth)2935 PHP_FUNCTION(imagefontwidth)
2936 {
2937 php_imagefontsize(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2938 }
2939 /* }}} */
2940
2941 /* {{{ Get font height */
PHP_FUNCTION(imagefontheight)2942 PHP_FUNCTION(imagefontheight)
2943 {
2944 php_imagefontsize(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2945 }
2946 /* }}} */
2947
2948 /* {{{ php_gdimagecharup
2949 * workaround for a bug in gd 1.2 */
php_gdimagecharup(gdImagePtr im,gdFontPtr f,int x,int y,int c,int color)2950 static void php_gdimagecharup(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
2951 {
2952 int cx, cy, px, py, fline;
2953 cx = 0;
2954 cy = 0;
2955
2956 if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
2957 return;
2958 }
2959
2960 fline = (c - f->offset) * f->h * f->w;
2961 for (py = y; (py > (y - f->w)); py--) {
2962 for (px = x; (px < (x + f->h)); px++) {
2963 if (f->data[fline + cy * f->w + cx]) {
2964 gdImageSetPixel(im, px, py, color);
2965 }
2966 cy++;
2967 }
2968 cy = 0;
2969 cx++;
2970 }
2971 }
2972 /* }}} */
2973
2974 /* {{{ php_imagechar
2975 * arg = 0 ImageChar
2976 * arg = 1 ImageCharUp
2977 * arg = 2 ImageString
2978 * arg = 3 ImageStringUp
2979 */
php_imagechar(INTERNAL_FUNCTION_PARAMETERS,int mode)2980 static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode)
2981 {
2982 zval *IM;
2983 zend_long X, Y, COL;
2984 zend_string *C;
2985 gdImagePtr im;
2986 int ch = 0, col, x, y, i, l = 0;
2987 unsigned char *str = NULL;
2988 zend_object *font_obj = NULL;
2989 zend_long font_int = 0;
2990
2991 ZEND_PARSE_PARAMETERS_START(6, 6)
2992 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
2993 Z_PARAM_OBJ_OF_CLASS_OR_LONG(font_obj, gd_font_ce, font_int)
2994 Z_PARAM_LONG(X)
2995 Z_PARAM_LONG(Y)
2996 Z_PARAM_STR(C)
2997 Z_PARAM_LONG(COL)
2998 ZEND_PARSE_PARAMETERS_END();
2999
3000 im = php_gd_libgdimageptr_from_zval_p(IM);
3001
3002 col = COL;
3003
3004 if (mode < 2) {
3005 ch = (int)((unsigned char)*ZSTR_VAL(C));
3006 } else {
3007 str = (unsigned char *) estrndup(ZSTR_VAL(C), ZSTR_LEN(C));
3008 l = strlen((char *)str);
3009 }
3010
3011 y = Y;
3012 x = X;
3013
3014 gdFontPtr font = php_find_gd_font(font_obj, font_int);
3015
3016 switch (mode) {
3017 case 0:
3018 gdImageChar(im, font, x, y, ch, col);
3019 break;
3020 case 1:
3021 php_gdimagecharup(im, font, x, y, ch, col);
3022 break;
3023 case 2:
3024 for (i = 0; (i < l); i++) {
3025 gdImageChar(im, font, x, y, (int) ((unsigned char) str[i]), col);
3026 x += font->w;
3027 }
3028 break;
3029 case 3: {
3030 for (i = 0; (i < l); i++) {
3031 /* php_gdimagecharup(im, font, x, y, (int) str[i], col); */
3032 gdImageCharUp(im, font, x, y, (int) str[i], col);
3033 y -= font->w;
3034 }
3035 break;
3036 }
3037 }
3038 if (str) {
3039 efree(str);
3040 }
3041 RETURN_TRUE;
3042 }
3043 /* }}} */
3044
3045 /* {{{ Draw a character */
PHP_FUNCTION(imagechar)3046 PHP_FUNCTION(imagechar)
3047 {
3048 php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3049 }
3050 /* }}} */
3051
3052 /* {{{ Draw a character rotated 90 degrees counter-clockwise */
PHP_FUNCTION(imagecharup)3053 PHP_FUNCTION(imagecharup)
3054 {
3055 php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3056 }
3057 /* }}} */
3058
3059 /* {{{ Draw a string horizontally */
PHP_FUNCTION(imagestring)3060 PHP_FUNCTION(imagestring)
3061 {
3062 php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
3063 }
3064 /* }}} */
3065
3066 /* {{{ Draw a string vertically - rotated 90 degrees counter-clockwise */
PHP_FUNCTION(imagestringup)3067 PHP_FUNCTION(imagestringup)
3068 {
3069 php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
3070 }
3071 /* }}} */
3072
3073 /* {{{ Copy part of an image */
PHP_FUNCTION(imagecopy)3074 PHP_FUNCTION(imagecopy)
3075 {
3076 zval *SIM, *DIM;
3077 zend_long SX, SY, SW, SH, DX, DY;
3078 gdImagePtr im_dst, im_src;
3079 int srcH, srcW, srcY, srcX, dstY, dstX;
3080
3081 ZEND_PARSE_PARAMETERS_START(8, 8)
3082 Z_PARAM_OBJECT_OF_CLASS(DIM, gd_image_ce)
3083 Z_PARAM_OBJECT_OF_CLASS(SIM, gd_image_ce)
3084 Z_PARAM_LONG(DX)
3085 Z_PARAM_LONG(DY)
3086 Z_PARAM_LONG(SX)
3087 Z_PARAM_LONG(SY)
3088 Z_PARAM_LONG(SW)
3089 Z_PARAM_LONG(SH)
3090 ZEND_PARSE_PARAMETERS_END();
3091
3092 im_dst = php_gd_libgdimageptr_from_zval_p(DIM);
3093 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
3094
3095 srcX = SX;
3096 srcY = SY;
3097 srcH = SH;
3098 srcW = SW;
3099 dstX = DX;
3100 dstY = DY;
3101
3102 gdImageCopy(im_dst, im_src, dstX, dstY, srcX, srcY, srcW, srcH);
3103 RETURN_TRUE;
3104 }
3105 /* }}} */
3106
3107 /* {{{ Merge one part of an image with another */
PHP_FUNCTION(imagecopymerge)3108 PHP_FUNCTION(imagecopymerge)
3109 {
3110 zval *SIM, *DIM;
3111 zend_long SX, SY, SW, SH, DX, DY, PCT;
3112 gdImagePtr im_dst, im_src;
3113 int srcH, srcW, srcY, srcX, dstY, dstX, pct;
3114
3115 ZEND_PARSE_PARAMETERS_START(9, 9)
3116 Z_PARAM_OBJECT_OF_CLASS(DIM, gd_image_ce)
3117 Z_PARAM_OBJECT_OF_CLASS(SIM, gd_image_ce)
3118 Z_PARAM_LONG(DX)
3119 Z_PARAM_LONG(DY)
3120 Z_PARAM_LONG(SX)
3121 Z_PARAM_LONG(SY)
3122 Z_PARAM_LONG(SW)
3123 Z_PARAM_LONG(SH)
3124 Z_PARAM_LONG(PCT)
3125 ZEND_PARSE_PARAMETERS_END();
3126
3127 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
3128 im_dst = php_gd_libgdimageptr_from_zval_p(DIM);
3129
3130 srcX = SX;
3131 srcY = SY;
3132 srcH = SH;
3133 srcW = SW;
3134 dstX = DX;
3135 dstY = DY;
3136 pct = PCT;
3137
3138 gdImageCopyMerge(im_dst, im_src, dstX, dstY, srcX, srcY, srcW, srcH, pct);
3139 RETURN_TRUE;
3140 }
3141 /* }}} */
3142
3143 /* {{{ Merge one part of an image with another */
PHP_FUNCTION(imagecopymergegray)3144 PHP_FUNCTION(imagecopymergegray)
3145 {
3146 zval *SIM, *DIM;
3147 zend_long SX, SY, SW, SH, DX, DY, PCT;
3148 gdImagePtr im_dst, im_src;
3149 int srcH, srcW, srcY, srcX, dstY, dstX, pct;
3150
3151 ZEND_PARSE_PARAMETERS_START(9, 9)
3152 Z_PARAM_OBJECT_OF_CLASS(DIM, gd_image_ce)
3153 Z_PARAM_OBJECT_OF_CLASS(SIM, gd_image_ce)
3154 Z_PARAM_LONG(DX)
3155 Z_PARAM_LONG(DY)
3156 Z_PARAM_LONG(SX)
3157 Z_PARAM_LONG(SY)
3158 Z_PARAM_LONG(SW)
3159 Z_PARAM_LONG(SH)
3160 Z_PARAM_LONG(PCT)
3161 ZEND_PARSE_PARAMETERS_END();
3162
3163 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
3164 im_dst = php_gd_libgdimageptr_from_zval_p(DIM);
3165
3166 srcX = SX;
3167 srcY = SY;
3168 srcH = SH;
3169 srcW = SW;
3170 dstX = DX;
3171 dstY = DY;
3172 pct = PCT;
3173
3174 gdImageCopyMergeGray(im_dst, im_src, dstX, dstY, srcX, srcY, srcW, srcH, pct);
3175 RETURN_TRUE;
3176 }
3177 /* }}} */
3178
3179 /* {{{ Copy and resize part of an image */
PHP_FUNCTION(imagecopyresized)3180 PHP_FUNCTION(imagecopyresized)
3181 {
3182 zval *SIM, *DIM;
3183 zend_long SX, SY, SW, SH, DX, DY, DW, DH;
3184 gdImagePtr im_dst, im_src;
3185 int srcH, srcW, dstH, dstW, srcY, srcX, dstY, dstX;
3186
3187 ZEND_PARSE_PARAMETERS_START(10, 10)
3188 Z_PARAM_OBJECT_OF_CLASS(DIM, gd_image_ce)
3189 Z_PARAM_OBJECT_OF_CLASS(SIM, gd_image_ce)
3190 Z_PARAM_LONG(DX)
3191 Z_PARAM_LONG(DY)
3192 Z_PARAM_LONG(SX)
3193 Z_PARAM_LONG(SY)
3194 Z_PARAM_LONG(DW)
3195 Z_PARAM_LONG(DH)
3196 Z_PARAM_LONG(SW)
3197 Z_PARAM_LONG(SH)
3198 ZEND_PARSE_PARAMETERS_END();
3199
3200 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
3201 im_dst = php_gd_libgdimageptr_from_zval_p(DIM);
3202
3203 srcX = SX;
3204 srcY = SY;
3205 srcH = SH;
3206 srcW = SW;
3207 dstX = DX;
3208 dstY = DY;
3209 dstH = DH;
3210 dstW = DW;
3211
3212 if (dstW <= 0) {
3213 zend_argument_value_error(7, "must be greater than 0");
3214 RETURN_THROWS();
3215 }
3216
3217 if (dstH <= 0) {
3218 zend_argument_value_error(8, "must be greater than 0");
3219 RETURN_THROWS();
3220 }
3221
3222 if (srcW <= 0) {
3223 zend_argument_value_error(9, "must be greater than 0");
3224 RETURN_THROWS();
3225 }
3226
3227 if (srcH <= 0) {
3228 zend_argument_value_error(10, "must be greater than 0");
3229 RETURN_THROWS();
3230 }
3231
3232 gdImageCopyResized(im_dst, im_src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);
3233 RETURN_TRUE;
3234 }
3235 /* }}} */
3236
3237 /* {{{ Get image width */
PHP_FUNCTION(imagesx)3238 PHP_FUNCTION(imagesx)
3239 {
3240 zval *IM;
3241 gdImagePtr im;
3242
3243 ZEND_PARSE_PARAMETERS_START(1, 1)
3244 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
3245 ZEND_PARSE_PARAMETERS_END();
3246
3247 im = php_gd_libgdimageptr_from_zval_p(IM);
3248
3249 RETURN_LONG(gdImageSX(im));
3250 }
3251 /* }}} */
3252
3253 /* {{{ Get image height */
PHP_FUNCTION(imagesy)3254 PHP_FUNCTION(imagesy)
3255 {
3256 zval *IM;
3257 gdImagePtr im;
3258
3259 ZEND_PARSE_PARAMETERS_START(1, 1)
3260 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
3261 ZEND_PARSE_PARAMETERS_END();
3262
3263 im = php_gd_libgdimageptr_from_zval_p(IM);
3264
3265 RETURN_LONG(gdImageSY(im));
3266 }
3267 /* }}} */
3268
3269 /* {{{ Set the clipping rectangle. */
PHP_FUNCTION(imagesetclip)3270 PHP_FUNCTION(imagesetclip)
3271 {
3272 zval *im_zval;
3273 gdImagePtr im;
3274 zend_long x1, y1, x2, y2;
3275
3276 ZEND_PARSE_PARAMETERS_START(5, 5)
3277 Z_PARAM_OBJECT_OF_CLASS(im_zval, gd_image_ce)
3278 Z_PARAM_LONG(x1)
3279 Z_PARAM_LONG(y1)
3280 Z_PARAM_LONG(x2)
3281 Z_PARAM_LONG(y2)
3282 ZEND_PARSE_PARAMETERS_END();
3283
3284 im = php_gd_libgdimageptr_from_zval_p(im_zval);
3285
3286 gdImageSetClip(im, x1, y1, x2, y2);
3287 RETURN_TRUE;
3288 }
3289 /* }}} */
3290
3291 /* {{{ Get the clipping rectangle. */
PHP_FUNCTION(imagegetclip)3292 PHP_FUNCTION(imagegetclip)
3293 {
3294 zval *im_zval;
3295 gdImagePtr im;
3296 int x1, y1, x2, y2;
3297
3298 ZEND_PARSE_PARAMETERS_START(1, 1)
3299 Z_PARAM_OBJECT_OF_CLASS(im_zval, gd_image_ce)
3300 ZEND_PARSE_PARAMETERS_END();
3301
3302 im = php_gd_libgdimageptr_from_zval_p(im_zval);
3303
3304 gdImageGetClip(im, &x1, &y1, &x2, &y2);
3305
3306 array_init(return_value);
3307 add_next_index_long(return_value, x1);
3308 add_next_index_long(return_value, y1);
3309 add_next_index_long(return_value, x2);
3310 add_next_index_long(return_value, y2);
3311 }
3312 /* }}} */
3313
3314 #define TTFTEXT_DRAW 0
3315 #define TTFTEXT_BBOX 1
3316
3317 #ifdef HAVE_GD_FREETYPE
3318 /* {{{ Give the bounding box of a text using fonts via freetype2 */
PHP_FUNCTION(imageftbbox)3319 PHP_FUNCTION(imageftbbox)
3320 {
3321 php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_BBOX);
3322 }
3323 /* }}} */
3324
3325 /* {{{ Write text to the image using fonts via freetype2 */
PHP_FUNCTION(imagefttext)3326 PHP_FUNCTION(imagefttext)
3327 {
3328 php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_DRAW);
3329 }
3330 /* }}} */
3331
3332 /* {{{ php_imagettftext_common */
php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS,int mode)3333 static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode)
3334 {
3335 zval *IM, *EXT = NULL;
3336 gdImagePtr im=NULL;
3337 zend_long col = -1, x = 0, y = 0;
3338 size_t str_len, fontname_len;
3339 int i, brect[8];
3340 double ptsize, angle;
3341 char *str = NULL, *fontname = NULL;
3342 char *error = NULL;
3343 gdFTStringExtra strex = {0};
3344
3345 if (mode == TTFTEXT_BBOX) {
3346 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ddss|a", &ptsize, &angle, &fontname, &fontname_len, &str, &str_len, &EXT) == FAILURE) {
3347 RETURN_THROWS();
3348 }
3349 } else {
3350 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oddlllss|a", &IM, gd_image_ce, &ptsize, &angle, &x, &y, &col, &fontname, &fontname_len, &str, &str_len, &EXT) == FAILURE) {
3351 RETURN_THROWS();
3352 }
3353 im = php_gd_libgdimageptr_from_zval_p(IM);
3354 }
3355
3356 /* convert angle to radians */
3357 angle = angle * (M_PI/180);
3358
3359 if (EXT) { /* parse extended info */
3360 zval *item;
3361 zend_string *key;
3362
3363 /* walk the assoc array */
3364 if (!HT_IS_PACKED(Z_ARRVAL_P(EXT))) {
3365 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(EXT), key, item) {
3366 if (key == NULL) {
3367 continue;
3368 }
3369 if (zend_string_equals_literal(key, "linespacing")) {
3370 strex.flags |= gdFTEX_LINESPACE;
3371 strex.linespacing = zval_get_double(item);
3372 }
3373 } ZEND_HASH_FOREACH_END();
3374 }
3375 }
3376
3377 #ifdef VIRTUAL_DIR
3378 {
3379 char tmp_font_path[MAXPATHLEN];
3380
3381 if (!VCWD_REALPATH(fontname, tmp_font_path)) {
3382 fontname = NULL;
3383 }
3384 }
3385 #endif /* VIRTUAL_DIR */
3386
3387 PHP_GD_CHECK_OPEN_BASEDIR(fontname, "Invalid font filename");
3388
3389 // libgd note: Those should return const char * ideally, but backward compatibility ..
3390 if (EXT) {
3391 error = gdImageStringFTEx(im, brect, col, fontname, ptsize, angle, x, y, str, &strex);
3392 } else {
3393 error = gdImageStringFT(im, brect, col, fontname, ptsize, angle, x, y, str);
3394 }
3395
3396 if (error) {
3397 php_error_docref(NULL, E_WARNING, "%s", error);
3398 RETURN_FALSE;
3399 }
3400
3401 array_init(return_value);
3402
3403 /* return array with the text's bounding box */
3404 for (i = 0; i < 8; i++) {
3405 add_next_index_long(return_value, brect[i]);
3406 }
3407 }
3408 /* }}} */
3409 #endif /* HAVE_GD_FREETYPE */
3410
3411 /* Section Filters */
3412 #define PHP_GD_SINGLE_RES \
3413 zval *SIM; \
3414 gdImagePtr im_src; \
3415 if (zend_parse_parameters(1, "O", &SIM, gd_image_ce) == FAILURE) { \
3416 RETURN_THROWS(); \
3417 } \
3418 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
3419
php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS)3420 static void php_image_filter_negate(INTERNAL_FUNCTION_PARAMETERS)
3421 {
3422 PHP_GD_SINGLE_RES
3423
3424 if (gdImageNegate(im_src) == 1) {
3425 RETURN_TRUE;
3426 }
3427
3428 RETURN_FALSE;
3429 }
3430
php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS)3431 static void php_image_filter_grayscale(INTERNAL_FUNCTION_PARAMETERS)
3432 {
3433 PHP_GD_SINGLE_RES
3434
3435 if (gdImageGrayScale(im_src) == 1) {
3436 RETURN_TRUE;
3437 }
3438
3439 RETURN_FALSE;
3440 }
3441
php_image_filter_brightness(INTERNAL_FUNCTION_PARAMETERS)3442 static void php_image_filter_brightness(INTERNAL_FUNCTION_PARAMETERS)
3443 {
3444 zval *SIM;
3445 gdImagePtr im_src;
3446 zend_long brightness, tmp;
3447
3448 ZEND_PARSE_PARAMETERS_START(3, 3)
3449 Z_PARAM_OBJECT_OF_CLASS(SIM, gd_image_ce)
3450 Z_PARAM_LONG(tmp)
3451 Z_PARAM_LONG(brightness)
3452 ZEND_PARSE_PARAMETERS_END();
3453
3454 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
3455
3456 if (gdImageBrightness(im_src, (int)brightness) == 1) {
3457 RETURN_TRUE;
3458 }
3459
3460 RETURN_FALSE;
3461 }
3462
php_image_filter_contrast(INTERNAL_FUNCTION_PARAMETERS)3463 static void php_image_filter_contrast(INTERNAL_FUNCTION_PARAMETERS)
3464 {
3465 zval *SIM;
3466 gdImagePtr im_src;
3467 zend_long contrast, tmp;
3468
3469 ZEND_PARSE_PARAMETERS_START(3, 3)
3470 Z_PARAM_OBJECT_OF_CLASS(SIM, gd_image_ce)
3471 Z_PARAM_LONG(tmp)
3472 Z_PARAM_LONG(contrast)
3473 ZEND_PARSE_PARAMETERS_END();
3474
3475 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
3476
3477 if (gdImageContrast(im_src, (int)contrast) == 1) {
3478 RETURN_TRUE;
3479 }
3480
3481 RETURN_FALSE;
3482 }
3483
php_image_filter_colorize(INTERNAL_FUNCTION_PARAMETERS)3484 static void php_image_filter_colorize(INTERNAL_FUNCTION_PARAMETERS)
3485 {
3486 zval *SIM;
3487 gdImagePtr im_src;
3488 zend_long r,g,b,tmp;
3489 zend_long a = 0;
3490
3491 ZEND_PARSE_PARAMETERS_START(5, 6)
3492 Z_PARAM_OBJECT_OF_CLASS(SIM, gd_image_ce)
3493 Z_PARAM_LONG(tmp)
3494 Z_PARAM_LONG(r)
3495 Z_PARAM_LONG(g)
3496 Z_PARAM_LONG(b)
3497 Z_PARAM_OPTIONAL
3498 Z_PARAM_LONG(a)
3499 ZEND_PARSE_PARAMETERS_END();
3500
3501 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
3502
3503 if (gdImageColor(im_src, (int) r, (int) g, (int) b, (int) a) == 1) {
3504 RETURN_TRUE;
3505 }
3506
3507 RETURN_FALSE;
3508 }
3509
php_image_filter_edgedetect(INTERNAL_FUNCTION_PARAMETERS)3510 static void php_image_filter_edgedetect(INTERNAL_FUNCTION_PARAMETERS)
3511 {
3512 PHP_GD_SINGLE_RES
3513
3514 if (gdImageEdgeDetectQuick(im_src) == 1) {
3515 RETURN_TRUE;
3516 }
3517
3518 RETURN_FALSE;
3519 }
3520
php_image_filter_emboss(INTERNAL_FUNCTION_PARAMETERS)3521 static void php_image_filter_emboss(INTERNAL_FUNCTION_PARAMETERS)
3522 {
3523 PHP_GD_SINGLE_RES
3524
3525 if (gdImageEmboss(im_src) == 1) {
3526 RETURN_TRUE;
3527 }
3528
3529 RETURN_FALSE;
3530 }
3531
php_image_filter_gaussian_blur(INTERNAL_FUNCTION_PARAMETERS)3532 static void php_image_filter_gaussian_blur(INTERNAL_FUNCTION_PARAMETERS)
3533 {
3534 PHP_GD_SINGLE_RES
3535
3536 if (gdImageGaussianBlur(im_src) == 1) {
3537 RETURN_TRUE;
3538 }
3539
3540 RETURN_FALSE;
3541 }
3542
php_image_filter_selective_blur(INTERNAL_FUNCTION_PARAMETERS)3543 static void php_image_filter_selective_blur(INTERNAL_FUNCTION_PARAMETERS)
3544 {
3545 PHP_GD_SINGLE_RES
3546
3547 if (gdImageSelectiveBlur(im_src) == 1) {
3548 RETURN_TRUE;
3549 }
3550
3551 RETURN_FALSE;
3552 }
3553
php_image_filter_mean_removal(INTERNAL_FUNCTION_PARAMETERS)3554 static void php_image_filter_mean_removal(INTERNAL_FUNCTION_PARAMETERS)
3555 {
3556 PHP_GD_SINGLE_RES
3557
3558 if (gdImageMeanRemoval(im_src) == 1) {
3559 RETURN_TRUE;
3560 }
3561
3562 RETURN_FALSE;
3563 }
3564
php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS)3565 static void php_image_filter_smooth(INTERNAL_FUNCTION_PARAMETERS)
3566 {
3567 zval *SIM;
3568 zend_long tmp;
3569 gdImagePtr im_src;
3570 double weight;
3571
3572 ZEND_PARSE_PARAMETERS_START(3, 3)
3573 Z_PARAM_OBJECT_OF_CLASS(SIM, gd_image_ce)
3574 Z_PARAM_LONG(tmp)
3575 Z_PARAM_DOUBLE(weight)
3576 ZEND_PARSE_PARAMETERS_END();
3577
3578 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
3579
3580 if (gdImageSmooth(im_src, (float)weight)==1) {
3581 RETURN_TRUE;
3582 }
3583
3584 RETURN_FALSE;
3585 }
3586
php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS)3587 static void php_image_filter_pixelate(INTERNAL_FUNCTION_PARAMETERS)
3588 {
3589 zval *IM;
3590 gdImagePtr im;
3591 zend_long tmp, blocksize;
3592 bool mode = false;
3593
3594 ZEND_PARSE_PARAMETERS_START(3, 4)
3595 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
3596 Z_PARAM_LONG(tmp)
3597 Z_PARAM_LONG(blocksize)
3598 Z_PARAM_OPTIONAL
3599 Z_PARAM_BOOL(mode)
3600 ZEND_PARSE_PARAMETERS_END();
3601
3602 im = php_gd_libgdimageptr_from_zval_p(IM);
3603
3604 if (gdImagePixelate(im, (int) blocksize, (const unsigned int) mode)) {
3605 RETURN_TRUE;
3606 }
3607
3608 RETURN_FALSE;
3609 }
3610
php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS)3611 static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS)
3612 {
3613 zval *IM;
3614 zval *hash_colors = NULL;
3615 gdImagePtr im;
3616 zend_long tmp;
3617 zend_long scatter_sub, scatter_plus;
3618
3619 ZEND_PARSE_PARAMETERS_START(4, 5)
3620 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
3621 Z_PARAM_LONG(tmp)
3622 Z_PARAM_LONG(scatter_sub)
3623 Z_PARAM_LONG(scatter_plus)
3624 Z_PARAM_OPTIONAL
3625 Z_PARAM_ARRAY(hash_colors)
3626 ZEND_PARSE_PARAMETERS_END();
3627
3628 if (scatter_sub < 0 || ZEND_SIZE_T_INT_OVFL(scatter_sub)) {
3629 zend_argument_value_error(3, "must be between 0 and %d", INT_MAX);
3630 RETURN_THROWS();
3631 }
3632
3633 if (scatter_plus < 0 || ZEND_SIZE_T_INT_OVFL(scatter_plus)) {
3634 zend_argument_value_error(4, "must be between 0 and %d", INT_MAX);
3635 RETURN_THROWS();
3636 }
3637
3638 im = php_gd_libgdimageptr_from_zval_p(IM);
3639
3640 if (hash_colors) {
3641 uint32_t i = 0;
3642 uint32_t num_colors = zend_hash_num_elements(Z_ARRVAL_P(hash_colors));
3643 zval *color;
3644 int *colors;
3645
3646 if (num_colors == 0) {
3647 RETURN_BOOL(gdImageScatter(im, (int)scatter_sub, (int)scatter_plus));
3648 }
3649
3650 colors = emalloc(num_colors * sizeof(int));
3651
3652 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(hash_colors), color) {
3653 *(colors + i++) = (int) zval_get_long(color);
3654 } ZEND_HASH_FOREACH_END();
3655
3656 RETVAL_BOOL(gdImageScatterColor(im, (int)scatter_sub, (int)scatter_plus, colors, num_colors));
3657
3658 efree(colors);
3659 } else {
3660 RETURN_BOOL(gdImageScatter(im, (int) scatter_sub, (int) scatter_plus));
3661 }
3662 }
3663
3664 /* {{{ Applies Filter an image using a custom angle */
PHP_FUNCTION(imagefilter)3665 PHP_FUNCTION(imagefilter)
3666 {
3667 zval *tmp;
3668
3669 typedef void (*image_filter)(INTERNAL_FUNCTION_PARAMETERS);
3670 zend_long filtertype;
3671 image_filter filters[] =
3672 {
3673 php_image_filter_negate ,
3674 php_image_filter_grayscale,
3675 php_image_filter_brightness,
3676 php_image_filter_contrast,
3677 php_image_filter_colorize,
3678 php_image_filter_edgedetect,
3679 php_image_filter_emboss,
3680 php_image_filter_gaussian_blur,
3681 php_image_filter_selective_blur,
3682 php_image_filter_mean_removal,
3683 php_image_filter_smooth,
3684 php_image_filter_pixelate,
3685 php_image_filter_scatter
3686 };
3687
3688 if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > IMAGE_FILTER_MAX_ARGS) {
3689 WRONG_PARAM_COUNT;
3690 } else if (zend_parse_parameters(2, "Ol", &tmp, gd_image_ce, &filtertype) == FAILURE) {
3691 RETURN_THROWS();
3692 }
3693
3694 if (filtertype >= 0 && filtertype <= IMAGE_FILTER_MAX) {
3695 filters[filtertype](INTERNAL_FUNCTION_PARAM_PASSTHRU);
3696 }
3697 }
3698 /* }}} */
3699
3700 /* {{{ Apply a 3x3 convolution matrix, using coefficient div and offset */
PHP_FUNCTION(imageconvolution)3701 PHP_FUNCTION(imageconvolution)
3702 {
3703 zval *SIM, *hash_matrix;
3704 zval *var = NULL, *var2 = NULL;
3705 gdImagePtr im_src = NULL;
3706 double div, offset;
3707 int nelem, i, j, res;
3708 float matrix[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}};
3709
3710 ZEND_PARSE_PARAMETERS_START(4, 4)
3711 Z_PARAM_OBJECT_OF_CLASS(SIM, gd_image_ce)
3712 Z_PARAM_ARRAY(hash_matrix)
3713 Z_PARAM_DOUBLE(div)
3714 Z_PARAM_DOUBLE(offset)
3715 ZEND_PARSE_PARAMETERS_END();
3716
3717 im_src = php_gd_libgdimageptr_from_zval_p(SIM);
3718
3719 nelem = zend_hash_num_elements(Z_ARRVAL_P(hash_matrix));
3720 if (nelem != 3) {
3721 zend_argument_value_error(2, "must be a 3x3 array");
3722 RETURN_THROWS();
3723 }
3724
3725 for (i=0; i<3; i++) {
3726 if ((var = zend_hash_index_find(Z_ARRVAL_P(hash_matrix), (i))) != NULL && Z_TYPE_P(var) == IS_ARRAY) {
3727 if (zend_hash_num_elements(Z_ARRVAL_P(var)) != 3 ) {
3728 zend_argument_value_error(2, "must be a 3x3 array, matrix[%d] only has %d elements", i, zend_hash_num_elements(Z_ARRVAL_P(var)));
3729 RETURN_THROWS();
3730 }
3731
3732 for (j=0; j<3; j++) {
3733 if ((var2 = zend_hash_index_find(Z_ARRVAL_P(var), j)) != NULL) {
3734 matrix[i][j] = (float) zval_get_double(var2);
3735 } else {
3736 zend_argument_value_error(2, "must be a 3x3 array, matrix[%d][%d] cannot be found (missing integer key)", i, j);
3737 RETURN_THROWS();
3738 }
3739 }
3740 }
3741 }
3742 res = gdImageConvolution(im_src, matrix, (float)div, (float)offset);
3743
3744 if (res) {
3745 RETURN_TRUE;
3746 } else {
3747 RETURN_FALSE;
3748 }
3749 }
3750 /* }}} */
3751 /* End section: Filters */
3752
3753 /* {{{ Flip an image (in place) horizontally, vertically or both directions. */
PHP_FUNCTION(imageflip)3754 PHP_FUNCTION(imageflip)
3755 {
3756 zval *IM;
3757 zend_long mode;
3758 gdImagePtr im;
3759
3760 ZEND_PARSE_PARAMETERS_START(2, 2)
3761 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
3762 Z_PARAM_LONG(mode)
3763 ZEND_PARSE_PARAMETERS_END();
3764
3765 im = php_gd_libgdimageptr_from_zval_p(IM);
3766
3767 switch (mode) {
3768 case PHP_GD_FLIP_VERTICAL:
3769 gdImageFlipVertical(im);
3770 break;
3771
3772 case PHP_GD_FLIP_HORIZONTAL:
3773 gdImageFlipHorizontal(im);
3774 break;
3775
3776 case PHP_GD_FLIP_BOTH:
3777 gdImageFlipBoth(im);
3778 break;
3779
3780 default:
3781 zend_argument_value_error(2, "must be one of IMG_FLIP_VERTICAL, IMG_FLIP_HORIZONTAL, or IMG_FLIP_BOTH");
3782 RETURN_THROWS();
3783 }
3784
3785 RETURN_TRUE;
3786 }
3787 /* }}} */
3788
3789 /* {{{ Should antialiased functions used or not*/
PHP_FUNCTION(imageantialias)3790 PHP_FUNCTION(imageantialias)
3791 {
3792 zval *IM;
3793 bool alias;
3794 gdImagePtr im;
3795
3796 ZEND_PARSE_PARAMETERS_START(2, 2)
3797 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
3798 Z_PARAM_BOOL(alias)
3799 ZEND_PARSE_PARAMETERS_END();
3800
3801 im = php_gd_libgdimageptr_from_zval_p(IM);
3802 if (im->trueColor) {
3803 im->AA = alias;
3804 }
3805
3806 RETURN_TRUE;
3807 }
3808 /* }}} */
3809
3810 /* {{{ Crop an image using the given coordinates and size, x, y, width and height. */
PHP_FUNCTION(imagecrop)3811 PHP_FUNCTION(imagecrop)
3812 {
3813 zval *IM;
3814 gdImagePtr im;
3815 gdImagePtr im_crop;
3816 gdRect rect;
3817 zval *z_rect;
3818 zval *tmp;
3819
3820 ZEND_PARSE_PARAMETERS_START(2, 2)
3821 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
3822 Z_PARAM_ARRAY(z_rect)
3823 ZEND_PARSE_PARAMETERS_END();
3824
3825 im = php_gd_libgdimageptr_from_zval_p(IM);
3826
3827 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "x", sizeof("x") -1)) != NULL) {
3828 rect.x = zval_get_long(tmp);
3829 } else {
3830 zend_argument_value_error(2, "must have an \"x\" key");
3831 RETURN_THROWS();
3832 }
3833
3834 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "y", sizeof("y") - 1)) != NULL) {
3835 rect.y = zval_get_long(tmp);
3836 } else {
3837 zend_argument_value_error(2, "must have a \"y\" key");
3838 RETURN_THROWS();
3839 }
3840
3841 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "width", sizeof("width") - 1)) != NULL) {
3842 rect.width = zval_get_long(tmp);
3843 } else {
3844 zend_argument_value_error(2, "must have a \"width\" key");
3845 RETURN_THROWS();
3846 }
3847
3848 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "height", sizeof("height") - 1)) != NULL) {
3849 rect.height = zval_get_long(tmp);
3850 } else {
3851 zend_argument_value_error(2, "must have a \"height\" key");
3852 RETURN_THROWS();
3853 }
3854
3855 im_crop = gdImageCrop(im, &rect);
3856
3857 if (im_crop == NULL) {
3858 RETURN_FALSE;
3859 }
3860
3861 php_gd_assign_libgdimageptr_as_extgdimage(return_value, im_crop);
3862 }
3863 /* }}} */
3864
3865 /* {{{ Crop an image automatically using one of the available modes. */
PHP_FUNCTION(imagecropauto)3866 PHP_FUNCTION(imagecropauto)
3867 {
3868 zval *IM;
3869 zend_long mode = GD_CROP_DEFAULT;
3870 zend_long color = -1;
3871 double threshold = 0.5f;
3872 gdImagePtr im;
3873 gdImagePtr im_crop;
3874
3875 ZEND_PARSE_PARAMETERS_START(1, 4)
3876 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
3877 Z_PARAM_OPTIONAL
3878 Z_PARAM_LONG(mode)
3879 Z_PARAM_DOUBLE(threshold)
3880 Z_PARAM_LONG(color)
3881 ZEND_PARSE_PARAMETERS_END();
3882
3883 im = php_gd_libgdimageptr_from_zval_p(IM);
3884
3885 switch (mode) {
3886 case GD_CROP_DEFAULT:
3887 case GD_CROP_TRANSPARENT:
3888 case GD_CROP_BLACK:
3889 case GD_CROP_WHITE:
3890 case GD_CROP_SIDES:
3891 im_crop = gdImageCropAuto(im, mode);
3892 break;
3893
3894 case GD_CROP_THRESHOLD:
3895 if (color < 0 || (!gdImageTrueColor(im) && color >= gdImageColorsTotal(im))) {
3896 zend_argument_value_error(4, "must be greater than or equal to 0 when using the threshold mode");
3897 RETURN_THROWS();
3898 }
3899 im_crop = gdImageCropThreshold(im, color, (float) threshold);
3900 break;
3901
3902 default:
3903 zend_argument_value_error(2, "must be a valid mode");
3904 RETURN_THROWS();
3905 }
3906
3907 if (im_crop == NULL) {
3908 RETURN_FALSE;
3909 }
3910
3911 php_gd_assign_libgdimageptr_as_extgdimage(return_value, im_crop);
3912 }
3913 /* }}} */
3914
3915 /* {{{ Scale an image using the given new width and height. */
PHP_FUNCTION(imagescale)3916 PHP_FUNCTION(imagescale)
3917 {
3918 zval *IM;
3919 gdImagePtr im;
3920 gdImagePtr im_scaled = NULL;
3921 int new_width, new_height;
3922 zend_long tmp_w, tmp_h=-1, tmp_m = GD_BILINEAR_FIXED;
3923 gdInterpolationMethod method, old_method;
3924
3925 ZEND_PARSE_PARAMETERS_START(2, 4)
3926 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
3927 Z_PARAM_LONG(tmp_w)
3928 Z_PARAM_OPTIONAL
3929 Z_PARAM_LONG(tmp_h)
3930 Z_PARAM_LONG(tmp_m)
3931 ZEND_PARSE_PARAMETERS_END();
3932
3933 if (tmp_m < GD_DEFAULT || tmp_m >= GD_METHOD_COUNT) {
3934 zend_argument_value_error(4, "must be one of the GD_* constants");
3935 RETURN_THROWS();
3936 }
3937
3938 method = tmp_m;
3939
3940 im = php_gd_libgdimageptr_from_zval_p(IM);
3941
3942 if (tmp_h < 0 || tmp_w < 0) {
3943 /* preserve ratio */
3944 long src_x, src_y;
3945
3946 src_x = gdImageSX(im);
3947 src_y = gdImageSY(im);
3948
3949 if (src_x && tmp_h < 0) {
3950 tmp_h = tmp_w * src_y / src_x;
3951 }
3952 if (src_y && tmp_w < 0) {
3953 tmp_w = tmp_h * src_x / src_y;
3954 }
3955 }
3956
3957 if (tmp_w <= 0 || ZEND_SIZE_T_INT_OVFL(tmp_w)) {
3958 zend_argument_value_error(2, "must be between 1 and %d", INT_MAX);
3959 RETURN_THROWS();
3960 }
3961
3962 if (tmp_h <= 0 || ZEND_SIZE_T_INT_OVFL(tmp_h)) {
3963 zend_argument_value_error(3, "must be between 1 and %d", INT_MAX);
3964 RETURN_THROWS();
3965 }
3966
3967
3968 new_width = tmp_w;
3969 new_height = tmp_h;
3970
3971 /* gdImageGetInterpolationMethod() is only available as of GD 2.1.1 */
3972 old_method = im->interpolation_id;
3973 if (gdImageSetInterpolationMethod(im, method)) {
3974 im_scaled = gdImageScale(im, new_width, new_height);
3975 }
3976 gdImageSetInterpolationMethod(im, old_method);
3977
3978 if (im_scaled == NULL) {
3979 RETURN_FALSE;
3980 }
3981
3982 php_gd_assign_libgdimageptr_as_extgdimage(return_value, im_scaled);
3983 }
3984 /* }}} */
3985
3986 /* {{{ Return an image containing the affine tramsformed src image, using an optional clipping area */
PHP_FUNCTION(imageaffine)3987 PHP_FUNCTION(imageaffine)
3988 {
3989 zval *IM;
3990 gdImagePtr src;
3991 gdImagePtr dst;
3992 gdRect rect;
3993 gdRectPtr pRect = NULL;
3994 zval *z_rect = NULL;
3995 zval *z_affine;
3996 zval *tmp;
3997 double affine[6];
3998 int i, nelems;
3999 zval *zval_affine_elem = NULL;
4000
4001 ZEND_PARSE_PARAMETERS_START(2, 3)
4002 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
4003 Z_PARAM_ARRAY(z_affine)
4004 Z_PARAM_OPTIONAL
4005 Z_PARAM_ARRAY_OR_NULL(z_rect)
4006 ZEND_PARSE_PARAMETERS_END();
4007
4008
4009 src = php_gd_libgdimageptr_from_zval_p(IM);
4010
4011 if ((nelems = zend_hash_num_elements(Z_ARRVAL_P(z_affine))) != 6) {
4012 zend_argument_value_error(2, "must have 6 elements");
4013 RETURN_THROWS();
4014 }
4015
4016 for (i = 0; i < nelems; i++) {
4017 if ((zval_affine_elem = zend_hash_index_find(Z_ARRVAL_P(z_affine), i)) != NULL) {
4018 switch (Z_TYPE_P(zval_affine_elem)) {
4019 case IS_LONG:
4020 affine[i] = Z_LVAL_P(zval_affine_elem);
4021 if (affine[i] < INT_MIN || affine[i] > INT_MAX) {
4022 zend_argument_value_error(2, "element %i must be between %d and %d", i, INT_MIN, INT_MAX);
4023 RETURN_THROWS();
4024 }
4025 break;
4026 case IS_DOUBLE:
4027 affine[i] = Z_DVAL_P(zval_affine_elem);
4028 if (affine[i] < INT_MIN || affine[i] > INT_MAX) {
4029 zend_argument_value_error(2, "element %i must be between %d and %d", i, INT_MIN, INT_MAX);
4030 RETURN_THROWS();
4031 }
4032 break;
4033 case IS_STRING:
4034 affine[i] = zval_get_double(zval_affine_elem);
4035 if (affine[i] < INT_MIN || affine[i] > INT_MAX) {
4036 zend_argument_value_error(2, "element %i must be between %d and %d", i, INT_MIN, INT_MAX);
4037 RETURN_THROWS();
4038 }
4039 break;
4040 default:
4041 zend_argument_type_error(3, "contains invalid type for element %i", i);
4042 RETURN_THROWS();
4043 }
4044 }
4045 }
4046
4047 if (z_rect != NULL) {
4048 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "x", sizeof("x") - 1)) != NULL) {
4049 rect.x = zval_get_long(tmp);
4050 } else {
4051 zend_argument_value_error(3, "must have an \"x\" key");
4052 RETURN_THROWS();
4053 }
4054
4055 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "y", sizeof("y") - 1)) != NULL) {
4056 rect.y = zval_get_long(tmp);
4057 } else {
4058 zend_argument_value_error(3, "must have a \"y\" key");
4059 RETURN_THROWS();
4060 }
4061
4062 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "width", sizeof("width") - 1)) != NULL) {
4063 rect.width = zval_get_long(tmp);
4064 } else {
4065 zend_argument_value_error(3, "must have a \"width\" key");
4066 RETURN_THROWS();
4067 }
4068
4069 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(z_rect), "height", sizeof("height") - 1)) != NULL) {
4070 rect.height = zval_get_long(tmp);
4071 } else {
4072 zend_argument_value_error(3, "must have a \"height\" key");
4073 RETURN_THROWS();
4074 }
4075 pRect = ▭
4076 }
4077
4078 if (gdTransformAffineGetImage(&dst, src, pRect, affine) != GD_TRUE) {
4079 RETURN_FALSE;
4080 }
4081
4082 if (dst == NULL) {
4083 RETURN_FALSE;
4084 }
4085
4086 php_gd_assign_libgdimageptr_as_extgdimage(return_value, dst);
4087 }
4088 /* }}} */
4089
4090 /* {{{ Return an image containing the affine tramsformed src image, using an optional clipping area */
PHP_FUNCTION(imageaffinematrixget)4091 PHP_FUNCTION(imageaffinematrixget)
4092 {
4093 double affine[6];
4094 zend_long type;
4095 zval *options = NULL;
4096 zval *tmp;
4097 int res = GD_FALSE, i;
4098
4099 ZEND_PARSE_PARAMETERS_START(2, 2)
4100 Z_PARAM_LONG(type)
4101 Z_PARAM_ZVAL(options)
4102 ZEND_PARSE_PARAMETERS_END();
4103
4104 switch((gdAffineStandardMatrix)type) {
4105 case GD_AFFINE_TRANSLATE:
4106 case GD_AFFINE_SCALE: {
4107 double x, y;
4108 if (Z_TYPE_P(options) != IS_ARRAY) {
4109 zend_argument_type_error(1, "must be of type array when using translate or scale");
4110 RETURN_THROWS();
4111 }
4112
4113 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(options), "x", sizeof("x") - 1)) != NULL) {
4114 x = zval_get_double(tmp);
4115 } else {
4116 zend_argument_value_error(2, "must have an \"x\" key");
4117 RETURN_THROWS();
4118 }
4119
4120 if ((tmp = zend_hash_str_find(Z_ARRVAL_P(options), "y", sizeof("y") - 1)) != NULL) {
4121 y = zval_get_double(tmp);
4122 } else {
4123 zend_argument_value_error(2, "must have a \"y\" key");
4124 RETURN_THROWS();
4125 }
4126
4127 if (type == GD_AFFINE_TRANSLATE) {
4128 res = gdAffineTranslate(affine, x, y);
4129 } else {
4130 res = gdAffineScale(affine, x, y);
4131 }
4132 break;
4133 }
4134
4135 case GD_AFFINE_ROTATE:
4136 case GD_AFFINE_SHEAR_HORIZONTAL:
4137 case GD_AFFINE_SHEAR_VERTICAL: {
4138 double angle;
4139
4140 angle = zval_get_double(options);
4141
4142 if (type == GD_AFFINE_SHEAR_HORIZONTAL) {
4143 res = gdAffineShearHorizontal(affine, angle);
4144 } else if (type == GD_AFFINE_SHEAR_VERTICAL) {
4145 res = gdAffineShearVertical(affine, angle);
4146 } else {
4147 res = gdAffineRotate(affine, angle);
4148 }
4149 break;
4150 }
4151
4152 default:
4153 zend_argument_value_error(1, "must be a valid element type");
4154 RETURN_THROWS();
4155 }
4156
4157 if (res == GD_FALSE) {
4158 RETURN_FALSE;
4159 } else {
4160 array_init(return_value);
4161 for (i = 0; i < 6; i++) {
4162 add_index_double(return_value, i, affine[i]);
4163 }
4164 }
4165 } /* }}} */
4166
4167 /* {{{ Concat two matrices (as in doing many ops in one go) */
PHP_FUNCTION(imageaffinematrixconcat)4168 PHP_FUNCTION(imageaffinematrixconcat)
4169 {
4170 double m1[6];
4171 double m2[6];
4172 double mr[6];
4173
4174 zval *tmp;
4175 zval *z_m1;
4176 zval *z_m2;
4177 int i;
4178
4179 ZEND_PARSE_PARAMETERS_START(2, 2)
4180 Z_PARAM_ARRAY(z_m1)
4181 Z_PARAM_ARRAY(z_m2)
4182 ZEND_PARSE_PARAMETERS_END();
4183
4184 if (zend_hash_num_elements(Z_ARRVAL_P(z_m1)) != 6) {
4185 zend_argument_value_error(1, "must have 6 elements");
4186 RETURN_THROWS();
4187 }
4188
4189 if (zend_hash_num_elements(Z_ARRVAL_P(z_m2)) != 6) {
4190 zend_argument_value_error(1, "must have 6 elements");
4191 RETURN_THROWS();
4192 }
4193
4194 for (i = 0; i < 6; i++) {
4195 if ((tmp = zend_hash_index_find(Z_ARRVAL_P(z_m1), i)) != NULL) {
4196 switch (Z_TYPE_P(tmp)) {
4197 case IS_LONG:
4198 m1[i] = Z_LVAL_P(tmp);
4199 break;
4200 case IS_DOUBLE:
4201 m1[i] = Z_DVAL_P(tmp);
4202 break;
4203 case IS_STRING:
4204 m1[i] = zval_get_double(tmp);
4205 break;
4206 default:
4207 zend_argument_type_error(1, "contains invalid type for element %i", i);
4208 RETURN_THROWS();
4209 }
4210 }
4211
4212 if ((tmp = zend_hash_index_find(Z_ARRVAL_P(z_m2), i)) != NULL) {
4213 switch (Z_TYPE_P(tmp)) {
4214 case IS_LONG:
4215 m2[i] = Z_LVAL_P(tmp);
4216 break;
4217 case IS_DOUBLE:
4218 m2[i] = Z_DVAL_P(tmp);
4219 break;
4220 case IS_STRING:
4221 m2[i] = zval_get_double(tmp);
4222 break;
4223 default:
4224 zend_argument_type_error(2, "contains invalid type for element %i", i);
4225 RETURN_THROWS();
4226 }
4227 }
4228 }
4229
4230 if (gdAffineConcat (mr, m1, m2) != GD_TRUE) {
4231 RETURN_FALSE;
4232 }
4233
4234 array_init(return_value);
4235 for (i = 0; i < 6; i++) {
4236 add_index_double(return_value, i, mr[i]);
4237 }
4238 } /* }}} */
4239
4240 /* {{{ Get the default interpolation method. */
PHP_FUNCTION(imagegetinterpolation)4241 PHP_FUNCTION(imagegetinterpolation)
4242 {
4243 zval *IM;
4244 gdImagePtr im;
4245
4246 ZEND_PARSE_PARAMETERS_START(1, 1)
4247 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
4248 ZEND_PARSE_PARAMETERS_END();
4249
4250 im = php_gd_libgdimageptr_from_zval_p(IM);
4251
4252 #ifdef HAVE_GD_GET_INTERPOLATION
4253 RETURN_LONG(gdImageGetInterpolationMethod(im));
4254 #else
4255 RETURN_LONG(im->interpolation_id);
4256 #endif
4257 }
4258 /* }}} */
4259
4260 /* {{{ Set the default interpolation method, passing -1 or 0 sets it to the libgd default (bilinear). */
PHP_FUNCTION(imagesetinterpolation)4261 PHP_FUNCTION(imagesetinterpolation)
4262 {
4263 zval *IM;
4264 gdImagePtr im;
4265 zend_long method = GD_BILINEAR_FIXED;
4266
4267 ZEND_PARSE_PARAMETERS_START(1, 2)
4268 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
4269 Z_PARAM_OPTIONAL
4270 Z_PARAM_LONG(method)
4271 ZEND_PARSE_PARAMETERS_END();
4272
4273 im = php_gd_libgdimageptr_from_zval_p(IM);
4274
4275 if (method == -1) {
4276 method = GD_BILINEAR_FIXED;
4277 }
4278 RETURN_BOOL(gdImageSetInterpolationMethod(im, (gdInterpolationMethod) method));
4279 }
4280 /* }}} */
4281
4282 /* {{{ Get or set the resolution of the image in DPI. */
PHP_FUNCTION(imageresolution)4283 PHP_FUNCTION(imageresolution)
4284 {
4285 zval *IM;
4286 gdImagePtr im;
4287 zend_long res_x, res_y;
4288 bool res_x_is_null = true, res_y_is_null = true;
4289
4290 ZEND_PARSE_PARAMETERS_START(1, 3)
4291 Z_PARAM_OBJECT_OF_CLASS(IM, gd_image_ce)
4292 Z_PARAM_OPTIONAL
4293 Z_PARAM_LONG_OR_NULL(res_x, res_x_is_null)
4294 Z_PARAM_LONG_OR_NULL(res_y, res_y_is_null)
4295 ZEND_PARSE_PARAMETERS_END();
4296
4297 im = php_gd_libgdimageptr_from_zval_p(IM);
4298
4299 if (!res_x_is_null && !res_y_is_null) {
4300 if (res_x < 0 || ZEND_SIZE_T_UINT_OVFL(res_x)) {
4301 zend_argument_value_error(2, "must be between 0 and %u", UINT_MAX);
4302 RETURN_THROWS();
4303 }
4304 if (res_y < 0 || ZEND_SIZE_T_UINT_OVFL(res_y)) {
4305 zend_argument_value_error(3, "must be between 0 and %u", UINT_MAX);
4306 RETURN_THROWS();
4307 }
4308 gdImageSetResolution(im, res_x, res_y);
4309 RETURN_TRUE;
4310 } else if (!res_x_is_null && res_y_is_null) {
4311 if (res_x < 0 || ZEND_SIZE_T_UINT_OVFL(res_x)) {
4312 zend_argument_value_error(2, "must be between 0 and %u", UINT_MAX);
4313 RETURN_THROWS();
4314 }
4315 gdImageSetResolution(im, res_x, res_x);
4316 RETURN_TRUE;
4317 } else if (res_x_is_null && !res_y_is_null) {
4318 if (res_y < 0 || ZEND_SIZE_T_UINT_OVFL(res_y)) {
4319 zend_argument_value_error(3, "must be between 0 and %u", UINT_MAX);
4320 RETURN_THROWS();
4321 }
4322 gdImageSetResolution(im, res_y, res_y);
4323 RETURN_TRUE;
4324 }
4325
4326 array_init(return_value);
4327 add_next_index_long(return_value, gdImageResolutionX(im));
4328 add_next_index_long(return_value, gdImageResolutionY(im));
4329 }
4330 /* }}} */
4331
4332
4333 /*********************************************************
4334 *
4335 * Stream Handling
4336 * Formerly contained within ext/gd/gd_ctx.c and included
4337 * at the the top of this file
4338 *
4339 ********************************************************/
4340
4341 #define CTX_PUTC(c,ctx) ctx->putC(ctx, c)
4342
_php_image_output_putc(struct gdIOCtx * ctx,int c)4343 static void _php_image_output_putc(struct gdIOCtx *ctx, int c) /* {{{ */
4344 {
4345 /* without the following downcast, the write will fail
4346 * (i.e., will write a zero byte) for all
4347 * big endian architectures:
4348 */
4349 unsigned char ch = (unsigned char) c;
4350 php_write(&ch, 1);
4351 } /* }}} */
4352
_php_image_output_putbuf(struct gdIOCtx * ctx,const void * buf,int l)4353 static int _php_image_output_putbuf(struct gdIOCtx *ctx, const void* buf, int l) /* {{{ */
4354 {
4355 return php_write((void *)buf, l);
4356 } /* }}} */
4357
_php_image_output_ctxfree(struct gdIOCtx * ctx)4358 static void _php_image_output_ctxfree(struct gdIOCtx *ctx) /* {{{ */
4359 {
4360 efree(ctx);
4361 } /* }}} */
4362
_php_image_stream_putc(struct gdIOCtx * ctx,int c)4363 static void _php_image_stream_putc(struct gdIOCtx *ctx, int c) /* {{{ */ {
4364 char ch = (char) c;
4365 php_stream * stream = (php_stream *)ctx->data;
4366 php_stream_write(stream, &ch, 1);
4367 } /* }}} */
4368
_php_image_stream_putbuf(struct gdIOCtx * ctx,const void * buf,int l)4369 static int _php_image_stream_putbuf(struct gdIOCtx *ctx, const void* buf, int l) /* {{{ */
4370 {
4371 php_stream * stream = (php_stream *)ctx->data;
4372 return php_stream_write(stream, (void *)buf, l);
4373 } /* }}} */
4374
_php_image_stream_ctxfree(struct gdIOCtx * ctx)4375 static void _php_image_stream_ctxfree(struct gdIOCtx *ctx) /* {{{ */
4376 {
4377 if(ctx->data) {
4378 ctx->data = NULL;
4379 }
4380 efree(ctx);
4381 } /* }}} */
4382
_php_image_stream_ctxfreeandclose(struct gdIOCtx * ctx)4383 static void _php_image_stream_ctxfreeandclose(struct gdIOCtx *ctx) /* {{{ */
4384 {
4385 if(ctx->data) {
4386 php_stream_close((php_stream *) ctx->data);
4387 ctx->data = NULL;
4388 }
4389 efree(ctx);
4390 } /* }}} */
4391
create_stream_context(php_stream * stream,int close_stream)4392 static gdIOCtx *create_stream_context(php_stream *stream, int close_stream) {
4393 gdIOCtx *ctx = ecalloc(1, sizeof(gdIOCtx));
4394
4395 ctx->putC = _php_image_stream_putc;
4396 ctx->putBuf = _php_image_stream_putbuf;
4397 if (close_stream) {
4398 ctx->gd_free = _php_image_stream_ctxfreeandclose;
4399 } else {
4400 ctx->gd_free = _php_image_stream_ctxfree;
4401 }
4402 ctx->data = (void *)stream;
4403
4404 return ctx;
4405 }
4406
create_output_context(zval * to_zval,uint32_t arg_num)4407 static gdIOCtx *create_output_context(zval *to_zval, uint32_t arg_num) {
4408 gdIOCtx *ctx;
4409
4410 if (to_zval != NULL) {
4411 php_stream *stream;
4412 int close_stream = 1;
4413
4414 ZEND_ASSERT(arg_num > 0);
4415
4416 if (Z_TYPE_P(to_zval) == IS_RESOURCE) {
4417 php_stream_from_zval_no_verify(stream, to_zval);
4418 if (stream == NULL) {
4419 return NULL;
4420 }
4421 close_stream = 0;
4422 } else if (Z_TYPE_P(to_zval) == IS_STRING) {
4423 if (CHECK_ZVAL_NULL_PATH(to_zval)) {
4424 zend_argument_type_error(arg_num, "must not contain null bytes");
4425 return NULL;
4426 }
4427
4428 stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH, NULL);
4429 if (stream == NULL) {
4430 return NULL;
4431 }
4432 } else {
4433 zend_argument_type_error(arg_num, "must be a file name or a stream resource, %s given", zend_zval_value_name(to_zval));
4434 return NULL;
4435 }
4436
4437 ctx = create_stream_context(stream, close_stream);
4438 } else {
4439 ctx = ecalloc(1, sizeof(gdIOCtx));
4440
4441 ctx->putC = _php_image_output_putc;
4442 ctx->putBuf = _php_image_output_putbuf;
4443 ctx->gd_free = _php_image_output_ctxfree;
4444 }
4445
4446 return ctx;
4447 }
4448
4449 /* }}} */
4450