gd.c 106 KB

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