GD-2.78/0000755000175000017500000000000014450761211011311 5ustar rurbanrurbanGD-2.78/ChangeLog0000644000175000017500000003152414450761142013073 0ustar rurbanrurban2.78 * Fix Use of uninitialized value $pkg in concatenation warning (RT #148899 and GH #47). Thanks to ppisar for the analysis. Adds a new hard Test::NoWarnings test requirement. 2.77 * add BMP support with libgd 2.1.0, PR #49 by PeterCJ * don't link to -lXPM without XPM nor X11, GH #45 * rename ANIMGIF feature to GIFANIM * fix unused variable failure in GH CI, RT #141125 by PhilterPaper 2.76 * fix broken TIFF and AVIF support, PR #43 by Paul Howarth * re-enable XBM support (always on) * provide xbm magic support (a hack, for GD::Graph) 2.75 * add experimental support for TIFF and RAQM (with freetype) * improve GD2 tests (GH #42, RT #140856) * also list the unsupported image formats in the GD::Image pod * fix copyRotated pod (it rotates CCW) PR #36 by LorenzoTo * fix GD::Simple->fontMetrics docs and implementation GH #37 by Ben Crowell. fix lineheight calculation according to the docs. You might need to fix your code! * add image methods tiff, webp, heif, avif, and its documentation. * fix the fix for the poly->transform documentation RT #140043 2.74 * add experimental support for WEBP, HEIF and AVIF * document all supported Image formats in the GD::Image lib * added Github actions (for PR's) * fix poly->transform documentation RT #140043 * fix GD,GD2 detection and tests RT #139399 (since libgd 2.3.3) fixed tests by Håkon Hægland. * POD: Remove indirect object constructors from example code snippet (PR #39) * patch from Ben Crowell that fixes incorrect behaviour of GD::Simple->fontMetrics * fix cross-compilation if gdlib.pc has no cflags by Fabrice Fontaine 2.73 * allow --options override the libgd options. Not recommended. See GH #33 and RT #130045 2.72 * fix CVE 2019-6977 colorMatch for older unpatched libgd versions. This is a severe security problem, an exploitable heap-overflow. See https://nvd.nist.gov/vuln/detail/CVE-2019-6977 2.71 * skip Test::Fork on freebsd (GH #25) 2.70 * fixes for hardened CCFLAGS with -Werror (RT #128167) 2.69 * little spelling error, GH #29 Xavier Guimard 2.68 * fix GD::Polygon->clear, RT #124463 Michael Cain 2.67 * fix thread-safety for GD::Simple %COLORS (#26 melak) * fix arc start-angle docs, RT #123277 Andrew G Gray * improve setBrush docs, RT #123194 Andrew G Gray * improve StringFT docs, RT #123193 * replace MacOSX by darwin, and not by Mac OS X/macOS as suggested in PR #24 * add GD::Image->_file method as suggested in RT #60488 by Kevin Ryde, also the helper GD::supportsFileType 2.66 * throw proper error on newFrom* with not-existing file * add t/transp.t from RT #40525 * Improve RT #54366 multiple gd.h warning * better doc for GD::Simple->arc * fix ANIMGIF with libgd 2.3.0-dev 2.65 * fix --gdlib_config_path to accept an argument (fperrad) 2.64 * Update doc for LIBGD_VERSION() * Fix 5.6.2, which does not have float in its typemap 2.63 * renamed VERSION() to LIBGD_VERSION(), RT #121307. It was treated magically by "use GD 2.18" 2.62 * fixed wrong <5.14 code generated with ExtUtils::Constants RT #121297. Don't generate const-xs.inc, only when missing. * add -liconv on hpux also (our pkgconfig parser cannot handle it) 2.61 * add CONFIGURE_REQUIRES META * add --gdlib_config_path * add Image Filters: scatter, pixelate, negate, grayscale, brightness, contrast, color, selectiveBlur, edgeDetectQuick, gaussianBlur, emboss, meanRemoval, smooth, copyGaussianBlurred * add palette methods: createPaletteFromTrueColor, neuQuant (but discouraged), colorMatch. * add interpolation methods: copyScale, copyRotateInterpolated, interpolationMethod. * add double GD::VERSION * add all gd.h constants 2.60 * add missing methods newFromWBMP, newFromXbm, (RT #68784) and some missing docs * Add --lib_fontconfig_path, --fcgi options * rewrote most of the XS code * cleanup Makefile.PL #20 2.59 * error on failing libgd calls * fix colorClosestAlpha, colorAllocateAlpha * add missing documentation 2.58 * fix VERSION_STRING for 2.0.x * honor --lib_gd_path specific gdlib-config * Loosen the comparison tests with GDIMAGETYPE ne gd2 * Improve gdlib-config parsing (PR #17), esp. with 2.0.34 2.57 * fix Jpeg magic number detection RT #26146 * fix RGB - HSV roundtrips: RT #120572 by J2N-FORGET * fix -print-search-dirs errors RT #106265 * co-maint to rurban * add hv_fetchs, CI smokers * add GD::VERSION_STRING api 2.56_03 * add alpha method * improve option handling * fix meta data 2.56_02 * fix feature extraction >= 2.2 [RT #119459] 2.56_01 * rm Build.PL, fix permissions, fix for missing gdlib-config 2.56 * Fix Makefile.PL so that it works again. 2.55 * Great simplification of regression framework ought to fix make test problems. * Replace ExtUtils::MakeMaker script with Module::Build system (just in time for Module::Build to be deprecated). * Remove archaic qd.pl (for creating QuickDraw picts) from distribution. 2.54 Patch from yurly@unet.net to fix image corruption in rotate180 when image height is odd. 2.53 Points to Gabor Szabo's GD::Simple tutorial, and fix link to repository. 2.52 Fix regression tests to run on Ubuntu 12.04 64bit. 2.51 Fix misleading warning message about location of gd.h file. 2.50 Fix gdUseFontConfig so that it can be called as a class method. 2.49 Add GitHub information to README. 2.48 Fix compile crash on windows and strawberry (https://rt.cpan.org/Public/Bug/Display.html?id=67990). 2.47 Fix compilation on older perl's without the Newxz macros. 2.46 Added a basic "use" test for GD::Simple 2.45 Clarified the GD license. There is now a formal LICENSE file in the package. 2.44 GD::Group now installed properly. Quenched compiler warning caused by Newxs() calls. 2.43 Added "transparent" color to GD::Simple. Fixed Makefile so that GD/Image.pm depends both on GD/Image.pm.PLS and .config.cache 2.42 Fixed magic number detection to autodetect certain missed jpeg files (thanks to Mike Walker) 2.41 Added backend support for grouping features in GD::SVG module. 2.40 ** Do not use - contains a bug ** 2.39 Makefile.PL will refuse to run if the proper version of libgd is unavailable. 2.38 Fixed bizarre warning about /usr/include/gd.h != /usr/include/gd.h. 2.37 GD/Image.pm did not bring in croak() properly, meaning that incorrect error messages are printed out when any of the newFromXXX() calls are made. 2.36 Instructions on using gdAntiAliased with palette images. 2.35 Some instructions on installation for Windows users. Doesn't push libpng onto @LIBS unless png support is requested. Supports Storable's freeze/thaw via a custom serializer. Remove "scale redefined" message during compilation of Polyline. 2.34 Added a check for stray gd.h include files from older installations. If any are found, Makefile.PL will issue a warning. Fixed incorrect documentation of GD::Simple->string() method. The method call *does* move the pen. 2.33 Added appropriate #ifdefs to allow to compile under version 5.6.0 (due to lack of threading macros before 5.8). 2.32 Added a GD::Simple->HSVtoRGB() method. Documentation fixes from Mark Manning. Added a clear() method to GD::Polygon to remove all vertices. 2.31 Fixed GD::Simple->transparent to support symbolic color names. Made changes that should render the module thread-safe. Changed newSVpv calls to newSVpvn, in hopes of improving performance. Added a GD::Simple->HSVtoRGB() method. Fixed incorrect freeing of user-provided raw data in newFromGdData() and newFromGd2Data() (this caused segfaults; patch provided by Nigel Sandever) 2.30 Migrated polyline() support into GD::Simple. 2.29 Better support for fonts and brushed patterns in GD::Simple 2.28 Having troubles getting all the modules installed correctly. Should work now. 2.27 Reworked the way that GD.pm is created at compile time so that CPAN picks up correct version information. No code changes. 2.26 CPAN isn't propagating GD, so I'll upload another version 2.25 Fixed Makefile.PL so that GD::Polyline and GD::Simple are installed (thanks to Guy Albertelli). 2.24 Fixed gif/anim gif support so that you can't have animated gif support without having gif support. 2.23 Added patch from Slaven Rezic which makes it possible to call GD constants in an OO way (without generating warnings), and removes #! from the top of autogenerated GD.pm Rewrote tests 11 and 12 - if they continue to randomly fail on various platforms, they will be removed. 2.22 Changed the way the gd and gd2 round-trip tests are evaluated. This might fix test failures that have been reported on some platforms. 2.21 Regression tests are now functional for versions of libgd compiled exclusively with PNG, JPEG or GIF support. 2.20 GD::Image->newFromGdData() and newFromGd2Data() got broken somewhere along the line. They are now fixed (and have a regression test). Added copyRotated() method. 2.19 Added a HAVE_FTCIRCLE define to handle versions of libgd that do not have the gdImageStringFTCircle() function. 2.18 This version needs libgd 2.0.28 or higher. Fixed documentation bug in synopsis of GD::Simple. Updated Polyline to version 0.20 2.17 Added animated GIF patches from Jaakko Hyvätti. Added dynamic bitmapped font loading support. Added fontconfig support. Added a simplified API called GD::Simple. Added support for kern control and other libgd-based FT improvements. Fixed a define that caused gif functions to be miscompiled on some platforms. Documentation fixes. 2.16 Fixed bug in GIF #IFDEFs pointed out by BZAJAC Added #IFDEF for WIN32 provided by Randy Kobes 2.15 Brought back GIF support (requires libgd 2.0.28 or higher). Takes advantage of gdlib-config support in libgd 2.0.27 or higher. 2.14 Support for AMD64 libraries. 2.12 Fixed regression test 10 to succeed when used with libgd 2.0.22 2.11 More alpha functions from Cory Watson 2.10 Suppress CAPI warning. Warn about Math::Trig warning 2.09 VMS documentation patch from Martin Zinser Non-standard library finding path options from Peter Kruty 2.08 Applied 5.00503 compatibility patch from Mathieu Arnold New check for JPEG magic tag returned by some digital cameras. 2.07 Now compatible with (and requires!) libgd 2.0.12. Added setThickness() method. Added support for compression level argument to png(). Added support for antialiasing drawing using setAntiAliased() and setAntiAliasedDontBled(). Added extended options to stringFT(). Added filledArc(), ellipse() and filledEllipse() methods. Added command-line options to Makefile.PL provided by David Eisenberg. 2.06 Added saveAlpha() and alphaBlending() methods. 2.05 Alpha methods courtesy Georges Arnould. 2.041 Added a regression test to detect certain versions of freetype. 2.04 Removed the patch file since Tom has begun adding his own configure file. Changed the context member from free to gd_free to allow for compiling. Fixed the regression tests since the gd-generated images have changed slightly. 2.03 Skipped so as to remain version number compatible with libgd. 2.02 Changed Math::Trig version requirement from 0.0 to 1.0 as Perl 5.8 no long recognizes this as a valid version number. 2.01 Added Math::Trig to the prerequisites because GD::Polyline needs it. 2.00 Folded in support for gd version 2.0 from Dan Palermo Folded in support for splines (GD::Polyline) from Dan Harasty. Removed all GIF support. 1.43 Added demo of Type1 fonts to truetype demo from Slaven Rezic. 1.42 Fixed the patch_gd.pl file Version 2.0 is coming. 1.39 Fixed FreeType test, at least on some platforms. Added patches from Stephen Clouse to allow to build on 5.8.0rc1. 1.35 Patches to support Philip Warner's GIF-reinstating library maintained at http://www.rime.com.au/gd/ 1.34 Fixed problems that arise when compiling against older versions of libgd that do not have XPM support. 1.33 Updated patch file for gd 1.8.4 1.32 Added support for Tru64 UNIX v5.0 1.29 Fixed a corrupted .xpm file in the regression suite (caused test 9 to fail) 1.28 Added support for gd 1.8.3 1.27 Fixed strict refs problem on 5.00503 and earlier 1.26 Brought up to date with libgd 1.8.1 1.24-1.25 More tweaks to Makefile.PL. 1.23 Added a bunch more libraries and includes... might or might not port to other platforms now 1.22 Fix to Makefile.PL to accomodate linking static libraries. Added newFromGd2Part() method. Supports libgd 1.7.1. 1.21 Slight fix in regression tests so that test 8 doesn't fail when compiled without TrueType support. 1.20 Rewritten for libgd 1.6.3 1.19 Fixed Makefile.PL for better compilation on Windoze machines GD-2.78/META.yml0000644000175000017500000000140214450761210012556 0ustar rurbanrurban--- abstract: 'Perl interface to the libgd graphics library' author: - 'Lincoln Stein ' build_requires: ExtUtils::MakeMaker: '0' Test::Fork: '0.02' Test::More: '0.88' Test::NoWarnings: '1.00' configure_requires: ExtUtils::Constant: '0.22' ExtUtils::PkgConfig: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.70, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: GD no_index: directory: - t - inc requires: Math::Trig: '0' resources: license: https://dev.perl.org/licenses/ repository: git://github.com/lstein/Perl-GD.git version: '2.78' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' GD-2.78/META.json0000644000175000017500000000337314450761210012737 0ustar rurbanrurban{ "abstract" : "Perl interface to the libgd graphics library", "author" : [ "Lincoln Stein " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.70, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "GD", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::Constant" : "0.22", "ExtUtils::PkgConfig" : "0" } }, "develop" : { "requires" : { "Algorithm::Diff" : "0", "Class::XSAccessor" : "0", "List::MoreUtils" : "0", "Pod::Spell::CommonMistakes" : "0", "Test::Kwalitee" : "0", "Test::NoWarnings" : "1.00", "Test::Pod" : "1.00", "Text::CSV_XS" : "0" } }, "runtime" : { "requires" : { "Math::Trig" : "0" } }, "test" : { "requires" : { "Test::Fork" : "0.02", "Test::More" : "0.88", "Test::NoWarnings" : "1.00" } } }, "release_status" : "stable", "resources" : { "license" : [ "https://dev.perl.org/licenses/" ], "repository" : { "type" : "git", "url" : "git://github.com/lstein/Perl-GD.git", "web" : "https://github.com/lstein/Perl-GD" } }, "version" : "2.78", "x_serialization_backend" : "JSON::PP version 4.16" } GD-2.78/testcpan.sh0000755000175000017500000000100614435047450013473 0ustar rurbanrurban#!/bin/sh p=$(cat ~/.alias-perl | sed 's,alias p=,,') test -n "$p" || p=perl alias ppan='$p -S cpan' $p Makefile.PL && make test && sudo make install clean ppan -f GD::Graph GD::Text Barcode::Code128 GD::Thumbnail GD::SVG GD::Text::Arc GD::Thumbnail \ GD::Tiler GD::Wbmp GD::Window GD::Image::AnimatedGif GD::Image::Orientation \ GD::Image::Scale2x GD::Image::Thumbnail GD::Map GD::Map::Mercator \ GD::Chart GD::Barcode GD::Arrow GD::3DBarGrapher GD::Dashboard # wrong tests, assuming stable png ppan GD::OrgChart GD-2.78/const-xs.inc0000644000175000017500000000512613430523556013573 0ustar rurbanrurbanvoid constant(sv) PREINIT: #ifdef dXSTARG dXSTARG; /* Faster if we have it. */ #else dTARGET; #endif STRLEN len; int type; IV iv = 0; /* NV nv; Uncomment this if you need to return NVs */ /* const char *pv; Uncomment this if you need to return PVs */ INPUT: SV * sv; const char * s = SvPV(sv, len); PPCODE: /* Change this to constant(aTHX_ s, len, &iv, &nv); if you need to return both NVs and IVs */ type = constant(aTHX_ s, len, &iv); /* Return 1 or 2 items. First is error message, or undef if no error. Second, if present, is found value */ switch (type) { case PERL_constant_NOTFOUND: sv = sv_2mortal(newSVpvf("%s is not a valid GD macro", s)); PUSHs(sv); break; case PERL_constant_NOTDEF: sv = sv_2mortal(newSVpvf( "Your vendor has not defined GD macro %s, used", s)); PUSHs(sv); break; case PERL_constant_ISIV: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHi(iv); break; /* Uncomment this if you need to return NOs case PERL_constant_ISNO: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHs(&PL_sv_no); break; */ /* Uncomment this if you need to return NVs case PERL_constant_ISNV: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHn(nv); break; */ /* Uncomment this if you need to return PVs case PERL_constant_ISPV: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHp(pv, strlen(pv)); break; */ /* Uncomment this if you need to return PVNs case PERL_constant_ISPVN: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHp(pv, iv); break; */ /* Uncomment this if you need to return SVs case PERL_constant_ISSV: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHs(sv); break; */ /* Uncomment this if you need to return UNDEFs case PERL_constant_ISUNDEF: break; */ /* Uncomment this if you need to return UVs case PERL_constant_ISUV: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHu((UV)iv); break; */ /* Uncomment this if you need to return YESs case PERL_constant_ISYES: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHs(&PL_sv_yes); break; */ default: sv = sv_2mortal(newSVpvf( "Unexpected return type %d while processing GD macro %s, used", type, s)); PUSHs(sv); } GD-2.78/typemap0000644000175000017500000000010213076115435012710 0ustar rurbanrurbanTYPEMAP GD::Image T_PTROBJ GD::Font T_PTROBJ GD::Polygon T_PTROBJ GD-2.78/README0000644000175000017500000003244314435047447012212 0ustar rurbanrurbanGD.pm -- A perl5 interface to Thomas Boutell's gd library. ABSTRACT: This is a autoloadable interface module for libgd, a popular library for creating and manipulating PNG files. With this library you can create PNG images on the fly or modify existing files. Features include: a. lines, polygons, rectangles and arcs, both filled and unfilled b. flood fills c. the use of arbitrary images as brushes and as tiled fill patterns d. line styling (dashed lines and the like) e. horizontal and vertical text rendering f. support for transparency and interlacing g. support for TrueType font rendering, via libfreetype. h. support for spline curves, via GD::Polyline i. support for symbolic font names, such as "helvetica:italic" j. support for symbolic color names, such as "green", via GD::Simple k. produces output in png, gif, jpeg, xbm and other formats supported by libgd l. produces output in svg format via GD::SVG. For full information on usage, see the accompanying man and html documentation. Also check the FAQ at the bottom of this document. INSTALLATION: 1. Windows users can find a binary PPM package in the repositories at these sites: http://trouchelle.com/perl/ppmrepview.pl http://www.bribes.org/perl/ppmdir.html These packages are not always updated to the most recent version, but GD is pretty stable and you usually won't miss the bleeding edge version. For Unix/darwin users and those who have a developer's kit installed on Windows (e.g. cygwin): 2. Make sure you have downloaded and installed the following packages: a. Perl 5.6.0 or higher: http://www.perl.com/ b. The gd graphics library: http://libgd.org c. The PNG graphics library: http://www.libpng.org/pub/png/libpng.html d. The zlib compression library: http://www.gzip.org/zlib/ (OPTIONAL) e. The FreeType font rendering library for TrueType fonts: http://www.freetype.org/ f. The JPEG library, version 6b or later: ftp://ftp.uu.net/graphics/jpeg/ g. The XPM library, a standard part of modern X Windows distributions. If you don't have a modern version of X, don't try to get XPM working. 3. On darwin, you can use these package managers to resolve dependencies and build libgd: i. MacPorts http://www.macports.org/ ii. Homebrew http://mxcl.github.io/homebrew/ If this module fails to compile and link, you are probably using an older version of libgd. Symptoms of this problem include errors about functions not being recognized in the gd.h header file, and undefined symbols from the linker. If you are having this type of error, please REMOVE all versions of libgd, gd.h from your system and reinstall libgd 2.0.28 or higher. Do not contact Lincoln for help until you have done this. Use GD 1.41 for libgd versions 1.8.4 and lower. 3. Unpack the tar file: zcat GD-2.XX.tar.gz | tar xvf - (Where "XX" is the most recent revision number.) This will create the directory GD-2.XX. 4. To compile GD.pm: a. cd GD-2.XX b. perl Makefile.PL c. make d. make test f. sudo make install This will create GD.pm and install it into the system-wide Perl library directory. You'll need root privileges to do the install step. If you don't have them, see below. During step (b), Makefile.PL will look for the program gdlib-config or gdlib.pc that newer versions of libgd install for you. If this program is not present, the Makefile.PL script will ask you whether to build support for JPEG, FreeType and/or XPM image formats. Please answer "y" (the default) if libgd was built with the feature, and "n" if it was not. Failure to answer correctly will lead to link errors. If, during step (b) you see notes about missing libraries, then this module will probably not link correctly, even though the warning may say "probably harmless". 5. Before you install GD, you will want to run the regression tests. You can do this after the "make" step by typing: make test 6. There are some demos you can run in ext/GD/demos. They print PNG files to standard output. To view the files, pipe their output to "display" or "xv" in this way: a. cd GD-2.XX/demos b perl shapes.pl | display - You will need a graphics program that can read and display PNG format. I recommend Image::Magick's display program, available from ftp://ftp.wizards.dupont.com/pub/ImageMagick/ If you don't have any display programs handy, you can save to a temporary file and display with recent versions of Netscape or Internet Explorer. 7. A program named fonttest is included in this package under demos. This generates an image showing all the built-in fonts available. If you have built libgd with TrueType support, and you have a directory containing some TrueType fonts, you can create a simple font listing by running the program truetype_test, also located in demos. 8. See demos/gd_example.cgi for an example of how to use GD to create a picture dynamically with a CGI script. It's intended to be run under a Web server. To see it work, install it in your server's cgi-bin/ directory and invoke it from a browser by fetching a URL like: http://your.site/cgi-bin/gd_example.cgi IF YOU RUN INTO PROBLEMS If the make and install all seem to go well but you get errors like "Fatal error: can't load module GD.so", or "Fatal error: unknown symbol gdFontSmall" when you try to run a script that uses GD, you may have problems with dynamic linking. Check whether other dynamically-linked Perl modules such as POSIX and DB_File run correctly. If not, then you'll have to link Perl statically, as described above. Other problems may be fixed by compiling libgd as a shared library, as described in step (2) of the installation instructions. If you are trying to compile and link GD on a Windows or Macintosh machine and fail, please verify that you are able to build the Perl distribution from source code. If you can't do that, then you don't have the compiler/linker/make tools required for building Perl modules. You may not even need to do this, as ActiveState and MacPerl both include precompiled versions of GD. If you have problems and can't solve it on your own, post a message to the newsgroup "comp.lang.perl.modules". There are some systems that require obscure compiler and linker options in order to compile correctly, and unfortunately I have a limited number of systems at my disposal. You're much more likely to get correct answers from the gurus on the newsgroup than from myself. THE GD::SIMPLE LIBRARY GD::Simple is a simplified API for GD. It supports turtle graphics, a unified interface for drawing text, and symbolic color names (like "green"). Run "perldoc GD::Simple" for information on using it. The GD::SVG LIBRARY GD::SVG, which is available separately on CPAN, provides a subset of GD method calls. For this subset, you can create images in SVG (scalable vector graphics) format. THE QUICKDRAW LIBRARY This is no longer supported. FREQUENTLY ASKED QUESTIONS 1. I get a warning about prerequisite Math::Trig not being found The version of Math::Trig that comes with Perl version 5.6.0 and lower has a bug in it that causes it not to be found even when it is installed. Try running perl -MMath::Trig -e0 from the command line. If you get no errors, go ahead and install GD. If you get an error, install Math::Trig from CPAN. 2. Why do I get errors about functions not being found when building this module? You need libgd (the C library that does all the work) version 2.0.28 or higher. Older versions will give you errors during GD installation. Get the latest version from http://libgd.org and install it. Sometimes just installing the new version of libgd is not enough: you must remove the old library first. Find the gd.h include file and all libgd files and remove them from your system. 3. Why do I get errors about symbols being undefined when building this module? See (1). 4. The %&#&#! thing doesn't compile at all! I'm getting lots of compile errors! Does "make" fail with messages like these? GD.xs: In function 'newDynamicCtx': GD.xs:440: error: 'gdIOCtx' has no member named 'gd_free' GD.xs: In function 'gd_cloneDim': GD.xs:460: error: 'struct gdImageStruct' has no member named 'alpha' GD.xs:460: error: 'struct gdImageStruct' has no member named 'alpha' GD.xs:466: error: 'struct gdImageStruct' has no member named 'thick' GD.xs:466: error: 'struct gdImageStruct' has no member named 'thick' If so, then you may have an old gd.h include file located somewhere in your system include path. Please find it and remove it. A typical location is /usr/include/gd.h. The way to make sure you are removing the correct gd.h is to run "gdlib-config --cflags" to find out where the current gd.h lives: % gdlib-config --cflags -I/usr/local/include This tells you that /usr/local/include/gd.h is the correct gd.h. Please find and remove any other gd.h. 5. My scripts fail with "Can't locate object method 'png' via package "GD::Image". libgd can now be built with support for one or more of the PNG, GIF, XPM or JPEG formats. If one or more of these formats are not supported by libgd, then the corresponding GD::Image methods will be unavailable. Unfortunately, many older scripts assume that the png() method will always be present. You can work around this issue with code like the following: my $image = $gd->can('png') ? $gd->png : $gd->gif; or if you prefer eval {} my $image = eval {$gd->png} || $gd->gif; As of libgd 2.0.33, GIF support is always compiled in, so (for the time being!) this is a safe fallback. 6. Is there a utility to convert X Windows BDF fonts into GD fonts. Yes. See the utility bdf2gdfont.pl. Run "bdf2gdfont.pl -h" to get help on using this. 7. Does GD run with Macintosh OS X? Yes. GD compiles just fine under OSX. However, you may need to remove old versions of libgd, libpng, and libz and reinstall the current versions before you try to install GD. 8. Does GD run with Win32 Perl? The latest ActiveState binaries for Win32 systems come with GD already compiled in and ready to go. I don't own any Win32 systems, and cannot provide you with help in compiling GD from scratch on such systems. Github actions and appveyor are used to test the windows builds. 9. GD won't compile on system XX. Because libgd relies on multiple external libraries, GD does as well. Unfortunately, different systems place their libraries in different places and sometimes are picky about the order in which libraries are linked. The best thing to do is to install the latest version of libgd. Recent versions of libgd contain a gdlib-config utility, which GD will use to determine which libraries are necessary and in which order to link them. Another thing to be aware of is that some Unix distributions provide a faulty precompiled version of Perl which is unable to build and load new C-based modules (like this one). If you are getting errors like this: /arch/auto/GD/GD.so: undefined symbol: SetCPerlObj at .... then you may have such a faulty version of Perl. The most reliable thing to do is to recompile Perl from source code, thereby ensuring that it is complete. 10. When I try to load an XPM file, all I get is blackness! The libgd createFromXpm() function works with some XPM files, and not with others. The problem is buried deep in the libXpm library somewhere. 11. The stringFTCircle() method doesn't work! I know. I think this might be a problem in libgd because I have never gotten it to work as a C program. If you have any insight into this problem let me know. 12. Test XX fails The regression tests for GD involve generating images, saving them as PNG, JPEG or GIF files, and then comparing the files bit-for-bit to known "correct" files. Sometimes one of the underlying C libraries such as libz, libpng or libgd is updated, causing GD to generate an image that is subtly different. These differences are usually insignificant, such as a reordering of colors in the color table, but they will call isolated tests to fail. If you are seeing the great majority of GD tests pass, but one or two fail, then you are probably seeing the effect of a new library. Just go ahead and install GD and drop me a note about the problem. BUG REPORTS Please report bugs, feature requests and propose code changes using the GitHub repository at https://github.com/lstein/Perl-GD. We do not check the CPAN RT bug system with any frequency. ACKNOWLEDGEMENTS: I'd like to thank Jan Pazdziora, Geoff Baysinger, and David Kilzer for their contributions to the library, as well as Thomas Boutell who wrote libgd. SOURCE CODE AND UPDATES: The current version of GD can be found in CPAN. The development version can be found on GitHub at https://github.com/lstein/Perl-GD. AUTHOR and LICENSE Copyright 1995-2014 Lincoln Stein Maintainance taken over by Reini Urban 2017. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. package for details. GD-2.78/const-c.inc0000644000175000017500000006405713430523556013373 0ustar rurbanrurban#define PERL_constant_NOTFOUND 1 #define PERL_constant_NOTDEF 2 #define PERL_constant_ISIV 3 #define PERL_constant_ISNO 4 #define PERL_constant_ISNV 5 #define PERL_constant_ISPV 6 #define PERL_constant_ISPVN 7 #define PERL_constant_ISSV 8 #define PERL_constant_ISUNDEF 9 #define PERL_constant_ISUV 10 #define PERL_constant_ISYES 11 #ifndef NVTYPE typedef double NV; /* 5.6 and later define NVTYPE, and typedef NV to it. */ #endif #ifndef aTHX_ #define aTHX_ /* 5.6 or later define this for threading support. */ #endif #ifndef pTHX_ #define pTHX_ /* 5.6 or later define this for threading support. */ #endif static int constant_7 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_BELL GD_SINC gdChord gdEdged gdTiled */ /* Offset 3 gives the best switch position. */ switch (name[3]) { case 'B': if (memEQ(name, "GD_BELL", 7)) { /* ^ */ #ifdef GD_BELL *iv_return = GD_BELL; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'S': if (memEQ(name, "GD_SINC", 7)) { /* ^ */ #ifdef GD_SINC *iv_return = GD_SINC; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'd': if (memEQ(name, "gdEdged", 7)) { /* ^ */ #ifdef gdEdged *iv_return = gdEdged; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'h': if (memEQ(name, "gdChord", 7)) { /* ^ */ #ifdef gdChord *iv_return = gdChord; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'i': if (memEQ(name, "gdTiled", 7)) { /* ^ */ #ifdef gdTiled *iv_return = gdTiled; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant_8 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_POWER gdNoFill gdRedMax gdStyled */ /* Offset 2 gives the best switch position. */ switch (name[2]) { case 'N': if (memEQ(name, "gdNoFill", 8)) { /* ^ */ #ifdef gdNoFill *iv_return = gdNoFill; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'R': if (memEQ(name, "gdRedMax", 8)) { /* ^ */ #ifdef gdRedMax *iv_return = gdRedMax; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'S': if (memEQ(name, "gdStyled", 8)) { /* ^ */ #ifdef gdStyled *iv_return = gdStyled; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case '_': if (memEQ(name, "GD_POWER", 8)) { /* ^ */ #ifdef GD_POWER *iv_return = GD_POWER; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant_9 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_BESSEL GD_LINEAR gdBlueMax gdBrushed */ /* Offset 6 gives the best switch position. */ switch (name[6]) { case 'E': if (memEQ(name, "GD_LINEAR", 9)) { /* ^ */ #ifdef GD_LINEAR *iv_return = GD_LINEAR; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'M': if (memEQ(name, "gdBlueMax", 9)) { /* ^ */ #ifdef gdBlueMax *iv_return = gdBlueMax; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'S': if (memEQ(name, "GD_BESSEL", 9)) { /* ^ */ #ifdef GD_BESSEL *iv_return = GD_BESSEL; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'h': if (memEQ(name, "gdBrushed", 9)) { /* ^ */ #ifdef gdBrushed *iv_return = gdBrushed; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant_10 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_BICUBIC GD_BSPLINE GD_DEFAULT GD_HAMMING GD_HANNING GD_HERMITE gdAlphaMax gdDashSize gdGreenMax */ /* Offset 5 gives the best switch position. */ switch (name[5]) { case 'C': if (memEQ(name, "GD_BICUBIC", 10)) { /* ^ */ #ifdef GD_BICUBIC *iv_return = GD_BICUBIC; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'F': if (memEQ(name, "GD_DEFAULT", 10)) { /* ^ */ #ifdef GD_DEFAULT *iv_return = GD_DEFAULT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'M': if (memEQ(name, "GD_HAMMING", 10)) { /* ^ */ #ifdef GD_HAMMING *iv_return = GD_HAMMING; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'N': if (memEQ(name, "GD_HANNING", 10)) { /* ^ */ #ifdef GD_HANNING *iv_return = GD_HANNING; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'P': if (memEQ(name, "GD_BSPLINE", 10)) { /* ^ */ #ifdef GD_BSPLINE *iv_return = GD_BSPLINE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'R': if (memEQ(name, "GD_HERMITE", 10)) { /* ^ */ #ifdef GD_HERMITE *iv_return = GD_HERMITE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'e': if (memEQ(name, "gdGreenMax", 10)) { /* ^ */ #ifdef gdGreenMax *iv_return = gdGreenMax; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'h': if (memEQ(name, "gdAlphaMax", 10)) { /* ^ */ #ifdef gdAlphaMax *iv_return = gdAlphaMax; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } if (memEQ(name, "gdDashSize", 10)) { /* ^ */ #ifdef gdDashSize *iv_return = gdDashSize; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant_11 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_BLACKMAN GD_GAUSSIAN GD_MITCHELL GD_TRIANGLE gdMaxColors */ /* Offset 5 gives the best switch position. */ switch (name[5]) { case 'A': if (memEQ(name, "GD_BLACKMAN", 11)) { /* ^ */ #ifdef GD_BLACKMAN *iv_return = GD_BLACKMAN; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'C': if (memEQ(name, "gdMaxColors", 11)) { /* ^ */ #ifdef gdMaxColors *iv_return = gdMaxColors; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'I': if (memEQ(name, "GD_TRIANGLE", 11)) { /* ^ */ #ifdef GD_TRIANGLE *iv_return = GD_TRIANGLE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'T': if (memEQ(name, "GD_MITCHELL", 11)) { /* ^ */ #ifdef GD_MITCHELL *iv_return = GD_MITCHELL; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'U': if (memEQ(name, "GD_GAUSSIAN", 11)) { /* ^ */ #ifdef GD_GAUSSIAN *iv_return = GD_GAUSSIAN; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant_12 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_CMP_COLOR GD_CMP_IMAGE GD_FLIP_BOTH GD_QUADRATIC GD_WEIGHTED4 */ /* Offset 10 gives the best switch position. */ switch (name[10]) { case 'D': if (memEQ(name, "GD_WEIGHTED4", 12)) { /* ^ */ #ifdef GD_WEIGHTED4 *iv_return = GD_WEIGHTED4; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'G': if (memEQ(name, "GD_CMP_IMAGE", 12)) { /* ^ */ #ifdef GD_CMP_IMAGE *iv_return = GD_CMP_IMAGE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'I': if (memEQ(name, "GD_QUADRATIC", 12)) { /* ^ */ #ifdef GD_QUADRATIC *iv_return = GD_QUADRATIC; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'O': if (memEQ(name, "GD_CMP_COLOR", 12)) { /* ^ */ #ifdef GD_CMP_COLOR *iv_return = GD_CMP_COLOR; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'T': if (memEQ(name, "GD_FLIP_BOTH", 12)) { /* ^ */ #ifdef GD_FLIP_BOTH *iv_return = GD_FLIP_BOTH; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant_13 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_CATMULLROM GD_CMP_SIZE_X GD_CMP_SIZE_Y GD_RESOLUTION gdAlphaOpaque gdAntiAliased gdTransparent */ /* Offset 12 gives the best switch position. */ switch (name[12]) { case 'M': if (memEQ(name, "GD_CATMULLRO", 12)) { /* M */ #ifdef GD_CATMULLROM *iv_return = GD_CATMULLROM; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'N': if (memEQ(name, "GD_RESOLUTIO", 12)) { /* N */ #ifdef GD_RESOLUTION *iv_return = GD_RESOLUTION; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'X': if (memEQ(name, "GD_CMP_SIZE_", 12)) { /* X */ #ifdef GD_CMP_SIZE_X *iv_return = GD_CMP_SIZE_X; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'Y': if (memEQ(name, "GD_CMP_SIZE_", 12)) { /* Y */ #ifdef GD_CMP_SIZE_Y *iv_return = GD_CMP_SIZE_Y; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'd': if (memEQ(name, "gdAntiAliase", 12)) { /* d */ #ifdef gdAntiAliased *iv_return = gdAntiAliased; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'e': if (memEQ(name, "gdAlphaOpaqu", 12)) { /* e */ #ifdef gdAlphaOpaque *iv_return = gdAlphaOpaque; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 't': if (memEQ(name, "gdTransparen", 12)) { /* t */ #ifdef gdTransparent *iv_return = gdTransparent; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant_15 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_AFFINE_SCALE GD_METHOD_COUNT gdEffectOverlay gdEffectReplace gdStyledBrushed */ /* Offset 8 gives the best switch position. */ switch (name[8]) { case 'B': if (memEQ(name, "gdStyledBrushed", 15)) { /* ^ */ #ifdef gdStyledBrushed *iv_return = gdStyledBrushed; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'D': if (memEQ(name, "GD_METHOD_COUNT", 15)) { /* ^ */ #ifdef GD_METHOD_COUNT *iv_return = GD_METHOD_COUNT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'E': if (memEQ(name, "GD_AFFINE_SCALE", 15)) { /* ^ */ #ifdef GD_AFFINE_SCALE *iv_return = GD_AFFINE_SCALE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'O': if (memEQ(name, "gdEffectOverlay", 15)) { /* ^ */ #ifdef gdEffectOverlay *iv_return = gdEffectOverlay; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'R': if (memEQ(name, "gdEffectReplace", 15)) { /* ^ */ #ifdef gdEffectReplace *iv_return = gdEffectReplace; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant_16 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_AFFINE_ROTATE GD_BICUBIC_FIXED GD_CMP_INTERLACE GD_CMP_TRUECOLOR GD_FLIP_VERTICAL GD_MAJOR_VERSION GD_MINOR_VERSION gdEffectMultiply */ /* Offset 8 gives the best switch position. */ switch (name[8]) { case 'E': if (memEQ(name, "GD_AFFINE_ROTATE", 16)) { /* ^ */ #ifdef GD_AFFINE_ROTATE *iv_return = GD_AFFINE_ROTATE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'I': if (memEQ(name, "GD_BICUBIC_FIXED", 16)) { /* ^ */ #ifdef GD_BICUBIC_FIXED *iv_return = GD_BICUBIC_FIXED; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'M': if (memEQ(name, "gdEffectMultiply", 16)) { /* ^ */ #ifdef gdEffectMultiply *iv_return = gdEffectMultiply; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'N': if (memEQ(name, "GD_CMP_INTERLACE", 16)) { /* ^ */ #ifdef GD_CMP_INTERLACE *iv_return = GD_CMP_INTERLACE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'R': if (memEQ(name, "GD_CMP_TRUECOLOR", 16)) { /* ^ */ #ifdef GD_CMP_TRUECOLOR *iv_return = GD_CMP_TRUECOLOR; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'V': if (memEQ(name, "GD_FLIP_VERTICAL", 16)) { /* ^ */ #ifdef GD_FLIP_VERTICAL *iv_return = GD_FLIP_VERTICAL; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case '_': if (memEQ(name, "GD_MAJOR_VERSION", 16)) { /* ^ */ #ifdef GD_MAJOR_VERSION *iv_return = GD_MAJOR_VERSION; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } if (memEQ(name, "GD_MINOR_VERSION", 16)) { /* ^ */ #ifdef GD_MINOR_VERSION *iv_return = GD_MINOR_VERSION; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant_17 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_BILINEAR_FIXED GD_CMP_BACKGROUND GD_CMP_NUM_COLORS */ /* Offset 13 gives the best switch position. */ switch (name[13]) { case 'I': if (memEQ(name, "GD_BILINEAR_FIXED", 17)) { /* ^ */ #ifdef GD_BILINEAR_FIXED *iv_return = GD_BILINEAR_FIXED; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'L': if (memEQ(name, "GD_CMP_NUM_COLORS", 17)) { /* ^ */ #ifdef GD_CMP_NUM_COLORS *iv_return = GD_CMP_NUM_COLORS; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'O': if (memEQ(name, "GD_CMP_BACKGROUND", 17)) { /* ^ */ #ifdef GD_CMP_BACKGROUND *iv_return = GD_CMP_BACKGROUND; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant_18 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_CMP_TRANSPARENT GD_RELEASE_VERSION gdAlphaTransparent gdEffectAlphaBlend */ /* Offset 5 gives the best switch position. */ switch (name[5]) { case 'L': if (memEQ(name, "GD_RELEASE_VERSION", 18)) { /* ^ */ #ifdef GD_RELEASE_VERSION *iv_return = GD_RELEASE_VERSION; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'P': if (memEQ(name, "GD_CMP_TRANSPARENT", 18)) { /* ^ */ #ifdef GD_CMP_TRANSPARENT *iv_return = GD_CMP_TRANSPARENT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'e': if (memEQ(name, "gdEffectAlphaBlend", 18)) { /* ^ */ #ifdef gdEffectAlphaBlend *iv_return = gdEffectAlphaBlend; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'h': if (memEQ(name, "gdAlphaTransparent", 18)) { /* ^ */ #ifdef gdAlphaTransparent *iv_return = gdAlphaTransparent; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant_19 (pTHX_ const char *name, IV *iv_return) { /* When generated this function returned values for the list of names given here. However, subsequent manual editing may have added or removed some. GD_AFFINE_TRANSLATE GD_FLIP_HORINZONTAL GD_PIXELATE_AVERAGE */ /* Offset 4 gives the best switch position. */ switch (name[4]) { case 'F': if (memEQ(name, "GD_AFFINE_TRANSLATE", 19)) { /* ^ */ #ifdef GD_AFFINE_TRANSLATE *iv_return = GD_AFFINE_TRANSLATE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'I': if (memEQ(name, "GD_PIXELATE_AVERAGE", 19)) { /* ^ */ #ifdef GD_PIXELATE_AVERAGE *iv_return = GD_PIXELATE_AVERAGE; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'L': if (memEQ(name, "GD_FLIP_HORINZONTAL", 19)) { /* ^ */ #ifdef GD_FLIP_HORINZONTAL *iv_return = GD_FLIP_HORINZONTAL; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } static int constant (pTHX_ const char *name, STRLEN len, IV *iv_return) { /* Initially switch on the length of the name. */ /* When generated this function returned values for the list of names given in this section of perl code. Rather than manually editing these functions to add or remove constants, which would result in this comment and section of code becoming inaccurate, we recommend that you edit this section of code, and use it to regenerate a new set of constant functions which you then use to replace the originals. Regenerate these constant functions by feeding this entire source file to perl -x #!/usr/local/bin/perl5.24.1d-nt -w use ExtUtils::Constant qw (constant_types C_constant XS_constant); my $types = {map {($_, 1)} qw(IV)}; my @names = (qw(GD_AFFINE_ROTATE GD_AFFINE_SCALE GD_AFFINE_SHEAR_HORIZONTAL GD_AFFINE_SHEAR_VERTICAL GD_AFFINE_TRANSLATE GD_BELL GD_BESSEL GD_BICUBIC GD_BICUBIC_FIXED GD_BILINEAR_FIXED GD_BLACKMAN GD_BOX GD_BSPLINE GD_CATMULLROM GD_CMP_BACKGROUND GD_CMP_COLOR GD_CMP_IMAGE GD_CMP_INTERLACE GD_CMP_NUM_COLORS GD_CMP_SIZE_X GD_CMP_SIZE_Y GD_CMP_TRANSPARENT GD_CMP_TRUECOLOR GD_DEFAULT GD_FLIP_BOTH GD_FLIP_HORINZONTAL GD_FLIP_VERTICAL GD_GAUSSIAN GD_GENERALIZED_CUBIC GD_HAMMING GD_HANNING GD_HERMITE GD_LINEAR GD_MAJOR_VERSION GD_METHOD_COUNT GD_MINOR_VERSION GD_MITCHELL GD_NEAREST_NEIGHBOUR GD_PIXELATE_AVERAGE GD_PIXELATE_UPPERLEFT GD_POWER GD_QUADRATIC GD_RELEASE_VERSION GD_RESOLUTION GD_SINC GD_TRIANGLE GD_WEIGHTED4 gdAlphaMax gdAlphaOpaque gdAlphaTransparent gdAntiAliased gdArc gdBlueMax gdBrushed gdChord gdDashSize gdEdged gdEffectAlphaBlend gdEffectMultiply gdEffectNormal gdEffectOverlay gdEffectReplace gdGreenMax gdMaxColors gdNoFill gdPie gdRedMax gdStyled gdStyledBrushed gdTiled gdTransparent)); print constant_types(), "\n"; # macro defs foreach (C_constant ("GD", 'constant', 'IV', $types, undef, 3, @names) ) { print $_, "\n"; # C constant subs } print "\n#### XS Section:\n"; print XS_constant ("GD", $types); __END__ */ switch (len) { case 5: /* Names all of length 5. */ /* gdArc gdPie */ /* Offset 4 gives the best switch position. */ switch (name[4]) { case 'c': if (memEQ(name, "gdAr", 4)) { /* c */ #ifdef gdArc *iv_return = gdArc; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'e': if (memEQ(name, "gdPi", 4)) { /* e */ #ifdef gdPie *iv_return = gdPie; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } break; case 6: if (memEQ(name, "GD_BOX", 6)) { #ifdef GD_BOX *iv_return = GD_BOX; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 7: return constant_7 (aTHX_ name, iv_return); break; case 8: return constant_8 (aTHX_ name, iv_return); break; case 9: return constant_9 (aTHX_ name, iv_return); break; case 10: return constant_10 (aTHX_ name, iv_return); break; case 11: return constant_11 (aTHX_ name, iv_return); break; case 12: return constant_12 (aTHX_ name, iv_return); break; case 13: return constant_13 (aTHX_ name, iv_return); break; case 14: if (memEQ(name, "gdEffectNormal", 14)) { #ifdef gdEffectNormal *iv_return = gdEffectNormal; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 15: return constant_15 (aTHX_ name, iv_return); break; case 16: return constant_16 (aTHX_ name, iv_return); break; case 17: return constant_17 (aTHX_ name, iv_return); break; case 18: return constant_18 (aTHX_ name, iv_return); break; case 19: return constant_19 (aTHX_ name, iv_return); break; case 20: /* Names all of length 20. */ /* GD_GENERALIZED_CUBIC GD_NEAREST_NEIGHBOUR */ /* Offset 13 gives the best switch position. */ switch (name[13]) { case 'D': if (memEQ(name, "GD_GENERALIZED_CUBIC", 20)) { /* ^ */ #ifdef GD_GENERALIZED_CUBIC *iv_return = GD_GENERALIZED_CUBIC; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 'I': if (memEQ(name, "GD_NEAREST_NEIGHBOUR", 20)) { /* ^ */ #ifdef GD_NEAREST_NEIGHBOUR *iv_return = GD_NEAREST_NEIGHBOUR; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } break; case 21: if (memEQ(name, "GD_PIXELATE_UPPERLEFT", 21)) { #ifdef GD_PIXELATE_UPPERLEFT *iv_return = GD_PIXELATE_UPPERLEFT; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 24: if (memEQ(name, "GD_AFFINE_SHEAR_VERTICAL", 24)) { #ifdef GD_AFFINE_SHEAR_VERTICAL *iv_return = GD_AFFINE_SHEAR_VERTICAL; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; case 26: if (memEQ(name, "GD_AFFINE_SHEAR_HORIZONTAL", 26)) { #ifdef GD_AFFINE_SHEAR_HORIZONTAL *iv_return = GD_AFFINE_SHEAR_HORIZONTAL; return PERL_constant_ISIV; #else return PERL_constant_NOTDEF; #endif } break; } return PERL_constant_NOTFOUND; } GD-2.78/t/0000755000175000017500000000000014450761210011553 5ustar rurbanrurbanGD-2.78/t/GD.t0000644000175000017500000002370214174320760012242 0ustar rurbanrurban#!/usr/bin/perl use strict; use warnings; use FileHandle; use FindBin qw($Bin); use lib "$Bin/../blib/lib","$Bin/../blib/arch","$Bin/../lib"; use constant FONT=>"$Bin/test_data/Generic.ttf"; use constant IMAGE_TESTS => 7; use Test::More tests => 14; use IO::Dir; use_ok('GD',':DEFAULT',':cmp'); use_ok('GD::Simple'); chdir $Bin || die "Couldn't change to 't' directory: $!"; my $images = './test_data/images'; my $arg = shift; write_regression_tests() if (defined $arg && $arg eq '--write'); run_image_regression_tests(); run_round_trip_test(); catch_libgd_error(); test_cve2019_6977(); exit 0; sub write_regression_tests { # TODO get all the supported image formats dynamically my @image_types = qw(png gif jpeg tiff wbmp webp heif avif); if (GD::LIBGD_VERSION() < 2.0302 ) { # GD 2.3.2 disabled the old GD and GD2 formats by default unshift @image_types, 'gd2', 'gd'; } warn "Writing regression files..."; for my $suffix (@image_types) { my $op = ucfirst $suffix; $op = 'WBMP' if $suffix eq 'wbmp'; unless (GD::Image->can("newFrom$op")) { print "# not writing $op regression test: not supported\n"; next; } for my $t (1..IMAGE_TESTS) { my $data = eval "test${t}('$suffix')" or die $@; write_regression_test($data,$t,$suffix); } } } sub write_regression_test { my ($data,$test,$suffix) = @_; my $base = "$images/t${test}"; mkdir $base unless -d $base; my $count = 0; my $filename = sprintf ("$base/$test-%02d.$suffix",$count); while (-e $filename) { $count++; $filename = sprintf ("$base/$test-%02d.$suffix",$count); } open my $fh,'>',$filename or die "$filename: $!"; binmode($fh); print $fh $data->$suffix; close $fh or die "$filename: $!"; } sub compare { my ($data,$test,$suffix) = @_; my @files_to_match = glob("$images/t${test}/*.$suffix"); my $matched; for my $file (@files_to_match) { $matched ||= compare_image($data,$file,$suffix); } return $matched; } sub compare_image { my ($data1,$file,$suffix) = @_; my $op = ucfirst($suffix); my $method = "newFrom${op}"; my $data2 = eval {GD::Image->$method($file)} or die $@; return ! $data1->compare($data2) & GD_CMP_IMAGE(); } sub test1 { my $suffix = shift; my $im = new GD::Image(300,300); my($white) = $im->colorAllocate(255, 255, 255); my($black) = $im->colorAllocate(0, 0, 0); my($red) = $im->colorAllocate(255, 0, 0); my($green) = $im->colorAllocate(0,255,0); my($yellow) = $im->colorAllocate(255,250,205); my $fn = "./test_data/tile.$suffix"; my $op = ucfirst($suffix); my $tile = eval "GD::Image->newFrom${op}('$fn')" or die $@; return unless $tile; $im->setBrush($tile); $im->arc(100,100,100,150,0,360,gdBrushed()); $im->setTile($tile); $im->filledRectangle(150,150,250,250,gdTiled()); $im->rectangle(150,150,250,250,$black); $im->setStyle($green,$green,$green,gdTransparent(),$red,$red,$red,gdTransparent()); $im->line(0,280,300,280,gdStyled()); return $im; } sub test2 { my($im) = new GD::Image(300,300); my($white,$black,$red,$blue,$yellow) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); my($brush) = new GD::Image(10,10); $brush->colorAllocate(255,255,255); # white $brush->colorAllocate(0,0,0); # black $brush->transparent($white); # white is transparent $brush->filledRectangle(0,0,5,2,$black); # a black rectangle $im->setBrush($brush); $im->arc(100,100,100,150,0,360,gdBrushed()); my($poly) = new GD::Polygon; $poly->addPt(30,30); $poly->addPt(100,10); $poly->addPt(190,290); $poly->addPt(30,290); $im->polygon($poly,gdBrushed()); $im->fill(132,62,$blue); $im->fill(100,70,$red); $im->fill(40,40,$yellow); $im->copy($im,150,150,20,20,50,50); $im->copyResized($im,10,200,20,20,100,100,50,50); return $im; } sub test3 { my($im) = new GD::Image(100,50); my($black,$white,$red,$blue) = ( $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 255, 255), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255) ); $im->arc(50, 25, 98, 48, 0, 360, $white); $im->fill(50, 21, $red); return $im; } sub test4 { my($im) = new GD::Image(225,180); my($black,$white,$red,$blue,$yellow) = ($im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 255, 255), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); my($poly) = new GD::Polygon; $poly->addPt(0,50); $poly->addPt(25,25); $poly->addPt(50,50); $im->filledPolygon($poly,$blue); $poly->offset(100,100); $im->filledPolygon($poly,$red); $poly->map(50,50,100,100,10,10,110,60); $im->filledPolygon($poly,$yellow); $poly->map($poly->bounds,50,20,80,160); $im->filledPolygon($poly,$white); return $im; } sub test5 { my($im) = new GD::Image(300,300); my($white,$black,$red,$blue,$yellow) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); $im->transparent($white); my($brush) = new GD::Image(10,10); $brush->colorAllocate(255,255,255); $brush->colorAllocate(0,0,0); $brush->transparent($white); $brush->filledRectangle(0,0,5,2,$black); $im->string(gdLargeFont(),150,10,"Hello world!",$red); $im->string(gdSmallFont(),150,28,"Goodbye cruel world!",$blue); $im->stringUp(gdTinyFont(),280,250,"I'm climbing the wall!",$black); $im->charUp(gdMediumBoldFont(),280,280,"Q",$black); $im->setBrush($brush); $im->arc(100,100,100,150,0,360,gdBrushed()); my $poly = new GD::Polygon; $poly->addPt(30,30); $poly->addPt(100,10); $poly->addPt(190,290); $poly->addPt(30,290); $im->polygon($poly,gdBrushed()); $im->fill(132,62,$blue); $im->fill(100,70,$red); $im->fill(40,40,$yellow); return $im; } sub test6 { my $dtor = 0.0174533; my $pi = 3.141592654; my $xsize = 500; my $ysize = 500; my $scale = 1; my $x_offset = $xsize/2; my $y_offset = $ysize/2; my $im = new GD::Image($xsize,$ysize); my $poly = new GD::Polygon; my $col_bg = $im->colorAllocate(0,0,0); my $col_fg = $im->colorAllocate(255,255,0); my $col_fill = $im->colorAllocate(255,0,0); my $r_0 = 100; my $theta_0 = 20; my $spring_factor = 30; for(my $theta=0;$theta<=360;$theta++) { my $r = $r_0 + $spring_factor*sin(2*$pi*$theta/$theta_0); my $x = int($r * cos($theta*$dtor))*$scale+$x_offset; my $y = int($r * sin($theta*$dtor))*$scale+$y_offset; $poly->addPt($x,$y); } $im->filledPolygon($poly,$col_fill); # Call gdImageFilledPolygon() return $im; } sub test7 { my $im = GD::Image->new(400,250); if (!$im) { printf("Test7: no image");}; my($white,$black,$red,$blue,$yellow) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); # Some TTFs $im->stringFT($black,FONT,12.0,0.0,20,20,"Hello world!") || warn $@; $im->stringFT($red,FONT,14.0,0.0,20,80,"Hello world!") || warn $@; $im->stringFT($blue,FONT,30.0,-0.5,60,100,"Goodbye cruel world!") || warn $@; return $im; } sub run_image_regression_tests { my $default_image_type = 'gd2'; if (!GD::Image->can("newFromGd2") || GD::LIBGD_VERSION() >= 2.0302) { $default_image_type = 'png'; } my $suffix = $ENV{GDIMAGETYPE} || $default_image_type; print STDERR "# Testing gd ".GD::VERSION_STRING()." using $suffix support.\n"; for my $t (1..IMAGE_TESTS) { my $gd = eval "test${t}('$suffix')"; if (!$gd) { fail("unable to generate comparison image for test $t with $suffix: $@"); } else { my $ok = compare($gd,$t,$suffix); unless ($ok) { if (($suffix ne 'gd2') or ($t == 7)) { ok(1, "TODO image comparison test $t $suffix failed (regen with --write)"); } else { ok($ok, "image comparison test $t $suffix"); } diag("gd: ",GD::VERSION_STRING(), ", files: ",join(" ",glob("$images/t${t}/*.$suffix"))); } else { ok($ok, "image comparison test $t $suffix"); } } } } sub run_round_trip_test { my $image = GD::Image->new(300,300); $image->colorAllocate(255,255,255); $image->colorAllocate(0,0,0); $image->colorAllocate(255,0,0); $image->rectangle(0,0,300,300,0); $image->filledRectangle(10,10,50,50,2); if (GD::Image->can("newFromGd")) { my $gd = $image->gd; my $image2 = GD::Image->newFromGdData($gd); ok(!$image->compare($image2) & GD_CMP_IMAGE(),'round trip gd'); my $gd2 = $image->gd2; $image2 = GD::Image->newFromGd2Data($gd2); ok(!$image->compare($image2) & GD_CMP_IMAGE(),'round trip gd2'); } else { # GD 2.3.2 disabled the old GD and GD2 formats by default my $png = $image->png; my $image2 = GD::Image->newFromPngData($png); ok(!$image->compare($image2) & GD_CMP_IMAGE(),'round trip png'); my $gif = $image->gif; $image2 = GD::Image->newFromGifData($gif); ok(!$image->compare($image2) & GD_CMP_IMAGE(),'round trip gif'); } } sub catch_libgd_error { diag("ignore corrupt png error messages..."); my $image = eval { GD::Image->newFromPng("test_data/images/corrupt.png") }; is($image, undef); ok($@, 'caught corrupt png'); } sub test_cve2019_6977 { my $img1 = GD::Image->new(0xfff, 0xfff, 1); my $img2 = GD::Image->new(0xfff, 0xfff, 0); $img2->colorAllocate(0, 0, 0); $img2->setPixel (0, 0, 255); if (GD::LIBGD_VERSION() >= 2.10) { $img1->colorMatch ($img2); } ok(1, 'survived CVE 2019-6977'); # fails only under valgrind or asan } GD-2.78/t/z_pod-spell-mistakes.t0000644000175000017500000000117513415647142016021 0ustar rurbanrurban# -*- perl -*- use strict; use Test::More; plan skip_all => 'No RELEASE_TESTING' unless -d '.git' || $ENV{RELEASE_TESTING}; eval "use Pod::Spell::CommonMistakes;"; plan skip_all => "Pod::Spell::CommonMistakes required" if $@; my @docs = qw( lib/GD.pm lib/GD/Group.pm lib/GD/Image.pm lib/GD/Polygon.pm lib/GD/Polyline.pm lib/GD/Simple.pm ); plan tests => scalar @docs; for my $f (@docs) { my $r = Pod::Spell::CommonMistakes::check_pod($f); if ( keys %$r == 0 ) { ok(1, "$f"); } else { ok(0, "$f"); foreach my $k ( keys %$r ) { diag " Found: '$k' - Possible spelling: '$r->{$k}'?"; } } } GD-2.78/t/windows_bmp.t0000644000175000017500000000051214434720223014267 0ustar rurbanrurban#!/usr/bin/perl use strict; use warnings; use Test::More tests => 4; use_ok('GD'); my $winbmp = "t/test_data/windows.bmp"; my $im = GD::Image->newFromBmp($winbmp); ok defined($im), "windows bmp does not return undef"; is $im->width, 2, "windows bmp has width 2"; is $im->height, 2, "windows bmp has height 2"; GD-2.78/t/HSV.t0000644000175000017500000000211613415647142012407 0ustar rurbanrurban#!/usr/bin/perl # -*- encoding: utf-8; indent-tabs-mode: nil -*- # See https://rt.cpan.org/Ticket/Display.html?id=120572 # checks 5832 RGB triples, executes a # round trip RGB -> HSV -> RGB and compares the initial and final # RGB triples. Of course, there will be rounding errors, so the # final RGB triple will be a little different from the initial. # So I compare the Manhattan distance between the two triples and # compare it with a fuzz value. use Test::More tests => 1; use strict; use warnings; use GD::Simple; my $fmt = " %3d" x 10; my $step = 15; my $fuzz = 3; my $neg_fix = 0; for (my $r0 = 0; $r0 <= 255; $r0 += $step) { for (my $g0 = 0; $g0 <= 255; $g0 += $step) { for (my $b0 = 0; $b0 <= 255; $b0 += $step) { my ($h, $s, $v) = GD::Simple->RGBtoHSV($r0, $g0, $b0); my ($r1, $g1, $b1) = GD::Simple->HSVtoRGB($h, $s, $v); my $delta = abs($r1 - $r0) + abs($g1 - $g0) + abs($b1 - $b0); if ($delta > $fuzz) { diag(sprintf $fmt, $h, $s, $v, $r0, $g0, $b0, $r1, $g1, $b1, $delta); fail(); exit; } } } } pass(); GD-2.78/t/test_data/0000755000175000017500000000000014450761210013523 5ustar rurbanrurbanGD-2.78/t/test_data/images/0000755000175000017500000000000014450761210014770 5ustar rurbanrurbanGD-2.78/t/test_data/images/corrupt.png0000644000175000017500000000236613415647142017212 0ustar rurbanrurbanPNG  IHDR.,SFPLTEܸ L$}IDATxڽn@`R5q EԜիo7{g490$%!Mp8Sv܆)˴m4mQ#Q\U._U+T_+\vq+R1b\c*j S+.ڐJT >qa*R+.|\ ڸr[V(kǕ K/1~\`e̥₶5F5 kU.֠2ӏNN\,R`2,Z\ -JXӈ,ѡ]EXNÜXɰhVkaɸ`ZqXaMq[X,HXS\XѰƸ˕ӡhQƸȲ7>"rua q鰒aqYZ,r!bth`6{:ºX?,R\Vji2:ZڬE=du˳\dZr;u:d:v_Xټ!,?#Y'gyF"tYpKYded},:miec?'uez J 2vx27~sV`%Y;b5v۫U)S2{o&K!vZU X{Ed%KVaCn{)vvz$+٢ZY;/W VEZ`V4.,w1VzVEW>kX.xJ`;ldZ"Xru3 %° %| m-?z8oэK իd\^Xfen?z?'_XErTk˪ѩ \EenS8Vy2k z i< 55ĺbc,Ea]p̸31WeX{՞Sv7Ͼ^*ޣہϮ5S++w;F;~Go)فדh`&osNG&7,ڍA~wS>D| G%lh3=f%x|dD}L}<A ~@W8rܨ7';H[dwabGݍ#L'z&"#1{GKֻA=8~TGOakN>6uM>]c/œV XO$w+C䂢 -x[map{ R?ѩ { , ~8thrkW\j 5Ov罃Oz{Mى-.f݀w'=xh7B=W0t62b-QovW{h;o#qptN?PEdoA/}&{clzkI3Cm@]v;tKSWCnG7RKiZ՛G _zcT uw]WnrwtՎf_\i^f=W9ir~KNݨN5,ˢVk.A]'v.kIKP}$׫k4v*>_"&W,} w7|-B+-kL= dp]KVv{nj_즋I]OYvv?۰KulSV˛j;N/{*b? of%rʮV4Kھ٥% .I yCtʼnr$^/_o=mpy=O\פnV?2&۷kbWx]ˊ3',=/e߯ھU{3Xg?"ras=({m:ꃽlj{j{wK5nti?>|g6/".>n͛cnqX`W+.\`˖ ɦR;!B!B!B!B!B!B!B!vRdT3^IENDB`GD-2.78/t/test_data/images/t6/6-00.gd20000644000175000017500000000707713076115435016321 0ustar rurbanrurbangd2'92+%PC p% 7   % % % %$x1 Om @xα 0FYsO ax10A#$*8uNx1 Om x2:xЁ 0 C!,ngP4In?ٿ }a_xA"1CQ?t.l2 Z{ xx<ʞԡ?}mgANS:ia @7QF,׫Uj_ 7@?XPWmY<|)?<n"OS}'O$}ṡ/fpM;ŧБa+ėh_-)o%GCq>>cCPG!~'h?0aۧ>#M%Z$H}1[> `Ƭ~@csĜ4 )Qg,>[_Y0 V~U/*%[ .}o[ X7ྦྷ/`}uk/2~9{?s?Ogo*߿J]/oHҀ;VIxInC1 @?t7]XzhX?g~~~}7뻏__S'kR$槍[RTǔǍkx؇OƇOYCV5I&Zc{d[H;|6nˏ0ggX𬏦,ѐ'}w,oiWx/>_]|n3Oy@/o_^ZK~b;g[k׻?F>w3ş wxu>0^3'Cm|]77< 9J|"I "4 B /?1x1 Om x2:x 1C;?},pZ"<?Y^xn0 РahHdRB.z5:t լ^z'9g|"u:+㾯.oo?!AZcwi5yTO>ч7U[O?W|*y9I:x?9|}5b*]G><_ós˼S%>>;>>mSo-?1c7{k}N>[U3zW<ЃKU3ztp|SW=7emZ3~OT!!?GnPGH>Ț~%هxQ}I}V}.I>7 G4UmSmDk>^m}M >ܧ_>d`}d;};t Ib7بu~~NaNGzꩧ?xv0CQ}%Kɓ,g<B}oY }q^v\7_ 0_(0r T`}s*D@ R>Z󱂤D}  đѷ>۽O;?&|dӗKW.jX2ӿ'E^3O |2:`<.S0~$|CupCO-Cnp 6~*b+:۷\j>Ӫ>PP/.ŀ~?O=,K϶o9.oݾlnma[_>ߚMN 9ox1 Om x2:x1 Om x2:x1 Om x2:x1 Om x2:xàS_U|4GD-2.78/t/test_data/images/t6/6-00.gd0000644000175000017500000075223513076115435016242 0ustar rurbanrurbanGD-2.78/t/test_data/images/t6/6-00.gif0000644000175000017500000000473513076115435016410 0ustar rurbanrurbanGIF87a,ڋ޼H扦ʶ L ĢL*̦ JԪjܮ N (8HXhx)9IYiy *:JZjz +;K[k{ ,N^n~/?O_o0 <0… :|1ĉ+Z1;z2ȑ$K<2ʕ,[| 3̙4kڼ3Ν<{ 4СD=4ҥL:} 5ԩTZ5֭\z 65Kٵi%=[)53 w[bn_ю;8La! 'ncǏD!re˗'S<0˘9t- N~0_ܺݶW,Aqo,4g^t͝ӆt*c]vݽK};+O~+/[xqEhW}`!\lAp-`>aN%6qg.aZbчH7ژ@-'3G"yC2$Qzi@2Rch%i" &|@&hk&9gZN&R#zV&wX`깡y@ yxZ ?b藁)TiY (f~z jRjP)ZiH먶SjdK'S ƊyJ5-%>[-e}J-v5vnU:. ʮmUKaҦɯo< +o;yS[. o5/ +KZ 8*d u.,q,r-3Ϭv9o1LE\tӸ hAܬVI۴WMWQ͵邍,rP]vGNM*wdMj 8w/4܁ m6V⹊x|E.o>8әw1 s%pN&I8벇r${kk{сs Ὗd5',} <_͠{4t>}~wo7O'@9n(g*p[aWJd56mWRJf 3} A|pC q H!qz 'PR۪8`q.R!3фj$ ۈF"c}gG(0<c?Z&! y!T\$"H$Y$% K:В|d;)FEz%iPN-2t"+[W&rD!kE3rr_14"1%c<])gBS{fޮh$$79oN&dK9])PɤelFFP9% l CiЇI%[^Y;m 6w?}ԗ+7ICnh yOLiOgҒxyNKB>:/aFHդ7m+bT;dA.5QCG2hTJQvԊGU*Ql)\&X8W]md`͟uYE [o|=)CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((+kúb^4bFoOp=>**qrgV S^4)Vt{v!m#?CV*U#R<;W]ЫQEQWn4[E꾄.QM&5BHPj:-JTQEQQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEe_۴*wyT$Hd)*280Ev B4sJѷc^zƵU{\ 5asMWӧs+><+Ks#3W]äZA7>uJ>)c'>]i7.w$c2 ^mukCn 1Vy}M;x $:sfŠ(AR3k=x~=Aq~t+mrv|uOWVc x;~9_b6t*1Ī{;^qoռJ2>Zi, ppr nx=|e]b)v{Ky z O=Bi\SAW~e|Q&F Ĭ$ +SŐwBLߥr]#sev٧9|+kkF+~Wu[ m"A1z~mNZV| a==MiVg?sЅi'YJ@@=F :X}ϓYuX㨢FycooO3}zt5w)y$'zEo]=v)Rvv6qʞ .+cu=8y}^Y[yż7QdCهOq}跸99G\ooK^&~gXw8mWFNczQh_c !ma]JV +<>֊6 (?^(bX:sL`][_WQTt :9X|?ǃ%8Э VJt_8t6 ɧZ)VXPF8bnp{ N8_V~v*u$R#8==TӺ7#8KgSM[ \z@*Q)964B8ӂJ+Ӭ5y]Q_$nϯӽtQ1tU:1.JՒ)G%><=kq ߿Sk [1x1zՊxp0>D/=ԫ^\Ϯ/躼*=^^qCwXm#5TM%4^G9,j:hRPQ?5q_J^((((((((((((((((( EbKm _ ( s?Ns\dr<2p]G&E\:_<x\L;z6OTEѮXĀOnF1%Ƌ[@hqߎwW-֞!j`}Kb>g]EW}PE$I %PbdQE ( ( ( oç6?Ө)YHPTzUj2NJөVҗ,];Kn/(0da~i|E-'%Z]pe.y3(]r;1 .v/e5!)˖(bidzd8{"S4\LLsƉfg/#5{|? :~_fy**T5y3 FŢ(/g?.# e؏ȚxKk>KY8^c>VK1SN?W=:柅M7{]{Wic>VK2Ssj<+5Ru\kvڎT?'9֝W[ 4`i#U87x+#0qƟ.&JRQPuQ@Q@Q@Q@Q@Q@Q@T7vy1F\m9曲&B[XCh8GX:rNg1.r/_ֺ}>noo\ol7gi?1:ur2ɔ_v;Q]԰4ᬵ>WBV$M!y]VciQ]Ͷۻ (Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@oi~#kHR#$H0^l J5,׃WT%gն܎'62V_Oִݶ{f1ê+^ϫ񄖘_?EqSI4 0,o|Uv=Xqf_%w̽W6vW3 w8_ƭl):pXO Y}e6i#ni}m|҉7X4VHU6}V(EQ@Q@Q@Q@Q@Q@Q@j'!x \3;f,rI9$ץrhE :3},lir%p\]GQ욿_$yˤi(Vs.T 1nTFB)LgEu[³./w >?2v?ÙrszjkiԮ:SOTxdŠ(HQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEKoo5Ԣ(#iQzMʌe6vȨo ]J3q*@>f~m>1)᎟r҆~"Q_-u-i뎃zkY u:8;Pn>=UTPUF Z⩏/C|'g]}_ĩe.  X?Nn+RrwljTт8DQE#@((((((f!f1$d!m \RmQ\&ԡ𣎪֙ U[k5O|SfvW U[hy[-4X?֬Š*V#x)#~MQ'Yww*e 0AW+[K[[bs$k'9϶sӶ= 5NX5Ok:0Yҗ4>cTQEw(QEQEQEQEQEQEQEQEQEQEQEQEQEQEQWt{]J)T=;MhSJʛJ慄ao%RS?:mᵈEk:ST !Q ?_ ¼ZX> ZH'ߙ_﹧Ec]:-Isbc* +2Uϛu!vS0šb8OJI_I$p^WTA՘ lS:TA(i]ƣ0XԬy#_>Ycn@QԞ}Og^)ivv9'0nOizOEW1Q@Q@Q@Q@Q@Q@Q@/t[qҹGwlLÿoƊޖ&-dLrnm.?3S-?xrNJӈ'E9RϯzqPϱgb ɮh2WO̥EWIQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ohkKRr?n \4E7цv$N2zӢ3O>$dŧH};xVP$h0TQ^cw՟s$VV-7uF^q{V%/*푐\cE\1RkFsRPVTiؖ(:((((( nkhc dWh9~sZk_ uFx@롮7]ўVf$OOۆUף>g;x3 6Kv]uvױ﷙d::ŤX) [~$ M5u2-`r`T9_u_2VPEc}>F!؆3ӏ;{{ 'igGj*Jq>*^W0O ,¹$}>9\+#e*pA ץfGۖU)ÿ'Wfjm熩NZ[~(X(((((((((((((((((+д/'m~q>ўѐF,yOW^>qx_O]*+mb2"ƃW=⟽~kA*Bu_f\iY{s@c\;ص^nz{fg/#4C ,0y(R4yⱲt{zY|OzjjKFyT"<é=k,R+t9ϩ:EgVwl- oE(fTRUFI' Ȱ?uy!b"$9sϰ?LNRM_JNoޛ_Cb(:B()$k"#:|Ryluǭm-QE ̸#ՖvD O֝`c[βt}q0i- }XokINQ53 d?+_*9d4C4wиxd0+Tϣ*C48M_K}2.ɓv>uz-7={YI=l`0g [N ^w//ֵ:9$@;#ShSiKhEE'"7R"YV~Ɵ_0+C(((((((((((((((((z(UuU"Tnt\NLƤyTWK\Mu)yG=ڢI%dxܤWQ8,fOXsV{ylgw?zq1$H0Tz\8ܱ[˕j5o_Ek`kQ>tʤb}/K I֬^#I&+^Jg'r*NO+fgbřI'$|1oifR2 ` uׄhWSrM\9UmvVZ~TsʰA$ XԱy)_C)IE9={ #Ÿ9t549Ko,8;^]*]x%?My't܂Ha*:32B6I\ϋx?/vqk,m鷫cÁه_E[?7g6؎ooOʻ M/eQ.?H܊;y ep}RF8ãaEzUq~$>dQC.zN_Rpx_ JZ??[L4"<poU]:Ԭn>=س1fcI&4\LLsƣ_AQHE-aAD'μyH #8HL_ OZ֪e MɊ;pH36O^ߙoW s c_ԚS窟mOkqWJ)?w >f]z O=@f}سp$ @{9*;s_iW3sW3sŃ<~I"fQ:igZ_g1g½LUk 7G9qI\]5gn?x#[u,I E*H1^5)MKV? Xii~=?'HXѱRGL;~7(Y+e9kL/cWnޟsVu(¢ق18)Pnz\Ǵ=8>%E4hƒj&g[0jVI4Š(8(((((((((((((((((((*H%h'el 棢'GI'd1-&`:KirXtVTӧ+Nz%+QZ*7VT"UoWW []y^Gy[KnYK`d^tř3NI5X˃\tirÙhi ȳr%{#v7M`E!s¦uG`yw,Phs.+&G+()H) ޢk %5,Rf׊r?8uΌRwdsTsMqARd#E܉WHQUPSD5XZlmؑV[CŠ[3j+}xE?<4,/ ~MXfG<0Lt{c'`͡Xck~az q~=ԛQj:>ߔZ0EkP<[} u?ݟ?yӇd5x2392}翟]/D2~yXao`5nr;u!:Cgr.^~ zȧjΓVw?Ӏf q>_: ?y>&.gDq~iby@ާ5b>1 ,Xa91 ю,82mDp1 :|>ߞG(4 |6p; ˿\Ӏ/KA=ø 2'ɿ:#[z߿)ѾBv/[_z ix1 DHlORl94UP {=_[J){ʡԲ:7fm<1Vc׾?~! $9e]99vz(wh-L;wxJhx۹k^Wy|x1 Om @xc``Q0 FHx A$w‘! [ R!!_ʌGRX%{יۿ.bxZK D&؀w=>BG݋IF\N[k4[o`)_]#ħz{ټ`2"W}QwvzC5 J3BZM>illhɋE'Jf$?և(M|ΏsSCg8N>lj,y0d.f@8B~^l!)Yt|g©8gqfcd>h?rsqA$ ;a'(9%gEPv@BOEHӞρ_>AAC>&Hed2* ߜy!T-saJ *!{BbJE^6T&TFbP+UO"Gƒp|y&(Hܰhldw1Arvםl!ڸM(?N> Gd9 F.#ʢ*ͬC.SoWE'G>,dk[!6l SozNDt=쒫k[2t$Uog +;"V.ԛ3٨O%?5O0}r&Οڅa- 3ʺ)̝ $OVne/ U?ϐ_ύzr<ϐЊ HRfI4Ci[byn/BbJ̐8)[3$$ 9ʥx!qEzs!)V0͐ZBMW`7QK/i!lhQD-k/P%Put3z._7nh888888888888888888888 dxY[#! D&?v[L'3V.1FP( BP( BP( b-[k ѻos5xBaMzH能j=sasA2}y\)[kٻSnO"v}hSi&_l p&nH~: { bHfGẗ́E-Ÿ*6 h\>Лt ޖ~ DXCi}EѷY)͝/-eX@>喙\6QJsJZ՜-:A^ $)j'Oc[~yhSzޏrzP8tYm29|^s_\ӳp8w}b׶a-ؽ!U(_pOxc``Q0 F`GD-2.78/t/test_data/images/t7/7-00.png0000644000175000017500000000645213076115435016427 0ustar rurbanrurbanPNG  IHDRyvPLTE___???GGG///oooSSS??__SS//ccwwOO77__??//ww XIDATx ma1K&mӦd],xKAG\ xKٵULʆv>6 %Pݷ.ϝ7=< )H Pz[UWSLCnW1_vص `4~ekSvMmIc@֍.ꖅҜ2w3HAMo^\؟͏M;|1NF&(ȹ'ece.>6Ms=}V=XAKGb9_T^A~hذ]ađm]|%i>S_Ù|ɕg|;#ģO?+˥狯MSDG6jh^#isxd =Ϳq<լM~vg'y\_ϱtԐK>Hz3u^ieqtƁ 1 _?r<ٺ?ы^Dr%]|m~C"B: iFL7h{%i. ќi1X8lbCu և$Г:;G/臯6 |zփuh:þ;;ITp׹oH_AIzG4/4W?Wr4/7|9 ]H$[z|AH5Rb*}+~!LBo7 녰k,{S/pj 'U^G5x})yW/`CGN ~Nu"G ^' RkBG G O^(§ZF Z2='&% !" '!Դ!o.0S὆Dr1$b?JJ,£tYZL ʭ8S_0aW6Q U6qV"ؖ9!8r b&QǮ J4j4dE4 %"w3"ِoK\K1,^Bң [+grH$7hC'5y$+F mP>hKo,.XgEؕ(#oE""yL~tq0H~C)J *JVD HK086zU6bbRwrwrzTny œP{9юy$֣#5T Ä֫2k!-Bݽ f/L[}4DtӐ3wv!_JdؓZ"ڷ]_X ,%X Nǎ(OHk@.t1~sġö,qYc8%79LLq;Lȅb[jEPkCAX/ BМL$[~o5e*;H$n^xüqcVVVBB|# .픱cΕm㮊S/6K%{ndI8NrT2>DWi)Ɉ4eA 8W ^ҥ4c9m6^@2""s;o+R\XdDzowĂo.%ۿxTrcע8/?0b[s%X22-͕fq3ѩKq>\X1ЧXvâ>+7G:>E<ܲr>)l>קC)' qb8d>Ez!}"$ /k}xUInJ٫S\}P!t́΅EJ!B}Z KVaʏ؜]i c)s2C)[XDNK-CH>3 T zrj{zi "䎝ň,T0^bqXd0j OV|G. 3Ʉ/4en%':=<2\+ ېHy /~`ÙIgJs#eB^  g-_^dV0YT0  #QwH$7"Qkyz&><^];d X9QOmkM4`exqn_I>m4RT hFH_ЀAe&klkx8>Z9dnQ1Lں7Ww?66`E'4YQ(MF烬ܮVEX(t`R%ؚ(U*v0Wඪ)%UiF0W\ a|܃x+)ˆE̒LDH^b΄U#O7^5sqey쾱H1`iJ#&x.XY \WŸ'bNi^P|h}CKXBZpC\iQH|N9=Ҫ\S\$_'OJIq0&¾@Г0z.e)jAvTn ""] +O} 21C=Oc2.NuA H$ЮtӒ4JH~RY>tĜ)}WS=sN Sʒ/t> C*4ǧT DIF!Beߐ x K_ ǿ?)RAԍ,MC0 KY*ja;X]׍"+VFaOywfZFB0R,G#GæZɶ-VJ+" Vf{ K2ZZ=#ۨcڦ? H&HɋP*ɐ4SA?S8J>` E  Ft܊|5-D] D m"nN:וj~F~_4fV5:lIW0ZG V>xJY@4toM`K--bDѧQ>qB3 .:IQAR~i봐\E [dtU *Ix *.T3pi!e~ݢ>NE44K}.{L[K/#>{> ]-ػѰ[΄bpBoϛyegE0hc#銪sz.#k;zobߓ1q>; >&-q=}˨x +sٲzc9הY,ol-1@c%t ΫI0oCoWxGok'F?ѵ>ևіi8>~Aw(P|s {9ltܕ΄rn@LE^`:&d[;۳dnpnѓnu'b?%?]7t+ki^7Nޏti 'W짿!|,G<v~Oo+fԭ?W緕[{g+C8% /Ӱf9?| Boxx1!,(ṲHUn}Sr14k&C>YZ F5[h~؉}^=5-D׵w] M_6N}l$K羅ev{j7;sw$WjX7ހ+߿qSx1 Om @xc``Q0 FHx @&ED?!$ JhzNg12 #GוEeUWaz+ѪxYK0t΂{K' CO$Ij>9<:KVHtO3l?Ayo}cwtP}1!6v_^8^>?eڇTc1ϕPxݟcU~I`$><1exI*τ@ PJ:q/gz%[򷿏IJIzלذJeAgז${II_S?4Ps5^/ TlG6D5F?57&eANڛ‚WYڔFтy442(>n:| 9NvkKvJvk18]F0zFHHq)8:f!gkb^R/.?1)BWvj g%odbdP/ V9biЬ=.&Z>COŨO˲ή(k@܋.4.q:z\uu TB6Gk/l\_n,R=}"ًK8vH77,|,,!z$1ƀCxvH).wH85P}O;6Eh)JC&?wH] eurY-f%nwH,b_V=y!qݬ'O;~ fյ}od8OK&Π&o^f5`FSAuS4| 5|Z OjWK:㽍 qkxY[0`3ƀ_IkC+Q_Pe0 `0 `0 0gKwtrG c8IOt21znt.?W eכ(̾^*ϡCTjH4a>tsTƒb$q0cֹ/pG %\h&ܥ_m(3' 7i-=d^G\>=7=@6XԯB:G=8^4KױFZnCk0 eB+!\`Nˢws"ȓWُOJN՚j[eP|+"Hto~Ud`vɲ#T{JW%/kT_8}Ua̠u_"3z|vzSp|{WYBzj Em(%\bj7dAL4meڌ "L t񩖾hBb.m~P1}A)ޚoTo:GP9`oupH4b~w'|wϬe آ~2XB-k !e\qCl+6j^^3W ¸d:?"8I]vmx 9c쟼QvoPUrxc``Q0 F`GD-2.78/t/test_data/images/t7/7-00.gif0000644000175000017500000000664013076115435016407 0ustar rurbanrurbanGIF87a___???GGG///oooSSS??__SS//ccwwOO77__??//ww,@pH,Ȥrl:ШtJZجvzxL.zn|N~dG BB G BaC  E`CB GŠ OٙԱ w Ǩ Iv~xkzGqV(,Y4fNj BGd \;M20*=e W8Z0/F6Y TP9ɵkCx5AhrJC67l1'+’Dx.ђh̘r yBd,Bj3ŧ<o=pwZUU;FB,Rj";IA~}Ͽ(h& 6F(Vhfv ($h(,0(4h8<@)DiH&L6PF)TViXf\v`)difD`pPɕL0HDoamZ M *H\P'᨝C9n AIf 'tf F4B(xYJgk~Y+*Rj:V@`' 'zA Zl kti.Nֻhժ먚j`-E A ƹ\ Hɯ2iq⩮0Lrj ̣'/CB*P*,,(4~="뮜J ]_Zb1ʫp,Npmض` Gc*8i^t *OL!,yބ33Ѿ5Jiޢ.ΦNS.W-?yv8r: a,.?0oI^0AZloGTkfi(Ko# A L@`'߅D@ M@B& K@x$j#0 @PA#`aK B#p/< Chp&!D =!"JMP`ԐM,\^"F @d,c"`U\t ~g! R8 m$ JE8q"HdEC>?#G@'r5H14%1BБE+&HOJR'PA$Q`@1 ]! OpJjБ4" (Q3; %G#Jw:fW@Ai$B#Hg 4K m(Es&bgG!s2dH BLD6X{ _N";$`!dNq`BPBz~ DHMT4W_:{J$>;jhڔ~CQN$JЩ(Zb"<I.B2%O&"d>meLYP#$+xE>psCE f(XJDF%DHCԟn,$ !)T"h=kF;<" ْ:Q(VXZ=k۪z_DCB&=jёBV']JeڽB=I*Z׾Uh,bg7‘Ԭ [y"Dp" 5"R\{;`Nkێ&➒d1Ob(8 +G;xD-?#"5CkhO"y5/oP7OC]"xe]2WHoW  yt$DoJУK Y$&[Ǹ 8./9ʼn|ORt-z RԀ'X>ծ^ya%kϹîO:J9n&F$O54GP=jV&L@oaa9 @DG0 Y8 ;%}> (0䎖{ ֣=., =iJA\cm8`mnPD\ 89r,+\2gbk *nO] ,lkNrJ; c;@$ Hm~~2[nagh;!n;k] $`dRwWOMco큧W ó3cP փ3+Z <~[|V-s 5Rȏ}-'w!L=q߿יvySo)0H%y^6? 5_9F)QCP WzE@zUB7D`3Aۘw~kIu񮈧z+I|v'whYm&me?U| lN6o}_5sDIrDtX`o*Ep'~*HgbCXT$1XpTCn}_&X`RdW\eKSpWOI'@)HH F:OePє~\N.[Ie~7xSQ@ ؆,ugǂhhNI6^wƇYS@mTeqU*$^d(d]dmdex;5aLJh1Ha, ^BUx@s8U8H凯X.'E&\QF^BUbRTւU6eBPSDjktGm4&tUD\MuaC@zØ|Cwa|VHcMCx}uE@4D~>wHG5aFVtXH8Y#FI>xe|74dvHȌ v].EopUHG4|7gU䈀 ~VRqU`T!8xN5g@xJ%@nc%6,LBƷyQUHt^y}1Y\X؉B{.Y{JXCuIm9*9ireh{w'ia=\EGgHyZi\@*dH{G}☎FDL<8^KIS8zǘrȗNڦIU`F)>VUO988EAYdb4)9S i1u))Yy)&A;GD-2.78/t/test_data/images/t7/7-00.jpeg0000644000175000017500000002120613076115435016562 0ustar rurbanrurbanJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( +#"uwA|ąUV {Wj?uãHc,5bcsswtE +l. $} Eyt?gKc] d6rܙv 2 su=oN]ۓjf9乘/tW|gˍz(/h٨O2m&EU[0vƽYϥq&gA+khRg$$@Zgsp8z~{mcFߺ}OAuv E|8̂rN9^S0ڭŹ@6\>xJ mFH oZ놷) t_j77zEfyΩL[ʁ\"!Fx%ȟ_;VQEZzu)ϗ{xUn`M\Kh\95VsfO|vqq3\7a|AmصX]ou:Aa*1$a`9倌zNs؝Ib4Bm1@͖v=?S+'Q{_K'{[PxHy JV#;6cՀ}'e4Z/!?#>۸`"\ƿ<ޤp8{I woIΟ嶫4DqRB=:r^j\M0^'Y5I^{-]׫]]gRPKV˻[sT.uڲ<3i aeݥM!wǐ? ׮I$f!S)B6_aEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEV/:[Dފ&bcX{EmmI#`>׿Pޫ;+"H⸋~2efҭ-'޽{ W?E5:`#ye* Ҿ;:uk5~U{GڿǝU(>"[ijgiq=鍕}Xӭ^7/Ʈ X(7i$ zqr;/7U[#!T9<)þ)q=B5̛~Rx'OI5o[#JWVzQ^QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEVOoH|1"_)h+ud Vt*sS|;-um V<"".@Qu 95Gl!]Z ʸxTLu^:v׻>t/$jU!e(K{dǒ=wsjl,-요=$6oG}k+R/ڦ+;FUb QkwZCJIMÁPx<׻ZX(2I%.U}~C<xBu5{vޒ3JҪ:_*[F69^_2i W萮ۂbi-@rnj`|KWQsXu"3qx mW7ki6jEG;AnQ+xzr)I_$EۿӰo5{hK[PcI=؜{Vome"fGf9ְ7E$ý6(\bkе> cךxC ףӬMk*w=+zi+R7Q>} 7zG_.5uK!eru s^\??x w![~Q1 * r?N5s̡8(8htхQ^qaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP'<)WQ*`oqp=yOXlt-:ݭ @\t.q^QW03Ē AK/̧ ތoe}5Ȝ9Gi_% ,<5|1JFd|}e,XBh![9k v(s^kO2HEl0+KO xfbuibmoP$ڽz9Ԩ^&[k]#NYu % 2*@Iɯ 4ո.]Luڈ$I98MַǨV;y Lx8SWU*Qv97v^vpʛGҺ_G;7b/9AkW>K8Zb.;n.TWo|JYh>6ЗOeH.mtlIRnK(UpRK4yD#hԺ(#P(((((((((((((((((((((/g}:/6)^Mw6ݢKҼ]r#Llg J7:[Un|&pY UH6G\Vχ84>scKIq`#Ԋ1:4Ѹ#S;* {n0ʲ2b,EO^M;3P)QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE:_|@|O5H1lK3lwrtT+PeMҸ2$z Pm{Dү0]Dcn9\a<5Uzi%ͭ׳iu%gUox: Ŕ+Hk̽늽~όme2[AS鸑W_zOtŲf|%>{:|Ys{ 0^+0 7z=;pkգVV8,KWdF^=8w>ObHyr^jܙz2%j]cse.)$n~ӉUiTV~1=χ+c]Zqi}*Ktc[kd1¢]!'3|':5)tqM2Cj((((((((((((((((((((((_Hv/q ۼ`A ꨭhWBIKMY/ٰ־R]\LPLu"Z? z8?gwInicǞ :tyMd+G# ryZC7=nןd%wϞ/>skoi:\"rS^:`gi .4i`OVYTxIgU?J4/];OS<({tO|%Ix = Z٢p3OxIJT4](P/u /Rxwm`ڽ88cku_g@g$ҿ |;785ڧ~5k&6Z ϕz{g|7}'šhmDHy/)fAc*ZN/ ,vwԤ,Ԃ3cj?x䌌 uwUbWMVsJ%bˠQEPQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWxM%D7Vw?  4I[ I汻yTCen>rH'wW[?$С]N2뷀7)48$`7<sx/ŷIhj$, (D^X$ zK ioH1_{}A`6d ]$IYaR[[O0_3i5-R 86dqz 79 終!>꫚Éux߾ymmc+<o|C>\\"U7D?0r +`j`(MtkTc%%tQEqQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEfM*M7TϵvV+9#KhNmi:ugyHoV?ZѢ=|_VW6|n-p)S!]+VyxʆAX6&2`JIxtl7ܠ& >I?;棫hZr@}u$2HJWq*<%)(](_kCI+ٜW4_x7waf -)~O'-v^ZzvBg|x䌷 }zՏ#?Q?\Io?10/bSWߓ^yx!Ӵ[XI @H,ezJU툏cվJMi1+GeAgUuUKOz|^n|=Ʈ兏&$oBG,}W;_iY!@ CZIʂ3򎼎k+MoMqoW=\ur%*^Nvwɭw=G@/h.5:=>^IVa K,HFr>7<$dU{yٵ*2REWAEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPHJH- ^'o(oe3^ѝwGpln@zz'l+]W&PRVgz>cm2>׸pr :0+~|8_^Z꺚Yc*SϽt^%A2}ms1_H\)y]Jo]̆E#<\?OGRTZPWG)un[I8.{~"9]:Kk)~VDǘܻtE*JIQmQ?JnTB~Z|4y=RS弾QH:qSxG᥶ɮ듍W_C+\8"b`;̨a)Z:TV5w:d#߳HΜ=+m`$qª 35W- (Š((((((((((((((((((((((;Ngi1:}[ey%w'8һ(*iՓm++IlQEb0(((GD-2.78/t/test_data/images/t1/0000755000175000017500000000000014450761210015314 5ustar rurbanrurbanGD-2.78/t/test_data/images/t1/1-00.gd20000644000175000017500000000467513076115434016307 0ustar rurbanrurbangd2,,azL/ 5 Q% v% "ܸ xI DQP7F UTP88No7}p_7O=-0| Z=`=_GK tf=-C|!@I_+`§Ha>>s~32> { 7@GC@~>a+/B /yu秾-'1bǾ~>1ߜ}뿁?}>~MLJh,Vs]}Xח<}OGxA0C7Q-}[Tʲ,˲,&M/@p 8@p (8 (8 (8Ƈ||&GV>l/=`7 >`o+9`7ǟ>X?/q>QN?"o?\sy#_x㏏zIgz]߿&Sx  Omx0 \{ݹFa<ӌ{Fg/;_DQ,'دcF   0^':xiVzw葏+6xkg{=tk-0`;xkz=0߆PL_ iނn~go v c8+xZ0wP#O?U@'8~Gh~h `AqX!B!B!B!Bx[>++++++kw}oT?O?>>~m.|BM_lKgp;x1 ep>M_lKgp;xc``쀙(zQ@!{UGD-2.78/t/test_data/images/t1/1-00.gd0000644000175000017500000026163513076115434016226 0ustar rurbanrurban,,ܸ GD-2.78/t/test_data/images/t1/1-00.png0000644000175000017500000000236613076115434016412 0ustar rurbanrurbanPNG  IHDR,,SFPLTEܸ L$}IDATxڽn@`R5q EԜիo7{g490$%!Mp8Sv܆)˴m4mQ#Q\U._U+T_+\vq+R1b\c*j S+.ڐJT >qa*R+.|\ ڸr[V(kǕ K/1~\`e̥₶5F5 kU.֠2ӏNN\,R`2,Z\ -JXӈ,ѡ]EXNÜXɰhVkaɸ`ZqXaMq[X,HXS\XѰƸ˕ӡhQƸȲ7>"rua q鰒aqYZ,r!bth`6{:ºX?,R\Vji2:ZڬE=du˳\dZr;u:d:v_Xټ!,?#Y'gyF"tYpKYded},:miec?'uez J 2vx27~sV`%Y;b5v۫U)S2{o&K!vZU X{Ed%KVaCn{)vvz$+٢ZY;/W VEZ`V4.,w1VzVEW>kX.xJ`;ldZ"Xru3 %° %| m-?z8oэK իd\^Xfen?z?'_XErTk˪ѩ \EenS8Vy2k z i< 55ĺbc,Ea]p̸31WeX{CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222,," }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( +/Q&-i3X&+2qy5^_y%#Ld!E*z%|Jw:khOt$!ՈJjxEnm;( Hb@_+ d;0م z&";f o_zg|y+iwqg>TpG=kĺ/TKb*RџY^}|3}+#z0 1ےS`Et򖟨%q^Lhsۡ~!tA=U\CѽG8C'/6Fְ~GoEWaAEPEPEPEPEPEPEPEPEPEPEPEP'|Oc  !ϴ.ׂrH냁x8umSƞ(Ԯe& =I<𽸔[Y(`p 2 54Ap;(3W^ ,D91ivAxrH%p$/{(zI&_Ӵ&>^58gnAkT`(j1]OJ2&QUg`I5 Lkdl~9Һ (L #z}=ZYysM}g*OTqڗT2 T|T. KfNhWh-rP+Ȍ(ea#xZWYZ]NraE{XlٴWK9q92Gz)¢ 朇Qȁ$Cz}:ruZ^-)2J? 'Y:][ӟ@F=9?8`mcz(Zily$fK[{Y'Yba x>o _5֜u=?1_5~9Rx:ߪO|!h|Q%bK[P I ?Z?{ cld <ZWC]gzbaU_/(Š((((((((((/i~qŘxi>}[2^=.R%ڧ}=x+ Ww[- *C>ჸWك=wr '󽣩ٛJvMۤ덣#+𝪥L;$s{WE_-὎-~]?31S杻Q^QEQExI椱F}s /=x }L³\yLٰ2@l$A_Vamcw+0k(TG֩KFu4mbc|~ עQ҈~A瑸3Wx:f[ˈ@Z08k4F%*gWoџYOz>+?8 ( ( ( ( ( ( ( ( ( ( T ݿ\ӻЊ6`&mn.%yy$3I{ׯ~G(4t>%w+83>xj4}T)e9]i5R ʊæA#?ξ;kJ>u/nU;oiʃr8csVzpPvZ-݅QV ((+xfw2rFT_x};wP(Yxܠi_۪|+oב»Tdy$ܢNWDŽ?'7p??Z<05UXzy#x&7TQYI3,$g ;bPIkJD~}RpQE2(((((((((b%۷yQ{c5|,rC#*2HU ׷yOs_|+Wo'ªqv`F{kr3oup! $l'}$IRu0PEWQ@Q@Q@x' & +. l$#5uu*^%} HϘv| q20ЊJܵ68 i楹 6jv_fGõy0?<5kgN2KndӏN+VU1kKuR8 +ɂ((((((((((suټP.Udw f.HS={pֹ Z\7 INSw91 Oy٥/ik|7Nʁ"%1 y2$h89XRD9FE|\q0%⍸f5)R}u5F~ Zߤ8&*nӏ-_w++QL3 \{]?GQQ|$ʮ^NN01Jtft+ T5pe_QE0QEQ\'?_ _؅Q`dbA]ps@2@m3.c} IId"kAk_!c5YK}w8,NDk'"ݟKX W{y/v? n 46gev@2N+mkBH'xԈA tkkWEuw~Sxa}_E!EPEPEPEPEPEPEPEPEPEPTu2-gGӦ;Vt`;QN2qjKt)EI8mͼRN%r.A2=uMaO?z;FZMU47P(0P1' \xZ;#-kpq8z:9Ֆ_{7oFvXa=+ٮ18b$I pq2=z eX4?^3 ,gy^24*8XKFzW|Me0]Zr76#Wnbt`p08;+ؼ/L>gx~ǩ>cp7WFjͲ f5=;Z(<;w{YP0Tհ YgGoi~յixU^^W=v8 8|S}jy8 X*MOz]_ȁBG @ '$N=bV>m\=o*ƶ">#$p4`1L:ץW2]RbE>Re~W}?u֫Ij4`01/) ޠ^;XpFb/rO'_j,"[֝wUG#@1ǥq8k?:H"K?!>|xž%]&8/Ӄ== 2Jtcg~}T{[O2̱NKM[Ls/?UoZ]c'/!WWBOS.n]{ɜ8_o/3X%^u- ơ"vF_P\j83^ jˡ搳1ӓUoY]*"/0|,XT+{;k:⣀۔ok}]?|9OjOMO[E%yUXyi'^ .? ?µkW~W9lFR#ؤ(㪶tT|O 4qE_0x: ^q$?VKZ.T-:緰U'Wӥ뽾G-W~|G)fRU$?W]ԼM *,ڼoF_UU'FsbqwW|3*mEe.? ]N L[y!e}+"zKjĭzԚ3^hWNżsTZQirۿdXb*4.ǢQEyEPEPEPEPEPvL7*u&7+GמGC^ i>=Q4-rFAЂ5]s-𕿉l.o\C1_w\_yyĿZ~+1gqry5\^h2= 5iZz88K:zo(a{twdvu7-ڏzOӼ3I^UomFa!_2۠f䞨ܿ8*u5x >{ &#y@u㓞> igzI6zyw~Gv$BOC۞? ޯ>?ƽfqjizeU\c44q$1EDF)/ Vc$B(y<А=?Ʀ2ܯt#{KY?ta _>NZnQYG0Q˱$EE mC]=E t#J: csLutG7F7V6}y-`~?nk/}_i3qW^͟E^[j "UNXCm}^e6y5%yzxB?_ʯϛ*αOkH<7+cO6L~v~ _Kyw>l!4'l&T¯l\]?װN2"G5j]m}Y^űXglDӡ!Fy&f<% B)m:?]f!*φ91^|4H?k/<>wrڷ.lԼ6v0y ڎqM׽ =F.4:IU5\Sbjwϧ#—i$ qj/riNk)R骜9@s-_ T-yXZyZ=4zξ/J5v ($((((((|3x Q$P 6G>הk^ 3\ľsFIf_UNGWxk.sz7!i<8J[|)# t<+ğ"o>kt 'o/G5s¾5ƌ19kM&yL ɷ˧&?kͫ-GynK/fx#L#SyU}җ꿻{|E.\|!e>[8&ƗuO^ ^? ›i7l{V?Q: d(((((((((((,"C#\ZR2L\W^ !^x{Wa'Vn*KY6G5`|g]t:|Mhr[_GtTzV>6¼'MxZߕ 鏍y?/y' y\!l?^[__;/cnKgxcKΖ`LLG8#޹frٹhxK~m` ;NskVrE|쯩.1NK= PҴۯb<K}s·5cK? mfƸIFqz6պ9~c.h:]-elHdĽ|78!qFFFE^Y9]z7:nw~fwg 򰐨*>ý1_'gQW?&OV 2Kce~s~[+>_¾y|⼾ӗ%oÚmY\K+~;U_:iQar~?uo.;'fq uQڸ ?յݗi>l*U)SqቅZRQ}XKi+R7uW3?%s(m6K=`1ҷ-x~ǛoZp,|ǧ[ž'WJ<${W m-5q#L_2y'urD 2e,'s^srח}UQRckmb}J).#ʪNA?JIuiE;N XMq]2:?i–ѿ;vfў-|ϑ&Q}~"N|?=O$դVˮN9+ng ^\4yЌcU5_iŮG{:u ~m,BdR\ʯoxXU_HYOy%z$ V_:$мRkGR7Xo3?%FFJm s}HJ$]bK-V=&%[Z#'5?fu|̀3xj-(45Toƺ Nuŕ\鐶⊘UF0cC JJ: ~ 0d[&>Q]QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU#iecٖȉsq/r=FBM-6^8?(zJϷ#ӛ yhGFBM-6^8?(zJfZ"&m̼p~Q^}?.[̻ER:6Z:mḧ12G#zPtm,,t2?0.cn>eGve*Ѵбl@dD9҃iecٖȉsq/r=oG7˵.TfZ"&m̼p~QK- 6̴DL ۏx=(~?=9~]vtm,,t2?0.cn>eGYhXe2"`\|AEn˴U#iecٖȉsq/r=FBM-6^8?(zJ/>ߏNokw-]K- 6̴DL ۏx=(:6Z:mḧ12G#zQyzs|[o2HYhXe2"`\|AAѴбl@dD9ҋϷ#ӛ yhGFBM-6^8?(zJfZ"&m̼p~Q^}?.[̻ER:6Z:mḧ12G#zPtm,,t2?0.cn>eGve*Ѵбl@dD9҃iecٖȉsq/r=oG7˵.TfZ"&m̼p~QK- 6̴DL ۏx=(~?=9~]vtm,,t2?0.cn>eGYhXe2"`\|AEn˴U#iecٖȉsq/r=FBM-6^8?(zJ/>ߏNokw-]K- 6̴DL ۏx=(:6Z:mḧ12G#zQyzs|[o2HYhXe2"`\|AAѴбl@dD9ҋϷ#ӛ yhGFBM-6^8?(zJfZ"&m̼p~Q^}?.[̻ER:6Z:mḧ12G#zU-BG POӗU}%*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEGD-2.78/t/test_data/images/t1/1-00.gif0000644000175000017500000000553313076115434016372 0ustar rurbanrurbanGIF87a,,ܸ ,,,0I8ͻ`(dihlp,tmx|pH,Ȥrl:ШtJZجvzxLannzNixn{Dm-1> Nۢ"dJ ( dKֶˀjV;/S#'/pz2[%k 2!2+Dj&+ 39;DokH/mҾP,sƸ RrV4]K\8[|mk, G&M|3p8s9񠽾S^9@:i;ӓ+y=k7=X~7"ȓ!H F"h0 P!{h£Q+ o.p|Z%=VZAmRN3Mھε+pڏ浬 <ڎ&tu}fZVv{ >{`jT v-n[Mv3 bp[p3n's;ַӝ[[v뱭x+'8yL\eF#~q~C'2'g?;vnn:֬nKo;6[r[f}rK5ҍr.z+K[t\::؝u0G>{]aoq}|/??}I]ٞ[诺3?=n~R}oywg ؀WwN瀵p 8o HhWzyxz!&ȁ%Hq#{+xzg1Wx7x7ԃo@B8DXFxHJL؄NPR8TXVxXZ\؅^`b8dXf li8k؆ojȆu8xhpz(w}(tȇy8xh~Hhx38Xx؊8Xx ;GD-2.78/t/test_data/images/t5/0000755000175000017500000000000014450761210015320 5ustar rurbanrurbanGD-2.78/t/test_data/images/t5/5-00.gd20000644000175000017500000000604013076115435016304 0ustar rurbanrurbangd2,,a6 6@ Gn R1 m 0x[0 i|GBW C&n86_|>Wi}~OwVcsç]Zu۸ /׷޾lcCG*^Fճt<WM/~U$&q*?Hh3/`I@ ~%*ȗ_!g8}1Pa9yvo/oy|3םSbygHxnԾRV />· ַb]|Wwm|q~q.>') /|GBb|O|~O(}~OÏi# ? ̇HX}T?Nf#x[r0 PK3vt;Hm!1FGdLp>nϗU ~~3v~+>-ߥ8s;(m/YmI>F]X;w?eu` uUc_~H]H1>^&433;QRz=ݟksHw,Wk_ p"~A8'|5 hv^2\mf,__n0}szfoU bb\oYoX/A Y(U0Q8{\o[ojP ` >XンO`#侭O'm}jA W!"Gx 0s |΀Evjۼz6{FLx 0ns6Q6;d |<:)\ē>0S`>J@>0OLCi?03 yOd| R~~6 0 ~* ????? p`Y/_@S/ j:_ X^a )9iU36w{ {{wMD9xY0QlόH$6r|WrgqܤZ$W.~=駽ߟZ^t#rk6|)w_H`'\iy?CΏ.W`|G*p }Ǿ&WpK,}g" p L}>[_4O.}8ؗ pξb d0>>>`TPƇ >P'>8O| 0SL:>38 P_P'_P_P_?q5xQ C_z8v06Ť6vq!l;n`#@o0'csɾ-}D<{\d yYҒ kxͱ 0,MQ׶~s~>j//-x 1 ka+$9j}Xgui>}c|է tȀH<>wB},֚lxc`` 0#JAP A qjwo`*!%GD-2.78/t/test_data/images/t5/5-00.jpeg0000644000175000017500000002462413076115435016565 0ustar rurbanrurbanJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222,," }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( (=>3kZťV5˰y>7(hih}ެy~)\|=3;:3%4niBWirr1Kp>xmm常8` $Q@$i6!̻'v# "WQ_+I,Fs, 2s]3ZEǟ-֤_LP@!rx!K<7ms"kJlXIUÒ[c^_Mqm+O@ Uo9 Ak ;(((zvu}2Em Xg=iAbU١e |!@sҺ-BM].ESM]N\2#h۹YHꧡ4_[ tȷEToS) H9vVGd`v:M[;\$-QE ( *~HeF˷r;#OBiyjPXo6hdH(P~r9)8[Ur^;hCs*qV)}I\[Q@(((xmm常8` $Q@$ԕcG;*Pi!f2U 5><};sa~qd3r~nu[aO -+y^{=`0zE"ϖRp/ TP=i=[} ;hV5-2B39,J< = O5=F}>qtJ Ļ@8޸qםqӒvM;"*mnpqӞ=UG3;YQ2K*y#`\`tOT,tM2RԮR7+Q'$ɯuU 6qX1LL [rFUELa*~H?|CŦA +J?2%rg.򵾕I8BcI#=qkt ;2^#ry}>Ǒod.ʣ${j0{>Dyfֿw=]-}9UrWf㐪':y-~ѥe` ;“Fld~尖:QIY5~]#8˥r|N.ϻo;8,.໵;&A"6  88 ¬W>6V;&դq0E02H _K|7nS:sFwrp⧐ ५Z*PV-5ўbi(f_" jI,S*" kT'FI9$M؄$t㩞xyHK$Q@$2QKnmɠ:6*eGs5s.tRQӽյ9Gky=KC,ZhsYyCę `כA3̲ʌQԨ* .O c5PO{im$q]C}Œ@e^:/ՔwIJ󧭺w北7~mA%fI%hʳ<23I]v9t}5ŴrګZ?/!w'zJ)*{yw沷5ۦ2KTm!fTbL!TO@ m5rK @E#H kD7|2?sO<1)y$($wZ\d m}|9.n'YCy kփ͂Kv̒Jѕg *xѸ2v4ss*K 9#`FApAJ^OS||^[gh%ǰӻtqqZ4T7^Oڮϕa͐/#tEV881zE''7Ԟi@Je@B$;*G*;$U`J6`2z{ӳ$)QEQEW'j۪?o83cWR袊 B^}ܞ]M4ϴ8V+?mKS>guIļs9'g#( ]89ݎS=K. Y=<1lgF@"4rp>w*Қs:A{s6_}QE}X#IxeJ+Yr3b:ppk+ERY;fPrOקb%BwVkj|5]oq==}>;Idphzm'nqjFPTڱ 2_Sӑ_Yv/2GD\_0cl +B|#cxwXtۙ-|3!B8 A ;~,u4ܤȧ *p3ШTVks4? }L1<KXԳl9 p2N0$ $umBie}6yl#>v@H B)WyEmGnO˲qy֟_۾m/7WgXwZӤ.-vaɥL(Xar\)NRP_OO.' 8{I]>iu8]>8#hY݄e3j"|?mIZ"Kgs xVG!Vg)P ?sޗm=卵֭IWh IS9Qj1ի_Wep2GI>na|Gvݿ6/~66+Qլ pE0ig;)vnHC,W5,KTVGQsWOV]VH Qj (,E-!-Lrjh5e7֍auLl +x:|[_n]..0<,3C,60$sѺ VXQko:LʆRnSEYVUySGpǚz춖qMCxlĬ%;.M;6I>P1Wmt!W#Gg*nx~@g*;eQZ(]|]pzƴj8l^`V6ddJ$9^km^Recs|[BH휂NT;[K~_ :((((+?5}_nKfQEy'5DŽ5Me۳E+2H^p\ר_iPɫfkZg,$sI=y]V7m3V|IQEQEQEQEQEQEQEQEQEQEN Tz(j3h;uFk@JD,-MO{~%kQn5!91099ʪx8$DP=+ö~!Jĥoc$1Щ]d__QEp`QEQEq~$>dQC.z'9G?ZEMY`rOW;?#ֿDw.!R{I[_.(_;lz1OCvq3ϵ}u-VSvgx<6H4?8x{H׬W͟f4^*tX!pA7 sbVNIGxQEQEQEQEQEQEQEQEQEQEW'j۪?o83cWR< ׂWD2+;$+><0'ՒYQg"V` ;U`OjH|(s6NUP;`WU\τWM\t?NᨥSkQErQEQE ݺKc)\k-WNv2?JAl-y P$^MO3FGYu' Oޣ(V6gO:y$Rȉ2Nvzʧ}w_|oz ,q!yP3PYuQr;}_QEQEQEQEQEQEQEQEQEQEW'j۪?o83cWRξ8[|+f=ZKls"E OMsΧWgWM\A-D{ +wiSŠ(S ( ( M; 0<noTj )..֔gQH̰ZTiN+O(ѓsɫg&˕FkQ*<2kŪzRz?#ѴMσ6}W aCǣ*|s}_ |__hQEQEQEQEQEQEQEQEQEQEW'j۪?o83cWR#vW H˛ 76 2xֵ1;jj|C᩼aSn|dzҹoi_AVɊ m=P^y2eaA"yMuGp# :xŢ+ࢊ(((m62ROLZ*o Ҏcmzd?ZLٶXf}k86[e%`~Vz==cn$~?ɑD*1ב^⾗OVdڕ.6e?LWWyEPEPEPEPEPEPEPEPEPEP_n _uJ[0>+5>q4 G[ۋyd&d$1@\~zzdk#`=C~|4,FymɈhuL3p?)<|#57oy}xkJkTGE䟩Q@Q@Q@u!rpv?+kipgbpI7LCqnO\Uƙ_ZʓBAASzz|ϸt"c%~ hxKI @ZZG@4F kb::΍c[w Fp}M\@(((((((mwGMFM9[glnHʪseEPEP_n _uJ[0>+5 {㇁'mzgNեg!U>pr>bY#/?P oG{_kO \e 08 >I\M\?CmJ?֭`z {'Z*}G9ARtFJ͋:ʟlVg=]5BW^yr(3邊(QK3U$)ku;u뤒Z4eV\,ʖQwMJ\㷶VDBN2I8]įx#VK5gGmS 럔91ø.KkGAvG’,Bt7u"%vkrТ2iPEpePs؞GZ}`!?'W*]#Լ.\2U`| uf'Ky2;\>x,V2˲U<H>h؎=sQ@Q@Q@Q@Q@Q@Q@ssj/iioՈ, yb01228$m=%yޱm[xN_t5"m`i.]Gt%6K((+?5}_nKfQEyEPG|5DIՠ-Yxxtt=g ^5a/Ҷy.Wf"d3ʜ98ZQW :nRGwwa~3+ A %z]%\4X|YW3NMq-9]C,>.Iv)1=a! pqk)OXSEb#'Tԭl3c!,ïJ>gV=nXV1Þ6H﮳/$z;緦0z牎 GPgݿuRtgidpB~gǁ2I8dugZ\[k!dh$9'$;sV ~6&m^LF9f㌓qZ妬bkbj{JQEfb|wfGŻ-a-HU,&01P@B_b_[zueI4/8<:vGj Yvxrs.O#;E+euJmc?4lGU\tѧ.hfՙQEX((((((hwڇ|?ir \EL߽E_8mv:_;]_]7i%"63J m%s (((N U|~pgƯ-[EQ@Q@Q@Q@Q@Q@KVH˘MX|#빀)z>'=k]O#UeyO GdwMW'8?Y%դe&VX)PyuaI>Тxn⸷9$l]H #ԕ@QEQEQEQEQEQEWK@bví\BLK*GV6H7&ĹqX&oũ]$ 'vXp{e-p0EPEP_n _uJ[0>+5 ( ( ( ( ( ( ٵ3ň6ӔH3󈻁U_W_k.Sг<Ԙ$t4.Y5׾X#O;X2qNA%|:ET-Gb,Y`ғ{3 ( ( ( ( ( ( xoL|s`M|֘,(DYI3v 1ۅzpqw.Yfy=]X#*DnضeQEQEW'j۪?o83cWR袊 B(((((((/#iQ%:4¼d2u ?:2 ặXTeu# 8 s_4~Z?|Yj$w֦&0$M7$^s__|2қt~}}eEe c 1dIz4yEU(((((+GirxH\Omr-q*EpA #p7PPķ/꺦. GKx ۴(D EhR_vZ;( ( _u_`W'j۪RفQ^aQEQEQEQEQEQEQEt~4J>|LݞFp9z:|TiS^X2U G?= uᥣGQEtQEQEQEQEQE^ZꉦZKi<~Z?3,N>TeM)monQXw%cʂYy]DHKsF#1 f;nQEQEW'j۪?o83cWR袊 B(((((((i}nVL3ib– ƌ t-^e?d-:\r!3ȠUOO4.YKc{E5FD(P' P#|5χ$i 2 *RI =rs#=;^QEQEQEQEQEW/oag}& O]Iߕa}a$E86TBnA-`mW<;wy{1oQEQEW'j۪?o83cWR袊 B(((((((Y[Z}ͅ~eM ɸ V(<+|*ZI{$,M-av|@h-x-]URX22v~"{) (#'?_ve>tz>v~"DG.\'?_vh;[=?WPDnV#ݕSђ8/6kmHчW(Vz`b,zx^iyo%0 Ty/}nmn4^c%P:v|ޡX*:utl2>ˢ+bB((((ƞ14Z%̒wXDIӿV~hߕX9n38=r |YxNԓJm[xflo/H@S)GqUl,8- ;!1.I' 8$ƬPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPGD-2.78/t/test_data/images/t5/5-00.gif0000644000175000017500000000615413076115435016403 0ustar rurbanrurbanGIF89a,,!,,,0I8ͻ`(dihlp,tmx|pH$q)L:PsڌZX u[z^GzȮ4mK{}we6 3-d5 1 )D7/"ǺȫǫŔڠ4ӻC츚{B6zXJm@/ !'rNTFVD%,&AD\jO#O.;3cGz7*魢F!\h9)Yժo8iOWm_~sI-1gqQv.nNtEk 8>D10ƍ?Ld-{e9`ΝC}ZtMoF}c0 xNص*ctC1D hm\ؒʙܜCuف>pyzڱc~GDw|^xDGB5~g߄> ^X߆iw!w *`{`3uh!"@e&Xr ע0d/r}NhcLGe#GF')ݓ_MF#(%UNCUdGIfmdߠIߏ7P-_/CggrH"um⥞m*lZuʨ]iliz`ʒ6֩ i+hKk2 rmZY`V"be^Fn(E- /P;缪|-[*V+/+Kq gk`D|'r3mJ:ۯS{,׿7]?;T<*X\{S;OO}wV~7?o_>ֻ|?zQj?ˁ|&@ ˠ=yp3D6vh9a|GC-/~b. Qy| X|0=lah+bE`$K2 a!tmэ*9HG1wxԂG5nym 2BT =ҐD" %A#7I3R5hcXJkE\%+K+ `y咓^$( Y0YhL`z}4b&GVF e)Il~2Ԥ oBa7iNtJ3K$9Lw4%ӖJmnl=99Q%f F&td$9iiҙ/hQ1'Qi˖u,&HخiU*cXwBֳ Zhcfs=jD+=e$*V]nh2EgbF}-l]6=:{3|mfyWҺ].^zGCj_h_b|΋W[6#A\pKC8rT`{pt dktK˻']+Iڔ%sa,ּu 6#ɶnw6'?y~޹ pZoypJ-8=k\ϋ +vKnr} Y([~mb)|箎~\nD/:+P+ӟS0TW uO=Fs/':Y=f`.;u#Z{=tkz߻*/ނ`xG<ToCݒ\/5^\|3v}Is|ؓj]~}6;z=}/^yӽJO~YOkW{_+޾1nbzY|W|+P}܇Hr|̶~}|?7w*m/lȀ$3~8z)жg@XsBx,\2xFyc#S=cG(*ȅ_q$ׄN%8헆OgnxpֆuvI,fZxdhqh&FVH`2syqvtLj\'3RSa>~([x'({(,x({؅v*h}h苷sɨ(؂t؊،x즍cm)a(YȍȎ(H&(#Y"눍aw9h:8|8 ,F@^xeɏ6pKI,ْI[H`hy}?u.w=vHJILPR)lN9VyX#\ٕ^`b9dYfyhjlI] ;GD-2.78/t/test_data/images/t5/5-00.png0000644000175000017500000000356113076115435016421 0ustar rurbanrurbanPNG  IHDR,,SFPLTEogtRNSv8 IDATxn0`{$U~Wـ 3X%ishJ ߣ BbƂ%IUB=X wR=_4mA3=şV+=O*f1%u,ugvyY2 ׆5w|_:5ܞ܉PqP @b^sE HbEA4Pͬ?ܿ\(M5zJsOa'FKWM7z*ɦR%5z]k|^Jd^r)2,c 7Vo 6u]O?Mi'bϓsXVd+7=&X OV'`*֚y\CﻅOOrkc2Lrb:@Xb-hKsm{#6F9Ybm%DQ#?xtX6y9ВةBp\ZQg9Pɼb 2T2XJ+fC5h| +1ׇ|'cO{E6nVb+V" S϶M(IENDB`GD-2.78/t/test_data/images/t3/3-00.jpeg0000644000175000017500000000411013076115435016545 0ustar rurbanrurbanJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), default quality C    $.' ",#(7),01444'9=82<.342C  2!!222222222222222222222222222222222222222222222222222d" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?iWoi\\>ȢNdxpz=xMa1o'BְYb.HaSZФ&vrF:߲8}3lVs]mrYd*<88l pxM%4gv+FЀv-RWkB[?4 :x Jjf^|Dܟ!hs$:-x}XB&7R"(w!`/lD%HQ!l]])#qo,y98ÿ)iyRo+.H_*v.c<7JFAdY;85qtcLebSk"yc*ܞ25Ek uU_0?xz;w?ԴKF[}SO:u DrF@`2ϱukW 2(5 0<Ԑrr6B'smw"O"K%m!#0sw zqpχ8|Pz8:( 㺷1y <ҋ9@6up$y XoỴ`T/, M2I$sUI;J2n[`+(((X_iN\ےE<WdJӵk[qBVŖHmU$ ~P+ƾ ѦѴQi~#JLXW,gn ~1!  K|S.-5O$JsXu#V>cu1++rLu|t?>Y4m˶hx+Wfqmvggu4]ފ@%D}jGD-2.78/t/test_data/images/t3/3-00.gd0000644000175000017500000001362513076115435016225 0ustar rurbanrurband2GD-2.78/t/test_data/images/t3/3-00.gif0000644000175000017500000000044713076115435016376 0ustar rurbanrurbanGIF87ad2,d2TF@(ʶh~rL_( E,M*Vg튝Lg*1ۺt%ҮF~ӧhx3xPxxH(Y0gC 8yiJz"ʈ+kHk+I[[j6LlL\ |< yXM(m-\ o"oLc/?~ˮ_'s$PEX#;GD-2.78/t/test_data/images/t2/0000755000175000017500000000000014450761210015315 5ustar rurbanrurbanGD-2.78/t/test_data/images/t2/2-00.gd20000644000175000017500000000544613076115435016307 0ustar rurbanrurbangd2,,a64T  9i m x[0 i|GBW C&n86_|>Wi}~OwVcsç]Zu۸ /׷޾lcCG*^Fճt<WM/~U$&q*?Hh3/`I@ ~%*ȗ_!g8}1Pa9yvo/oy|3םSbygHxnԾRV />· ַb]|Wwm|q~q.>') /|GBb|O|~O(}~OÏi# ? ̇HX}T?Nf#xA P*L^ 8뺮뺮뺮{}8 p@  8`K|*`{p'>$>`x|D>r?`O2gޏ ~~O}7#mü~]AG?~?<?8Q/ *x  Omx0DQlZh vegu)OLSe8/0sE>1O 3\>?>+O 0ƀ~`)O,>!&5$3fo bkłu}!$<N 4jA3K{t P~V6dlWP| #ZCioe4#_|˗/_|d\_>}ܻn?\>[qcuGK˧EkE[=oty/~G@c5 xێ еUt%`,g`עbl]{?:_O7@"RYRE_>Or?n—ڧgk6ncJ_m/_?K~3uKLҲ/M }'_})lˀO볭/Z|_ |V||2s='˿~>~ 4>2> p/@ P>*>0>(@Z# !BF|D>! +`̷G0 1 "&||@3eX}Mx  OmxA DQj݂u%SϪYQo;X3/HW:?GWiZ~E1x 1 ka+$9j}Xgui>}c|է tȀH<>wB},֚lxc``Q0 F@GD-2.78/t/test_data/images/t2/2-00.gif0000644000175000017500000000561613076115435016377 0ustar rurbanrurbanGIF87a,,,,,0I8ͻ`(dihlp,tmx|pH$q)L:PsڌZX u[z^GzȮ4mK{}we d{DhV@C;xRb+› \ѓ} b}b[LSOߔ{D=* CoBk1A\P#%|=NHG%M&BR%-Q5S~ْNB1}ZP"JhSK*5UVv| W7_k֜fϚIko-۶Bn+7LO%k_D2ܔpaz|er2%l3ϼ*Ɗ9sB z5!5ڶ]޳?.unyc!G<5Sױ]Q}sy7Q}wSi iSHP"!c נQGFn]\hÃD;E/'[+؂lc~6Rx[d Chd)YbN8m*(>*kjj뤔º箩Iʨ^OjN8F+ʚj鵼>#♧JP R˒:K*Bn+CR0 Wo{oYW,mz_ȶJc/pr8 21O1, LW RRlHvzfO|sT\r@cLDb.o-C[-,O}0mh+ wt\ ݷvs т^7y(.C3SSM&8;^s>難py{:d-~+ /^)޵3|Ռs7?c_ޯOO!G&׃o>λpGK}' P{a_py. DU?eP3!jP$8A!~[ BNw2 kh bF ;RK 7djm$TH$ojEJQz!FE耱NJ\4`ZqMغ91v, 8.@ $H>EϏWb$G #r#Y$"B2,-7fg(Ir"(xJN`]Lܥ-I=J+ "0]X_ &+WeLIA3&5(2rN|3wtBB/\Dl)jf,f[nzLd Z@ ~F̔BLB/$NBR4EJH{*ZRQJ-JE4I%4SxiKEhHԧiCqjO:[rN*541QSӈTC5iQ-XkXźSALh'V g\sŮr[ٱ׫֯]a)fM$ _JNmլ]ݨFjIuc=M(eDGkXTuw]l+Y.浳iQ[T nB:WLo۟&Z.mT\Z=-f{N""wK^;0oy{^Ln{@],#{_7uo_OnQ'8 $`FpzOni9DI)jdLI]џؗ11D;fGm(c8q䥦ثd*9L.`<,k62u#k<w|f unDhH+iASZ̛==P+%e~OhzaEud^ k(upo\z<`5-G2djH{k5vbXC=Pkn j@{;s{NJfuyso[ߎPCgv:>qEi }nG3'׻n;=/O1>r@<杅t'=:K6Pa#>Dխ>jK]M/G׽3}c'clݽx=;}gn$nkt{>xT~p/|oZS[P˝xz#K.DgzԧDz<9{{;a~D{#'~no)a~z~7>S.=׻mk~Om}|o;[E57~gk2|~~z\  Ȁ 2VG~~8xe{_WE؂x)_Te'X7xi9 ({~(:SWWeH J؁vG7|FXA|"8xZ_^*8N\d=hQ+jhg88w7rXhhw@XDŽwiZ8'ElqXG>MZ򈖘~І$fL}'M&$ƈbA%`$A":Et"JEfπ抣ȋR!l⋛t(H؇mF ;GD-2.78/t/test_data/images/t2/2-00.gd0000644000175000017500000026163513076115435016231 0ustar rurbanrurban,,GD-2.78/t/test_data/images/t2/2-00.png0000644000175000017500000000313213076115435016405 0ustar rurbanrurbanPNG  IHDR,,SFPLTE1tRNS@fIDATxۑ MUf3ʖoQyNuƒlo!,)?D_i,)d-r]0̹k#4 u X;祺M4ԛU!\1T k1Qke-F>\u5 XP̼ՁEopJj.*)+tV TB.xQ%\`9P7˅To2Yn-z6Xz]֤6F K /\do.P,'+WekEh,XG劲:YrEYb,W*֙yX(,S\:Gq-W}JQ]\XYb)b顚yL,OUQX(bd97-3󐭫G(B!Cm]顶CX取>p DKE@,dPuV.Q P|. P*pŽbRYÊ "xYw+-(Ɗ "vy,ؙ`VAw=AIXvYr,QE!-}\p; KVe%bݴKTe%CQ,?bjpH:`%b3_S\/g%fCV j#_LE.^j}fYնSjJ袬z.-OVY0]Q,B=,d=4lcZqVk ]\{=pC)*ϊm]{Q/ k6X?+.(..,Q-?+Xq嚕,0@ԎUgy˥>zZf[5ۨoքaO;UXg$eP~cMVfk7rΧi,e R๫yMRwlaU{ dYO5~VXCY*WTx/ײ&eysMEb{lHj(`YYr`XE`Y"EeJcX`eX9rFݳ2H.G.VNgM J{jU \ OjUfݬ\ӭTa1H..U*2gkXEv b+1;\yaJb+rX+vXQ`EkU`YB?(3\b*kSQp}KXQxJc>YQbY'd,RT+\w,NXWs,Ngi(9H#\"H,FE(+?\,=5TaXQIJEdYQJVvi,K1CYeH,(YBcX"\$j%6XM`X`c_B(Y(IENDB`GD-2.78/t/test_data/images/t2/2-00.jpeg0000644000175000017500000002303013076115435016545 0ustar rurbanrurbanJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222,," }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( (=>3kZťV5˰y>7(hih}ެy~)\|=3;:3%4niBWirr1Kp>xmm常8` $Q@$i6!̻'v# "WQ_+I,Fs, 2s]3ZEǟ-֤_LP@!rx!K<7ms"kJlXIUÒ[c^_Mqm+O@ Uo9 Ak ;(((((((((((((*9[cHU I9I_;|cү5 ֞fc/eP J#[mOC6wvN#8'G^+?hm_Urҷî<'\gq'n*yn ZB ub]&="(QEQEQEQEQEQEQEQEQEQEQEN Tz(P׶nsw'mmM3'j(%'zU㷏Rυ4l9E)q/'r WNr7cRrCByO2Lp[Q?4"=2=Ïʷ΅g`)?ux=\Ew ~ù*b}EoQEqV6Hh'GR=A= wJQlbԖpٔC?,~uXP՚Z!?itg@ 2jtOY"xIv91oaG~' IՕ[ݒ Qzv5_p/}z_? Az"@Ou?c⋿O>-uFۏd I#3+>Wʸ'k)ʜ;W J8->'TV~m{Lռ'֑\[lށ83Z'HQEQEQEQEQEQEQEQEQEQEW'j۪?o83cWR袳F%]G%צd7Dh*r89HbHaBd+!!|kތC8CBvQE}QEQEFe0~Klkc]5gn?x#\+ZqܸI%o~ȸ|l꣨I? oq@> Z9MIH~Ϛæӝ4۹"X7f v^_6~͚xYc.,ñph*1[['^ ^')F*JȬ8TGpHlVIeDyY.r6V8=Χ#WgS=;U@r]Us>]5r_;YMҘQE{EPEP7vwi, HrFp{{uشa\9G +*Y@sׯ {6.X|BwM?ϋ=bMf:2b l*>zZ2_?0ٝ?ސK"$:J_% 7*|ybxm-/<ą@AfG=H~&zAEPEPEPEPEPEPEPEPEPEP_n _uJ[0>:eouQhIi,@ẘv/?I5a:ƍ^͞]5rQ3+\g?OᦞYNS (Ot((+6[$<`~uP^x0ZQ%E#2k Ru8>LFOC&U.W=F`XɯxkI F7>n#Y^`77}=|KJoO%}_EPEPEPEPEPEPEPEPEPEP_n _uJ[0>\j^-#.nl'h(rGZעMQ9_һJ]+S[_&+KCn%dBykVWPA |}5}l4=S(낊(((]65I<>YAi=3kx}7J96k3fb=99jo⍗gA>q[7u=nZǛXt&G>Wy^Do{^v>kZK}jWgdCڼg9t1^^iQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@|~pgƯ+?5)lފ(0&Enkwn-4 8J'$F{-q鑯H@_L|Axy&#-C e0 awc*Gk=SgG~'kEW~QEQEQEW3[eԅ x? "IGjYI'Ws -2WLǾ}?qVfmg'uk*M kNe6?> xqĖϷ)=-'H)IiiRp3rFNryP:5n,F+` 5rŠ((((((((((?o83cWWꔶ`}oEWjNΝJB&||ijG^~ޏi HMqː@`pAWN|~h۔1?{Zg$|OU";؎7.r:iڌ: 8t'?\ج?#{9XjgQ\gQ@#2f 2I8R)vKGI$=ӮhʬQY,RעʚƹomK 4 dqһ_ "G_*|Ӿ$&cA["b2y{noqg?ľR1}iZִj9⒰QE!EPEPEPEPEPEP_n _uJ[0>+5 (2%k)v»6$1TyҊTqt4Z]>6ӼM˼ qeu Xdrf/kb-g12Ə*ʸrkodwNñM1 sCYOJz(C=?*k`P9c~zW_a7K_Z;Mp#?< I${?r] %Ψ+@i&I9! `Sn°_C𵡵4,oP`7967dg׮4-5d|#[SW3ࢊ+3 h?xH#n8#I@`p1%OT6Z,>3x+Qd." ^<9'*?-z4ڳ=O7`_XZ襭4 (G/- o%G8Przv 6>+|Vik'Ht.G*xoZ-#qy{'$ҵԛq~$ҾJ1n+uU(T(֒etVQEl`QEQEQEQEQEQEN Tz(P((((((D3O ;fPJ6ҹ_Cdv$wh(zѲ_3PGe?D=O7`_XZ襭찯>1xnPI]1][62FYʪddWп[o/5m|g( #n;V%a0ݿ ֛PpWo'KSl87# L<OPON )%Q^aEPEPEPEPEPEP_n )5u`+Q^qxm=Γ{||?*h<̰h0 <;=e>.K?@#j|W>'񷈼c_Ce8︣9ڽ}+;EujiZU/gŽSv,yb֗խ9试_~1l,ww7$|&NH9Mjݟo[y8!ݜ6r#vzxjw邏vqǧoNQEQEQE:?+;J`lpꋵ<t,)%u&?0x:lLͿ?R|:ET-Gb,Y`ғ{c;^cqv6pe*XR<#v̬d?*u04zYNe!pvߣ>L袖 oog_|/-QEuQEQEQEQEQEQE._›S8#GJ_P uZ}fegU,Dr-뽢ɽŠ(EPEPEPEPEP|4R@Iy^h2C: AE}[qo,sA*H2AG9?h,5tH;Slw&囎~W~\p_9>iM?>>21sԘH$=rfos*QEQEQEQEQEQEQEQE|M̭oF[x}EWjQEQEQEPֵ?úDq{(6g۹y t|r.nSP}춙Ww[0*LӠ?<}} *NP8U-AW [K EϮh,((: k o%vOuEVU&CP#g8~"6ziqB<DPfV#E>n巸&T)$r(eu#x  >*FҴ) J,*Q#ĉ# (I ( ( ( ( ( ( ( (>V^^M̭oF>+5 ( ( 㧏 {'ʿڷ,rrO翥zoů)>Ǩ}Z?sn"yT±޼s_#WNL@_/˧x8_3)ˈ9y懡7#W?:9"kgOX S}OrG[Y[ܗ/.ko(>\((+A[k1**jvd1f,)blhO_|=Kآsʷ*Rc?,U\>J27? YY3[DlHOE 2p1{8+ٳ_aqrF B '1`r>SӿuQ@Q@Q@Q@Q@Q@Q@Q@?_+ѯV^@{QE嚅Q@V|K߲}_1=;Pݐ2Z&-z[\}>^ѧCu: 3t>I2Ea!Ti69n븸PnO_EﭖgMoo +5IN{_G3觮V?E=xQm7S0a% ~L( ((VsawmsC2n#r0!G#zU( ?^K5k:E+(c,G}_,~ i:WU#TV.̤y =_:/̺/\2?c3c'\φ-<ߏ#q{Wa\{XJRKyhz맘WUG3觮V=+O smmz@ܥ ua޸i#?*ϥ#'?_v?e>GQ^G k/;G4O߈}+|#@oEhO]Ey4O߈>v~"{) ?$#F*٣$p>_P+l>/P$$XoUcG.,5Ky8a ԩ#2J_hK5uBWTt:)(٢d}EVąQ@Q@Q@Q@Q@Q@Q@?_+ѯV^@{QE嚅Q@eZ~W7/uec3˖6~@9i_?hׂWuh-οM\ϟ8Kv$'=ZTr~ǗV N}z+g% K)뒮-/觧CD5/ɟCQE'EPEPEPEPEPEPEPEPEPEPEPGD-2.78/t/test_data/images/t4/0000755000175000017500000000000014450761210015317 5ustar rurbanrurbanGD-2.78/t/test_data/images/t4/4-00.jpeg0000644000175000017500000000747313076115435016566 0ustar rurbanrurbanJFIF>CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?((((((((((((((((٧oDMXw0@}k֡e}oc7R*\EWhQEhk:gEvwvݸIv'g3JϯX,XEeigJ) a"=UGP: z((((((((((*{kfu4[[4胩UUE tBWM;­^]નT`+E(Y#wi2F>nYT7fH}k­~{>믮ݑZa|Uiw "{{ $dCYu|+?(xz]wg]Ҿ =#QNjq ?a^_GҚgVk57nxǓcݱQEQEQEQEQEQEQEQEQEQEioE _ EzαJ1D{8v-hK/S?U(/eſ ?%~Gjnf?aIrzOm6kw4a,-渔19*PŅ3du,RLdy,eA=!Xi6RNrݚ%ch-6kF&%W'%Hhu"q?C}PQk"ē $r$yUc9*(((((((((((((+f_kWWC²訨(Osyۏ/ŷ9VslOM/hڣ4~EőE bx1*ǧp(eg-Z,HP`˹ :w>hknͮy" s$gתKᧀlƺ%ZH9}ۂ WYxmZXk;!E$Am"Q<_ޟgWoKVd}SG+,m4D<"p'N|#CN?9 :' "⫖NrܥdoXGTstOET7N|#CN?9 :' "}۞n巸&T)$r(eu#x 1 >m߇ɽl1ޱ\Ӣ/*N|#CNa;3> )iu 0HRv69 W9_i/[oqMh%BG%,` `;W]gͻM&OkwonǒTeraZIJ*ˢi-Ս2Vk+7\e'pl3T+((((}?6E$5;w*XY1PI=&ۯ> ^пI䯯n$Ӽ;~gG>WpF:#WWO4 (((W,H>zRU4JYrSo*QEŠ(((((((((` F_Oϟ4ljn(ȒXXUIJ Huw҈+7?|H4ˇ X)`=>$(459r~w9Kc|>&I^L4"MNl_϶Xa@QD0o k*([_QEQEQEQEQEQEQEQElXĚevv m-c`4\N OV?; z f⫟:NaC^?; z f⫟$y%I$Y$I'tQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@GD-2.78/t/test_data/images/t4/4-00.gif0000644000175000017500000000161213076115435016373 0ustar rurbanrurbanGIF87a,0I8ͻ`(dihlp,tmx|pH,Ȥrl:ШtJZجvzxL.ύz}R"7|ޑ;:p{U-zN,Q+)KJ(FmE&A%<#9q>!ƺ74u2/,*y+A  0ȰBB$JbA%Te#-?bhOMFA2 ˖'IŒr&6̹R&O)(S4TP"E:I ӦJBE"u*ѠVT:d+W EK~e Ilضnv.vu͋Y+x  *܅9č Hv, ɘ%3|%g͹8SL)ĉ^mBXn5ٸiӱ$oox+M8G+7^9Йq$u_;;>5lӓb 5>}_~7'Q7Àx2$蠂Hރx'T!>' w(Ha~c`,I6cȣ;B F@I>dĔ2HNi70֓6W\Y-Y$ ciLzS)ÛtB%' tԝ.R|C jf 6'4*iNlTi`L0j¨d* Ҫ"*I "歸r+k,DZZZ*lFKгDkm?n`dke@~:nFrczKޫ,l' 7 ;GD-2.78/t/test_data/images/t4/4-00.gd0000644000175000017500000012110113076115435016214 0ustar rurbanrurbanGD-2.78/t/test_data/images/t4/4-00.png0000644000175000017500000000117513076115435016416 0ustar rurbanrurbanPNG  IHDRV PLTE͠?[;)IDATxIn0 ᤹@}'( ty=M{2` ⻧v Bw_ ^_6OLwY?J ~ /~O;f$i 6@/M_?j 7 [߬6(~Ï#*J?ҏ#*s~he}aGH'hxֱ CAg7cnz ><8<.q;?@6sO3^^^^^^^> ׇb~KW/K^n ?xOyy?UY!/l?RJ)tdxֱ @NMORZ g-8r-` -` -` -@\@Z@XXQa'Zkڏ]&)GD-2.78/t/test_data/palettemap.png0000644000175000017500000000416613076115435016401 0ustar rurbanrurbanPNG  IHDR?1=IDATxOuGC-@J,DP$es:u2qVnYaԡJ3-3)Dc)(Hx^rlPD͒ 7k:imOdw-,}ޑs/mekKҾ(iƹe~piHx ``````````````->t`li{$izi,&iRi_ݿ@ڧrB5yig Ǥ}v}`JZia4i#^{H{FFFFFFFFFFFFFF|xtfViy{?iIzi?iǘҾ:1PgnUm{}LoϿ_(oh kkkkkkkkkkkkkkkEӥ [W[j_J?Z{ixϹ&7/G7I*^X+wʗ\```````````````-P:pt\ڟ~oNHS[^kt,/珘(GHvJ/H)񇚥=WX#X#X#X#X#X#X#X#X#X#X#X#X#X#X .,}[:.1ilܜOKIoI&I mIQ~riNUi=!Kڟ9Oگh-Zp8@aҾ}Ya"Qg7[}ɚv' ikai?SҾjF^0Q־Ҟ+Iʏ&"HW'GkGڷ}+lFw!nƭ'C1M>G ``````````````-wҁg%㊴ϳey~}T}j+T (J_eyד/I;=WX#X#X#X#X#X#X#X#X#X#X#X#X#X#X E$H/hG=DڏXiݏ^.7T}/G f79Y/S*/S Ñ}FFFFFFFFFFFFFF,.@:P$+Q>ҾU~h io~iFk?YߍC=}j<Ƴ޿H^\```````````````-$KWռ}ZAimri?Zڿ;VisYWJ@ DJѾ#"v~]ZiB)ҁo}}QҾ.s!Q?tz߫~SL{i঱ҾwwMXO{i!F{>+Z]?"x|Liv?yji)4$-9+-O J;JP}EM>eh\}TXiւ6L:Ei?iU!/5H.]}o'(iY%פJKMfI[k7J>umҞ+2I)>o~ˮRi.;oFIڟHG׽$ "}C~mפŀ%Ҟ+r9+{IENDB`GD-2.78/t/test_data/tile.png0000644000175000017500000000043013076115435015170 0ustar rurbanrurbanPNG  IHDRR? PLTEܸ [ѧ:bKGDHIDATxc``Z:CCC?bBFCtEXtSoftware@(#)ImageMagick 4.1.0 98/09/08 cristy@mystic.es.dupont.comeB*tEXtSignature7a52b1cac1657d1b4f8ef32b4198eabc{;\tEXtPage21x22+0+0IENDB`GD-2.78/t/test_data/tile.jpeg0000644000175000017500000000067113076115435015340 0ustar rurbanrurbanJFIFHHC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222"* "1S!56as( a!145AQqr ?ROBqQhxZKhv;DtIM=k1mtK[ zt~, [T?+2tNJ~rS%dy ՟*>B8x+lGGD-2.78/t/test_data/Generic.ttf0000644000175000017500000005420413076115434015627 0ustar rurbanrurbanpOS/2O7X4NPCLT=ͺ <6cmap9 Xcvt ;Tfpgmahglyf tJhead Y@6hhea X$hmtxSiVhkernCxlocaTmaxpVW name:P post x DprepsT=  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a>z "   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV[WYZ\]`a^_X $4U !JfP hP!wohB+'ym/+)fZ?+'oj=7^`T) omb!@ ,C b#BfV-,*CTx+X9Y+Xf  H  n * (D* "6, F !"##$f%b&f'B((()x**+,-R--./0l1.124556v78 9T:@:;8?4@@ABCxDtEEGDGGH.HIXJJJ@$i Uiii4 <++{b  "$%&'()*+,-./0123456789:;<=?BDEFGHIJKLMNOPQRSTUVWXYZ[\](7>F F F  V 4b    ArtBrushMediumFontMonger:ArtBrush MediumArtBrush Medium001.001ArtBrushArtBrushMediumFontMonger:ArtBrush MediumArtBrush Medium001.001ArtBrush!ArtBrush Medium7@"@33  +1+0!!'!!B!B!!@   ^ #+1?*04722632.1".5467632#"UP $& .5+w!?@ Y V;wZ )G J.@gLl' H!@ a #+1?*0>7#"'>6%>7#"'>6o5%,.>xL!S<,.=xM !!(N \JYz.BlC'A `HVy,Cld@X  //    D!+1????++073737#7#''#'IHőFC–îǏgb`^`3bwV[fqG@=hg`\H@86/  n k khgd`\YVRMJFC@:64/,)#! 8<s+1???*0263267632.547&#"#.#"507#"'&54>732763.5>7>746>74&'7257 IAT+/QU 1܏!; -HVOp,ņD PGf+69`lc Ck5*:W9?/g:@5bN&Ej7 J1K[o+@#e^UL8-"D cZQ4) n?q++??*0#"&567>724>3#"'&&#"'.'&54>72"327>543267654'"#"3V! R_K2\UDon'#+< hMI7uD LVFly-.= `*G :Y n%` $UFI՗B p'-=|d}-LEwr32##"'&54>7&54>7632#&54673267 32>7&54654P&GI2 IwЌY]ZN{(7#"'>6o5%,.>xL!!(N \JYz.Bl@  | ++?.0#.547721nV-+P9>o/S)٥?CC%?e& '@ |++?.0>54&'&5463"&5>6=1V-9(wH8*Ut٤P>V0'=C_ޯȺ& ÃFOR@DJBA76.*&#"N K I / !   JICBA<:765.-("! _>Q+1???????*0#"&'74&#"&57>54'&5467'>54637327632732%%'.#" T    % z!   P    " s     '  "    7!0,@%0-)  0&"! X2+1*0%.#"#"&'>54'&5467%>7>323267P !*& # L==& +% + & F+ /  &''@  i+1..0.547>3#"'4>54V:A'4? {X6Y2? )&./(4Yz2D55\@ ` +1..065>5%4&'4\& V   o ' {N@ f +1..07&5467632#"&3 :038&? 9219&=J1_!"1]!"@ R +1*06332632"#"'66V?ϱ(  {!By@?O/*`3)3@*( (+   $ |$p+++1++07.5467632 #" 3274.#"h#_Yw97M(2f "E.30栓I*$t'%شs~<`%00iL! @   V#+1??*0.'.5>72>76322632:" 8+U*'6l-=}<~u 7 ON+C l,=M6@.B F+'#KF@=60-+'#!@ 4O+1*+0>7632>32.'&5465.507>$7654&'&#".54'&&5ZtL:0G`67!e/L @@11  6q;I /1El= Am'oA64\y=]M1uߺF  !  &  93@;G2" $WU@KT/,'"K1 OK 1&  TQOCA>;," 5/ s GIo5*'$/Y++1?++0>7632#"'&54>732>74.#&54674&547>54'&#"&5465.&xd`563A^ffg?/o2A=HOK2]Y#pkcW 4 42I [g"6/'   ED>;/'& C1I+1????*0>763226323".'#>&546.547627>7 . gR! ",B A@F ?_wQQ_    4  '  '&K: 0IN@F/(%!;1 H =E0;1)  H=86% t6E(-r%!K+++++02632#"2#"&5>72332>54'.#".54'.56727:uFB8ܒՋvj>sE^5d O"-@X[*YQ[0 u, !  D K_]H4Q=K$5! N:#<9 !0$=3@*5)'7 0.'+ 7   < {3!?++??++06$763232632#"'&5466&#"#"'32>74De  #0 .Ą(cVfOiyT0Zrb?D 2LGA VR[)'#i@ WikvP{Q#('2=@NRQ. 50"@'&  /,)'& N2+1??..0>7632".'.527667&5465.54%]hU@0 )#] ) "IDXr    -cXT U`&5.  ^ 7ENL@@A-* N8 J ,    ?,6= KNJF j%D82|H6=/P+++????*+0672>7&'#"'.547.5432654%.'fQN^J!!N4  !77U" $U' (=6kpqn@1}Oi\d BFmD{M74_A, ( #E#,C7Qj9*.g4Ma)g\c+[k84FcR!8+@"/-'(7  % 3:++??.+0&54>7632.'#"&&3267632>54'&#" kݠ-Zl{mlt( UHeD~<RAF,Q0&<h_ۼ. `[ "${oX #$+k)852 %H%=P'5X$@#! c&+1*07&5467632#"&5467632#"3 ;/09'> 811;Rd 9/47T 900:Ts0b!!1^!1b=1_!X+@*!% h -+1*07.54763#"'4>54&5467632#"bFu5= KyC,h,3 9/47T 900:T+:#)i0,2BsF*T/91b=1_!?`.&@**)$"  Z -0+1*065>5%4&'465>5%4&'4++' n  ' o    PO;@00 E3C C3.+ oI+?=85 e Q++1??*+07&54>7632#"#".'&547>7>7654&'&#"&54654.547>7632\ 1!5:V# :e7654.'>7>7>72+9- OU@li+ @3j 8] ;3rK M'JfX6z 8 0o{>7o " [DBu7%9G_M@D\TPHB>=: FX 2.F( NK)&X# "  VPK>5.)} Bl\a++??++0>7632#"'.'.'.5667.54>&6$65.#">322>5.&𞰰4$B`NVw|);񥗌 7 #_"4oGB Pb/p8I)*c'9#uf(RTL4$:W5L<]{NBY[HMp?4P-" %}{~/*  5(feU.Xrh+7 # Al33!B4@(=7"9 )    3/, =o?D++????..+0%2367.'>732>76323#".'&5466z;!u$ -0L|+)1.. 8\*D,'/B5{u RL.SB&J.k-)R{`z0  6\Y6 \ڨKBQ@L^*  <,!.Z7632!&'&%6$>7654&(BhP0.ґN/~$& r&ZZ1`Z"SzcVT ?Q;id}D1@''"-   B>:74-,)"> /F+1???*0>72%#>32&'>7.'>7>7.'&&Ru*  `%f)CH5 *f;hNR18Tp ##Ju  ** )'%%% >+IAh|}:"eAvȥc 59A>.@%>; '  >;86'&%#  =*@+1??*0>7.'.'6$>32%.5>7>7>54'>3NTS ' HBC Պ )/*>n $-!'   P,,*I:) ! " #! 6`/.Oema$%>Xj>5<>-9G1@)D?"'A 85/,( 5,&DmFI++?*+06$763233.'6732>54'6$32.#"#"&'&54+ZE d. T7'=2"'#_d>^%-[FgW1#sS  /#O>C9X?a2C=B@3:P> =R"aaWs`@R_J  %59+"̈v"7YKW uG9@)$F -      ?<9-($ 74I+1????????..0>32%>7632>32.'.'>7".'.'>7.'>7>7>32+21&(9= L-6_A -S\k)2 OC;N**H!_U%  %Q0 XxDQ' MwNk*V@   [ +1????06332632.'>69@ LH;3:Q)5W -E\x%"@ A$+1?*067632 #"&'&54>7>6o3;/JE-Na%Z!J;%)!87S3Ao@t7'*@     : $)+1???*067632 .'.'6ŇE`*6/;Yaa*3]"9HI .w%-322>3#"'&'67>7>6*x0ʧOy#)  PC< 4 .2# ;1@%2 - * %   72/-*# 5 =+1?????*06;>32"&' .'>67.'>667632263>7>6):CH7-  =#SQ KP> "BE!  Mbk,LB@1UiF  31*KR{-Zx$*](\_] Bcw#@ #   < %+1???*0>72"&'. '&'.'>7>3h!`K0, K T-=->5r$)ra#9J ZT1!H$k)kF, 5*&@)! !  &g,++?+0%.54$7632 #"3267.#"7-/'Wp<ݑI4*4iŀ &60#.ۙQ;% QW($ֲ@f9@oC@*><@3+=5 != 1.5  51.)&# 9@++??++0>7632#"'".'.'7&54654&545>36$65.#"KkEP_)'%)*R-?0">8DqQ')-5$qՏUVb h '  & "Ha#!gH#G1 b(D=@3:70" C :7?- u ?42q-'F++1?.+0>7632.'#"&'&54327&54672>54'&#"uD;Ud3\d.0%i]26jiI'p$@8641(cB%;.,E[;-ߊ/") (J@2  qHZ^4CO 71",/#Y]Y(31@(&#1 *  *&#"~ /5++??*+0>7632&'.'66>7&#"ZiOUwyj :M EYqV ȲM lF550hMC4.'uC * 1 &ND`88MlB9L<,@$2" * 840-*  ? &>+1*+046$%632.547 #"'&54>7327>7.&-YEQb%)/@e 2l9f@{WU=X 9sV]S& S`Ko +$%2Q6&6"^w`Tp!>pDl aAHHwN0N~ * @!  !F ),+1??..0,%2.'.5.54.540b ~U B?jC]8Q"[ AC* ,()6Fۍ@ ('7y'#@ % 'l)++??.+0327632#"'$467>32632T#6^ }-+ߕPbpD 2QE_$5e '!#-Q0j ! @   = !+1??..0>7632.'.'47>7>32P$P *8! =1="V11Bc 2>  9^35/@%(%  5   520('   4 7+1???*0 632"&'.'&'676322>32>766767263 @:P *}zcddtF VC* >% V B }&  {pcrEk  #|a7+ J>/@$$< %  <830$ 6 ,@+1????*06$>722#"&'"#.'".'.'65&'>7>35!y%` ^dhz 5C' ^ "0 H*T A."$9  '+pu  hY^}+| 2s~" -f-8&  7-+@+(%   -(# I/+1?????*0>7632631.'>7.'6323>32B׃+2 $S+JPL;V2JO 29Q L%?OCVB<,[Li ##/*@")(" .,)('" ;%1+1?*0>7632>32 #.547467"54]Ǝ[h<za00  ()gA3'$+bb$ S(A   N%jJ65#@ R +1*0" '&&'>323#"&#"{>!AyA 6  (GǒO_*h@1 G+1+015!hh3#(36@*-' )  '  )z-!5++???+..+0>722#".'#"547#".'&54676$32>76m$:&'  ; ;7'X? F[_#1z:mbJ8 "  $a'a !<"%+Gi;dgV"0<@2.( .( ,& u,y&2++1?++0>7632632#"'&546632$7&#"քQ+ D t6,r`nG6\8S$kI ?D(: uxBTD]y#8Uɾ3a,| 39,@#(.8 +   41- w$;++??*+07&54>$76326322&#'.5>73267#"N &5V "Fx(),#o'1d6 yU%V\,0 : u 42: _1s .VNVh .*@!' ! ! u%0++??.+0>7632".'"'>7#"'&54$32>766 *-! 9  k5 `^0~_&F   #&%!3v;.a'bnE$3-@$%# ,' 2/,)% U 5+1?*+07&546$33267#"&#">7>54##n_r%>Z|7.h= -f8%1h?!.bom7Xr YF?bD4[A2 xn9'US-'xc3%Q" +B6@+41.) A    =:41.) K&D+1????*0>3".'7"2.'.'>7027#&5.'>76632+5@14E6#%P?]9 @v" |)&C)  R7L ,aB1V^M)7P< +%;u;q{3/5/c94G<@0' ;# D2 / ,  @ w9'I++?????.+02632 #".54763267>7#".'46$7226722>54'&#"C Ŷ?f(.>CZ1:Q!VJ!;)EK$A3>"#l! "M՜+͂!-$h.ც"Oy8;%eWnGpSQo!J;EK( Q#ܽ. qF1@#&D@+  B32".'.'>7>7".'.'>76>7>32326$y\.GD'.n +* @% 6/1yu9) . eX@ "R^   $V *m \*9"6(Vf? $PLr_h8n  CLj>Fx  h -"@% ( "  *r/++???*0&546?#"#"&'&567>76322632B3!T3P%!39AMS-pB & , RcN%7=jN*^@KT1.&1Ug!` +$@!( (D &-+1?*0&5467632 632>32 #"'.547B7!)(6JqA =w‡V#Kp&#I+'^04y* :tHF˺;//%#>klYF8@+=8+ D , &   B=:8+&#  M3H+1??????*0>32>7>7#.'".'>6724>7632{E 6e/CO"#$s{u57'n32.'.547>7V 0 8 8']: +k +#%b<X 4b((   FYUw\7@)R0V L I F 8 #   ZRN?0+~^++????????*0>32"&'.'&54665 ".'.5>65".'7676323>32>32VQk=z( RMMsT,VO 7 Q " 3  1ed+?'R*|1F%Q^,մ-  A#/#`B   ;5BQ7'$W@` E B.5(?/@$1& 6 , )  81.)!  S:A+1????*0%"&'.5>67".'.5>7>76323>32>32R 2L= ;tnE3|d0 YJQe3 / 6  JHI":7?=B) '=?4VuVA2% 3f ' %.61''1[oZ/&,@$   " t %{(+1++07&54>7632 #"&#"267>54Ns=@DpGepPB67H%TS9"O^ͬ8Jw9pbNSCAw}/-0H&5.@%+ 3"  )$q17++??*+067632#"'.'&#"#"52763232>7654#"+1!]W/UxCU_J- " i e`%3*yD=u%i\D@O/6 ^ 1Gy@_@F 1!/-@"', .   ,|'1++???..+0>7272&'.5>7#"'&54627654#"j9d:/\FF[7.'.5>763632>32:?  .F'/ 5 L@2# ?!L6" " P[n=tU. 3xH ) B'DK@B@;75$ = ',=**   n$@7k,v;/F++??++0467632#&547>7&#"#"'.547>3232674.&(6:qS . 5Mg<' !V!PJ\)Wd gBT7(^l Kf-Y@39\[ho, (8 A5='D& <*8LzbHM3"$hL$()L3[31`64@haXsD.@%'%>  A>;41/,)'% P F+1??*0"67 #".'&#"'>7""5465.547>7>7>7>72V?  j#Qc ))/UktS bP E D@; JMX  %   %8 lʚ 5) 0x,y &` 60@!05 & #    0-%t8++????????..07&5476322632>63232632".'.5467#"] - 0 [. D 71  8?' e`9fw(8p7p j! =!  1wbRE^%(@#   O *+1??..0747632>76;2632#"&'&&^," 9  շ$A8 u * '-:M]  !);[3  7GI@8D63'  A > ; /       DC63/'$"  98I+1??????????*06323632>676323>32"&'""'"547".'""'63212632> #Td}# :&P ' A.'H0%?&   $A i !u8H - 78cE3O!K92@&4  1 . !  61,'!  J&;+1?????*0>7632327632#"'&'.5.'6323>32s6r51 >#); . Z   Z4 7 O66$ B (X-Gdr $1Qnb6*@ 30-)  32$"!  E8+1???*0#4>7632.'&547&47>3232632>6Y`D1?  2.7 @8# (9 ' eenvT  C4F9 # ͤ®XR&;G-@$C@$ 0 C@520/+(&  L9I+1??*0.547>76322>32&5>5.5>7>7"=4 7@c$ 4-f!# pGN3=)MU!'G'/NJ /   + # c9>  * 1 )8"C##RDO(@"HE?862  H;32 # K)Q++*047>7'>5.'&54>746?632#4&'&&632 DYgcL# l/9O.0>Y}VL p"   %/' &s:  $"LN8o82%0H&E;:"L!]P.4vT77@ ]+1..0#".54>763238WP?sR46AoN_QiVi##[W@LWTJ@=<9+L 20-1 O2LZ1D 5 WTQOJD@=<90+ H 5H&]++1??++0".54>3232>54.#"&54>7632632.#'.5>73267#"hPmP@uPronqTr@(T[ ' "=H  :X 1orB]OgRkQs>nqqo@p),rtZ  B=  |1 W8  @V @  d "+1??..0&54>7632#"&#"267654VNCzI!#6$WJ% 1N;,9-3'b@#$:MɐpSA 2CP?@ Y +1..065>5%4&'4P' V   o )'h@ B +1..065>5%4&'4' n   )hN3-@"(2! &i2i!-5++1??..0#".547>72#".547>72 #0d,AxI ?5u#0d,AxI ?5u(!@2O+Fs@8&1i("=2O+Fs@8&1o73)@!+"2 %h'2- h 5++1*0.547>3#"'4>54%.547>3#"'4>54'V=5? }W6Z0'V=5? }W6Z0="):./*2Zy2F3="):./*2Zy2F3)N@ i+1?.0#".547>72B#0d,AxI ?5u("=2O+Fs@8&157@  i+1..0.547>3#"'4>549B&5? {X6Y2? (&./(4Zz2D55'FR;3'f' +7d'sF P'FPR9^ -%R F 7!7##DhPD{+qPB\T3H\X3^ {7DTqf5br d%bPqqf @ &k#GD-2.78/t/test_data/frog.jpg0000644000175000017500000000302313076115434015164 0ustar rurbanrurbanJFIFC    $.' ",#(7),01444'9=82<.342C  2!!2222222222222222222222222222222222222222222222222200"-!1"Q2AqB#3Ra/!1QAaq"#$2 ?Y5Ɗ:h҅2j|Қ{:T mA]{ϟkĩYkjrJaG 1:Ag%GfTI#pVg}w.x0F_r4ƹ,ݭ \b A9cz5m:+k1#|M{ebZdJQ,eRC$ddL$yQÿY|Vآ6T7ZeEpg$#C[D(*o=BڊAd x:m[Pz.<4 "1c*Kvxy(m f"˷p ;S]9Y q<IO`2HeaCsݐzzQ 0[;q20+:GBk IhxxIpӕL{64rCl(wFOrwPTT$"H BRJJn2 >5ZR $-T`ȪKc8>ՅKKeAdaT=yypԴ}0 ;X4lݧ-{UUHeNFꝺJi- m=2J 'v S~N%E0ƱDApzP`;=t݋RFGD-2.78/t/test_data/frog.xpm0000644000175000017500000002445413076115434015223 0ustar rurbanrurban/* XPM */ static char *magick[] = { /* columns rows colors chars-per-pixel */ "48 48 256 2", " c #060604040606", ". c #080888884040", "X c #9c9c9e9e4c4c", "o c #1f1fc7c73c3c", "O c #47478a8a5151", "+ c #4747c4c43939", "@ c #747448482828", "# c #4747a5a53131", "$ c #2020d8d8b8b8", "% c #a4a4c6c66c6c", "& c #71716a6a4444", "* c #0c0ca6a61414", "= c #4848aeae7474", "- c #c8c896960808", "; c #040446460c0c", ": c #4848d8d8a0a0", "> c #0505e9e9e5e5", ", c #a4a443431111", "< c #d4d4a6a67c7c", "1 c #d0d0a8a82424", "2 c #6464a2a24444", "3 c #2929ededd9d9", "4 c #242484845c5c", "5 c #4848b3b33737", "6 c #040427270606", "7 c #6767c7c75757", "8 c #a2a254541a1a", "9 c #eaeaaaaa1414", "0 c #4747d9d95454", "q c #4646c2c27878", "w c #2e2eaaaa2c2c", "e c #0808f6f6dede", "r c #4a4ab4b44f4f", "t c #282805050505", "y c #4747cfcf3d3d", "u c #e9e9adad4545", "i c #2828d6d63636", "p c #272787872f2f", "a c #4949e9e9c7c7", "s c #2626fafaf6f6", "d c #3737b5b52929", "f c #717155552727", "g c #4c4c60604040", "h c #040418180505", "j c #e4e48e8e0707", "k c #a3a353533333", "l c #3838c6c62828", "z c #5656c6c63c3c", "x c #6767adad7373", "c c #fafab4b41212", "v c #68688c8c4848", "b c #292993935959", "n c #a8a868680808", "m c #5959b5b55252", "M c #3c3cb5b55555", "N c #3333c7c75555", "B c #b5b54a4a2626", "V c #26269a9a1c1c", "C c #e4e49a9a5c5c", "Z c #4646a9a95454", "A c #484894943434", "S c #1818f9f9e9e9", "D c #e4e4caca4c4c", "F c #040434340808", "G c #fafaa9a90606", "H c #e8e89c9c0606", "J c #909054541717", "K c #4747c6c65252", "L c #a7a745452e2e", "P c #2929edededed", "I c #3c3ccece1c1c", "U c #f9f99a9a0707", "Y c #1c1ce9e9e9e9", "T c #36368b8b6666", "R c #6161e6e6d1d1", "E c #4646bbbb7474", "W c #b7b755551111", "Q c #3737b4b43d3d", "! c #414175754040", "~ c #181805050404", "^ c #9494c2c28484", "/ c #3939d2d2cfcf", "( c #10107e7e3030", ") c #6464cecec9c9", "_ c #161615150404", "` c #5656aaaa5a5a", "' c #ccccdededcdc", "] c #929263633737", "[ c #8c8c52522f2f", "{ c #a3a35c5c1717", "} c #4949bcbc5454", "| c #b6b658583939", " . c #2c2c6e6e2c2c", ".. c #565685856666", "X. c #3838fbfbf3f3", "o. c #e7e7fdfdf9f9", "O. c #c4c4bebe1414", "+. c #5757baba3737", "@. c #373788884444", "#. c #04041b1b2424", "$. c #3737c5c53b3b", "%. c #040428282222", "&. c #fbfba9a92020", "*. c #a2a24c4c2b2b", "=. c #09099a9a3737", "-. c #8484b2b26868", ";. c #4646caca3b3b", ":. c #8a8a44441c1c", ">. c #6666b9b96c6c", ",. c #5757bcbc5b5b", "<. c #3535bbbb3c3c", "1. c #45458b8b6c6c", "2. c #6666b6b65b5b", "3. c #26268b8b7e7e", "4. c #0606fcfcfafa", "5. c #a4a45b5b3838", "6. c #c9c967671919", "7. c #fafaa0a00808", "8. c #5757b8b87474", "9. c #59597a7a3737", "0. c #0707f1f1f2f2", "q. c #1515fbfbfbfb", "w. c #34346e6e5c5c", "e. c #8f8f43433737", "r. c #05050c0c0505", "t. c #4848dbdbdcdc", "y. c #3939ebebd4d4", "u. c #4747e6e6e4e4", "i. c #373798985959", "p. c #9191fefefcfc", "a. c #a4a49a9a1c1c", "s. c #6464e2e26c6c", "d. c #b8b8b8b83434", "f. c #2121b9b92525", "g. c #c4c4a2a24444", "h. c #ccccc2c29494", "j. c #acacc2c28484", "k. c #d3d3fefefbfb", "l. c #b4b4fefefcfc", "z. c #a4a4aeae5454", "x. c #717177773f3f", "c. c #6f6f9b9b4949", "v. c #efefbbbb3737", "b. c #8c8c78785050", "n. c #464696967070", "m. c #6060e8e8ecec", "M. c #6868dcdcb8b8", "N. c #c6c6a8a84646", "B. c #a9a964644545", "V. c #3939d8d83d3d", "C. c #7474cccc7272", "Z. c #2020a8a84343", "A. c #7c7cb2b2acac", "S. c #262699994040", "D. c #aeaeb9b95f5f", "F. c #24241a1a0404", "G. c #dcdcb2b2c4c4", "H. c #3939a6a65757", "J. c #2424bebe6464", "K. c #b8b8b7b7bcbc", "L. c #b4b4dede8c8c", "P. c #3737dfdfd4d4", "I. c #1010dddddcdc", "U. c #646465653a3a", "Y. c #69699e9e6c6c", "T. c #bcbca8a83c3c", "R. c #d4d4b9b94141", "E. c #4444f2f2cccc", "W. c #6c6c92927c7c", "Q. c #6161f3f3c4c4", "!. c #dada9d9d1414", "~. c #f4f4a2a24040", "^. c #09097d7d5151", "/. c #6565abab5959", "(. c #2a2a97977a7a", "). c #5959dede6767", "_. c #5757c8c86c6c", "`. c #f8f8aaaa4444", "'. c #5c5c9c9c5c5c", "]. c #5050f3f3ecec", "[. c #7878ceceb8b8", "{. c #2f2f7c7c5050", "}. c #bcbc72722c2c", "|. c #3434e4e44848", " X c #8484aeae4444", ".X c #5c5caeae4444", "XX c #717155554444", "oX c #424279795f5f", "OX c #94946d6d5151", "+X c #dcdc9c9c5454", "@X c #747478786060", "#X c #191999994040", "$X c #5757dbdbdada", "%X c #5c5cf2f2e8e8", "&X c #3c3ccfcf6464", "*X c #91914d4d1c1c", "=X c #2c2c7c7c6969", "-X c #1c1c8d8d4242", ";X c #808066664444", ":X c #7777aeae6f6f", ">X c #3939ecece8e8", ",X c #f8f8fcfcfafa", " q.q.UXs s p.l.k.k.,Xo.,Xo.k.k.o.k.k.k.l.p.t.P q.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.", "4.4.4.q.> q.I.>Xl.k.o.o.,X,Xk.o.o.o.,Xk.k.l.l.p.P 4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.> 4.4.", "0.4.4.4.4.q.S S P ].l.k.k.l.l.k.k.l.l.l.p.X.I.0.4.4.4.4.4.4.4.S 4.4.4.4.4.4.4.4.q.4.4.4.4.4.4.4.", "4.4.4.0.q.e s 0.e q.>Xp.m.m./ u.$Xt.t.>Xs q.4.4.4.4.4.4.4.4.0.q.4.4.4.4.4.4.4.4.UXS s q.e 4.4.0.", "4.0.4.q.X.>X0Xs S 0.> Y P Y P s Y s s 0.0.0.q.q.4.4.4.4.4.4.4.4.UXq.0.4.4.4.4.4.s P.t./ s 4.4.4.", "4.4.Y P %.%.eXy.3 S q.q.0.q.4.4.4.0.4.4.4.q.0.4.4.4.4.4.4.4.4.0.UXq.4.4.4.4.S y.P.eX#.%.u.UXq.4.", "4.UX].6 (.4 4 6 #.$X>XS q.0.4.4.4.4.0.4.4.0.4.4.4.4.4.4.4.0.q.0.4.4.4.4.4.S P.%.6 3.3.3.#.t.S 4.", "e X.h =XT H.sX@.gX6 / X.> q.4.4.4.0.X.0XP X.UXUXs UXX.0X0XX.UXq.0.4.4.4.S X.6 3.T T 3.zX=XeX$ S ", "y.F cXn.( -XbX-XE (.F t.S 4.4.4.4.S P.#.#.#.%.%X/ m.#.#.#.#.>XS 4.0.4.e y.%.T oX=X4 T =X=X3.%.y.", "R 6 4 4 8.#X#X=.=.bX^.eXs > 4.4.S 3 %.o.,X,Xk.#.M.h o.,X,Xk.6 E.0.4.q.X.%.=Xw.O {.Z sXi.cX3.%.SX", "r.n.(.bX4 1X#XN J.uX(.F y.S 4.s >X6 k.,Xt ~ ,X,Xh k.o. ,X,X#.s e S P.6 1.oX@.# -X( -XH.4 =Xh ", "r.w.3.= @.@.* N N &XE . F y.s I.$Xh ,X~ G.,X ,Xr.o. ' o. ,Xr.0Xs >X%.gX{.dXp LXQ s.#X. cXKXr.", "h x VX@.-XM K $.BXf.0 uXcX%.u.].) #.k. K.K.r.,Xr.,Xr.K.K. ,X#.>XP %.(.zX4 sX} HXZXo o &X-Xw. ", "h VXlXO S.N l y I BXIXAX= 6 6X6 6 h k.o.r.r.k.o.h o.,X ,Xo.6 a y.%.=Xi.i.Q ZX5 AX* i =.q lXr.", "6 VXT @.Z.f.l l I I o 0 Z 6 F uXM ,.h o.,Xo.k.h '.h o.,X,Xo.6 M 6 6 1.1.p z V + PXAXi i BXS.{.h ", "h n.9X1XJ.0 l I + IX&XQ F ,.5 $.y K .Xh h h 6 8.,.m h r.h 6 FXK K C.6 dX7 PXPX+ ;.d i 5Xi <.x h ", "F VX4 #XZ.N + PXjX} F 6 ,.5 + l BXIXd hX5 jX<.<.$.$.} m LXr AXIXl f.$.F LXLXz + IXV.|.5Xo &XZ h ", "A.#.bXbXZ.N r F 6 F r ,.} 5 <.;.uX} 5 7 5 LX).uXuX} FX7 7 # jXK l y <.).F 6 F F IX|.f.5X|.J.6 [.", "[.eX^.q = r 6 m z <.BXQ } ,.8.h 6 6 r.r.r.h h h 6 h h r.r.h h h h .X>.Z uXK jXFX6 F $.|.f.N F R ", ") %.4 -XF 6 2.6 LXjXjX} 6 h h r.r. ~ r. ~ r.r.h h h ,.Z m 6 9XE F <.$.&XF / ", "6X6 T 6 M jXdX6 h h h r. ~ ~ h ~ t qXt t ~ ~ t qXt t ~ r.r. ~ r.h #.h r.h 8.H.} ; 5 uXF GX", "GX6 sXh jXQ ,.h r.r. r.~ t r.~ < C u +XiXqX:.~.C u N.h ~ ~ r. r.h ` 7 LXF + uXF GX", "Y eX=XF r Q ,.Z h h h r. r. < +X~.~.!.n J J ~.v.u g.h. ~ ~ h h xX+.z PXF $.J.eXP ", "q.P h h m +._.r x r.h F r.h h h r.r. ~ 4XtXD d.R.R.1 1 T.F. r.r.r.h h 6 h X.%.oX6 6 6 m x :X:XO 2.9Xh h h h h h h h h h h 6 h h 6 h h 6 6 PXK K + IXPX+..X6 h _.E F X.UX", "q.P %.3.x dXm F 6 6 h F 6 m x >.2.7 LX,.jXr ,.,.2.Z Z ,.r m C.LX<.0 Q uXBX;.l ; F Z 8.gXq F 0Xs ", "q.I.y.F b HX5 PX+ ;.Q M ` 6 h h ` Z uXBX$.$.0 d ;.+ IX0 $.Q Z m + } ,.'.kX6 F IXd AXq q F a E.$ ", "a Q.Q.a F #Xw V l BX&XK Z h ! O 6 F K <.N + y PXd ;.;.uXuX} ,.,.5 6 h h h .X+ l BX$.H.6 6X6XCXCX", "N.D.C.: E.; ^._.-XK <._.h .i.r r jXF 6 6 6 6 F F 6 6 6 h 6 6 F F i.oXoX1XuXBXl $.LX6 L.% NXd.O.", "7.v.D.C.Q.: F 4 b p } H.F O -XZ.K 5 5 2.x {.O {.r 2.>.KX1.sXHXd r ,.h h @.} IXBXjXh % z.R.9 9 c ", "G 9 u T.pX% h 6 h F @.'.:Xh i.M o BXz # 6 @.b E r jXm 6 i.-X$.i ;.FXHX/.2.2.6 6 h h D.R.!.&.G 7.", "9 !.u tXt r.9.! /.` h 6 h h @.i.N BXl z 6 sXb -X&XV C.6 @.E BXo $.+ 6 6 h h kXKX2 -.6 r.1 v.j 7.", "9 u ~ h 9.O ` 1Xr LXK ,.m 6 r.lX= } + +.F 1XsX,.jXjXm 6 H.S.IXy uXjXF H.@.1X9X/.>.` A .6 z FX2.h U. dX-XQ z 6 @.9XO '.2.m 6 -XM y <.m 8.h zX{.T 6 nX@.6 >.h 2 c.h d.", "t ;X@Xr...oXh Y.Y.h Y.-.r.U.OX {.#XAXQ F h yXr. h h h S.#X;.PX2 h h r.W.g r.9.v 6 nX! 6 9.X _ ", "XX~ ~ & _ & U.r. & f ;XU.6 E Q + ` ^ XX;X lXT -XK w hXh & & U._ pX~ _ z.h h D.~ ~ N.", ";XmX[ 5.rX:.MXvXMXvX5.[ [ ;Xb.! @.-XZ.F .Xc. OXMX yX{.F M jX# h T.tXv.DX9 v.1 9 2X- 2X!.9 9 9 ", "vX@ B.7XL 7X3XJ J { *.k iX[ x.lXh /.2.h r.OX[ MXf _ h ! x h Xa.qXH G G 7.7.c 9 H c 7.7.G U &.", "8 { 7X*.| *.*.8 k 3XiX*XMXOX@ t t f ~ ~ f MXMXMX5.iX] vX~ ~ @ qXqX!.c G G 7.G G G G 7.7.7.7.U 7.", "7XW 5.*.:.rXk aX*XJ J iX[ 5.rXe.e.B.:.e.B.rX*.k { J *X3X8 8 }.J DXv.7.7.G 7.U U G 7.7.7.7.U 7.7.", "L L *.k B.B.*X:.5.8 iXiX[ rXL | | k rX| 5.e.rX[ J n n DX`.H fXfXc &.H G c 7.G G 7.G G G G G 7.&.", "B k | [ *X*X*.aX5.*.*.k k L L L k e.k , e.aX{ { { 9 fX7.c 7.9 c U 7.&.&.7.7.G 7.7.G G G 9 9 G G ", "e.L L *.7Xk B 7XB B L B B B B 7Xk iX3X, 6.~.fX7.!.c &.7.7.c 9 H G 7.G 7.H G G 7.G 7.G 9 9 G 9 G ", "aX8 7X6.JXJX6., B B B B , W W { 8 { 7XW j &.U G G 7.7.7.7.7.c 7.G wX7.7.7.c G G 7.G G G G G c G ", "H 7.H U 7.7.7.7.7.&.&.7.fX7.9 9 &.fX7.7.G c 7.c G U 7.G 7.7.G c G U G G G 7.H 7.G 7.7.G 7.G G G ", "c c G G G G G G G G 9 9 c c 9 9 H 7.G G G G G G G U 7.7.7.G G 7.G 7.G U G c 7.&.&.7.7.7.7.7.7.G " }; GD-2.78/t/test_data/tile.gif0000644000175000017500000000015413076115435015154 0ustar rurbanrurbanGIF89aܸ !,=˂I2zQ+yqcz C@׶z݃jAW!,B$;GD-2.78/t/test_data/tile.gd0000644000175000017500000000273313076115435015006 0ustar rurbanrurbanܸ GD-2.78/t/test_data/tile.gd20000644000175000017500000000207213076115435015064 0ustar rurbanrurbangd2!ܸ xc`&`vO FGD-2.78/t/test_data/windows.bmp0000644000175000017500000000010614434720223015713 0ustar rurbanrurbanBMF>(@GD-2.78/t/z_kwalitee.t0000644000175000017500000000205714174320547014111 0ustar rurbanrurban# -*- perl -*- use strict; use warnings; use Test::More; use Config; plan skip_all => 'requires Test::More 0.88' if Test::More->VERSION < 0.88; plan skip_all => 'No RELEASE_TESTING' unless -d '.git' || $ENV{RELEASE_TESTING}; # Missing XS dependencies are usually not caught by EUMM # And they are usually only XS-loaded by the importer, not require. # But even the most basic deps are missing mostly. for (qw( Class::XSAccessor Text::CSV_XS List::MoreUtils Algorithm::Diff )) { eval "use $_;"; plan skip_all => "$_ required for Test::Kwalitee" if $@; } if (!-e 'META.yml') { require File::Copy; File::Copy::cp('MYMETA.yml','META.yml'); File::Copy::cp('MYMETA.json','META.json'); } eval { require Test::Kwalitee; }; plan skip_all => "Test::Kwalitee required" if $@; my @args = ('-has_test_pod_coverage'); if ($Test::Kwalitee::VERSION lt '1.02') { push @args, '-proper_libs'; } Test::Kwalitee->import(tests => [ @args ]); #plan skip_all => 'Test::Kwalitee fails with clang -faddress-sanitizer' # if $Config{ccflags} =~ /-faddress-sanitizer/; GD-2.78/t/fork.t0000644000175000017500000000066514174320547012717 0ustar rurbanrurban# see [GH #25] # check that global %COLORS is concurrency safe use GD::Simple; use Test::More; BEGIN { eval 'use Test::Fork;'; plan skip_all => 'Test::Fork required' if $@; # see cpantesters, not repro for me plan skip_all => "Test::Fork broken on $^O" if $^O eq 'freebsd'; } plan 'no_plan'; for (1..10) { fork_ok(1, sub{ GD::Simple->new->bgcolor('transparent'); ok(!$@, $@); }); } GD-2.78/t/caller.t0000644000175000017500000000037014450761142013206 0ustar rurbanrurban# GH #47 use strict; use GD; use Test::More 'no_plan'; use Test::NoWarnings; # Use of uninitialized value $pkg my $image = GD::Image->newFromPng('t/test_data/tile.png'); f(); sub f { my $image = GD::Image->newFromPng('t/test_data/tile.png'); } GD-2.78/t/Polyline.t0000644000175000017500000000075413076115434013545 0ustar rurbanrurban# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl test.pl' ######################### # change 'tests => 1' to 'tests => last_test_to_print'; use Test; BEGIN { plan tests => 1 }; use GD::Polyline; ok(1); # If we made it this far, we're ok. ######################### # Insert your test code below, the Test module is use()ed here so read # its man page ( perldoc Test ) for help writing this test script. GD-2.78/t/transp.t0000644000175000017500000000361514174320547013263 0ustar rurbanrurbanuse strict; use warnings; # This is a feature: adding transparency changes the palette # https://rt.cpan.org/Ticket/Display.html?id=40525 use Test::More tests => 12; use_ok('GD'); my $gif = "t/test_data/tile.gif"; my $jpeg = "t/test_data/tile.jpeg"; my $frog = "t/test_data/frog.jpg"; my $im = GD::Image->newFromGif($gif); $im->transparent( -1 ); is($im->transparent, -1, 'image is not transparent'); my $closest = $im->colorClosest( 24, 53, 62 ); $im->transparent( $im->colorClosest( 24, 53, 62 ) ); is( $im->transparent, $closest, "transparency preserves RGB before $closest" ); is( $im->transparent, $im->colorClosest( 24, 53, 62 ), 'transparency preserves RGB after' ); SKIP: { skip "No JPEG support", 8 unless defined &GD::Image::newFromJpeg; $im = GD::Image->newFromJpeg($jpeg); $im->transparent( -1 ); is($im->transparent, -1, 'image is not transparent'); $closest = $im->colorClosest( 24, 53, 62 ); $im->transparent( $closest ); is( $im->transparent, $closest, 'transparency preserves RGB before' ); my ($t, $c) = ($im->transparent, $im->colorClosest( 24, 53, 62 )); if ($t == $c) { TODO: { local $TODO = 'colorClosest ignores alpha'; isnt( $t, $c, "Closest" ); } } else { isnt( $t, $c, "Closest" ); } is( $im->transparent, $im->colorClosestAlpha( 24, 53, 62, 255 ), "ClosestAlpha" ); $im = GD::Image->newFromJpeg($frog); $im->transparent( -1 ); is($im->transparent, -1, 'image is not transparent'); $closest = $im->colorClosest( 24, 53, 62 ); $im->transparent( $closest ); is( $im->transparent, $closest, 'transparency preserves RGB before' ); ($t, $c) = ($im->transparent, $im->colorClosest( 24, 53, 62 )); if ($t == $c) { TODO: { local $TODO = 'colorClosest ignores alpha'; isnt( $t, $c, "Closest" ); } } else { isnt( $t, $c, "Closest" ); } is( $im->transparent, $im->colorClosestAlpha( 24, 53, 62, 255 ), "ClosestAlpha" ); } GD-2.78/t/z_manifest.t0000644000175000017500000000105214435047450014103 0ustar rurbanrurban# -*- perl -*- use Test::More; if (!-d ".git" or $^O != /^(linux|.*bsd|darwin|solaris|sunos)$/) { plan skip_all => "requires a git checkout and a unix for git and diff"; } plan tests => 1; system("git ls-tree -r --name-only HEAD |" ." grep -E -v '(.gitignore|.appveyor.yml|.whitesource|.github|.travis.yml)' >MANIFEST.git"); if (-e "MANIFEST.git") { #diag "MANIFEST.git created with git ls-tree"; is(`diff -bu MANIFEST.git MANIFEST`, "", "MANIFEST.git compared to MANIFEST") and unlink "MANIFEST.git"; } else { ok(1, "skip no git"); } GD-2.78/t/z_pod.t0000644000175000017500000000036113415647142013062 0ustar rurbanrurban# -*- perl -*- use strict; use Test::More; plan skip_all => 'No RELEASE_TESTING' unless -d '.git' || $ENV{RELEASE_TESTING}; eval "use Test::Pod 1.00"; plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; all_pod_files_ok(); GD-2.78/Makefile.PL0000644000175000017500000006126114450761142013274 0ustar rurbanrurbanuse ExtUtils::MakeMaker qw(prompt WriteMakefile); use ExtUtils::Constant 'WriteConstants'; use Config; use strict; require 5.6.0; unless (@ARGV) { warn < PATHS: CHECK AND ADJUST <===== my (@INC,@LIBPATH,@LIBS,$LIBGD_VERSION); my $AUTOCONFIG = 0; # global set by try_to_autoconfigure() below my $HAVE_GD2 = 1; # until libgd 2.3.1, unset by try_to_autoconfigure() my ($options,$lib_gd_path,$lib_ft_path,$lib_png_path,$lib_jpeg_path,$lib_xpm_path, $lib_tiff_path,$lib_webp_path,$lib_raqm_path,$lib_heif_path,$lib_avif_path, $lib_zlib_path,$lib_fontconfig_path,$force,$FCGI,$gdlib_config_path); use Getopt::Long; my $result = GetOptions("ignore_missing_gd" => \$force, "options=s" => \$options, "lib_gd_path=s" => \$lib_gd_path, "lib_ft_path=s" => \$lib_ft_path, "lib_png_path=s" => \$lib_png_path, "lib_jpeg_path=s" => \$lib_jpeg_path, "lib_tiff_path=s" => \$lib_tiff_path, "lib_xpm_path=s" => \$lib_xpm_path, "lib_webp_path=s" => \$lib_webp_path, "lib_raqm_path=s" => \$lib_raqm_path, "lib_heif_path=s" => \$lib_heif_path, "lib_avif_path=s" => \$lib_avif_path, "lib_zlib_path=s" => \$lib_zlib_path, "lib_fontconfig_path=s" => \$lib_fontconfig_path, "gdlib_config_path=s" => \$gdlib_config_path, "fcgi" => \$FCGI, ); unless (try_to_autoconfigure() || $force) { die <.config.cache"; print F $DEFINES,"\n"; close F; my $CCFLAGS = $Config{ccflags}; $CCFLAGS .= " -Wall -Wextra -Wformat=1" if $Config{gccversion} and $] > 5.020; # hardened CFLAGS for testing #$CCFLAGS .= ' -D_GNU_SOURCE -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches'; my $LDDLFLAGS = $Config{lddlflags}; # fixup mingw linker problems with empty weak symbols $LDDLFLAGS .= " -Wl,--verbose" if $Config{gccversion} and $^O eq 'MSWin32'; my $LD = $Config{ld}; if ($LD eq 'g++' and $^O eq 'MSWin32') { $LD = 'gcc'; } my %WriteMakefileArgs = ( 'NAME' => 'GD', 'ABSTRACT' => 'Perl interface to the libgd graphics library', 'VERSION_FROM' => 'lib/GD.pm', 'PREREQ_PM' => { 'Math::Trig' => 0, }, 'CONFIGURE_REQUIRES' => { 'ExtUtils::Constant' => 0.22, 'ExtUtils::PkgConfig' => 0, }, 'TEST_REQUIRES' => { 'Test::More' => 0.88, 'Test::Fork' => 0.02, 'Test::NoWarnings' => '1.00', }, 'PL_FILES' => {'bdf_scripts/bdf2gdfont_pl.PL' => 'bdf_scripts/bdf2gdfont.pl', 'lib/GD/Image_pm.PL' => 'lib/GD/Image.pm'}, 'LIBS' => [join(' ',$ENV{'GD_LIBS'},@LIBPATH,@LIBS)], 'INC' => join(' ',$ENV{'GD_INC'},@INC), 'LD' => $LD, 'CCFLAGS' => $CCFLAGS, 'LDDLFLAGS' => $LDDLFLAGS, 'EXE_FILES' => ['bdf_scripts/bdf2gdfont.pl'], 'AUTHOR' => 'Lincoln Stein ', # Maintained by Reini Urban now $CAPI ? ('CAPI' => 'TRUE') : (), 'DEFINE' => $DEFINES, 'clean' => { FILES => '.config.cache cover_db MANIFEST.git *.gcov GD.gcda GD.gcno' .' META.yml META.json' }, 'LICENSE' => 'perl_5', 'META_MERGE' => { "meta-spec" => { version => 2 }, recommends => { 'ExtUtils::PkgConfig' => 0, 'Math::Trig' => 0, 'ExtUtils::Constant'=> '0.23', 'Test::More' => '0.88', 'Test::Fork' => '0.02', 'Test::NoWarnings' => '1.00', }, resources => { repository => { web => "https://github.com/lstein/Perl-GD", url => "git://github.com/lstein/Perl-GD.git", type => 'git', }, license => "https://dev.perl.org/licenses/", }, prereqs => { develop => { requires => { 'Class::XSAccessor' => 0, 'Text::CSV_XS' => 0, 'List::MoreUtils' => 0, 'Test::Kwalitee' => 0, 'Pod::Spell::CommonMistakes' => 0, 'Test::Pod' => '1.00', 'Algorithm::Diff' => 0, 'Test::NoWarnings' => '1.00', }, }, }, }, SIGN => 1, ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) { my $br = delete $WriteMakefileArgs{BUILD_REQUIRES}; my $pp = $WriteMakefileArgs{PREREQ_PM}; for my $mod ( keys %$br ) { if ( exists $pp->{$mod} ) { $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod}; } else { $pp->{$mod} = $br->{$mod}; } } } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; delete $WriteMakefileArgs{TEST_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; delete $WriteMakefileArgs{META_MERGE} unless eval { ExtUtils::MakeMaker->VERSION(6.46) }; WriteMakefile(%WriteMakefileArgs); my @constants_iv = qw( GD_CMP_IMAGE GD_CMP_NUM_COLORS GD_CMP_COLOR GD_CMP_SIZE_X GD_CMP_SIZE_Y GD_CMP_TRANSPARENT GD_CMP_BACKGROUND GD_CMP_INTERLACE GD_CMP_TRUECOLOR GD_PIXELATE_UPPERLEFT GD_PIXELATE_AVERAGE gdBrushed gdDashSize gdMaxColors gdStyled gdStyledBrushed gdTiled gdTransparent gdAntiAliased gdArc gdPie gdChord gdNoFill gdEdged gdEffectReplace gdEffectAlphaBlend gdEffectNormal gdEffectOverlay gdEffectMultiply gdAlphaMax gdAlphaOpaque gdAlphaTransparent gdRedMax gdGreenMax gdBlueMax GD_MAJOR_VERSION GD_MINOR_VERSION GD_RELEASE_VERSION GD_FLIP_HORINZONTAL GD_FLIP_VERTICAL GD_FLIP_BOTH GD_RESOLUTION GD_DEFAULT GD_BELL GD_BESSEL GD_BILINEAR_FIXED GD_BICUBIC GD_BICUBIC_FIXED GD_BLACKMAN GD_BOX GD_BSPLINE GD_CATMULLROM GD_GAUSSIAN GD_GENERALIZED_CUBIC GD_HERMITE GD_HAMMING GD_HANNING GD_MITCHELL GD_NEAREST_NEIGHBOUR GD_POWER GD_QUADRATIC GD_SINC GD_TRIANGLE GD_WEIGHTED4 GD_LINEAR GD_METHOD_COUNT GD_AFFINE_TRANSLATE GD_AFFINE_SCALE GD_AFFINE_ROTATE GD_AFFINE_SHEAR_HORIZONTAL GD_AFFINE_SHEAR_VERTICAL ); # Note that ExtUtils::Constant::ProxySubs creates code incompatible # with <5.14. Only 0.23_04 has that fixed. if (!-e 'const-xs.inc' or !-e"const-c.inc") { WriteConstants( #PROXYSUBS => {autoload => 1}, NAME => 'GD', NAMES => \@constants_iv, DEFAULT_TYPE => 'IV'); } exit 0; sub try_to_autoconfigure { #my ($options,$lib_gd_path,$INC,$LIBPATH,$LIBS) = @_; my ($version, $cflags, $ldflags, $libs, $libdir, $features, $includedir); # perl Makefile.PL --lib_gd_path /opt/libgd/2.1.1/lib my ($prefix) = $lib_gd_path ? ($lib_gd_path =~ m|(^.*)/lib|) : ""; my $bindir = $prefix ? "$prefix/bin/" : $lib_gd_path ? "$lib_gd_path/bin/" : ""; my $config = `${bindir}gdlib-config --all` if -e "${bindir}gdlib-config"; if (!$config and !-e "$prefix/lib/pkgconfig/gdlib.pc" and !-e "/usr/lib/pkgconfig/gdlib.pc") { $gdlib_config_path = "gdlib-config" unless defined($gdlib_config_path); $config = `$gdlib_config_path --all`; } unless ($config) { my %config; require ExtUtils::PkgConfig; %config = ExtUtils::PkgConfig->find ("$prefix/lib/pkgconfig/gdlib.pc") if $prefix; %config = ExtUtils::PkgConfig->find ("gdlib") unless %config; return unless %config; $version = $config{modversion}; warn "Configuring for libgd version $version.\n"; $cflags = $config{cflags}; $libs = $config{libs}; ($libdir, $libs) = $libs =~ m/-L(.*) (-lgd.*)/; # Requires.private: zlib libpng freetype2 >= 9.8.3 fontconfig libjpeg xpm libtiff-4 # Libs.private: -L/opt/local/lib -lz -L/opt/local/lib -lpng16 -L/opt/local/lib -lfreetype -L/opt/local/lib -lfontconfig -lfreetype -ljpeg -L/opt/local/lib -lXpm -lX11 -L/opt/local/lib -ltiff -lwebp # not in the hash! # check the .pc file from $config{pkg} if ($config{pkg} and -e $config{pkg}) { my $F; open $F, "<", $config{pkg}; my $private; while (<$F>) { next unless /^Requires.private/; $private = $_; } close $F; $features = 'GD_GIF GD_OPENPOLYGON'; $features .= ' GD_ZLIB' if $private =~ / zlib /; $features .= ' GD_PNG' if $private =~ / libpng /; $features .= ' GD_FREETYPE' if $private =~ / freetype/; $features .= ' GD_FONTCONFIG' if $private =~ / fontconfig/; $features .= ' GD_RAQM' if $private =~ / raqm/; $features .= ' GD_JPEG' if $private =~ / libjpeg/; $features .= ' GD_XPM' if $private =~ / xpm/; $features .= ' GD_TIFF' if $private =~ / libtiff/; $features .= ' GD_WEBP' if $private =~ / libwebp/; $features .= ' GD_HEIF' if $private =~ / libheif/; $features .= ' GD_AVIF' if $private =~ / libavif/; } else { $features = 'GD_GIF GD_OPENPOLYGON GD_ZLIB GD_PNG GD_FREETYPE GD_FONTCONFIG GD_JPEG GD_XPM GD_TIFF GD_WEBP'; #$features .= 'GD_WEBP' if $version ge '2.3.0';; $features .= ' GD_AVIF' if $version ge '2.3.2'; $features .= ' GD_HEIF' if $version ge '2.3.3'; } $AUTOCONFIG++; } else { $AUTOCONFIG++; ($version) = $config =~ /^GD library\s+(\S+)/m; warn "Configuring for libgd version $version.\n"; ($includedir) = $config =~ /^includedir:\s*(.+)$/m; ($cflags) = $config =~ /^cflags:\s*(.+)$/m; ($ldflags) = $config =~ /^ldflags:\s*(.+)$/m; ($libs) = $config =~ /^libs:\s*(.+)$/m; ($libdir) = $config =~ /^libdir:\s*(.+)$/m; ($features) = $config =~ /^features:\s*(.+)$/m; ($includedir) = $config =~ /^includedir:\s*(.+)$/m; } $LIBGD_VERSION = $version; @INC = map {s/^-I// && "-I$_"} split /\s+/,$cflags; @LIBS = split /\s+/,$libs; if ($libdir) { if ($config) { @LIBPATH = map {s/^-L// && "-L$_"} split /\s+/,$ldflags; ($lib_gd_path = $libdir) =~ s!/[^/]+$!!; } else { $lib_gd_path = $libdir; } push @LIBPATH,"-L$libdir"; } push @LIBS,"-lgd" unless $libs =~ /-lgd/; if (!$options) { $options = $features; my ($release, $major, $minor) = $version =~ /^(\d+)\.(\d+)\.(\d+)/; $options .= " GD_UNCLOSEDPOLY GD_FTCIRCLE VERSION_33" if defined($minor) && ($release > 2 || ($release == 2 && $major > 0) || ($release == 2 && $major == 0 && $minor >= 33)); $options .= " WINDOWS_BMP" if defined($minor) && ($release > 2 || ($release == 2 && $major > 0)); if (defined($minor) && ($release > 2 || ($release == 2 && $major > 3) || ($release == 2 && $major == 3 && $minor >= 2))) { $HAVE_GD2 = 0; $AVIF = 1; } else { $options .= " GD2"; $HAVE_GD2 = 1; $AVIF = 0; $HEIF = 0; } if (defined($minor) && ($release > 2 || ($release == 2 && $major > 3) || ($release == 2 && $major == 3 && $minor >= 3))) { $HEIF = 1; } } if ($config) { my @correct_inc = map {s/^-I// && $_} split /\s+/,$cflags; check_for_stray_headers($includedir,@correct_inc); } return 1; } sub check_for_stray_headers { my @official_libraries = @_; my %official_libraries = map {$_=>1} @official_libraries; print STDERR "Checking for stray libgd header files..."; my $cc = $Config{'cc'}; my $data = `$cc -print-search-dirs 2>/dev/null`; $data ||= ''; my ($libraries) = $data =~ /^libraries: =(.+)/m; my @cc_libs = split /:/,$libraries; foreach (@cc_libs) { s/\/$//; } my %libraries = map {$_=>1} (@cc_libs,'/include','/usr/include', '/usr/local/include','/opt/include', '/usr/X11R6/include'); my $problems; my $o = $official_libraries[0]; foreach (keys %libraries) { s/\blib\b/include/; next if $official_libraries{$_}; next unless -e "$_/gd.h"; if (-l "$_/gd.h" or -l "$o/gd.h") { next if (stat("$_/gd.h"))[1] == (stat("$o/gd.h"))[1]; } warn "\n\n** WARNING: found gd.h header file in ${_}/gd.h, but it is expected at $official_libraries[0]/gd.h. This may cause compile errors! **\n"; $problems++; } print STDERR $problems ? "** Possible problems found **\n" : "none found.\n"; print STDERR "\n"; } sub MY::postamble { my $postamble = <<'END'; html: lib/GD.pm pod2html --outfile=GD.html lib/GD.pm END $postamble; } package MY; # Ignore templates sub libscan { return 0 if $_[1] =~ /_p[ml].PL$/; return $_[1]; } sub processPL { my $inherited = shift->SUPER::processPL(@_); $inherited =~ s/(:: lib\/GD\/Image_pm\.PL)/$1 .config.cache/; $inherited; } sub depend { " release : dist git tag release_\$(VERSION_SYM) cpan-upload \$(DISTVNAME).tar\$(SUFFIX) git push git push --tags const-c.inc const-xs.inc : Makefile.PL GCOV = gcov test_cover :: pure_all \$(RM_RF) cover_db +\$(PERLRUNINST) -S cover -test test_coveralls :: pure_all +\$(PERLRUNINST) -S cover -test -report coveralls gcov : \$(BASEEXT).c.gcov \$(BASEEXT).gcov cover_db/\$(BASEEXT)-xs.html \$(BASEEXT).c.gcov \$(BASEEXT).xs.gcov : \$(BASEEXT).xs \$(MAKE) CCFLAGS=\"\$(CCFLAGS) -fprofile-arcs -ftest-coverage\" LDDLFLAGS=\"\$(LDDLFLAGS) -fprofile-arcs -ftest-coverage\" \$(GCOV) \$(BASEEXT).c \$(BASEEXT).xs cover_db/\$(BASEEXT)-xs.html : \$(BASEEXT).xs.gcov PERL5OPT=-MDevel::Cover make test -$^X -S gcov2perl \$(BASEEXT).c.gcov \$(BASEEXT).xs.gcov $^X -S cover gprof : \$(MAKE) CCFLAGS=\"\$(CCFLAGS) -pg\" LDDLFLAGS=\"\$(LDDLFLAGS) -pg\" " } GD-2.78/bdf_scripts/0000755000175000017500000000000014450761210013612 5ustar rurbanrurbanGD-2.78/bdf_scripts/cvtbdf.pl0000755000175000017500000001614013076115434015430 0ustar rurbanrurban#!/usr/local/bin/perl # Filename - cvtbdf.pl # Author - Geoff Baysinger (gbaysing@HiWAAY.net) # Purpose - Allows "simple" installation of additional BDF fonts for GD.pm # Usage - "cvtbdf.pl" (no arguments, see instructions) # License - Freely given to be distributed with the GD.pm libraries # (you may modify this script to your heart's content, # but it may only be distributed by the author or via the GD.pm # package.) # # Summary - # Uses "bdftogd", (provided with GD.pm) to convert BDF fonts to GD format. # It should makes the edits necessary to the GD.pm source files so that. # the "bdftogd" process is automated and all the user needs do is recompile # the GD.pm package (only "GD.so" is changed during compilation). # # Instructions - # 1) go to your GD.pm source installation directory # note: if you have already installed GD.pm, run a "make clean" # 2) create a subdirectory called "fonts" (mkdir fonts) # 3) copy the BDF font files you wish to convert to the "fonts" directory # note: The BDF font must be a type that "bdftogd" can convert, hence # it must be a standard monospaced character font, not a BDF # cursor file. Some monospaced fonts may still not work. Test # with "bdftogd" before running this script if you are unsure. # 4) copy "bdftogd" and "cvtbdf.pl" to the "fonts" directory # 5) run "cvtbdf.pl" # 6) go to your GD.pm source installation directory and install the new # version via a "make" and "make install" # # Notes - # A) Keep the "fonts" subdirectory and all fonts you wish to use in the # future. Each time you want to add a font you will need the old ones # in the directory, or they will disappear during the next recompile. # B) Add new fonts in the future is as easy as copying the .bdf file to # the "fonts" directory and running steps #5 and #6 again. # # Thanks - # To Lincoln Stein for the use of CGI.pm and GD.pm and to all other # contributors of those packages. # make sure we have the conversion program if (! -x "bdftogd") { die "OOPS!\n Can't execute 'bdftogd', is it even there?\n error: $!\n\n"; } &badnames; &saveorig("GD.pm","GD.xs","libgd/Makefile.PL"); ©orig("GD.pm","GD.xs","libgd/Makefile.PL"); for $i (@files) { open(OLDXS,"../GD.xs") || die "OOPS!\n Can't open '../GD.xs' for reading\n Make sure you're in a 'fonts' subdirectory\n error: $!\n\n"; open(NEWXS,"> ../GD.xs.fonts") || die "OOPS!\n Can't open '../GD.xs.fonts' for writing\n Make sure you're in a 'fonts' subdirectory\n error: $!\n\n"; open(OLDPM,"../GD.pm") || die "OOPS!\n Can't open '../GD.pm' for reading\n Make sure you're in a 'fonts' subdirectory\n error: $!\n\n"; open(NEWPM,"> ../GD.pm.fonts") || die "OOPS!\n Can't open '../GD.pm.fonts' for writing\n Make sure you're in a 'fonts' subdirectory\n error: $!\n\n"; open(OLDMAKE,"../libgd/Makefile.PL") || die "OOPS!\n Can't open '../libgd/Makefile.PL' for reading\n Make sure you're in a 'fonts' subdirectory\n error: $!\n\n"; open(NEWMAKE,"> ../libgd/Makefile.PL.fonts") || die "OOPS!\n Can't open '../libgd/Makefile.PL.fonts' for writing\n Make sure you're in a 'fonts' subdirectory\n error: $!\n\n"; # some state-keeping variables my $extern; my $package; my $export; my $preload; my $h; my $c; # figure out our "name" my $name = "BDF" . $i; $name =~ /(.*)\.bdf/; $name = $1; print "=> name = $name\n"; # do the actual font conversion: open(FONT,"$i"); # usage: bdftogd fontname filename, eg. bdftogd FontLarge gdfontl } my $fontname = "Font" . $name; my $filename = "font" . $name; my $gdname = "gdfont" . $name; open(CONVERT,"| bdftogd $fontname $filename"); while () { print CONVERT; } close CONVERT; # move the font files to "../libgd" open(OLD,"${gdname}.h"); open(NEW,"> ../libgd/${gdname}.h"); while () { print NEW; } close OLD; close NEW; unlink("${gdname}.h"); open(OLD,"${gdname}.c"); open(NEW,"> ../libgd/${gdname}.c"); while () { print NEW; } close OLD; close NEW; unlink("${gdname}.c"); ## Begin editing files # GD.xs: while () { $data = $_; if (! $extern && $data =~ /^extern[\s]{1,}gdFontPtr/) { $data = "extern gdFontPtr gdFont" . $name . ";\n" . $data; $extern = 1; } elsif (! $package && $data =~ /^MODULE[\s]*=[\s]*GD[\s]{1,}PACKAGE[\s]*=[\s]*GD::Font[\s]{1,}PREFIX=gd/) { $data .= "\nGD::Font\ngd" . $name . "(packname=\"GD::Font\")\n char * packname\n PROTOTYPE: \$\n CODE:\n {\n RETVAL = gdFont" . $name . ";\n }\n OUTPUT:\n RETVAL\n"; $package = 1; } print NEWXS $data; } # GD.pm: while () { $data = $_; if (! $export && $data =~ /\@EXPORT = qw\(/) { $data .= " gd" . $name . "Font\n"; $export = "done"; } elsif (! $preload && $data =~ /^# Preloaded methods go here./) { $data .= "sub GD::gd" . $name . "Font {\n return &GD::Font::" . $name . ";\n}\n"; $preload = "done"; } print NEWPM $data; } # libgd/Makefile.PL: while () { $data = $_; # 'H' => [qw(gd.h gdfontl.h gdfonts.h io.h gdfontg.h gdfontmb.h gdfontt.h mtables.h)], if (! $h && $data =~ /^([\s]*'H'[\s]*\=\>[\s]*\[qw\(gd\.h[\s])(.*)/) { $data = $1 . "${gdname}.h " . $2 . "\n"; $h = "done"; } elsif (! $c && $data =~ /^([\s]*'C'[\s]*\=\>[\s]*\[qw\(gdfontg\.c[\s])(.*)/) { # 'C' => [qw(gdfontg.c gdfontmb.c gdfontt.c gdfontl.c gdfonts.c libgd.c)], $data = $1 . "${gdname}.c " . $2 . "\n"; $c = "done"; } print NEWMAKE $data; } # close the files close OLDXS; close NEWXS; close OLDPM; close NEWPM; close OLDMAKE; close NEWMAKE; # copy the files to the proper extension open(NEWXS,"../GD.xs.fonts"); open(OLDXS,"> ../GD.xs"); open(NEWPM,"../GD.pm.fonts"); open(OLDPM,"> ../GD.pm"); open(NEWMAKE,"../libgd/Makefile.PL.fonts"); open(OLDMAKE,"> ../libgd/Makefile.PL"); while () { print OLDXS; } while () { print OLDPM; } while () { print OLDMAKE; } close NEWXS; close OLDXS; close NEWPM; close OLDPM; close NEWMAKE; close OLDMAKE; # unlink the temp files unlink "../GD.pm.fonts"; unlink "../GD.xs.fonts"; unlink "../libgd/Makefile.PL.fonts"; } sub saveorig { local (@files) = @_; for $file (@files) { if (! -f "../${file}.orig") { open(OLD,"../$file") || die $!; open(ORIG,"> ../${file}.orig") || die $!; while () { print ORIG; } close OLD; close ORIG; } } } sub copyorig { local(@files) = @_; for $file (@files) { open(ORIG,"../${file}.orig") || die $!; open(NEW,"> ../$file") || die $!; while () { print NEW; } close ORIG; close NEW; } } sub badnames { @badnames = (<*.BDF>,<*.Bdf>,<*.BDf>,<*.bDf>,<*.bDF>,<*.BdF>); for $i (@badnames) { my $goodname = $i; $goodname =~ tr/A-Z/a-z/; open(BAD,"$i"); open(GOOD,"> $goodname"); while () { print GOOD; } close BAD; close GOOD; unlink $i; } @files = <*.bdf>; } GD-2.78/bdf_scripts/README0000644000175000017500000000055313076115434014501 0ustar rurbanrurbanThe bdf2gdfont.pl script will convert an X11 BDF font into a bitmapped font that can be loaded into GD using the GD::Font->load() method. Some restrictions apply. Run "perldoc bdf2gdfont.pl" for details. Other scripts in this directory were designed for older versions of libgd in which the fonts are compiled in. Please use with care. Lincoln Stein Fall 2004 GD-2.78/bdf_scripts/bdftogd0000755000175000017500000000776213076115434015171 0ustar rurbanrurban#!/usr/bin/perl -w # # Simple convertor from bdf to gd font format. # # Author: Jan Pazdziora, adelton@fi.muni.cz, http://www.fi.muni.cz/~adelton/ # at Faculty of Informatics, Masaryk University in Brno, Czech Republic. # # Example of use: # fstobdf -s fontserverhost:7100 -fn 8x16 | ./bdftogd FontLarge gdfontl # use strict; my $VERSION = '0.60'; my $now = localtime; if (@ARGV < 2) { die "usage: bdftogd fontname filename, eg. bdftogd FontLarge gdfontl\n"; } my $gdname = shift; $gdname = 'gd' . $gdname unless $gdname =~ /^gd/i; my $filename = shift; $filename = 'gd' . $filename unless $filename =~ /^gd/i; if (-f "$filename.c") { die "File $filename.c already exists, won't overwrite\n"; } if (-f "$filename.h") { die "File $filename.h already exists, won't overwrite\n"; } my ($width, $height); my (@data, @left, @bottom); my ($globalleft, $globaltop); my ($minchar, $maxchar); my ($copyright, $fontdef); my $currentchar; my $gobitmap = 0; while (<>) { chomp; s/\r$//; my ($tag, $value) = split / /, $_, 2; die "Font is not fixed width\n" if $tag eq 'SPACING' and not $value =~ /[CM]/i; $currentchar = $value if $tag eq 'ENCODING'; $minchar = $currentchar if not defined $minchar or ($currentchar < $minchar && $currentchar >= 0); $maxchar = $currentchar if not defined $maxchar or ($currentchar > $maxchar && $currentchar >= 0); if ($tag eq 'ENDCHAR') { next if $currentchar < 0; $gobitmap = 0; my $bottom = $globaltop - $bottom[$currentchar]; if ($bottom > 0) { $data[$currentchar] = substr $data[$currentchar], 0, length($data[$currentchar]) - $bottom * $width; } else { $data[$currentchar] .= '0' x (-$bottom * $width); } } if ($tag eq 'FONTBOUNDINGBOX') { my ($tag, $wid, $hei, $left, $top) = split / /; if (defined $top) { $globalleft = $left; $globaltop = $top; $height = $hei; $width = $wid; } } if ($tag eq 'FONT' and not defined $fontdef) { $fontdef = $value; } if ($tag eq 'COPYRIGHT' and not defined $copyright) { $copyright = $value; } if ($tag eq 'BBX') { my ($tag, $wid, $hei, $left, $bottom) = split / /; if (defined $bottom) { $left[$currentchar] = $left; $bottom[$currentchar] = $bottom; } } if ($gobitmap) { my $value = pack 'H*', $_; my $bits = unpack 'B*', $value; $bits = ('0' x $left[$currentchar]) . $bits; $bits .= '0' x ($width - length $bits); $bits = substr $bits, 0, $width; $data[$currentchar] .= $bits; } if ($tag eq 'BITMAP') { $gobitmap = 1; $data[$currentchar] = ''; } } my $info = <<"EOF"; /* This is a header file for gd font, generated using bdftogd version $VERSION by Jan Pazdziora, adelton\@fi.muni.cz from bdf font $fontdef at $now. EOF if (defined $copyright) { $info .= <<"EOF"; The original bdf was holding following copyright: $copyright */ EOF } else { $info .= <<"EOF"; No copyright info was found in the original bdf. */ EOF } open FILEC, "> $filename.c" or die "Error writing $filename.c: $!\n"; open FILEH, "> $filename.h" or die "Error writing $filename.h: $!\n"; print FILEC <<"EOF"; $info #include "$filename.h" char ${gdname}Data[] = { EOF $minchar = 0 unless defined $minchar; $maxchar = 255 unless defined $maxchar; for (my $i = $minchar; $i <= $maxchar; $i++) { $data[$i] = '' unless defined $data[$i]; $data[$i] = '0' x ($width * $height - length $data[$i]) . $data[$i]; print FILEC "/* Char $i */\n"; for my $line (0 .. $height - 1) { print FILEC join ',', split(//, substr($data[$i], $line * $width, $width)), "\n"; } print FILEC "\n"; next; for my $line (0 .. $height - 1) { print substr($data[$i], $line * $width, $width), "\n"; } } my $capdef = "\U_${filename}_H_"; print FILEC <<"EOF"; }; gdFont ${gdname}Rep = { @{[ $maxchar - $minchar + 1]}, $minchar, $width, $height, ${gdname}Data }; gdFontPtr ${gdname} = &${gdname}Rep; /* This file has not been truncated. */ EOF close FILEC; print FILEH <<"EOF"; #ifndef $capdef #define $capdef 1 $info #include "gd.h" extern gdFontPtr $gdname; #endif EOF 1; GD-2.78/bdf_scripts/bdf2gdfont_pl.PL0000644000175000017500000001233013415647142016567 0ustar rurbanrurban#!perl use Config; use File::Basename qw(&basename &dirname); use Cwd; my $origdir = cwd; my $dir = dirname($0); chdir $dir; my $file = 'bdf2gdfont'; $file .= $^O eq 'VMS' ? '.com' : '.pl'; open OUT,">",$file or die "Can't create $file: $!"; print "Extracting $file (with variable substitutions)\n"; print OUT <<"!GROK!THIS!"; $Config{startperl} !GROK!THIS! # In the following, perl variables are not expanded during extraction. print OUT <<'!NO!SUBS!'; # # Simple convertor from bdf to loadable GD font format. # # Author: Lincoln Stein , heavily adopted from bdftogd from # Jan Pazdziora # # Example of use: # fstobdf -s fontserverhost:7100 -fn 8x16 | bdftofnt > myfont.fnt # use strict; our $VERSION = '1.00'; if ($ARGV[0] =~ /^--?h/) { exec "perldoc $0"; } my ($width, $height); my (@data, @left, @bottom); my ($globalleft, $globaltop); my ($minchar, $maxchar); my ($copyright, $fontdef); my $currentchar; my $gobitmap = 0; foreach (@ARGV) { $_ = "gunzip -c $_ |" if /\.gz$/; } while (<>) { chomp; s/\r$//; next unless $_; my ($tag, $value) = split / /, $_, 2; die "Font is not fixed width\n" if $tag eq 'SPACING' and not $value =~ /[CM]/i; $currentchar = $value if $tag eq 'ENCODING'; $minchar = $currentchar if not defined $minchar or ($currentchar < $minchar && $currentchar >= 0); $maxchar = $currentchar if not defined $maxchar or ($currentchar > $maxchar && $currentchar >= 0); if ($tag eq 'ENDCHAR') { next if $currentchar < 0; $gobitmap = 0; my $bottom = $globaltop - $bottom[$currentchar]; if ($bottom > 0) { $data[$currentchar] = substr $data[$currentchar], 0, length($data[$currentchar]) - $bottom * $width; } else { $data[$currentchar] .= '0' x (-$bottom * $width); } } if ($tag eq 'FONTBOUNDINGBOX') { my ($tag, $wid, $hei, $left, $top) = split / /; if (defined $top) { $globalleft = $left; $globaltop = $top; $height = $hei; $width = $wid; } } if ($tag eq 'FONT' and not defined $fontdef) { $fontdef = $value; } if ($tag eq 'COPYRIGHT' and not defined $copyright) { $copyright = $value; } if ($tag eq 'BBX') { my ($tag, $wid, $hei, $left, $bottom) = split / /; if (defined $bottom) { $left[$currentchar] = $left; $bottom[$currentchar] = $bottom; } } if ($gobitmap) { my $value = pack 'H*', $_; my $bits = unpack 'B*', $value; $bits = ('0' x $left[$currentchar]) . $bits; $bits .= '0' x ($width - length $bits); $bits = substr $bits, 0, $width; $data[$currentchar] .= $bits; } if ($tag eq 'BITMAP') { $gobitmap = 1; $data[$currentchar] = ''; } } $minchar = 0 unless defined $minchar; $maxchar = 255 unless defined $maxchar; binmode STDOUT; # for DOS/Windows systems my $length = $maxchar-$minchar+1; print pack ('VVVV',$length,$minchar,$width,$height); # header for (my $i = $minchar; $i <= $maxchar; $i++) { $data[$i] = '' unless defined $data[$i]; $data[$i] = '0' x ($width * $height - length $data[$i]) . $data[$i]; print pack('C*',split '',$data[$i]); } print STDERR "Successfully converted $length ${width}x$}height} characters\n"; __END__ =head1 NAME bdf2gdfont.pl - Convert X11 "BDF" fonts into a loadable font format for GD. =head1 SYNOPSIS % bdf2gdfont.pl courR12.bdf > courR12.fnt =head1 DESCRIPTION This script converts BDF-style X11 font files into a format that can be loaded by the GD module using the GD::Font->load() method. There are a number of ways to obtain BDF fonts. =over 4 =item 1. The font is already present on your system. Some BDF fonts can be found in the standard X11R6 distribution. This script will automatically uncompress gzipped font files if their extension ends with .gz (the gunzip program must be on your path). =item 2. From a font server. The "fstobdf" utility, a standard X11 utility, will read a named font from the font server of your choice and return it in BDF format. You can pipe it to bdf2gdfont.pl: fstobdf -s fontserverhost:7100 -fn 8x16 | bdf2gdfont.pl > newfont.fnt Use xlsfonts to find out what fonts are available. Most fonts will have long names like -B&H-LucidaTypewriter-Bold-R-Normal-Sans-18-180-75-75-M-110-ISO8859-10. =item 3. Using the pcf2bdf utility. Some fonts are only available in PCF (compiled) format. To obtain these, you can either turn on a font server and follow recipe (2), or use TAGA Nayuta's pcf2bdf utility. This utility is available from http://www.tsg.ne.jp/GANA/S/pcf2bdf/ (page is in Japanese, but you can find the download link). =back =head2 Limitations This font converter only works with fixed-width fonts. If used with a TrueType or proportional font it will die with an error message. =head1 SEE ALSO L =head1 AUTHOR Lincoln Stein , heavily adapted from bdftogd from Jan Pazdziora . Copyright (c) 2004 Cold Spring Harbor Laboratory This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut !NO!SUBS! close OUT or die "Can't close $file: $!"; chmod 0755, $file or die "Can't reset permissions for $file: $!\n"; exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':'; chdir $origdir; GD-2.78/MANIFEST.SKIP0000644000175000017500000000030514174320547013213 0ustar rurbanrurban^\.travis\.yml ^\.appveyor\.yml ^\.github/workflows/testsuite\.yml ^\.config ^\.gdbinit \bGD-\d+ \bGD\.c$ ^MYMETA\.yml$ ^MYMETA\.json$ \.git ~$ \.bak$ \b# lib/GD/Image.pm bdf_scripts/bdf2gdfont.pl GD-2.78/GD.xs0000644000175000017500000017543514435047447012211 0ustar rurbanrurban#ifdef PERL_CAPI #define WIN32IO_IS_STDIO #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include #include #include #include #include #include /* 2.0.x: < 2.1.0-alpha */ #ifndef GD_VERSION_STRING # if defined(GD2_VERS) && (GD2_VERS==2) # ifdef VERSION_33 # define GD_VERSION 20033 # define GD_VERSION_STRING "2.0.33" # else # define GD_VERSION 20032 # define GD_VERSION_STRING "2.0.x" # endif # else # define GD_VERSION 10000 # define GD_VERSION_STRING "?" # endif #else # define GD_VERSION ((GD_MAJOR_VERSION * 10000) +\ (GD_MINOR_VERSION * 100) +\ GD_RELEASE_VERSION) #endif #ifdef FCGI #include #else #ifdef USE_SFIO #include #else #include #endif #include #endif /* Copyright 1995 - 1998, Lincoln D. Stein. See accompanying README file for usage restrictions */ #ifndef PERL_REVISION # ifndef __PATCHLEVEL_H_INCLUDED__ # include "patchlevel.h" # endif # ifndef PERL_REVISION # define PERL_REVISION (5) /* Replace: 1 */ # define PERL_VERSION PATCHLEVEL # define PERL_SUBVERSION SUBVERSION /* Replace PERL_PATCHLEVEL with PERL_VERSION */ /* Replace: 0 */ # endif #endif #if (PERL_VERSION == 5) && (PERL_SUBVERSION==3) #ifndef PL_na # define PL_na na #endif #ifndef SvPV_nolen # define SvPV_nolen(sv) SvPV(sv, PL_na) #endif #endif /* 5.00503 */ #ifndef dMY_CXT # define dMY_CXT (void)0 #endif #ifndef PERL_UNUSED_ARG # define PERL_UNUSED_ARG(x) ((void)sizeof(x)) #endif #ifndef mPUSHp #define mPUSHp(p,l) PUSHs(sv_2mortal(newSVpvn((p), (l)))) #endif #ifndef mPUSHi #define mPUSHi(i) PUSHs(sv_2mortal(newSViv((i)))) #endif #ifndef mPUSHn #define mPUSHn(n) PUSHs(sv_2mortal(newSVnv((n)))) #endif #ifndef mXPUSHp # define mXPUSHp(p,l) STMT_START { EXTEND(sp,1); mPUSHp((p), (l)); } STMT_END #endif #ifndef mXPUSHi # define mXPUSHi(i) STMT_START { EXTEND(sp,1); mPUSHi((i)); } STMT_END #endif #ifndef mXPUSHn # define mXPUSHn(i) STMT_START { EXTEND(sp,1); mPUSHn((i)); } STMT_END #endif #ifndef hv_fetchs # define hv_fetchs(H, K, L) hv_fetch((H), (K), sizeof(K)-1, (L)) #endif #ifdef WIN32 # define snprintf _snprintf #endif #ifndef START_MY_CXT static int truecolor_default = 0; #endif #include "const-c.inc" typedef gdImagePtr GD__Image; typedef gdFontPtr GD__Font; typedef PerlIO * InputStream; #ifdef PERL_OBJECT # ifdef WIN32 #define GDIMAGECREATEFROMPNG(x) gdImageCreateFromPng((FILE*)x) #define GDIMAGECREATEFROMXBM(x) gdImageCreateFromXbm((FILE*)x) #define GDIMAGECREATEFROMJPEG(x) gdImageCreateFromJpeg((FILE*)x) #define GDIMAGECREATEFROMGIF(x) gdImageCreateFromGif((FILE*)x) #define GDIMAGECREATEFROMWBMP(x) gdImageCreateFromWBMP((FILE*)x) #define GDIMAGECREATEFROMBMP(x) gdImageCreateFromBmp((FILE*)x) #define GDIMAGECREATEFROMTIFF(x) gdImageCreateFromTiff((FILE*)x) #define GDIMAGECREATEFROMGD(x) gdImageCreateFromGd((FILE*)x) #define GDIMAGECREATEFROMGD2(x) gdImageCreateFromGd2((FILE*)x) #define GDIMAGECREATEFROMGD2PART(x,a,b,c,d) gdImageCreateFromGd2Part((FILE*)x,a,b,c,d) #define GDIMAGECREATEFROMWEBP(x) gdImageCreateFromWebp((FILE*)x) #define GDIMAGECREATEFROMHEIF(x) gdImageCreateFromHeif((FILE*)x) #define GDIMAGECREATEFROMAVIF(x) gdImageCreateFromAvif((FILE*)x) # endif #else # ifdef USE_PERLIO #define GDIMAGECREATEFROMPNG(x) gdImageCreateFromPng(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMXBM(x) gdImageCreateFromXbm(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMJPEG(x) gdImageCreateFromJpeg(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGIF(x) gdImageCreateFromGif(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMWBMP(x) gdImageCreateFromWBMP(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMBMP(x) gdImageCreateFromBmp(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMTIFF(x) gdImageCreateFromTiff(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGD(x) gdImageCreateFromGd(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGD2(x) gdImageCreateFromGd2(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGD2PART(x,a,b,c,d) gdImageCreateFromGd2Part(PerlIO_findFILE(x),a,b,c,d) #define GDIMAGECREATEFROMWEBP(x) gdImageCreateFromWebp(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMHEIF(x) gdImageCreateFromHeif(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMAVIF(x) gdImageCreateFromAvif(PerlIO_findFILE(x)) # else #define GDIMAGECREATEFROMPNG(x) gdImageCreateFromPng(x) #define GDIMAGECREATEFROMXBM(x) gdImageCreateFromXbm(x) #define GDIMAGECREATEFROMJPEG(x) gdImageCreateFromJpeg(x) #define GDIMAGECREATEFROMGIF(x) gdImageCreateFromGif(x) #define GDIMAGECREATEFROMWBMP(x) gdImageCreateFromWBMP(x) #define GDIMAGECREATEFROMBMP(x) gdImageCreateFromBmp(x) #define GDIMAGECREATEFROMTIFF(x) gdImageCreateFromTiff(x) #define GDIMAGECREATEFROMGD(x) gdImageCreateFromGd(x) #define GDIMAGECREATEFROMGD2(x) gdImageCreateFromGd2(x) #define GDIMAGECREATEFROMGD2PART(x,a,b,c,d) gdImageCreateFromGd2Part(x,a,b,c,d) #define GDIMAGECREATEFROMWEBP(x) gdImageCreateFromWebp(x) #define GDIMAGECREATEFROMHEIF(x) gdImageCreateFromHeif(x) #define GDIMAGECREATEFROMAVIF(x) gdImageCreateFromAvif(x) # endif #endif #define littleendian(a) \ (a[3]<<24)+(a[2]<<16)+(a[1]<<8)+a[0] /* definitions required to create images from in-memory buffers */ typedef struct bufIOCtx { gdIOCtx ctx; char* data; int length; int pos; } bufIOCtx; typedef struct bufIOCtx *bufIOCtxPtr; static int bufGetC (gdIOCtxPtr ctx) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; if (bctx->pos >= bctx->length) return EOF; return bctx->data[bctx->pos]; } static int bufGetBuf (gdIOCtxPtr ctx, void* buf, int len) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; int remain,rlen; remain = bctx->length - bctx->pos; if (remain >= len) { rlen = len; } else { if (remain <= 0) return EOF; rlen = remain; } memcpy(buf,(void*)(bctx->data + bctx->pos),rlen); bctx->pos += rlen; return rlen; } static int bufSeek (gdIOCtxPtr ctx, const int pos) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; bctx->pos = pos; if (bctx->pos > bctx->length) bctx->pos = bctx->length; return TRUE; } static long bufTell (gdIOCtxPtr ctx) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; return bctx->pos; } static void bufFree(gdIOCtxPtr ctx) { Safefree(ctx); } static gdIOCtx* newDynamicCtx (char* data, int length) { bufIOCtxPtr ctx; #ifdef Newz Newz(0,ctx,1,bufIOCtx); #else Newxz(ctx,1,bufIOCtx); #endif if (ctx == NULL) return NULL; ctx->data = data; ctx->pos = 0; ctx->length = length; ctx->ctx.getC = bufGetC; ctx->ctx.getBuf = bufGetBuf; ctx->ctx.seek = bufSeek; ctx->ctx.tell = bufTell; ctx->ctx.gd_free = bufFree; ctx->ctx.putC = NULL; ctx->ctx.putBuf = NULL; return (gdIOCtx*)ctx; } /* helper routines for image transformation */ static GD__Image gd_cloneDim(GD__Image src, int x, int y) { GD__Image dst; if (gdImageTrueColor(src)) { dst = (GD__Image) gdImageCreateTrueColor(x,y); if (!dst) croak("gdImageCreateTrueColor error"); } else { int i; dst = (GD__Image) gdImageCreatePalette(x,y); if (!dst) croak("gdImageCreatePalette error"); /* copy across the palette information */ for (i = 0; i < gdMaxColors; i++) { dst->red[i] = src->red[i]; dst->green[i] = src->green[i]; dst->blue[i] = src->blue[i]; dst->alpha[i] = src->alpha[i]; dst->open[i] = src->open[i]; } dst->colorsTotal = src->colorsTotal; dst->transparent = src->transparent; dst->interlace = src->interlace; dst->thick = src->thick; } return(dst); } void get_xformbounds(GD__Image src, int *x, int *y, int *x1, int *y1, int *x2, int *y2) { *x = gdImageSX(src); *y = gdImageSY(src); *x1 = *x - 1; *y1 = *y - 1; *x2 = *x / 2; *y2 = *y / 2; } /* helper macros for image transformations */ #define GDGetImagePixel(im,x,y) \ gdImageTrueColor(im) ? \ gdImageTrueColorPixel(im,x,y) : \ gdImagePalettePixel(im,x,y) #define GDSetImagePixel(im,x,y,p) \ gdImageTrueColor(im) ? \ (gdImageTrueColorPixel(im,x,y) = p) : \ (gdImagePalettePixel(im,x,y) = p) #define GDCopyImagePixel(dst,dx,dy,src,sx,sy) \ gdImageTrueColor(src) ? \ (gdImageTrueColorPixel(dst,dx,dy)=gdImageTrueColorPixel(src,sx,sy)) : \ (gdImagePalettePixel(dst,dx,dy)=gdImagePalettePixel(src,sx,sy)) /* Check the image format being returned */ void gd_chkimagefmt(GD__Image image, int truecolor) { if ((image != NULL) && !truecolor) { /* return a palette image */ if (gdImageTrueColor(image)) { gdImageTrueColorToPalette(image,1,gdMaxColors); } } } /* GLOBAL THREAD-SAFE DATA */ #ifdef START_MY_CXT #define MY_CXT_KEY "GD::_guts" XS_VERSION typedef struct { /* Current image true color default * 0 - create palette based images by default * 1 - create true color images by default */ int truecolor_default; } my_cxt_t; #define truecolor_default MY_CXT.truecolor_default START_MY_CXT #endif MODULE = GD PACKAGE = GD INCLUDE: const-xs.inc void VERSION_STRING() PPCODE: mXPUSHp(GD_VERSION_STRING,sizeof(GD_VERSION_STRING)-1); void LIBGD_VERSION() PPCODE: mXPUSHn(GD_VERSION/10000.0); #if GD_VERSION >= 20101 bool supportsFileType(char *filename, int writing=0) PROTOTYPE: $;$ CODE: RETVAL = gdSupportsFileType(filename, writing); OUTPUT: RETVAL #endif BOOT: { #ifdef START_MY_CXT MY_CXT_INIT; #endif truecolor_default = 0; } MODULE = GD PACKAGE = GD::Image PREFIX=gd # Set the new image true color default # 0 - create palette based images by default # 1 - create true color images by default int gdtrueColor(packname="GD::Image", ...) char * packname PROTOTYPE: $$ PREINIT: dMY_CXT; int previous_value = truecolor_default; CODE: PERL_UNUSED_ARG(packname); if (items > 1) truecolor_default = (int)SvIV(ST(1)); RETVAL = previous_value; OUTPUT: RETVAL GD::Image gd_new(packname="GD::Image", x=64, y=64, ...) char * packname int x int y PROTOTYPE: $;$$$ PREINIT: gdImagePtr theImage; dMY_CXT; int truecolor = truecolor_default; CODE: PERL_UNUSED_ARG(packname); if (items > 3) truecolor = (int)SvIV(ST(3)); if (truecolor) { theImage = (GD__Image) gdImageCreateTrueColor(x,y); if (!theImage) croak("gdImageCreateTrueColor error"); } else { theImage = (GD__Image) gdImageCreate(x,y); if (!theImage) croak("gdImageCreate error"); } RETVAL = theImage; OUTPUT: RETVAL #if GD_VERSION >= 20101 bool gd_file(image, filename) GD::Image image char * filename PROTOTYPE: $$ CODE: RETVAL = gdImageFile(image, filename); OUTPUT: RETVAL #endif #ifdef HAVE_PNG GD::Image gd_newFromPng(packname="GD::Image", filehandle, ...) char * packname InputStream filehandle PROTOTYPE: $$;$ PREINIT: dMY_CXT; int truecolor = truecolor_default; CODE: PERL_UNUSED_ARG(packname); RETVAL = (GD__Image) GDIMAGECREATEFROMPNG(filehandle); if (!RETVAL) croak("gdImageCreateFromPng error"); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL GD::Image gdnewFromPngData(packname="GD::Image", imageData, ...) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; dMY_CXT; int truecolor = truecolor_default; CODE: PERL_UNUSED_ARG(packname); data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromPngCtx(ctx); (ctx->gd_free)(ctx); if (!RETVAL) croak("gdImageCreateFromPngCtx error"); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL #endif #ifdef HAVE_GD2 GD::Image gdnewFromGdData(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$ PREINIT: char* data; STRLEN len; CODE: PERL_UNUSED_ARG(packname); data = SvPV(imageData,len); RETVAL = (GD__Image) gdImageCreateFromGdPtr(len,(void*) data); if (!RETVAL) croak("gdImageCreateFromGdPtr error"); OUTPUT: RETVAL GD::Image gdnewFromGd2Data(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$ PREINIT: char* data; STRLEN len; CODE: PERL_UNUSED_ARG(packname); data = SvPV(imageData,len); RETVAL = (GD__Image) gdImageCreateFromGd2Ptr(len,(void*) data); if (!RETVAL) croak("gdImageCreateFromGd2Ptr error"); OUTPUT: RETVAL #endif #ifdef HAVE_JPEG GD::Image gdnewFromJpegData(packname="GD::Image", imageData, ...) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; dMY_CXT; int truecolor = truecolor_default; CODE: PERL_UNUSED_ARG(packname); data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromJpegCtx(ctx); (ctx->gd_free)(ctx); if (!RETVAL) croak("gdImageCreateFromJpegCtx error"); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL #endif #ifdef HAVE_BMP GD::Image gdnewFromBmpData(packname="GD::Image", imageData, ...) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; dMY_CXT; int truecolor = truecolor_default; CODE: PERL_UNUSED_ARG(packname); data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromBmpCtx(ctx); (ctx->gd_free)(ctx); if (!RETVAL) croak("gdImageCreateFromBmpCtx error"); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL #endif GD::Image gdnewFromWBMPData(packname="GD::Image", imageData, ...) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; dMY_CXT; int truecolor = truecolor_default; CODE: PERL_UNUSED_ARG(packname); data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromWBMPCtx(ctx); (ctx->gd_free)(ctx); if (!RETVAL) croak("gdImageCreateFromWBMPCtx error"); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL GD::Image gd_newFromXbm(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: PERL_UNUSED_ARG(packname); RETVAL = GDIMAGECREATEFROMXBM(filehandle); if (!RETVAL) croak("gdImageCreateFromXbm error"); OUTPUT: RETVAL #ifdef HAVE_GD2 GD::Image gd_newFromGd(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: PERL_UNUSED_ARG(packname); RETVAL = GDIMAGECREATEFROMGD(filehandle); if (!RETVAL) croak("gdImageCreateFromGd error"); OUTPUT: RETVAL GD::Image gd_newFromGd2(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: PERL_UNUSED_ARG(packname); RETVAL = GDIMAGECREATEFROMGD2(filehandle); if (!RETVAL) croak("gdImageCreateFromGd2 error"); OUTPUT: RETVAL GD::Image gd_newFromGd2Part(packname="GD::Image", filehandle,srcX,srcY,width,height) char * packname InputStream filehandle int srcX int srcY int width int height PROTOTYPE: $$$$$$ CODE: PERL_UNUSED_ARG(packname); RETVAL = GDIMAGECREATEFROMGD2PART(filehandle,srcX,srcY,width,height); if (!RETVAL) croak("gdImageCreateFromGd2Part error"); OUTPUT: RETVAL #endif #ifdef HAVE_JPEG GD::Image gd_newFromJpeg(packname="GD::Image", filehandle, ...) char * packname InputStream filehandle PROTOTYPE: $$;$ PREINIT: dMY_CXT; int truecolor = truecolor_default; CODE: PERL_UNUSED_ARG(packname); RETVAL = GDIMAGECREATEFROMJPEG(filehandle); if (!RETVAL) croak("gdImageCreateFromJpeg error"); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL #endif #ifdef HAVE_TIFF GD::Image gd_newFromTiff(packname="GD::Image", filehandle, ...) char * packname InputStream filehandle PROTOTYPE: $$;$ PREINIT: dMY_CXT; int truecolor = truecolor_default; CODE: PERL_UNUSED_ARG(packname); RETVAL = GDIMAGECREATEFROMTIFF(filehandle); if (!RETVAL) croak("gdImageCreateFromTiff error"); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL #endif #ifdef HAVE_BMP GD::Image gd_newFromBmp(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ PREINIT: gdImagePtr img; SV* errormsg; CODE: PERL_UNUSED_ARG(packname); img = GDIMAGECREATEFROMBMP(filehandle); if (img == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with BMP support\n"); else croak("gdImageCreateFromBmp error"); XSRETURN_EMPTY; } RETVAL = img; OUTPUT: RETVAL #endif GD::Image gd_newFromWBMP(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ PREINIT: gdImagePtr img; SV* errormsg; CODE: PERL_UNUSED_ARG(packname); img = GDIMAGECREATEFROMWBMP(filehandle); if (img == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with WBMP support\n"); else croak("gdImageCreateFromWBMP error"); XSRETURN_EMPTY; } RETVAL = img; OUTPUT: RETVAL GD::Image gdnewFromXpm(packname="GD::Image", filename) char * packname char * filename PROTOTYPE: $$ PREINIT: #ifdef HAVE_XPM gdImagePtr img; #endif SV* errormsg; CODE: PERL_UNUSED_ARG(packname); #ifdef HAVE_XPM img = (GD__Image) gdImageCreateFromXpm(filename); if (img == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with xpm support\n"); else croak("gdImageCreateFromXpm error"); XSRETURN_EMPTY; } RETVAL = img; #else PERL_UNUSED_ARG(filename); errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with xpm support\n"); XSRETURN_EMPTY; #endif OUTPUT: RETVAL #ifdef HAVE_GIF GD::Image gd_newFromGif(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: PERL_UNUSED_ARG(packname); RETVAL = GDIMAGECREATEFROMGIF(filehandle); if (!RETVAL) croak("gdImageCreateFromGif error"); OUTPUT: RETVAL GD::Image gdnewFromGifData(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; CODE: PERL_UNUSED_ARG(packname); data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromGifCtx(ctx); (ctx->gd_free)(ctx); if (!RETVAL) croak("gdImageCreateFromGifCtx error"); OUTPUT: RETVAL #endif #ifdef HAVE_WEBP GD::Image gd_newFromWebp(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: PERL_UNUSED_ARG(packname); RETVAL = GDIMAGECREATEFROMWEBP(filehandle); if (!RETVAL) croak("gdImageCreateFromWebp error"); OUTPUT: RETVAL GD::Image gdnewFromWebpData(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; CODE: PERL_UNUSED_ARG(packname); data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromWebpCtx(ctx); (ctx->gd_free)(ctx); if (!RETVAL) croak("gdImageCreateFromWebpCtx error"); OUTPUT: RETVAL #endif #ifdef HAVE_HEIF GD::Image gd_newFromHeif(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: PERL_UNUSED_ARG(packname); RETVAL = GDIMAGECREATEFROMHEIF(filehandle); if (!RETVAL) croak("gdImageCreateFromHeif error"); OUTPUT: RETVAL GD::Image gdnewFromHeifData(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; CODE: PERL_UNUSED_ARG(packname); data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromHeifCtx(ctx); (ctx->gd_free)(ctx); if (!RETVAL) croak("gdImageCreateFromHeifCtx error"); OUTPUT: RETVAL #endif #ifdef HAVE_HEIF GD::Image gd_newFromAvif(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: PERL_UNUSED_ARG(packname); RETVAL = GDIMAGECREATEFROMAVIF(filehandle); if (!RETVAL) croak("gdImageCreateFromAvif error"); OUTPUT: RETVAL GD::Image gdnewFromAvifData(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; CODE: PERL_UNUSED_ARG(packname); data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromAvifCtx(ctx); (ctx->gd_free)(ctx); if (!RETVAL) croak("gdImageCreateFromAvifCtx error"); OUTPUT: RETVAL #endif void gdDESTROY(image) GD::Image image PROTOTYPE: $ CODE: gdImageDestroy(image); SV* gdSTORABLE_freeze(image,cloning) GD::Image image int cloning PROTOTYPE: $$ CODE: { void* data; int size; if (cloning) XSRETURN_UNDEF; data = gdImageGd2Ptr(image,0,GD2_FMT_COMPRESSED,&size); if (!data) croak("gdImageGd2Ptr error"); RETVAL = newSVpvn((char*)data,size); gdFree(data); } OUTPUT: RETVAL void gdSTORABLE_thaw(object,cloning,serialized) SV* object int cloning SV* serialized PREINIT: STRLEN length; void* data; GD__Image image; CODE: { if (cloning) XSRETURN_UNDEF; data = (void*) SvPV(serialized,length); image = gdImageCreateFromGd2Ptr(length,data); if (!image) croak("gdImageCreateFromGd2Ptr error"); sv_setiv(SvRV(object),(IV)image); } #ifdef HAVE_PNG SV* gdpng(image, ...) GD::Image image PROTOTYPE: $;$ PREINIT: CODE: { void* data; int size; int level; if (items > 1) { level = (int)SvIV(ST(1)); data = (void *) gdImagePngPtrEx(image,&size,level); if (!data) croak("gdImagePngPtrEx error"); } else { data = (void *) gdImagePngPtr(image,&size); if (!data) croak("gdImagePngPtr error"); } RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL #endif #ifdef HAVE_JPEG SV* gdjpeg(image,quality=-1) GD::Image image int quality PROTOTYPE: $ PREINIT: SV* errormsg; void* data; int size; CODE: data = (void *) gdImageJpegPtr(image,&size,quality); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with jpeg support\n"); else croak("gdImageJpegPtr error"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); OUTPUT: RETVAL #endif SV* gdgifanimbegin(image,globalcm=-1,loops=-1) GD::Image image int globalcm int loops PROTOTYPE: $$$ PREINIT: void* data; int size; CODE: #ifdef HAVE_GIFANIM data = (void *) gdImageGifAnimBeginPtr(image,&size,globalcm,loops); if (!data) croak("gdImageGifAnimBeginPtr error"); RETVAL = newSVpvn((char*) data,size); gdFree(data); #else PERL_UNUSED_ARG(data); PERL_UNUSED_ARG(size); PERL_UNUSED_ARG(image); PERL_UNUSED_ARG(globalcm); PERL_UNUSED_ARG(loops); die("libgd 2.0.33 or higher required for animated GIF support"); #endif OUTPUT: RETVAL SV* gdgifanimadd(image,localcm=-1,leftofs=-1,topofs=-1,delay=-1,disposal=-1,previm=0) GD::Image image int localcm int leftofs int topofs int delay int disposal GD::Image previm PROTOTYPE: $$$$$$$ PREINIT: void* data; int size; CODE: #ifdef HAVE_GIFANIM data = (void *) gdImageGifAnimAddPtr(image,&size,localcm,leftofs,topofs, delay,disposal,previm); if (!data) croak("gdImageGifAnimAddPtr error"); RETVAL = newSVpvn((char*) data,size); gdFree(data); #else PERL_UNUSED_ARG(data); PERL_UNUSED_ARG(size); PERL_UNUSED_ARG(image); PERL_UNUSED_ARG(localcm); PERL_UNUSED_ARG(leftofs); PERL_UNUSED_ARG(topofs); PERL_UNUSED_ARG(delay); PERL_UNUSED_ARG(disposal); PERL_UNUSED_ARG(previm); die("libgd 2.0.33 or higher required for animated GIF support"); #endif OUTPUT: RETVAL SV* gdgifanimend(image) GD::Image image PROTOTYPE: $ PREINIT: void* data; int size; CODE: PERL_UNUSED_ARG(image); #ifdef HAVE_GIFANIM data = (void *) gdImageGifAnimEndPtr(&size); if (!data) croak("gdImageGifAnimEndPtr error"); RETVAL = newSVpvn((char*) data,size); gdFree(data); #else PERL_UNUSED_ARG(data); PERL_UNUSED_ARG(size); die("libgd 2.0.33 or higher required for animated GIF support"); #endif OUTPUT: RETVAL #ifdef HAVE_BMP SV* gdbmp(image,compression=0) GD::Image image int compression PROTOTYPE: $ PREINIT: SV* errormsg; void* data; int size; CODE: data = (void *) gdImageBmpPtr(image,&size,compression); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with WBMP support\n"); else croak("gdImageBmpPtr error"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); OUTPUT: RETVAL #endif SV* gdwbmp(image,fg) GD::Image image int fg PROTOTYPE: $ PREINIT: SV* errormsg; void* data; int size; CODE: data = (void *) gdImageWBMPPtr(image,&size,fg); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with WBMP support\n"); else croak("gdImageWBMPPtr error"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); OUTPUT: RETVAL #ifdef HAVE_GIF SV* gdgif(image) GD::Image image PROTOTYPE: $ PREINIT: SV* errormsg; void* data; int size; CODE: data = (void *) gdImageGifPtr(image,&size); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with gif support\n"); else croak("gdImageGifPtr error"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); OUTPUT: RETVAL #endif #ifdef HAVE_GD2 SV* gdgd(image) GD::Image image PROTOTYPE: $ CODE: { void* data; int size; data = gdImageGdPtr(image,&size); if (!data) croak("gdImageGdPtr error"); RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL SV* gdgd2(image) GD::Image image PROTOTYPE: $ CODE: { void* data; int size; data = gdImageGd2Ptr(image,0,GD2_FMT_COMPRESSED,&size); if (!data) croak("gdImageGd2Ptr error"); RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL #endif #ifdef HAVE_TIFF SV* gdtiff(image) GD::Image image PROTOTYPE: $ PREINIT: SV* errormsg; void* data; int size; CODE: data = (void *) gdImageTiffPtr(image,&size); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with TIFF support\n"); else croak("gdImageTiffPtr error"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); OUTPUT: RETVAL #endif #ifdef HAVE_WEBP SV* gdwebp(image, ...) GD::Image image PROTOTYPE: $;$ PREINIT: SV* errormsg; void* data; int size; int quality; CODE: if (items > 1) { quality=(int)SvIV(ST(1)); data = (void *) gdImageWebpPtrEx(image,&size,quality); } else data = (void *) gdImageWebpPtr(image,&size); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with webp support\n"); else croak("gdImageWebpPtr error"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); OUTPUT: RETVAL #endif #ifdef HAVE_HEIF SV* gdheif(image, ...) GD::Image image PROTOTYPE: $;$ PREINIT: SV* errormsg; void* data; int size; int quality; //enum or char* codec: HEVC or AV1 CODE: if (items > 1) { quality=(int)SvIV(ST(1)); data = (void *) gdImageHeifPtrEx(image,&size,quality,GD_HEIF_CODEC_HEVC,GD_HEIF_CHROMA_444); } else data = (void *) gdImageHeifPtr(image,&size); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with heif support\n"); else croak("gdImageHeifPtr error"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); OUTPUT: RETVAL #endif #ifdef HAVE_AVIF SV* gdavif(image, ...) GD::Image image PROTOTYPE: $;$$ PREINIT: SV* errormsg; void* data; int size; int quality; // -1 for default int speed; // 6 is default CODE: if (items > 1) { quality=(int)SvIV(ST(1)); speed=items > 2 ? (int)SvIV(ST(2)) : 6; // AVIF_SPEED_DEFAULT data = (void *) gdImageAvifPtrEx(image,&size,quality,speed); } else data = (void *) gdImageAvifPtr(image,&size); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with avif support\n"); else croak("gdImageAvifPtr error"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); OUTPUT: RETVAL #endif int gdtransparent(image, ...) GD::Image image PROTOTYPE: $;$ PREINIT: int color; CODE: if (items > 1) { color=(int)SvIV(ST(1)); gdImageColorTransparent(image,color); } RETVAL = gdImageGetTransparent(image); OUTPUT: RETVAL void gdgetBounds(image) GD::Image image PROTOTYPE: $ PPCODE: mXPUSHi(gdImageSX(image)); mXPUSHi(gdImageSY(image)); int gdisTrueColor(image) GD::Image image PROTOTYPE: $ CODE: RETVAL = gdImageTrueColor(image); OUTPUT: RETVAL void gdtrueColorToPalette(image, dither=0, colors=gdMaxColors) GD::Image image int dither int colors PROTOTYPE: $;$$ CODE: gdImageTrueColorToPalette(image,dither,colors); GD::Image gdcreatePaletteFromTrueColor(image, dither=0, colors=gdMaxColors) GD::Image image int dither int colors PROTOTYPE: $;$$ CODE: RETVAL = gdImageCreatePaletteFromTrueColor(image,dither,colors); if (!RETVAL) croak("gdImageCreatePaletteFromTrueColor error"); OUTPUT: RETVAL #if GD_VERSION >= 20100 GD::Image gdneuQuant(image, colors=gdMaxColors, samplefactor=5) GD::Image image int colors int samplefactor PROTOTYPE: $;$$ CODE: RETVAL = gdImageNeuQuant(image,colors,samplefactor); if (!RETVAL) XSRETURN_UNDEF; OUTPUT: RETVAL # beware of CVE 2019-6977 https://bugs.php.net/bug.php?id=77270 # refuse to match truecolor with palette int gdcolorMatch(image, im2) GD::Image image GD::Image im2 PROTOTYPE: $$ CODE: #if GD_VERSION <= 20205 if (gdImageTrueColor(image) ^ gdImageTrueColor(im2)) XSRETURN_UNDEF; else #endif RETVAL = gdImageColorMatch(image,im2); OUTPUT: RETVAL #endif void gdrgb(image,color) GD::Image image int color PROTOTYPE: $$ PPCODE: mXPUSHi(gdImageRed(image,color)); mXPUSHi(gdImageGreen(image,color)); mXPUSHi(gdImageBlue(image,color)); void gdalpha(image,color) GD::Image image int color PROTOTYPE: $$ PPCODE: mXPUSHi(gdImageAlpha(image,color)); int gdboundsSafe(image,x,y) GD::Image image int x int y PROTOTYPE: $$$ CODE: RETVAL = gdImageBoundsSafe(image,x,y); if (RETVAL == 0) XSRETURN_UNDEF; OUTPUT: RETVAL int gdgetPixel(image,x,y) GD::Image image int x int y PROTOTYPE: $$$ CODE: RETVAL = gdImageGetPixel(image,x,y); OUTPUT: RETVAL void gdsetPixel(image,x,y,color) GD::Image image int x int y int color PROTOTYPE: $$$$ CODE: gdImageSetPixel(image,x,y,color); GD::Image gdcopyRotate90(src) GD::Image src PROTOTYPE: $ PREINIT: int x, y, x1, y1, x2, y2, i, j; CODE: get_xformbounds(src, &x, &y, &x1, &y1, &x2, &y2); RETVAL = gd_cloneDim(src, y, x); for (j=0;j 1) { if (SvOK(ST(1))) gdImageInterlace(image,1); else gdImageInterlace(image,0); } RETVAL = gdImageGetInterlaced(image); OUTPUT: RETVAL int compare(image1,image2) GD::Image image1 GD::Image image2 PROTOTYPE: $$ CODE: RETVAL = gdImageCompare(image1,image2); OUTPUT: RETVAL void colorDeallocate(image,color) GD::Image image int color PROTOTYPE: $$ CODE: gdImageColorDeallocate(image,color); void copy(destination,source,dstX,dstY,srcX,srcY,w,h) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int w int h PROTOTYPE: $$$$$$$$ CODE: gdImageCopy(destination,source,dstX,dstY,srcX,srcY,w,h); void copyResized(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int destW int destH int srcW int srcH PROTOTYPE: $$$$$$$$$$ CODE: gdImageCopyResized(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH); void copyResampled(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int destW int destH int srcW int srcH PROTOTYPE: $$$$$$$$$$ CODE: gdImageCopyResampled(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH); void copyMerge(destination,source,dstX,dstY,srcX,srcY,w,h,pct) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int w int h int pct PROTOTYPE: $$$$$$$$$ CODE: gdImageCopyMerge(destination,source,dstX,dstY,srcX,srcY,w,h,pct); void copyMergeGray(destination,source,dstX,dstY,srcX,srcY,w,h,pct) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int w int h int pct PROTOTYPE: $$$$$$$$$ CODE: gdImageCopyMergeGray(destination,source,dstX,dstY,srcX,srcY,w,h,pct); void paletteCopy(destination,source) GD::Image destination GD::Image source PROTOTYPE: $$ CODE: gdImagePaletteCopy(destination,source); void gdchar(image,font,x,y,c,color) GD::Image image GD::Font font int x int y char * c int color PROTOTYPE: $$$$$$ CODE: gdImageChar(image,font,x,y,*c,color); void gdcharUp(image,font,x,y,c,color) GD::Image image GD::Font font int x int y char * c int color PROTOTYPE: $$$$$$ CODE: gdImageCharUp(image,font,x,y,*c,color); void gdstring(image,font,x,y,s,color) GD::Image image GD::Font font int x int y char * s int color PROTOTYPE: $$$$$$ CODE: gdImageString(image,font,x,y,(unsigned char*)s,color); void gdstringUp(image,font,x,y,s,color) GD::Image image GD::Font font int x int y char * s int color PROTOTYPE: $$$$$$ CODE: gdImageStringUp(image,font,x,y,(unsigned char*)s,color); void gdstringFT(image,fgcolor,fontname,ptsize,angle,x,y,string,...) SV * image int fgcolor char * fontname double ptsize double angle int x int y char * string PROTOTYPE: $$$$$$$$;$ PREINIT: gdImagePtr img; int brect[8]; char *err; char *a; SV* errormsg; HV* hash; SV** value; int i; int hdpi; int vdpi; gdFTStringExtra strex; PPCODE: { #ifndef HAVE_FT errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with FreeType font support\n"); XSRETURN_EMPTY; #endif if (sv_isobject(image) && sv_derived_from(image, "GD::Image")) { IV tmp = SvIV((SV*)SvRV(image)); img = (gdImagePtr) tmp; } else { img = NULL; } if (items == 9) { /* hashref options at end */ if (SvTYPE(SvRV(ST(8))) != SVt_PVHV) croak ("Usage: $gd->stringFT(image,fgcolor,fontname,ptsize,angle,x,y,string,[{options}])"); hash = (HV*)SvRV(ST(8)); strex.flags = 0; strex.linespacing = 0; strex.charmap = 0; if ((value = hv_fetchs(hash,"linespacing",0))) { strex.flags |= gdFTEX_LINESPACE; strex.linespacing = SvNV(*value); } if ((value = hv_fetchs(hash,"charmap",0))) { strex.flags |= gdFTEX_CHARMAP; if (strEQ(SvPV_nolen(*value),"Unicode")) strex.charmap = gdFTEX_Unicode; else if (strEQ(SvPV_nolen(*value),"Shift_JIS")) strex.charmap = gdFTEX_Shift_JIS; else if (strEQ(SvPV_nolen(*value),"Big5")) strex.charmap = gdFTEX_Big5; else croak("Unknown charmap %s",SvPV_nolen(*value)); } #ifdef VERSION_33 if ((value = hv_fetchs(hash,"resolution",0))) { strex.flags |= gdFTEX_RESOLUTION; a = SvPV_nolen(*value); if (sscanf(a,"%d,%d",&hdpi,&vdpi) == 2) { strex.hdpi = hdpi; strex.vdpi = vdpi; } } if ((value = hv_fetchs(hash,"kerning",0))) { if (!SvTRUE(*value)) { strex.flags |= gdFTEX_DISABLE_KERNING; } else strex.flags &= gdFTEX_DISABLE_KERNING; } #endif err = gdImageStringFTEx(img,brect,fgcolor,fontname,ptsize,angle,x,y,string,&strex); } else { err = gdImageStringFT(img,brect,fgcolor,fontname,ptsize,angle,x,y,string); } if (err) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,err); XSRETURN_EMPTY; } else { EXTEND(sp,8); for (i=0;i<8;i++) { mPUSHi(brect[i]); } } } int gdstringFTCircle(image,cx,cy,radius,textRadius,fillPortion,fontname,points,top,bottom,fgcolor) GD::Image image int cx int cy double radius double textRadius double fillPortion char * fontname double points char * top char * bottom int fgcolor PROTOTYPE: $$$$$$$$$$$ PREINIT: char* err; SV* errormsg; CODE: { #ifdef HAVE_FT #ifdef HAVE_FTCIRCLE fprintf(stderr,"cx=%d,cy=%d,radius=%f,textRadius=%f,fillPortion=%f,fontname=%s,points=%f,top=%s,bottom=%s,fgcolor=%d", cx,cy,radius,textRadius, fillPortion,fontname,points,top,bottom,fgcolor); err = gdImageStringFTCircle(image,cx,cy,radius,textRadius, fillPortion,fontname,points,top,bottom,fgcolor); if (err) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,err); XSRETURN_EMPTY; } else { RETVAL = 1; } #else /* if we have FT but not FTCIRCLE, this is all that's compiled */ PERL_UNUSED_ARG(image); PERL_UNUSED_ARG(cx); PERL_UNUSED_ARG(cy); PERL_UNUSED_ARG(radius); PERL_UNUSED_ARG(textRadius); PERL_UNUSED_ARG(fillPortion); PERL_UNUSED_ARG(fontname); PERL_UNUSED_ARG(points); PERL_UNUSED_ARG(top); PERL_UNUSED_ARG(bottom); PERL_UNUSED_ARG(fgcolor); errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd must be version 2.0.33 or higher to use this function\n"); XSRETURN_EMPTY; #endif #else /* if we don't have FT, this is all that's compiled */ PERL_UNUSED_ARG(image); PERL_UNUSED_ARG(cx); PERL_UNUSED_ARG(cy); PERL_UNUSED_ARG(radius); PERL_UNUSED_ARG(textRadius); PERL_UNUSED_ARG(fillPortion); PERL_UNUSED_ARG(fontname); PERL_UNUSED_ARG(points); PERL_UNUSED_ARG(top); PERL_UNUSED_ARG(bottom); PERL_UNUSED_ARG(fgcolor); errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with FreeType support\n"); XSRETURN_EMPTY; #endif } OUTPUT: RETVAL int gduseFontConfig(image,flag) SV* image int flag PROTOTYPE: $$ CODE: { PERL_UNUSED_ARG(image); #ifdef HAVE_FONTCONFIG RETVAL = gdFTUseFontConfig(flag); #else SV* errormsg; PERL_UNUSED_ARG(flag); errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with fontconfig support\n"); XSRETURN_EMPTY; #endif } OUTPUT: RETVAL void gdalphaBlending(image,blending) GD::Image image int blending PROTOTYPE: $$ CODE: gdImageAlphaBlending(image,blending); void gdsaveAlpha(image,saveAlphaArg) GD::Image image int saveAlphaArg PROTOTYPE: $$ CODE: gdImageSaveAlpha(image,saveAlphaArg); void gdclip(image,...) GD::Image image PROTOTYPE: $;$$$$ PREINIT: int coords[4]; int i; PPCODE: if (items == 5) { for (i=0;i<4;i++) coords[i] = (int)SvIV(ST(i+1)); gdImageSetClip(image,coords[0],coords[1],coords[2],coords[3]); } else if (items > 1) /* something weird */ croak("Usage: $gd->clip() or $gd->clip(x1,x2,y1,y2)"); gdImageGetClip(image,&coords[0],&coords[1],&coords[2],&coords[3]); EXTEND(sp,4); for (i=0;i<4;i++) mPUSHi(coords[i]); void gdsetAntiAliased(image,color) GD::Image image int color PROTOTYPE: $$ CODE: gdImageSetAntiAliased(image,color); void gdsetAntiAliasedDontBlend(image,color,flag=1) GD::Image image int color int flag PROTOTYPE: $$$ CODE: gdImageSetAntiAliasedDontBlend(image,color,flag); MODULE = GD PACKAGE = GD::Font PREFIX=gd GD::Font gdload(packname="GD::Font",fontpath) char * packname char * fontpath PROTOTYPE: $$ PREINIT: int fontfile; int datasize; SV* errormsg; char errstr[256]; gdFontPtr font; unsigned char word[4]; char* fontdata; CODE: PERL_UNUSED_ARG(packname); fontfile = open(fontpath,O_RDONLY); if (fontfile < 0) { errormsg = perl_get_sv("@",0); snprintf(errstr,256,"could not open font file %s: %s",fontpath,strerror(errno)); sv_setpv(errormsg,errstr); XSRETURN_EMPTY; } font = (gdFontPtr)safemalloc(sizeof(gdFont)); if (font == NULL) croak("safemalloc() returned NULL while trying to allocate font struct.\n"); /* read header from font - note that the file is assumed to be littleendian*/ if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->nchars = littleendian(word); if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->offset = littleendian(word); if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->w = littleendian(word); if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->h = littleendian(word); datasize = font->nchars * font->w * font->h; fontdata = (char*)safemalloc(datasize); if (fontdata == NULL) croak("safemalloc() returned NULL while trying to allocate font bitmap.\n"); if (read(fontfile,fontdata,datasize) < datasize) croak("error while reading font file: %s",strerror(errno)); font->data = fontdata; close(fontfile); /* please don't leak file descriptors! */ RETVAL = font; OUTPUT: RETVAL void gdDESTROY(self) GD::Font self PROTOTYPE: $ CODE: if (self == gdFontGetSmall() || self == gdFontGetLarge() || self == gdFontGetGiant() || self == gdFontGetMediumBold() || self == gdFontGetTiny() ) XSRETURN_EMPTY; safefree(self->data); safefree(self); GD::Font gdSmall(packname="GD::Font") char * packname PROTOTYPE: $ CODE: PERL_UNUSED_ARG(packname); RETVAL = gdFontGetSmall(); if (!RETVAL) croak("gdFontGetSmall error"); OUTPUT: RETVAL GD::Font gdLarge(packname="GD::Font") char * packname PROTOTYPE: $ CODE: PERL_UNUSED_ARG(packname); RETVAL = gdFontGetLarge(); if (!RETVAL) croak("gdFontGetLarge error"); OUTPUT: RETVAL GD::Font gdGiant(packname="GD::Font") char * packname PROTOTYPE: $ CODE: PERL_UNUSED_ARG(packname); RETVAL = gdFontGetGiant(); if (!RETVAL) croak("gdFontGetGiant error"); OUTPUT: RETVAL GD::Font gdMediumBold(packname="GD::Font") char * packname PROTOTYPE: $ CODE: PERL_UNUSED_ARG(packname); RETVAL = gdFontGetMediumBold(); if (!RETVAL) croak("gdFontGetMediumBold error"); OUTPUT: RETVAL GD::Font gdTiny(packname="GD::Font") char * packname PROTOTYPE: $ CODE: PERL_UNUSED_ARG(packname); RETVAL = gdFontGetTiny(); if (!RETVAL) croak("gdFontGetTiny error"); OUTPUT: RETVAL int gdnchars(font) GD::Font font PROTOTYPE: $ CODE: RETVAL = font->nchars; OUTPUT: RETVAL int gdoffset(font) GD::Font font PROTOTYPE: $ CODE: RETVAL = font->offset; OUTPUT: RETVAL int gdwidth(font) GD::Font font PROTOTYPE: $ CODE: RETVAL = font->w; OUTPUT: RETVAL int gdheight(font) GD::Font font PROTOTYPE: $ CODE: RETVAL = font->h; OUTPUT: RETVAL # Image filters since 2.1.0 MODULE = GD PACKAGE = GD::Image PREFIX=gd #if GD_VERSION >= 20100 bool gdscatter(image, sub, plus) GD::Image image int sub int plus PROTOTYPE: $$$ CODE: RETVAL = (bool)gdImageScatter(image,sub,plus); OUTPUT: RETVAL bool gdscatterColor(image, sub, plus, colorav) GD::Image image int sub int plus AV *colorav PROTOTYPE: $$$\@ PREINIT: int i; int *colors; int numcolors; CODE: numcolors = AvFILL(colorav); colors = safemalloc(numcolors * sizeof(int)); for (i=0;i= 20200 GD::Image gdcopyGaussianBlurred(image, radius, sigma) GD::Image image int radius double sigma PROTOTYPE: $$$ CODE: RETVAL = gdImageCopyGaussianBlurred(image, radius, sigma); if (!RETVAL) croak("gdImageCopyGaussianBlurred error"); OUTPUT: RETVAL #endif # gd_interpolation #if GD_VERSION >= 20100 GD::Image gdcopyScaleInterpolated(image, width, height) GD::Image image int width int height PROTOTYPE: $$$ CODE: RETVAL = gdImageScale(image,width,height); if (!RETVAL) XSRETURN_UNDEF; OUTPUT: RETVAL GD::Image gdcopyRotateInterpolated(image, angle, bgcolor) GD::Image image NV angle int bgcolor PROTOTYPE: $$$ CODE: RETVAL = gdImageRotateInterpolated(image,(float)angle,bgcolor); if (!RETVAL) XSRETURN_UNDEF; OUTPUT: RETVAL #endif #if GD_VERSION >= 20200 int interpolationMethod(image, interpolationmethod=-1) GD::Image image int interpolationmethod PROTOTYPE: $;$ CODE: if (items > 1 && interpolationmethod >= 0) { gdImageSetInterpolationMethod(image, interpolationmethod); } RETVAL = gdImageGetInterpolationMethod(image); OUTPUT: RETVAL #gdTransformAffineGetImage #gdTransformAffineCopy #gdTransformAffineBoundingBox #endif GD-2.78/demos/0000755000175000017500000000000014450761210012417 5ustar rurbanrurbanGD-2.78/demos/tile.png0000644000175000017500000000043013076115434014063 0ustar rurbanrurbanPNG  IHDRR? PLTEܸ [ѧ:bKGDHIDATxc``Z:CCC?bBFCtEXtSoftware@(#)ImageMagick 4.1.0 98/09/08 cristy@mystic.es.dupont.comeB*tEXtSignature7a52b1cac1657d1b4f8ef32b4198eabc{;\tEXtPage21x22+0+0IENDB`GD-2.78/demos/gd_example.cgi0000755000175000017500000000126113076115434015217 0ustar rurbanrurban#!/usr/local/bin/perl use GD; print "Content-type: image/png\n\n"; # create a new image $im = new GD::Image(100,100); # allocate some colors $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); $red = $im->colorAllocate(255,0,0); $blue = $im->colorAllocate(0,0,255); # make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # Put a black frame around the picture $im->rectangle(0,0,99,99,$black); # Draw a blue oval $im->arc(50,50,95,75,0,360,$blue); # And fill it with red $im->fill(50,50,$red); binmode STDOUT; # Convert the image to PNG and print it on standard output print $im->png; GD-2.78/demos/truetype_test0000755000175000017500000000154613076115434015277 0ustar rurbanrurban#!/usr/local/bin/perl use lib '../blib/lib','../blib/arch'; use GD 1.20; use constant FONT_DIRECTORY => '/dosc/windows/fonts'; my $directory = shift || FONT_DIRECTORY; my @fonts = <$directory/*.pfa $directory/*.pfb $directory/*.ttf>; die "Usage: $0 \nDisplays a directory of TrueType and Type1 fonts\n" unless @fonts; my $im = new GD::Image(800,600); my ($white,$black) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0)); my ($x,$y) = (20,20); my $max_x = 0; for my $font (@fonts) { my ($font_name) = $font =~ /([^\\\/]+)$/; warn "rendering $font_name\n"; (my @h = $im->stringTTF($black,$font,12.0,0.0,$x,$y,$font_name)) || next; $y = $h[1] + 12 + 5; $max_x = $max_x > $h[4] ? $max_x : $h[4]; if ($y > 600) { $y = 20; $x = $max_x + 5; } } binmode STDOUT; # print the image to stdout print $im->png; GD-2.78/demos/brushes.pl0000755000175000017500000000164113076115434014440 0ustar rurbanrurban#!/usr/local/bin/perl use GD; $im = new GD::Image(300,300); # allocate white $white = $im->colorAllocate(255, 255, 255); # allocate black $black = $im->colorAllocate(0, 0, 0); # allocate red $red = $im->colorAllocate(255, 0, 0); # allocate green $green = $im->colorAllocate(0,255,0); # allocate yellow $yellow = $im->colorAllocate(255,250,205); # Get an image from a png file open (TILE,"./tile.png") || die; $tile = newFromPng GD::Image(TILE); close TILE; # use it as a paintbrush $im->setBrush($tile); $im->arc(100,100,100,150,0,360,gdBrushed); # use it as a tiling pattern to fill a rectangle $im->setTile($tile); $im->filledRectangle(150,150,250,250,gdTiled); $im->rectangle(150,150,250,250,$black); # Draw a dotted line $im->setStyle($green,$green,$green,gdTransparent,$red,$red,$red,gdTransparent); $im->line(0,280,300,280,gdStyled); binmode STDOUT; # print the image to stdout print $im->png; GD-2.78/demos/copies.pl0000755000175000017500000000211113076115434014240 0ustar rurbanrurban#!/usr/local/bin/perl use GD; $im = new GD::Image(300,300); $white = $im->colorAllocate(255, 255, 255); $black = $im->colorAllocate(0, 0, 0); $red = $im->colorAllocate(255, 0, 0); $blue = $im->colorAllocate(0,0,255); $yellow = $im->colorAllocate(255,250,205); # Create a flat wide rectangle paintbrush $brush = new GD::Image(10,10); $brush->colorAllocate(255,255,255); # white $brush->colorAllocate(0,0,0); # black $brush->transparent($white); # white is transparent $brush->filledRectangle(0,0,5,2,$black); # a black rectangle $im->setBrush($brush); $im->arc(100,100,100,150,0,360,gdBrushed); $poly = new GD::Polygon; $poly->addPt(30,30); $poly->addPt(100,10); $poly->addPt(190,290); $poly->addPt(30,290); $im->polygon($poly,gdBrushed); $im->fill(132,62,$blue); $im->fill(100,70,$red); $im->fill(40,40,$yellow); $im->interlaced(1); # Copy the 20,20,70,70 region # to a location at 150,150 $im->copy($im,150,150,20,20,50,50); # Same thing, but doubling the size $im->copyResized($im,10,200,20,20,100,100,50,50); binmode STDOUT; # print the image to stdout print $im->png; GD-2.78/demos/polys.pl0000755000175000017500000000142713076115434014135 0ustar rurbanrurban#!/usr/local/bin/perl use GD; $im = new GD::Image(225,180); $black = $im->colorAllocate(0, 0, 0); $white = $im->colorAllocate(255, 255, 255); $red = $im->colorAllocate(255, 0, 0); $blue = $im->colorAllocate(0,0,255); $yellow = $im->colorAllocate(255,250,205); # Create a triangle $poly = new GD::Polygon; $poly->addPt(0,50); $poly->addPt(25,25); $poly->addPt(50,50); $im->filledPolygon($poly,$blue); # offset it down and to the right $poly->offset(100,100); $im->filledPolygon($poly,$red); # make it twice as wide and move it upward a bit $poly->map(50,50,100,100,10,10,110,60); $im->filledPolygon($poly,$yellow); # make it real tall $poly->map($poly->bounds,50,20,80,160); $im->filledPolygon($poly,$white); binmode STDOUT; # print the image to stdout print $im->png; GD-2.78/demos/fonttest0000755000175000017500000000165013076115434014221 0ustar rurbanrurban#!/usr/bin/perl -w use lib './blib/arch','./blib/lib'; use strict; use GD; use subs qw( charmap ); my $teststring = pack 'C*', 32, 1 .. 255; my $im = new GD::Image(640, 500); my ($white, $black) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), ); # $im->transparent($white); $im->interlaced(1); charmap($im, gdGiantFont, "GiantFont 9x15", 20, 16); charmap($im, gdLargeFont, "LargeFont 8x16", 120, 16); charmap($im, gdMediumBoldFont, "gdMediumBoldFont 7x13b", 220, 13); charmap($im, gdSmallFont, "gdSmallFont 6x13", 320, 13); charmap($im, gdTinyFont, "gdTinyFont 5x8", 420, 8); binmode(STDOUT); print $im->png; sub charmap { my $im = shift; my ($font, $title, $topoffset, $lineskip) = @_; $im->string($font, 16, $topoffset, $title.':', $black); my $line; for $line (0 .. 4) { $im->string($font, 16, $topoffset + (1 + $line) * $lineskip, substr($teststring, $line * 64, 64), $black); } } GD-2.78/demos/ttf.pl0000755000175000017500000000134613076115434013564 0ustar rurbanrurban#!/usr/local/bin/perl use lib '../blib/lib','../blib/arch'; use GD 1.20; use constant font => '../t/Generic.ttf'; $im = new GD::Image(400,250); warn $GD::VERSION; ($white,$black,$red,$blue,$yellow) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); $im->interlaced(1); # cool venetian blinds effect # Some TTFs $im->stringTTF($black,font,12.0,0.0,20,20,"Hello world!") || die $@; $im->stringTTF($red,font,14.0,0.0,20,80,"Hello world!")|| die $@;; $im->stringTTF($blue,font,30.0,-0.5,60,100,"Goodbye cruel world!")|| die $@;; binmode STDOUT; # print the image to stdout print $im->png; GD-2.78/demos/polyline.pl0000644000175000017500000002122013076115434014610 0ustar rurbanrurban############################################################################ # # Sample code for use of Polyline.pm # # Author: Dan Harasty # Email: harasty@cpan.org # Version: 0.1 # Date: 7/20/2002 # # use GD; use GD::Polyline; $PI = 3.14159; $TWO_PI = 2 * $PI; sub r2d {$_[0] * 180 / $PI}; $splinekey = "
  • Green: original polygon or polyline
  • Blue: control points added with addControlPoints()
  • Black: spline generated by toSpline()
"; if (1) { use GD; use GD::Polyline; # create an image $image = new GD::Image (500,300); $white = $image->colorAllocate(255,255,255); $black = $image->colorAllocate( 0, 0, 0); $red = $image->colorAllocate(255, 0, 0); # create a new polyline $polyline = new GD::Polyline; # add some points $polyline->addPt( 0, 0); $polyline->addPt( 0,100); $polyline->addPt( 50,125); $polyline->addPt(100, 0); # polylines can use polygon methods (and vice versa) $polyline->offset(200,100); # rotate 60 degrees, about the centroid $polyline->rotate(3.14159/3, $polyline->centroid()); # scale about the centroid $polyline->scale(1.5, 2, $polyline->centroid()); # draw the polyline $image->polydraw($polyline,$black); # create a spline, which is also a polyine $spline = $polyline->addControlPoints->toSpline; $image->polydraw($spline,$red); # output the png #binmode STDOUT; #print $image->png; SampleImage($image, "polyline-synopsis.png", "Synopsis", "Polyline created by 'SYNOPSIS' section of documentation."); } if (1) { $image = NewImage(); $offset = 50; for $poly (new GD::Polygon, new GD::Polyline) { $table_info = []; $poly->addPt( 0, 0); $poly->addPt( 0,100); $poly->addPt( 50,125); $poly->addPt(100, 0); #print "this " . ref($poly) . " has " . $poly->length() . " points\n"; push @$table_info, ["".ref($poly).""]; push @$table_info, ['vertex number: ', 0..($poly->length()-1)]; @coords = $poly->vertices(); @coords = map {"[".int($_->[0]).",".int($_->[1])."]"} @coords; push @$table_info, ['coordinates (pre-offset): ', @coords]; @lengths = $poly->segLength(); @lengths = map {int($_+0.5)} @lengths; #print "segLengths are : @lengths\n"; #print "perimeter is : " . int($poly->segLength()) . "\n"; push @$table_info, ['segment lengths: ', @lengths]; @angles = $poly->segAngle(); @angles = map {int(r2d($_)+0.5)} @angles; #print "seg angles are : @angles\n"; push @$table_info, ['segment angles: ', @angles]; @angles = $poly->vertexAngle(); @angles = map {defined ($_) ? int(r2d($_)+0.5) : "undef"} @angles; #print "vertex angles are: @angles\n"; push @$table_info, ['vertex angles: ', @angles]; $poly->offset(50 + $offset,80); $offset += 200; # draw the original poly $image->polydraw($poly,$black); #print "\n\n"; push @$summary_table, genHTMLTable($table_info, 0); } SampleImage($image, "polyline-simple.png", "Simple", "GD::Polygon and GD::Polyline with same vertexes.

" . genHTMLTable([$summary_table], 1)); } if (1) { $image = NewImage(); $offset = 50; for $poly (new GD::Polygon, new GD::Polyline) { $poly->addPt( 0, 0); $poly->addPt( 0,100); $poly->addPt( 50,125); $poly->addPt(100, 0); $poly->offset(50 + $offset,80); $offset += 200; # draw the original poly $image->polydraw($poly,$green); # create and draw the control line for the spline $ctrlline = $poly->addControlPoints(); $image->polydraw($ctrlline,$cyan); # create and draw the spline itself $spline = $ctrlline->toSpline(); $image->polydraw($spline,$black); } SampleImage($image, "polyline-spline.png", "Spline", "Splines fit to vertices of polygon and polyline. $splinekey"); } if (1) { $image = NewImage(); $triangle = new GD::Polygon; $triangle->addPt( 0, 0); $triangle->addPt(-19, 95); $triangle->addPt( 19, 95); $triangle->offset(250,50); foreach (1..9) { $image->polydraw($triangle,gdBrushed); $triangle->rotate($TWO_PI / 9, 250, 150); } SampleImage($image, "polyline-star9.png", "Nine Pointed Star", "A triangle, rotated about a point other than the origin.
Demonstration of \$poly->rotate() and \$poly->offset()"); } if (1) { $image = NewImage(); $cloverControl = new GD::Polyline; $cloverControl->addPt(45,45); $cloverControl->addPt(10,10); $cloverControl->addPt(90,10); $cloverControl->addPt(55,45); $cloverControl->addPt(90,10); $cloverControl->addPt(90,90); $cloverControl->addPt(55,55); $cloverControl->addPt(90,90); $cloverControl->addPt(10,90); $cloverControl->addPt(45,55); $cloverControl->addPt(10,90); $cloverControl->addPt(10,10); $cloverControl->addPt(45,45); $clover = $cloverControl->toSpline(); # note that the three following transformations # could have been called on $cloverControl, instead, # followed by the above call $clover->offset($clover->centroid(-1)); $clover->scale(3, 3); $clover->offset(250, 150); $image->filledPolygon($clover,$green); SampleImage($image, "polyline-clover.png", "Clover", "Sample image generated by GD::Polygon"); } if (1) { $image = NewImage(); $polyline = new GD::Polyline; for (0..15) { $polyline->addPt(30 * $_ + 10, rand(90) + 5); } $image->polyline($polyline,$green); $ctrlline = $polyline->addControlPoints(); $ctrlline->offset(0,100); $image->polyline($ctrlline,$cyan); $spline = $ctrlline->toSpline(); $spline->offset(0,100); $image->polyline($spline,$black); SampleImage($image, "polyline-zigzag.png", "Zigzag", "Spline fit to random function. $splinekey"); } if (1) { $image = NewImage(); $ring_network = new GD::Polygon; $num_nodes = 10; $randfactor = 80; for (1..$num_nodes) { $x = 250 + 150 * cos($TWO_PI * $_/$num_nodes); $y = 150 + 100 * sin($TWO_PI * $_/$num_nodes); $x += rand($randfactor)-$randfactor/2; $y += rand($randfactor)-$randfactor/2; $ring_network->addPt($x, $y); } $image->setBrush($brush2); $image->polyline($ring_network->addControlPoints->toSpline,gdBrushed); $ring_node = new GD::Polygon; $ring_node->addPt( 0, 0); $ring_node->addPt(10, 0); $ring_node->addPt(10,10); $ring_node->addPt( 0,10); for $ring_vertex ($ring_network->vertices()) { $ring_node->offset($ring_node->centroid(-1)); $ring_node->offset(@$ring_vertex); $image->filledPolygon($ring_node,$grey); } SampleImage($image, "polyline-ring-network.png", "Ring Network", "Closed spline fit to nodes at somewhat random positions."); } WriteToFile("polyline-example.html", theHTML()); print "\n"; print "open 'polyline-example.html' in your favorite browser that supports PNG.\n"; print "\n"; print "done! " . localtime() . "\n"; ########################## # # helper functions # sub NewImage { $image = new GD::Image (500,300); $white = $image->colorAllocate(255,255,255); $black = $image->colorAllocate( 0, 0, 0); $grey = $image->colorAllocate(128,128,128); $red = $image->colorAllocate(255, 0, 0); $orange = $image->colorAllocate(255,196, 0); $green = $image->colorAllocate( 0,255, 0); $blue = $image->colorAllocate( 0, 0,255); $cyan = $image->colorAllocate( 0,255,255); $purple = $image->colorAllocate(206, 0,165); $brush_width = 2; $brush_color = [255,128,0]; $brush = new GD::Image($brush_width,$brush_width); $brush->transparent($brush->colorAllocate(255,255,255)); $brush->filledRectangle(0,0,$brush_width,$brush_width,$brush->colorAllocate(@$brush_color)); $brush1 = $brush; $brush_width = 3; $brush_color = [206,0,165]; $brush = new GD::Image($brush_width,$brush_width); $brush->transparent($brush->colorAllocate(255,255,255)); $brush->filledRectangle(0,0,$brush_width,$brush_width,$brush->colorAllocate(@$brush_color)); $brush2 = $brush; $image->setBrush($brush1); $image; } my $html; sub SampleImage { my $image = shift; my $file = shift; my $title = shift; my $text = shift; WriteToBinaryFile($file, $image->png()); $html .= "
\n"; $html .= "$title - $file
\n"; $html .= "

$text


\n"; } sub theHTML { $html; } sub WriteToFile { my $file = shift || return 0; my $contents = shift || ""; open (NEWFILE, ">" . $file) or die "couldn't write to file $file"; print NEWFILE $contents; close(NEWFILE); print "created file $file\n"; } sub WriteToBinaryFile { my $file = shift || return 0; my $contents = shift || ""; open (NEWFILE, ">" . $file) or die "couldn't write to file $file"; binmode NEWFILE; print NEWFILE $contents; close(NEWFILE); print "created file $file\n"; } sub genHTMLTable { my $array_of_arrays = shift; my $border = shift; my $html_table; $html_table .= ""; for my $array_of_items (@$array_of_arrays) { $html_table .= ""; } $html_table .= "
"; $html_table .= join("", @$array_of_items); $html_table .= "
"; $html_table; } GD-2.78/demos/font_list.png0000644000175000017500000005307613076115434015145 0ustar rurbanrurbanPNG  IHDR XhXCPLTE???___///"c IDATxے0&& Ur'/%par/+L$aC$ē'=IOzғ'=Qo]*QmeVixkV"&M7-QVב m8Cd͏Q C_Ut6jo<*/onZw=o;qڀ*y_^*">H}˛#Om/8 zm hio}"ڰ_v].R/̪থ;^Z<`S羬Kțx5'2 ZCiy! QTY\}VQ^bF+ <ľ&v& H_|.+zw9%xnĔ+*'2 ĕWhmG㲬FvhU݌phDnpUd^cs|/?] @"R^l9AB`ӎz`TXy } `ƵpR=  {;d@ly;s ϶)> h-rH]"bYӽp :Y%7$QwWg{T1&Y?ߧ=1LCl`ȀoyS-u!(J$@tu;gޑtjQ6D?=Ɖ juTEb38n3Ul* YZx~~mzS_<񐫿(#KVޅ*ϒL:z)x I'&BI >: _UAHވ ؎HzwzwE! c} nE)ªh'c"i&mA{"aqUsi!0(c O3a2r6h?DwuTWu PQXySj^yU i1mpwgԇml0v,=64ĐyP2;+'bG_ꭼ{aG9 u|.ͯ*&$6J×:~_J{bO͓H'fOzғ;L;# DMrV^No)b:E#[*`h0 ‘o}.fY|Чh`HS@Zh`T\MG[ fkjGi~U|)]o̮|*sձEQs{*Ϲ^5Kix-fMEHbES1-JkL65݁z:Vv_΀$~J$F!;iQ%G :fgD`xm'f`(F.*pUOܣ'@~4iX 5?֯?(`DM1, ۋ>j"}*cse MS6M`H`q uwiX'laMuQ_JHC"f~Ofwi~$oVmH_&5A7)}j/wHct%RR ,4|hFd?M:4ñ6Ĥa:Pr(tt0lpCþ~h{.BoZRG4AMnq7Xoq^&t˪/B@o*r6G&~Eҗ4i}))XtRk Kѷmۗ0T޷jt#'tEdŸ @،~G=iT9vwGHj(xb,q)+1.6TS4=zrhM8VwBd! xEAh'9v gl+KҀ?p4fW^pR.C[aۄI[j{]32*^P}; ğ‰e @jwӾݵ_,=(`wR:jX#ԫu]H¬l+ sh+R=,6Ni-,xlLo: ^|ۊg,Ċz!P3/>`xBAdc8ƓN˃1u>ݥ^.#ƴv:/Y6Btŷt\w?ٕp tLxJvi.Eyr6(b&&!*;vV7LNBwt7^wB~wB\?WGh3"fz/aUE҅Nۃ]W =7P'Am(;+G|#&)ۥ]1/~&0ɾFRc)$Uɺ5!% tk9hƔV٩yHTECN"!䢟l*.零mjW0)JLa؅94g/ Y$fL:T~T{]CUmv_5 dw^t&x.cRk!\*h۴ ]i0J5 QK#_;'kZz\(1.^#$TXŢ+Fd"xVjpکDhߖ(A1;k7;G?.S(O k*U>K vW R26 ^"e-Jck%`tOPy Jw>TQcT Fn:hJQTMyD-zB :C9U[&6mP^~_=?^ߟ*f>y)9t?£.(rpb:?|"-ݡԇ7)qik:yûW~G;:&(JȅH#XCj,㜍 z-'/ OCm O}H׻$){AoH9Swk˦uΗ>wl;nj)dQ2@viȪln _MuF¬o&fɡlS#ocmPBIM}rm3 csSfBۨgō55)_!4ea3\%N,%]Ssj(ssdu!.3j\p/oz-5n)m08.ηCc奸k)“HN NJmM{]am)(u9n 6u`vz\ho&3r4NfgAuL01s@FÛc?[y`._wSםOqna#Avd-jx[st)S& XnͰȜo=uG%)9>ZQľIW;l#fC+\4V"[ d18`Pį'^&gIXtR;q8lxMG iu kS*WwjuRTQFsMXnI0Rm;,v7í씓NNѠעB9rv .&e¥r"7ewW@8_J~ӌko9.iwe;ECށ`7ۯwWͦo~39 Ci=.E #=pQ1wqzMNrU}kӒ !i%YiWVL^U%''RFD4 eyWTi74~:~dĊ#I(yD㎪1 cC3ɸ'qn@"aK1$b6tQ(n,{ "IlǶ]ctq? 2q˥+OGZ]H'/H_"_Bsjy YR/"dx21;Q 0+^ꣃ>潘Qw(E2YY$ }!Tf:NBm.Jس6{CK@S>S}L6!gnEo5cp(u-?`9wO@Mʥxr$`K\EPṚUW|qȒ {F@E4yYe2 za\BNu<-<lnz"9z 5Nnm/5OoTAc#DU'd=DH7I! ~* ϤZ/z=@ @R;{ǹ,R5#C! 2DȄm"5my /xȸ6+i~!mmGrI~1CΪ8s^m@@sEYsy *i/v>$@:1W;V{ #5`28ooEU6es:eÉ,]Ӱ9F)2jc(ƥȉ%YT˪G/i驫)GsoĿHiUW}# ! qa=JJ,1|oR9D&=Vze:q̑gnD2:5rhry_ɱcڮJy>DGMpmbo=)vL¯d)bOv.rc)E!w$']\*M2 Y6BN X*w)55)a2Duo[<YΘA``ΎB4ۭ $3<1밸m>*f9 dwz qN5o .vi#a.#l|Y_L&E,b\R'j(dT6"GEC;qDiXʀ\1 E5%Pm\+6ChxdbMZffq֢քZ]< $UѿZl ȫL @aAp7\Kʀ8pXlŢ \C[ [F*ÚJ5zV)Gsw* +6F cTWErYQ Q|n5A3U %F2eyYUJ;Ak$y\BIlk>7' L:>k 'K@.COo9NgQSN9畤SKi7ڷwy;tg. T4<ˬm[ f!ho@&: ˓-Fxҫ J1i{mQ o)}y|cKVVkh8S03 cRrEyWeary5(@/ 2e ޵yȯ 0uM8Δba|n$5_B uD9 FR-i|Hsě3@tҐ5+Wev:<.nO72r 5)Mbg@BaȪ X\w |t|?a4q V {Cu;Pr+x@E3AvoK@8 JgHaP&k<_>lm9WYm>~ q@DD9HΌ0wci T2Bzc^ `Ŀh 5zH*lhIy WM, aהE0C?#ijŌVlur}\C RZKa#jnGCSݙc-ua*GxF~u# ڍ{M/z܂{YLVفI`hu0[D> f!a=KIKViz):ORV *' "!# :8Dm{Cߴ y<lPeLK, '-ɢ4yhpP;b&Mtf =䄅?!3DE+=rd9 MK ++dy3B| $e"&KRM8rn߾ >&@t`5u QH,,gVdlNcD$wokHjU,o_3$tzvDG+0+HO< ^Cjso\-y}r; 區)5#ʀ$\ͦW$ue `DsX/9-O藀z-@vFUtPE[K#-@T)ڊW7:Iy!? o/{~(EHy:(C"uڒ_u^ZV>)[Ħ!*P,I5#iyl՛BjCl,Zz-OFЅoG)*1XtRsXވ<^mL<{p 4@ mH:"!fa*Nv1(tj~ Vs1(6_f2 u_Q X`['QPDdHdڀ;nVڸy.Y}GHNezfk5.Ƞ E X\rFr:BgҰʙuɗoh,`ua ȉʑ>o֓27 Hwt J#pCI=KY&R 6k Cfo _dd`T(GX= grxk_ד'Fi<ò[?Wp}^ @VPE*诐w7XiyrkZw#Nͼv!)罚7_N(8 $S(.t;xJ 릩k*K5\m1=޾ԗ\8wLv³^*-̙^cM |^F7$&)L +474$_@ K@]F?HPW=@I\;e:Q7{*yQC,pM@R01:]ڂkڢEWTQ鬼i;ZD!+]ҍ؊ZP{eURFN'ț*LʂWl+#)K"noQ֤,Cbrg@]'}FTl@^aIb ChM2|j'bzᇛ\.QypZ^6נ^9Fep"##ދBiG,^xH2D:Lq f?H,ͧu%P"V\, I U<;>R˵U7 0f{d=ZfXBDϛ&?%DAȼ&eYHKH>Lug PGJ.  ֓i7RC7Fƣ%y(e@-FUY?F +,4 Z9 jʩn63@v7]w';(G9Y &dzP;p **\m21.V"_d4֖PHΫ.Z 45{xq R,t܍+HU4˻ Ȋ29xǮN;đ&ZIrݑ@c˪lEgj9[8OWwY)Γ^W9NZ<{*ih8٦ymm[Iv Y^"/ җJc qDt!^l_^Vx#0k#fC. L13$ߜ0rQ}  Hgd|:+M# &tz䊯I]K׷]@9wc4 V43z+w*vDmT9 CT2ʩP4\Qt^^EEb!ᅹmN=R'r6hCF7Y,Hp_s)K0 ,eW$JTJ8Jr#BV2Cۆ}l49){?[ ?u861 @_\д Va] ,gWG:)7-ͳшK[rgU@h#fpK,mAUz}~A 7iZOKaty )K 0`[ʼn݉''mÝ/3)DQf#S{3Ey. *d/6n#T؁ڞC;\" &7Xp\a%ϱD 3Ȃw ysjE͟aMe]QbvЈY␕D $/gK>k-؍~z#`ъ)1Oښm^΀,(l=É+M{|!bC=Dp_= WnowQ6r&Up@<$MN\]KNY!`uDf) 1Du/z״@E홓_0A$ <ĭ .6qqUSt ۙ%MMd@&>yғ~\e\?/ ~=͖i T \ַl P(t'C ׹YBM@],R#}Ǎh 89[@Tb u N̆`h6;9 DRzMf@ts޳> y8,յbWDwh)!HR%Kx5#XBԂV=8z.p]]UX]rrͱϷ Hƨ.Kwf 9&$.4 W{:]+wS`"*ٌ9p.Y8oü@A }?e3s@`Iw] @M<`7wJ-ĒsщNV%)[x.8 G-@¼agvcXP SCkY"~#dtrrj)&UjWKע>!b>yC0Wf% <^n&j!mrx/kk\SgGB-6tTe|G"U xoFfH1L0)ڀ]QZ;X:i^&AgMX ?j}͉mz<;x'Kٳ2\0{ 3 gE@\Ig%jcHn% @L3]" rZI.i~:3̳! \$V8j+@w'T:!g w`tGB$KXcP qE@UjX/9 H<Q_UGN(gHdNY9I:/ShJho\Si7 TYF%iWtɆ<7FfB$gV&Q3 -;gsɜ>{aj_B]W¨<zdMF|@C0NI!~B 76Mcu҇}ܔLdC!GoUSJ& *ɌaTC2f L6$cV'@~g>##Tr`_28ɡ[!3WNO[N&5`"mIOb'UBK(7;OF.~`ťw߹l}Ҍ?e I6H#Zd&T}{PuI%0́{?VoVb!irRZ1Ȕ\Xa*8V>I^ڼ|k<dR9v  .%@RuVqD7&i#]Th? @$<*6H&J!'@tMżlFճP~# T)z~[,BY!%V[_3k)df=PDQ!ʰIَ'mBKg+J.هjXח*B@P\9|i6K@0oyNF}D7E_o9pvSJ)5 i#B1$,6,,p .i Ȋl'NWē[cgs#5B aϐAKex_HM#-)hRl|qWTT%GBhH"یP]i~e@=Dc\- W8Ц55a=1 "׻G_o{, ѷ҆Hy#R̴D{T)>Y||\Ѳ xt 艎3ɕr(X!tMŹm\C|/C}g q#1`ϥzS'ߥw9}D̻8w~,pw҆ 0Q_4%l+j|Ճ׊6'@-;,'*jۢ;.n䬪ݢYe]xYl l虧^%{omx}ۿAIњm2D(K Jo{D44iҢJ*>hYf4H0V;[@-/蕖ǿp2|hAFbN!@dmzm ]͆J!-s' ib 4dvZ|*)ٿI=$6 uVbt~b/L7r 1F99jG?d^2Ma  fsLqqأf#' ENwR; 8`K3_g,?GJ` 柣D}DT{ӊ#[' W|о^RkQ!VO!}г :Sg/Gnfw|btbKU 5gRֲ=窴 w< 0fVf ;@b\ʃ?wpO<0 rI һUv3gM["Osd˜o'} d8Á f w%@soR>>Y+Nc,2K@C {p<&@spQ֋IFtF.S>%f\s@g/E(i^3"D\x YrB"^21%bqa%ݳOL]pD<#1]]ܢ4# -ʍ,uc$<3oeOp^wB#ۡag1oǘ<}}U} <"d s u h3@ЙT mĉ0͞Jxޤ G.L;9\zCx(rꀜ/UϢ/jh#n F [2-~uRvRlQܬ,b-hJ)%cJd$=:q ͏ Ga$>g$B[=$.d{$aa\@i[2 h3tXyƉdIQ-t!b<ĉ:Z/yƉ+IIYI뛥'=ZRɳrΛf*Η|OIv${$HwtYhX_ݓKeU} 4o]Fe5<G)EB|M/X"jEv.wߤqKGrGH3Z0NZ"^Tπ`'mk;-I7e9W-8_?q!^{!y~e.HNGm_V'@$ m;p U4#ͻ<*˟l9ӇV >J|o#Ī*v会L5 ?׀p> a|'_%BINCV1uB]p,C:v3/:Avdwȳ% ɸF@t-Ѓ!]!$sIȃdLYe b<"E\H2Eaǔ'BcY JVfNNHC~ Ph봝v՗TsF} IGNYi挘𙵑M+e|[μ=W佥Hl|9cy5zC<.Nڔo>t1/F^| Ãb萘 !"j1M@ .' ɰnf_5yD QUl :L7mw!\"@I+sQ;H c&^IO׾']a']O@4^[j$xh R}*uvnm}rrҞPɧfW&#NJjg؄h]?m.\,OD 3vlH֩iqI$iڤwg7Ӧ%ώ/\k\J #6/i}F!|Q)8\zVIPhUy:k H[j]Aq_(:t SsWĦ&XM^>¢ b?bÐ 8,hN2!Tc~'7ѦRjJ\B㸃;1L;N&)X l]N \]YS'/Q1 㔰4AD5ЫfG=TGh(ܳkeRC.ro"D!*=¯-KiJmOeA,6! 3wH6HnY@A!0@+E48kTQhB-g\oܓGTz҇^?H'=IOA &q9] xƀXuҝHw:p9.s @HGs d9^gcC ^٤!R^/dp3Utm@n6T䰑t^="]F-\ьHz7e[,q0oոbywT)*|> R{h;vDk:ݩ]KW1_ͭ&mX-EyȿJ.݉{:Υs@8QOŻFݮorLH"|{RS) R&*X@N}M?-!SViG{}7B2> bj [ -iC~Ysуe#h`ͮN]DqP]# _»0Mi|l om+F*B!8:v2 Y Eoqg?x$KU|z:8j`;Ht`^Co ZFS?4cTvaރ(\2Q+1Nl?834rS NY'0 XكQ4Է`׌}3{*A"7AH{u\>7b*FO%_#8Y'OlX!ȹ7wyfP!NRlT]$ᏓyOWT6іYqiSĝfmKq8+;8 1jOMls_[2zڈ!"huxV]CyH*m}$ngb٪X6ĜH{i#k3zJOh@1FR(Jv2Ytti3| !k5Ij -i676gj[rPro[O:7g%JMO$᎛T`DjP5<+(n=0?Mbo=JĈ\B`1AZ]z Nv/퟈KyZrYdg@!S Y! Yrg' Pʎ)!hۍO@eMIENDB`GD-2.78/demos/shapes.pl0000755000175000017500000000242313076115434014247 0ustar rurbanrurban#!/usr/local/bin/perl use GD; $im = new GD::Image(300,300); ($white,$black,$red,$blue,$yellow) = ( $im->colorAllocate(255, 255, 255), $im->colorAllocate(0, 0, 0), $im->colorAllocate(255, 0, 0), $im->colorAllocate(0,0,255), $im->colorAllocate(255,250,205) ); $im->transparent($white); # white color is transparent $im->interlaced(1); # cool venetian blinds effect # Create a flat wide rectangle paintbrush $brush = new GD::Image(10,10); $brush->colorAllocate(255,255,255); # white $brush->colorAllocate(0,0,0); # black $brush->transparent($white); # white is transparent $brush->filledRectangle(0,0,5,2,$black); # a black rectangle # Draw a friendly title (ha!) $im->string(gdLargeFont,150,10,"Hello world!",$red); $im->string(gdSmallFont,150,28,"Goodbye cruel world!",$blue); $im->stringUp(gdTinyFont,280,250,"I'm climbing the wall!",$black); $im->charUp(gdMediumBoldFont,280,280,"Q",$black); # Draw an oval $im->setBrush($brush); $im->arc(100,100,100,150,0,360,gdBrushed); $poly = new GD::Polygon; $poly->addPt(30,30); $poly->addPt(100,10); $poly->addPt(190,290); $poly->addPt(30,290); $im->polygon($poly,gdBrushed); $im->fill(132,62,$blue); $im->fill(100,70,$red); $im->fill(40,40,$yellow); binmode STDOUT; # print the image to stdout print $im->png; GD-2.78/demos/transform.pl0000755000175000017500000000136014174320547015001 0ustar rurbanrurban#!/usr/local/bin/perl use GD; # test scaling, translation, transformation $im = new GD::Image(380,225); $black = $im->colorAllocate(0, 0, 0); $white = $im->colorAllocate(255, 255, 255); $red = $im->colorAllocate(255, 0, 0); $blue = $im->colorAllocate(0,0,255); $yellow = $im->colorAllocate(255,250,205); # Create a triangle $poly = new GD::Polygon; $poly->toPt(50,50); $poly->toPt(100,0); $poly->toPt(-50,50); $poly->toPt(-50,-50); $im->filledPolygon($poly,$yellow); # Stretch it a bit $poly->scale(1.8,1.0); $poly->offset(100,0); $im->filledPolygon($poly,$red); # Rotate it (scale by 0.5,0.2, rotate by 0,1, move by -25,50) $poly->transform(0.5,0.2, 0,1, -25,50); $im->filledPolygon($poly,$blue); binmode STDOUT; print $im->png; GD-2.78/demos/fills.pl0000755000175000017500000000112413076115434014072 0ustar rurbanrurban#!/usr/local/bin/perl use GD; $im = new GD::Image(100,50); # allocate black -- this will be our background $black = $im->colorAllocate(0, 0, 0); # allocate white $white = $im->colorAllocate(255, 255, 255); # allocate red $red = $im->colorAllocate(255, 0, 0); # allocate blue $blue = $im->colorAllocate(0,0,255); #Inscribe an ellipse in the image $im->arc(50, 25, 98, 48, 0, 360, $white); # Flood-fill the ellipse. Fill color is red, and will replace the # black interior of the ellipse $im->fill(50, 21, $red); binmode STDOUT; # print the image to stdout print $im->png; GD-2.78/demos/draw_colors.pl0000755000175000017500000000166013076115434015304 0ustar rurbanrurban#!/usr/bin/perl -w use strict; use lib '.','./blib/lib','./blib/arch'; use GD::Simple; my @color_names = GD::Simple->color_names; my $cols = int(sqrt(@color_names)); my $rows = int(@color_names/$cols)+1; my $cell_width = 100; my $cell_height = 50; my $legend_height = 16; my $width = $cols * $cell_width; my $height = $rows * $cell_height; my $img = GD::Simple->new($width,$height); $img->font(gdSmallFont); for (my $c=0; $c<$cols; $c++) { for (my $r=0; $r<$rows; $r++) { my $color = $color_names[$c*$rows + $r] or next; my @topleft = ($c*$cell_width,$r*$cell_height); my @botright = ($topleft[0]+$cell_width,$topleft[1]+$cell_height-$legend_height); $img->bgcolor($color); $img->fgcolor($color); $img->rectangle(@topleft,@botright); $img->moveTo($topleft[0]+2,$botright[1]+$legend_height-2); $img->fgcolor('black'); $img->string($color); } } print eval {$img->png} || $img->gif; GD-2.78/testlibs.sh0000755000175000017500000000042414174320547013507 0ustar rurbanrurban#!/bin/sh sudo mv /usr/include/gd.h /usr/include/gd.h.orig for d in `ls /opt/libgd/` do echo perl Makefile.PL --lib_gd_path /opt/libgd/$d/lib perl Makefile.PL --lib_gd_path /opt/libgd/$d/lib make make test done sudo mv /usr/include/gd.h.orig /usr/include/gd.h GD-2.78/MANIFEST0000644000175000017500000000445214450761210012446 0ustar rurbanrurbanChangeLog GD.xs LICENSE MANIFEST MANIFEST.SKIP Makefile.PL README README.QUICKDRAW bdf_scripts/README bdf_scripts/bdf2gdfont_pl.PL bdf_scripts/bdftogd bdf_scripts/cvtbdf.pl const-c.inc const-xs.inc demos/brushes.pl demos/copies.pl demos/draw_colors.pl demos/fills.pl demos/font_list.png demos/fonttest demos/gd_example.cgi demos/polyline.pl demos/polys.pl demos/shapes.pl demos/tile.png demos/transform.pl demos/truetype_test demos/ttf.pl lib/GD.pm lib/GD/Group.pm lib/GD/Image.pm lib/GD/Image_pm.PL lib/GD/Polygon.pm lib/GD/Polyline.pm lib/GD/Simple.pm t/GD.t t/HSV.t t/Polyline.t t/caller.t t/fork.t t/test_data/Generic.ttf t/test_data/frog.jpg t/test_data/frog.xpm t/test_data/images/corrupt.png t/test_data/images/t1/1-00.gd t/test_data/images/t1/1-00.gd2 t/test_data/images/t1/1-00.gif t/test_data/images/t1/1-00.jpeg t/test_data/images/t1/1-00.png t/test_data/images/t2/2-00.gd t/test_data/images/t2/2-00.gd2 t/test_data/images/t2/2-00.gif t/test_data/images/t2/2-00.jpeg t/test_data/images/t2/2-00.png t/test_data/images/t3/3-00.gd t/test_data/images/t3/3-00.gd2 t/test_data/images/t3/3-00.gif t/test_data/images/t3/3-00.jpeg t/test_data/images/t3/3-00.png t/test_data/images/t4/4-00.gd t/test_data/images/t4/4-00.gd2 t/test_data/images/t4/4-00.gif t/test_data/images/t4/4-00.jpeg t/test_data/images/t4/4-00.png t/test_data/images/t5/5-00.gd t/test_data/images/t5/5-00.gd2 t/test_data/images/t5/5-00.gif t/test_data/images/t5/5-00.jpeg t/test_data/images/t5/5-00.png t/test_data/images/t6/6-00.gd t/test_data/images/t6/6-00.gd2 t/test_data/images/t6/6-00.gif t/test_data/images/t6/6-00.jpeg t/test_data/images/t6/6-00.png t/test_data/images/t7/7-00.gd t/test_data/images/t7/7-00.gd2 t/test_data/images/t7/7-00.gif t/test_data/images/t7/7-00.jpeg t/test_data/images/t7/7-00.png t/test_data/images/t7/7-01.gd2 t/test_data/palettemap.png t/test_data/tile.gd t/test_data/tile.gd2 t/test_data/tile.gif t/test_data/tile.jpeg t/test_data/tile.png t/test_data/windows.bmp t/transp.t t/windows_bmp.t t/z_kwalitee.t t/z_manifest.t t/z_pod-spell-mistakes.t t/z_pod.t testcpan.sh testlibs.sh typemap META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) SIGNATURE Public-key signature (added by MakeMaker) GD-2.78/LICENSE0000644000175000017500000000053013076115434012317 0ustar rurbanrurbanThe GD.pm interface is copyright 1995-2010, Lincoln D. Stein. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. package for details. GD-2.78/SIGNATURE0000644000175000017500000002372514450761211012606 0ustar rurbanrurbanThis file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.88. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: RIPEMD160 SHA256 dbb094246b77cc9efe1933d3bd222d5cdaef1108facdfec54f9ca11b54be7255 ChangeLog SHA256 0b8b34e17c938acaf2c686bd45d3b34feddc9dc7baac119c4103778064ab233c GD.xs SHA256 1e2250289d6df4ba1c24f7550982d7ffaff2c97cd02e847659406e1afd28e83f LICENSE SHA256 76cc90e4a381e2ff22e1e871def956e28ba3d65d9ff49bfd5234895c8c88b953 MANIFEST SHA256 51cf5b6389b11ec8ec1d097acca1a21b19fcfb7f628b6955e78040388bcde56e MANIFEST.SKIP SHA256 05f6ab2d750252b8bf65a7533f215163f7b1854f6ac624e2b5c73290d9978193 META.json SHA256 c431da110702fa0acab96a575166e939e236c79801db65554a346b4cc80b0b39 META.yml SHA256 9d65af42c76b870890bf835dca096022e5bfef4e3b45788b9491262aa1bfdcd4 Makefile.PL SHA256 8ca417a6dc173c495e6f740ed0b58f439d8ac67875c6ea93ced9d7fb6234e559 README SHA256 fd15127ae2613fa8a6ea308371cf256a89654c64aa39d2cd4da6fa445b4bf094 README.QUICKDRAW SHA256 2be4d75aad4a18cfa9da42c3f2ac46c22f7c1798d9be5b09d591ea8dd3c6c94a bdf_scripts/README SHA256 4d92f1e9396b93ccb5349d6cff5cbbb362905bfd8186013c1b40d341ea6fc5f3 bdf_scripts/bdf2gdfont_pl.PL SHA256 db51e897adca852b24f4abd6911931f8e3f603b444a689f8149a142ed6ebd641 bdf_scripts/bdftogd SHA256 bd77a5a3576cbd1204aecaabdfc709d30b927473eb575ac48a1f990719f5b2d1 bdf_scripts/cvtbdf.pl SHA256 238c62dc99cd09fef60dde80293c4f8fc4aacbe5418c93590a8133917c8c052a const-c.inc SHA256 7fd8d328ed6ecc36d3dfff96a7a911ebe515a8f15d6182a9e3b00b01fe0d3280 const-xs.inc SHA256 3b971106343d1dff28634f90d005280c3629594bd89c6fc5f4160e54a353f41e demos/brushes.pl SHA256 a44764db8ddb5a8fbd4abf1fc509566456578a7f603391201fa0a97bddc71d90 demos/copies.pl SHA256 2a63fe1a1961079c5dea7954495c20f9225546efcc77527b565e0b4ff930c4a5 demos/draw_colors.pl SHA256 87ad695787fe8f5d3cf916e727ab141ecb7d5748b337fcd749115eeffae98909 demos/fills.pl SHA256 2278a2d0416bde0baa4980ce749f2ad031a3c5ab4e4eaace2b0695ce3bfe254b demos/font_list.png SHA256 ffd82647fb1f94b304bc3802215ba86ecd96d4af03898e9c60483f53660afa7e demos/fonttest SHA256 f7e90489830fbfff462e4cf88c17e55d90c04ef7ba466d8ab8b25f06ee5f5c7a demos/gd_example.cgi SHA256 485c022cc8d4acff29e554bf9a2647d81e26cb58813239334e8c49e860a53788 demos/polyline.pl SHA256 a29b89da1c4fc4f9b47bae92bb2d99bcfdebaf152615569c02924518175c1acd demos/polys.pl SHA256 16fd81aa8cd3f804b7691cefc7dd4b58d05fabed34d1db9a1beb4dcee419c87f demos/shapes.pl SHA256 d1d9bb1fbcf22a008f7daff62f0c02d9983ff3ace2d504363c7aa73db8da863e demos/tile.png SHA256 e91060fff5e229f72f0499f40b67a4e842b9c6f817f152e26fe301027521f4e6 demos/transform.pl SHA256 855052638bff1622bad600fe5bdad5fd4c92321eceefd18b4cee1dcb336cab38 demos/truetype_test SHA256 278cf272eb8a93a1e850fa54e815e450c48a3e2c25c57ecc54034cb398dd5646 demos/ttf.pl SHA256 e351911ac23e42b6c0470ce25f9836cc92c6bd90f897b1c1e1770d83f3051fa0 lib/GD.pm SHA256 a5c8d2674d72cc5fccb54aedf6665b524a52ce86b3852e6767fbde74141274fc lib/GD/Group.pm SHA256 960849a0bc1663f4bf2e1dc926f0f50d87f04f93e8adb8a9ec2b10c5e0fa0213 lib/GD/Image.pm SHA256 0e3b26c5f58642aa2fff3a419718ce3d159613c96cd3fcf3b9dfadd7f5cadf00 lib/GD/Image_pm.PL SHA256 4ed3a88e7b9c2e709f86c3599a45163239d36b62b341fb11769e70a8cb96c048 lib/GD/Polygon.pm SHA256 3ebe1c4f9224d59a632186445f127729debcf2d36833c0a2a6ea7c22d6e83802 lib/GD/Polyline.pm SHA256 19cf8d16f8f430eef4b22af0d1deeed9ed0ae31b10dc82dd2bf628d058378a7a lib/GD/Simple.pm SHA256 357ed3cad3c6efc3937d544f21ea275e9e14f200fb5bc8606f47e11f7aba980c t/GD.t SHA256 0444099f93e5564e7aed93a99037d5a2d8b0179107efe670c3c4ef59a58b5691 t/HSV.t SHA256 f2d7cc77efeaa1af76d10e5aee57447ada1d0ddcb3e037877e3dd4918d7b0290 t/Polyline.t SHA256 88a8bc61ab6e6d7dbde28668e51bbf12714cf93654110e8539951bbfcbd47691 t/caller.t SHA256 72230075340aaa8c56e0b4d9605a05b90d34a26923d149e9ec24342a38940aaa t/fork.t SHA256 053128eeff24a4357fd0cd2ff272ffdf6bce8f387699c6d3c8400948b063f833 t/test_data/Generic.ttf SHA256 45c0fa1761b9d4303209aee4719b93c7e8032fbf473e134dccab0adc0af78b31 t/test_data/frog.jpg SHA256 087f17d8c96ef82b866ad132f56c8c60d69c9d3a198998eea75523e5ff66aaa5 t/test_data/frog.xpm SHA256 dd220b2f06c705d260b50d463c26f3e69ef2f401412a2da9f1c7364dabb4eb30 t/test_data/images/corrupt.png SHA256 a9e457b32e004472d676c8601f290d7e2652e8d27cd480f48bd0c3f7ea703c7f t/test_data/images/t1/1-00.gd SHA256 7f6a2498e6ec6cf37de274f50d2b2d6f0b8b5965654ecd6385a7c9bcc602d2a9 t/test_data/images/t1/1-00.gd2 SHA256 3ea0b49f7a4d4216a4d30bae175337cfb712b03827555b6e75321b8ffcafa757 t/test_data/images/t1/1-00.gif SHA256 a14e389ae06db6ee64d6f3dc496e187860a55513e102878a12346258697961fd t/test_data/images/t1/1-00.jpeg SHA256 92834cda18d539b373eb1f4b0d37cdc875b08abd4de08a40ef3799f70f2cc314 t/test_data/images/t1/1-00.png SHA256 42ee9ea8654be7a078ed7dca7857b672c590e33c232beba68b075e5d825f0068 t/test_data/images/t2/2-00.gd SHA256 ecbaecf9b8d6881ba2c599d1d524f712f8d40d165583a03704e2991cb5c604d1 t/test_data/images/t2/2-00.gd2 SHA256 8c3843081f2d034d16a5739cef6ac3722a85adfd9f6075f900cdaf9252b99ced t/test_data/images/t2/2-00.gif SHA256 35ad6eb9a565c23757c5fdc2182f60465343c13ee333db148a1d7c15242ddbad t/test_data/images/t2/2-00.jpeg SHA256 b988c65df39b4d626893974b145217f3284bc111b92b0728289637aee6fcac32 t/test_data/images/t2/2-00.png SHA256 2948bcdb12b2705c2ccbf3b8551475fe25a7eeb3213ac10512c3eef4df981f34 t/test_data/images/t3/3-00.gd SHA256 16fe069e12e6ce4316d171cfbff96c95676874154d30f35d1a90b8f11bd2ea4c t/test_data/images/t3/3-00.gd2 SHA256 d29baca65890900fc8a78b0638b04530cfe474444fe62f46794d2cff3a315b78 t/test_data/images/t3/3-00.gif SHA256 2cfc768792a7b552ade95b8dc5592937e90ced0a1ffa289bebdbe95b6e85c758 t/test_data/images/t3/3-00.jpeg SHA256 352d7b27d2ffaf6ffe11abf1bf9c69764948f5de1e169b5cd2b45959f0bbed17 t/test_data/images/t3/3-00.png SHA256 a2d9b0f1590987c608a4c883f35307b6f49fbf33621bc7843754d8e1e6871ea5 t/test_data/images/t4/4-00.gd SHA256 5c783dc9a514a728dff15916b4ff49002d0057c66f6c07ab707e4824fb4fdce4 t/test_data/images/t4/4-00.gd2 SHA256 a09fe48ef459b0f359133f780b686262cbac91e3a84b6f10c85afc39c4a64d3d t/test_data/images/t4/4-00.gif SHA256 8c57e1d0f6435d7cd4f0767a59e1458ebde6d9d36110fe713d5d5284f04632f9 t/test_data/images/t4/4-00.jpeg SHA256 b603a6acb53b04c438d0e3dacff2aaa977aecb498d95d11ee61c6d805a1e6ac3 t/test_data/images/t4/4-00.png SHA256 2749011d015c8dc98defd638ff199ab119dd70c60b8738a84b630b7325dd9aad t/test_data/images/t5/5-00.gd SHA256 31b6e7f0061a6e6c1043badb7a2124b011b6345b495ae5b07c9afc8e6a8dfe72 t/test_data/images/t5/5-00.gd2 SHA256 cb8f76d3763a14de5eeb37f1d7db6ae880898d31c61a4fb2d70c2d123992e900 t/test_data/images/t5/5-00.gif SHA256 30b05f3b9098d77482bbb064c62010e76c5f4743b56251300db01a337f4a8a7f t/test_data/images/t5/5-00.jpeg SHA256 95578c4e2b263292025b90a715c2a1f88b97cce2a112bba5af708ad4aa2c7d59 t/test_data/images/t5/5-00.png SHA256 8f692c00ce60655eb0d2b75cf33ec997975ae48af58d3491d9e23f2511767b00 t/test_data/images/t6/6-00.gd SHA256 be60a821d3e1ae30ecbeac3a93b08dce483b1977ef66ce748dd81597662f9b53 t/test_data/images/t6/6-00.gd2 SHA256 634fa7ddba2856dfde1c5b9737986750c098a3696e395b7b60934d0f09fb71b9 t/test_data/images/t6/6-00.gif SHA256 e165488626f6d2e205a97d78e1b6775e80737d9ec6850bd9fd0515a55208f0fb t/test_data/images/t6/6-00.jpeg SHA256 517aa6c163d36b7bff2dd7bac566cf191343bdf03299a51b746d54a22a6f6ac2 t/test_data/images/t6/6-00.png SHA256 383dd91a8ab0029f0aeec4c1975b2e988d07214267284814a43e24faf1f92df5 t/test_data/images/t7/7-00.gd SHA256 15b0eedf17c4c81e76596a0f95d657e33861e409df1ff47e1627b888148a99ad t/test_data/images/t7/7-00.gd2 SHA256 cb8abae8430dec8caf9201220b7e3a51644f35e07093d45dfd2087082740da1f t/test_data/images/t7/7-00.gif SHA256 1aa3d06d1a0b85b78153ae22d41f2ff13378e44f0696e4fdf8e98241d5c55682 t/test_data/images/t7/7-00.jpeg SHA256 7036a641f5c87c0fc7497126517daeb1ffa9f84b667251f887f25413dde73327 t/test_data/images/t7/7-00.png SHA256 5fdcf93779fa1d6cd692aef3c198404459921cf9836d89c1849d479ee45f651a t/test_data/images/t7/7-01.gd2 SHA256 012da1186237cb42cf7c76d1c89bccf9bff41fb75e279549ab417513d10058e8 t/test_data/palettemap.png SHA256 8b0ee873ff1ab575b8a701e77797fd0d8c95ee3ad260239d25cae12eb7b634f7 t/test_data/tile.gd SHA256 9e94b89e682a71cfcb0636bb6d31c27a08b1899a0b6d5383d8156bbf951fd1a5 t/test_data/tile.gd2 SHA256 f3dcf8c35db5a8efb91fa3b6343ed877dd9a097cf5bc8fb59ea26e57e764a51b t/test_data/tile.gif SHA256 7fc4cabf75a1265bdbdb490b19843813f3c092949bf24502a80cce014b9187ab t/test_data/tile.jpeg SHA256 d1d9bb1fbcf22a008f7daff62f0c02d9983ff3ace2d504363c7aa73db8da863e t/test_data/tile.png SHA256 bd19cb90fc148fff24a75c312c9761e28471d6156dd642a810e5394177ed46dd t/test_data/windows.bmp SHA256 5d56264c29e72427573cb329360b4c91937638dcb98d460f64c3ce142836677b t/transp.t SHA256 10dd4cc144a109c4c33a761454e2ad76df3dd6d080c88768a5ae6c88b49d289c t/windows_bmp.t SHA256 04df534e56f8031e065153e3c80f5c7ae93f83aba8d5df58e3449e2fbe324d98 t/z_kwalitee.t SHA256 89445d163e2a24a2229ab9e6fca0d96f4f01a5ba051388d9b864a4e41c277589 t/z_manifest.t SHA256 f60c3190f3d4a3f79cd000071ce34cc6de122abaac9649ccc6371385366fca52 t/z_pod-spell-mistakes.t SHA256 20745a3f76d051aed139c90e33416e116b7a6d76b840151545c23cbfe5581528 t/z_pod.t SHA256 747c066bfdc7f458de8ea00574d1433161dfa49f0a81eceea70003196b9e5ece testcpan.sh SHA256 c686a6e1baa8214bdd64ece68263ad96d335eb964b7202eb040003e83da96c60 testlibs.sh SHA256 15513754e6de8f9d0d297935e78568953431754ac3d735cf95092afb55955532 typemap -----BEGIN PGP SIGNATURE----- iQEzBAEBAwAdFiEEKJWogdNCcPq/6PdHtPYzOeZdZBQFAmSj4okACgkQtPYzOeZd ZBTN0gf/SybYJS+hEnjABI9Y9qjYKLDMjyvTf5dtzVpKZt0oV99CsMPqh0WTNVwD DeraIfOUz3Fbffx/UtlCQrd7RWi1noyKEV3HuxPrP15s/lBO4ycJWdj8kj4rcmi0 Y6+nWgSnDqcfuFcT5MUuXI1qxyrXgA/1Gt9lfwN/MjVl33zH29leYoJmm/qTOrXj h08G92HhBm0ZFZ5WlwZ1S2uPYV5O4W0yJexpvXj4PSsPyCJbSOh9gW5pjMX6ESRw 3HdlfmkweGTL8aLrGan+4HBhpDQQ/SIgSwjrKsC0XNHy53EV670q1FxmUKq3Dusw 0z/L9fcwPYTzicTBVDgTIrd2Ddw6yQ== =rZDu -----END PGP SIGNATURE----- GD-2.78/README.QUICKDRAW0000644000175000017500000000012313076115434013521 0ustar rurbanrurbanSupport for the archaic Quickdraw format was withdrawn from GD as of version 2.55. GD-2.78/lib/0000755000175000017500000000000014450761210012056 5ustar rurbanrurbanGD-2.78/lib/GD.pm0000644000175000017500000021366014450761142012722 0ustar rurbanrurbanpackage GD; # Copyright 1995 Lincoln D. Stein. See accompanying README file for # usage information use strict; require 5.004; require FileHandle; require Exporter; require DynaLoader; require AutoLoader; use Carp 'croak','carp'; use GD::Image; use GD::Polygon; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $AUTOLOAD); $VERSION = '2.78'; our $XS_VERSION = $VERSION; $VERSION = eval $VERSION; @ISA = qw(Exporter DynaLoader); # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. @EXPORT = qw( gdBrushed gdDashSize gdMaxColors gdStyled gdStyledBrushed gdTiled gdTransparent gdAntiAliased gdArc gdChord gdPie gdNoFill gdEdged gdTinyFont gdSmallFont gdMediumBoldFont gdLargeFont gdGiantFont gdAlphaMax gdAlphaOpaque gdAlphaTransparent ); @EXPORT_OK = qw ( GD_CMP_IMAGE GD_CMP_NUM_COLORS GD_CMP_COLOR GD_CMP_SIZE_X GD_CMP_SIZE_Y GD_CMP_TRANSPARENT GD_CMP_BACKGROUND GD_CMP_INTERLACE GD_CMP_TRUECOLOR ); %EXPORT_TAGS = ('cmp' => [ @EXPORT_OK ] ); # documentation error *GD::Polygon::delete = \&GD::Polygon::deletePt; sub AUTOLOAD { # This AUTOLOAD is used to 'autoload' constants from the constant() # XS function. If a constant is not found then control is passed # to the AUTOLOAD in AutoLoader. my($constname); ($constname = $AUTOLOAD) =~ s/.*:://; undef $!; my $val = constant($constname); if ($! != 0) { if ($! =~ /Invalid/) { $AutoLoader::AUTOLOAD = $AUTOLOAD; goto &AutoLoader::AUTOLOAD; } else { my($pack,$file,$line) = caller; die "Your vendor has not defined GD macro $pack\:\:$constname, used at $file line $line $!.\n"; } } eval "sub $AUTOLOAD { $val }"; goto &$AUTOLOAD; } bootstrap GD; # Preloaded methods go here. sub GD::gdSmallFont { return GD::Font->Small; } sub GD::gdLargeFont { return GD::Font->Large; } sub GD::gdMediumBoldFont { return GD::Font->MediumBold; } sub GD::gdTinyFont { return GD::Font->Tiny; } sub GD::gdGiantFont { return GD::Font->Giant; } sub GD::Image::startGroup { } # does nothing - used by GD::SVG sub GD::Image::endGroup { } # does nothing - used by GD::SVG sub GD::Image::newGroup { my $self = shift; GD::Group->new($self,$self->startGroup); } =head1 NAME GD.pm - Interface to Gd Graphics Library =head1 SYNOPSIS use GD; # create a new image $im = GD::Image->new(100,100); # allocate some colors $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); $red = $im->colorAllocate(255,0,0); $blue = $im->colorAllocate(0,0,255); # make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # Put a black frame around the picture $im->rectangle(0,0,99,99,$black); # Draw a blue oval $im->arc(50,50,95,75,0,360,$blue); # And fill it with red $im->fill(50,50,$red); # make sure we are writing to a binary stream binmode STDOUT; # Convert the image to PNG and print it on standard output print $im->png; =head1 DESCRIPTION B is a Perl interface to Thomas Boutell's gd graphics library (version 2.01 or higher; see below). GD allows you to create color drawings using a large number of graphics primitives, and emit the drawings as PNG files. GD defines the following four classes: =over 5 =item C An image class, which holds the image data and accepts graphic primitive method calls. =item C A font class, which holds static font information and used for text rendering. =item C A simple polygon object, used for storing lists of vertices prior to rendering a polygon into an image. =item C A "simple" class that simplifies the GD::Image API and then adds a set of object-oriented drawing methods using turtle graphics, simplified font handling, ability to work in polar coordinates, HSV color spaces, and human-readable color names like "lightblue". Please see L for a description of these methods. =back A Simple Example: #!/usr/bin/perl use GD; # create a new image $im = GD::Image->new(100,100); # allocate some colors $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); $red = $im->colorAllocate(255,0,0); $blue = $im->colorAllocate(0,0,255); # make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # Put a black frame around the picture $im->rectangle(0,0,99,99,$black); # Draw a blue oval $im->arc(50,50,95,75,0,360,$blue); # And fill it with red $im->fill(50,50,$red); # make sure we are writing to a binary stream binmode STDOUT; # Convert the image to PNG and print it on standard output print $im->png; Notes: =over 5 =item 1. To create a new, empty image, send a new() message to GD::Image, passing it the width and height of the image you want to create. An image object will be returned. Other class methods allow you to initialize an image from a preexisting JPG, PNG, GD, GD2, XBM or other supported image files. =item 2. Next you will ordinarily add colors to the image's color table. colors are added using a colorAllocate() method call. The three parameters in each call are the red, green and blue (rgb) triples for the desired color. The method returns the index of that color in the image's color table. You should store these indexes for later use. =item 3. Now you can do some drawing! The various graphics primitives are described below. In this example, we do some text drawing, create an oval, and create and draw a polygon. =item 4. Polygons are created with a new() message to GD::Polygon. You can add points to the returned polygon one at a time using the addPt() method. The polygon can then be passed to an image for rendering. =item 5. When you're done drawing, you can convert the image into PNG format by sending it a png() message (or any other supported image format). It will return a (potentially large) scalar value containing the binary data for the image. Ordinarily you will print it out at this point or write it to a file. To ensure portability to platforms that differentiate between text and binary files, be sure to call C on the file you are writing the image to. =back =head1 Object Constructors: Creating Images See L for the current list of supported Image formats. The following class methods allow you to create new GD::Image objects. =over 4 =item B<$image = GD::Image-Enew([$width,$height],[$truecolor])> =item B<$image = GD::Image-Enew(*FILEHANDLE)> =item B<$image = GD::Image-Enew($filename)> =item B<$image = GD::Image-Enew($data)> The new() method is the main constructor for the GD::Image class. Called with two integer arguments, it creates a new blank image of the specified width and height. For example: $myImage = GD::Image->new(100,100) || die; This will create an image that is 100 x 100 pixels wide. If you don't specify the dimensions, a default of 64 x 64 will be chosen. The optional third argument, $truecolor, tells new() to create a truecolor GD::Image object. Truecolor images have 24 bits of color data (eight bits each in the red, green and blue channels respectively), allowing for precise photograph-quality color usage. If not specified, the image will use an 8-bit palette for compatibility with older versions of libgd. Alternatively, you may create a GD::Image object based on an existing image by providing an open filehandle, a filename, or the image data itself. The image formats automatically recognized and accepted are: GIF, PNG, JPEG, XBM, XPM, BMP, GD2, TIFF, WEBP, HEIF or AVIF. Other formats, including WBMP, and GD version 1, cannot be recognized automatically at this time. If something goes wrong (e.g. insufficient memory), this call will return undef. =item B<$image = GD::Image-EtrueColor([0,1])> For backwards compatibility with scripts previous versions of GD, new images created from scratch (width, height) are palette based by default. To change this default to create true color images use: GD::Image->trueColor(1); before creating new images. To switch back to palette based by default, use: GD::Image->trueColor(0); =item B<$image = GD::Image-EnewPalette([$width,$height])> =item B<$image = GD::Image-EnewTrueColor([$width,$height])> The newPalette() and newTrueColor() methods can be used to explicitly create an palette based or true color image regardless of the current setting of trueColor(). =item B<$image = GD::Image-EnewFromPng($file, [$truecolor])> =item B<$image = GD::Image-EnewFromPngData($data, [$truecolor])> The newFromPng() method will create an image from a PNG file read in through the provided filehandle or file path. The filehandle must previously have been opened on a valid PNG file or pipe. If successful, this call will return an initialized image which you can then manipulate as you please. If it fails, which usually happens if the thing at the other end of the filehandle is not a valid PNG file, the call returns undef. Notice that the call doesn't automatically close the filehandle for you. But it does call C for you, on platforms where this matters. You may use any of the following as the argument: 1) a simple filehandle, such as STDIN 2) a filehandle glob, such as *PNG 3) a reference to a glob, such as \*PNG 4) an IO::Handle object 5) the pathname of a file In the latter case, newFromPng() will attempt to open the file for you and read the PNG information from it. Example1: open (PNG,"barnswallow.png") || die; $myImage = GD::Image->newFromPng(\*PNG) || die; close PNG; Example2: $myImage = GD::Image->newFromPng('barnswallow.png'); To get information about the size and color usage of the information, you can call the image query methods described below. Images created by reading PNG images will be truecolor if the image file itself is truecolor. To force the image to be palette-based, pass a value of 0 in the optional $truecolor argument. The newFromPngData() method will create a new GD::Image initialized with the PNG format B contained in C<$data>. =item B<$image = GD::Image-EnewFromJpeg($file, [$truecolor])> =item B<$image = GD::Image-EnewFromJpegData($data, [$truecolor])> These methods will create an image from a JPEG file. They work just like newFromPng() and newFromPngData(), and will accept the same filehandle and pathname arguments. Images created by reading JPEG images will always be truecolor. To force the image to be palette-based, pass a value of 0 in the optional $truecolor argument. =item B<$image = GD::Image-EnewFromGif($file, [$truecolor])> =item B<$image = GD::Image-EnewFromGifData($data)> These methods will create an image from a GIF file. They work just like newFromPng() and newFromPngData(), and will accept the same filehandle and pathname arguments. Images created from GIFs are always 8-bit palette images. To convert to truecolor, you must create a truecolor image and then perform a copy. =item B<$image = GD::Image-EnewFromXbm($file, [$truecolor])> This works in exactly the same way as C, but reads the contents of an X Bitmap (black & white) file: open (XBM,"coredump.xbm") || die; $myImage = GD::Image->newFromXbm(\*XBM) || die; close XBM; There is no newFromXbmData() function, because there is no corresponding function in the gd library. =item B<$image = GD::Image-EnewFromWBMP($file)> This works in exactly the same way as C, but reads the contents of a Wireless Application Protocol Bitmap (WBMP) file: open (WBMP,"coredump.wbmp") || die; $myImage = GD::Image->newFromWBMP(\*WBMP) || die; close WBMP; There is no newFromWBMPData() function, because there is no corresponding function in the gd library. =item B<$image = GD::Image-EnewFromBmp($file)> This works in exactly the same way as C, but reads the contents of a Windows Bitmap (BMP) file: open (BMP,"coredump.bmp") || die; $myImage = GD::Image->newFromBmp(\*BMP) || die; close BMP; There is no newFromBmpData() function, because there is no corresponding function in the gd library. =item B<$image = GD::Image-EnewFromGd($file)> =item B<$image = GD::Image-EnewFromGdData($data)> NOTE: GD and GD2 support was dropped witn libgd 2.3.2. These methods initialize a GD::Image from a Gd file, filehandle, or data. Gd is Tom Boutell's disk-based storage format, intended for the rare case when you need to read and write the image to disk quickly. It's not intended for regular use, because, unlike PNG or JPEG, no image compression is performed and these files can become B. $myImage = GD::Image->newFromGd("godzilla.gd") || die; close GDF; =item B<$image = GD::Image-EnewFromGd2($file)> =item B<$image = GD::Image-EnewFromGd2Data($data)> NOTE: GD and GD2 support was dropped witn libgd 2.3.2. This works in exactly the same way as C and newFromGdData, but use the new compressed GD2 image format. =item B<$image = GD::Image-EnewFromGd2Part($file,srcX,srcY,width,height)> This class method allows you to read in just a portion of a GD2 image file. In addition to a filehandle, it accepts the top-left corner and dimensions (width,height) of the region of the image to read. For example: open (GDF,"godzilla.gd2") || die; $myImage = GD::Image->newFromGd2Part(\*GDF,10,20,100,100) || die; close GDF; This reads a 100x100 square portion of the image starting from position (10,20). =item B<$image = GD::Image-EnewFromXpm($filename)> This creates a new GD::Image object starting from a B. This is unlike the other newFrom() functions because it does not take a filehandle. This difference comes from an inconsistency in the underlying gd library. $myImage = GD::Image->newFromXpm('earth.xpm') || die; This function is only available if libgd was compiled with XPM support. NOTE: The libgd library is unable to read certain XPM files, returning an all-black image instead. =item B<$bool = GD::supportsFileType($filename, $is_writing)> This returns a TRUE or FALSE value, if libgd supports reading or when the 2nd argument is 1, if libgd supports writing the given filetype, depending on the filename extension. Only with libgd versions E= gd-2.1.1. Assuming LibGD is compiled with support for these image types, the following extensions are supported: .gif .gd, .gd2 .wbmp .bmp .xbm .tga .png .jpg, .jpeg .tiff, .tif .webp .heic, .heix .avif .xpm Filenames are parsed case-insensitively. .avifs is not yet suppurted upstream in libavif. =back =head1 GD::Image Methods Once a GD::Image object is created, you can draw with it, copy it, and merge two images. When you are finished manipulating the object, you can convert it into a standard image file format to output or save to a file. =head2 Image Data Output Methods The following methods convert the internal drawing format into standard output file formats. =over =item B<$pngdata = $image-Epng([$compression_level])> This returns the image data in PNG format. You can then print it, pipe it to a display program, or write it to a file. Example: $png_data = $myImage->png; open (DISPLAY,"| display -") || die; binmode DISPLAY; print DISPLAY $png_data; close DISPLAY; Note the use of C. This is crucial for portability to DOSish platforms. The optional $compression_level argument controls the amount of compression to apply to the output PNG image. Values range from 0-9, where 0 means no compression (largest files, highest quality) and 9 means maximum compression (smallest files, worst quality). A compression level of -1 uses the default compression level selected when zlib was compiled on your system, and is the same as calling png() with no argument. Be careful not to confuse this argument with the jpeg() quality argument, which ranges from 0-100 and has the opposite meaning from compression (higher numbers give higher quality). =item B<$gifdata = $image-Egifanimbegin([$GlobalCM [, $Loops]])> For libgd version 2.0.33 and higher, this call begins an animated GIF by returning the data that comprises animated gif image file header. After you call this method, call gifanimadd() one or more times to add the frames of the image. Then call gifanimend(). Each frame must be the same width and height. A typical sequence will look like this: my $gifdata = $image->gifanimbegin; $gifdata .= $image->gifanimadd; # first frame for (1..100) { # make a frame of right size my $frame = GD::Image->new($image->getBounds); add_frame_data($frame); # add the data for this frame $gifdata .= $frame->gifanimadd; # add frame } $gifdata .= $image->gifanimend; # finish the animated GIF print $gifdata; # write animated gif to STDOUT If you do not wish to store the data in memory, you can print it to stdout or a file. The image that you call gifanimbegin on is used to set the image size, color resolution and color map. If argument $GlobalCM is 1, the image color map becomes the GIF89a global color map. If $Loops is given and >= 0, the NETSCAPE2.0 application extension is created, with looping count. Looping count 0 means forever. =item B<$gifdata = $image-Egifanimadd([$LocalCM [, $LeftOfs [, $TopOfs [, $Delay [, $Disposal [, $previm]]]]]])> Returns the data that comprises one animated gif image frame. You can then print it, pipe it to a display program, or write it to a file. With $LeftOfs and $TopOfs you can place this frame in different offset than (0,0) inside the image screen. Delay between the previous frame and this frame is in 1/100s units. Disposal is usually and by default 1. Compression is activated by giving the previous image as a parameter. This function then compares the images and only writes the changed pixels to the new frame in animation. The Disposal parameter for optimized animations must be set to 1, also for the first frame. $LeftOfs and $TopOfs parameters are ignored for optimized frames. =item B<$gifdata = $image-Egifanimend()> Returns the data for end segment of animated gif file. It always returns string ';'. This string must be printed to an animated gif file after all image frames to properly terminate it according to GIF file syntax. Image object is not used at all in this method. =item B<$jpegdata = $image-Ejpeg([$quality])> This returns the image data in JPEG format. You can then print it, pipe it to a display program, or write it to a file. You may pass an optional quality score to jpeg() in order to control the JPEG quality. This should be an integer between 0 and 100. Higher quality scores give larger files and better image quality. If you don't specify the quality, jpeg() will choose a good default. =item B<$gifdata = $image-Egif()>. This returns the image data in GIF format. You can then print it, pipe it to a display program, or write it to a file. =item B<$gddata = $image-Egd> This returns the image data in GD format. You can then print it, pipe it to a display program, or write it to a file. Example: binmode MYOUTFILE; print MYOUTFILE $myImage->gd; =item B<$gd2data = $image-Egd2> Same as gd(), except that it returns the data in compressed GD2 format. =item B<$bmpdata = $image-Ebmp([$compression])> This returns the image data in BMP format, which is a Windows Bitmap. If compression is set to 1, it will use RLE compression on the pixel data; otherwise, setting it to 0 (the default) will leave the BMP pixel data uncompressed. =item B<$wbmpdata = $image-Ewbmp([$foreground])> This returns the image data in WBMP format, which is a black-and-white image format. Provide the index of the color to become the foreground color. All other pixels will be considered background. =item B<$tiffdata = $image-Etiff()> This returns the image data in TIFF format. =item B<$webpdata = $image-Ewebp([$quality])> This returns the image data in WEBP format, with the optional quality argument. The default is 80, also chosen by the value -1. A quality value of >= 101 is considered Lossless. =item B<$webpdata = $image-Eheif([$quality])> This returns the truecolor image data in HEIF format, with the optional quality and speed arguments. If truecolor is not set, this fails. The default quality is 80, also chosen by the value -1. A quality value of 200 is considered Lossless. =item B<$webpdata = $image-Eavif([$quality,$speed])> This returns the truecolor image data in AVIF format, with the AVif encoder and 444 chroma, and the optional quality argument. If truecolor is not set, this fails. The default compression quality 1-100 is -1, the default speed 0-10 is 6. =item B<$success = $image-E_file($filename)> Writes an image to a file in the format indicated by the filename, with libgd versions E= gd-2.1.1. File type is determined by the extension of the file name. See C for an overview of the parsing. For file types that require extra arguments, C<_file> attempts to use sane defaults: C chunk size = 0, compression is enabled. C quality = -1 (i.e. the reasonable default) C foreground is the darkest available color C quality default C quality default, codes = HEVC, chroma = 444 C quality default, speed = 6 Everything else is called with the two-argument function and so will use the default values. C<_file> and the underlying libgd C has some rudimentary error detection and will return FALSE (0) if a detectable error occurred. However, the image loaders do not normally return their error status so a result of TRUE (1) does **not** mean the file was saved successfully. =back =head2 Color Control These methods allow you to control and manipulate the GD::Image color table for palette, non-truecolor images. =over 4 =item B<$index = $image-EcolorAllocate(red,green,blue)> This allocates a color with the specified red, green and blue components and returns its index in the color table, if specified. The first color allocated in this way becomes the image's background color. (255,255,255) is white (all pixels on). (0,0,0) is black (all pixels off). (255,0,0) is fully saturated red. (127,127,127) is 50% gray. You can find plenty of examples in /usr/X11/lib/X11/rgb.txt. If no colors are allocated, then this function returns -1. Example: $black = $myImage->colorAllocate(0,0,0); #background color $white = $myImage->colorAllocate(255,255,255); $peachpuff = $myImage->colorAllocate(255,218,185); =item B<$index = $image-EcolorAllocateAlpha(reg,green,blue,alpha)> This allocates a color with the specified red, green, and blue components, plus the specified alpha channel. The alpha value may range from 0 (opaque) to 127 (transparent). The C function changes the way this alpha channel affects the resulting image. =item B<$image-EcolorDeallocate(colorIndex)> This marks the color at the specified index as being ripe for reallocation. The next time colorAllocate is used, this entry will be replaced. You can call this method several times to deallocate multiple colors. There's no function result from this call. Example: $myImage->colorDeallocate($peachpuff); $peachy = $myImage->colorAllocate(255,210,185); =item B<$index = $image-EcolorClosest(red,green,blue)> This returns the index of the color closest in the color table to the red green and blue components specified. If no colors have yet been allocated, then this call returns -1. Example: $apricot = $myImage->colorClosest(255,200,180); =item B<$index = $image-EcolorClosestAlpha(red,green,blue,alpha)> This returns the index of the color closest in the color table to the red green blue and alpha components specified. If no colors have yet been allocated, then this call returns -1. Example: $apricot = $myImage->colorClosestAlpha(255,200,180,0); =item B<$index = $image-EcolorClosestHWB(red,green,blue)> This also attempts to return the color closest in the color table to the red green and blue components specified. It uses a Hue/White/Black color representation to make the selected color more likely to match human perceptions of similar colors. If no colors have yet been allocated, then this call returns -1. Example: $mostred = $myImage->colorClosestHWB(255,0,0); =item B<$index = $image-EcolorExact(red,green,blue)> This returns the index of a color that exactly matches the specified red green and blue components. If such a color is not in the color table, this call returns -1. $rosey = $myImage->colorExact(255,100,80); warn "Everything's coming up roses.\n" if $rosey >= 0; =item B<$index = $image-EcolorExactAlpha(red,green,blue,alpha)> This returns the index of a color that exactly matches the specified red green blue and alpha components. If such a color is not in the color table, this call returns -1. $rosey = $myImage->colorExactAlpha(255,100,80,0); warn "Everything's coming up roses.\n" if $rosey >= 0; =item B<$index = $image-EcolorResolve(red,green,blue)> This returns the index of a color that exactly matches the specified red green and blue components. If such a color is not in the color table and there is room, then this method allocates the color in the color table and returns its index. $rosey = $myImage->colorResolve(255,100,80); warn "Everything's coming up roses.\n" if $rosey >= 0; =item B<$index = $image-EcolorResolveAlpha(red,green,blue,alpha)> This returns the index of a color that exactly matches the specified red green blue and alpha components. If such a color is not in the color table and there is room, then this method allocates the color in the color table and returns its index. $rosey = $myImage->colorResolveAlpha(255,100,80,0); warn "Everything's coming up roses.\n" if $rosey >= 0; =item B<$colorsTotal = $image-EcolorsTotal> I This returns the total number of colors allocated in the object. $maxColors = $myImage->colorsTotal; In the case of a TrueColor image, this call will return undef. =item B<$index = $image-EgetPixel(x,y)> I This returns the color table index underneath the specified point. It can be combined with rgb() to obtain the rgb color underneath the pixel. Example: $index = $myImage->getPixel(20,100); ($r,$g,$b) = $myImage->rgb($index); =item B<($red,$green,$blue) = $image-Ergb($index)> This returns a list containing the red, green and blue components of the specified color index. Example: @RGB = $myImage->rgb($peachy); =item B<($alpha) = $image-Ealpha($index)> This returns an item containing the alpha component of the specified color index. Example: @RGB = $myImage->rgb($peachy); =item B<$image-Etransparent($colorIndex)> This marks the color at the specified index as being transparent. Portions of the image drawn in this color will be invisible. This is useful for creating paintbrushes of odd shapes, as well as for making PNG backgrounds transparent for displaying on the Web. Only one color can be transparent at any time. To disable transparency, specify -1 for the index. If you call this method without any parameters, it will return the current index of the transparent color, or -1 if none. Example: open(PNG,"test.png"); $im = GD::Image->newFromPng(PNG); $white = $im->colorClosest(255,255,255); # find white $im->transparent($white); binmode STDOUT; print $im->png; =back =head2 Special Colors GD implements a number of special colors that can be used to achieve special effects. They are constants defined in the GD:: namespace, but automatically exported into your namespace when the GD module is loaded. =over 4 =item B<$image-EsetBrush($image)> You can draw lines and shapes using a brush pattern. Brushes are just palette, not TrueColor, images that you can create and manipulate in the usual way. When you draw with them, their contents are used for the color and shape of the lines. To make a brushed line, you must create or load the brush first, then assign it to the image using setBrush(). You can then draw in that with that brush using the B special color. It's often useful to set the background of the brush to transparent so that the non-colored parts don't overwrite other parts of your image. Example: # Create a brush at an angle $diagonal_brush = GD::Image->new(5,5); $white = $diagonal_brush->colorAllocate(255,255,255); $black = $diagonal_brush->colorAllocate(0,0,0); $diagonal_brush->transparent($white); $diagonal_brush->line(0,4,4,0,$black); # NE diagonal # Set the brush $myImage->setBrush($diagonal_brush); # Draw a circle using the brush $myImage->arc(50,50,25,25,0,360,gdBrushed); =item B<$image-EsetThickness($thickness)> Lines drawn with line(), rectangle(), arc(), and so forth are 1 pixel thick by default. Call setThickness() to change the line drawing width. =item B<$image-EsetStyle(@colors)> Styled lines consist of an arbitrary series of repeated colors and are useful for generating dotted and dashed lines. To create a styled line, use setStyle() to specify a repeating series of colors. It accepts an array consisting of one or more color indexes. Then draw using the B special color. Another special color, B can be used to introduce holes in the line, as the example shows. Example: # Set a style consisting of 4 pixels of yellow, # 4 pixels of blue, and a 2 pixel gap $myImage->setStyle($yellow,$yellow,$yellow,$yellow, $blue,$blue,$blue,$blue, gdTransparent,gdTransparent); $myImage->arc(50,50,25,25,0,360,gdStyled); To combine the C and C behaviors, you can specify C. In this case, a pixel from the current brush pattern is rendered wherever the color specified in setStyle() is neither gdTransparent nor 0. =item B Draw filled shapes and flood fills using a pattern. The pattern is just another image. The image will be tiled multiple times in order to fill the required space, creating wallpaper effects. You must call C in order to define the particular tile pattern you'll use for drawing when you specify the gdTiled color. details. =item B The gdStyled color is used for creating dashed and dotted lines. A styled line can contain any series of colors and is created using the setStyled() command. =item B The C color is used for drawing lines with antialiasing turned on. Antialiasing will blend the jagged edges of lines with the background, creating a smoother look. The actual color drawn is set with setAntiAliased(). =item B<$image-EsetAntiAliased($color)> "Antialiasing" is a process by which jagged edges associated with line drawing can be reduced by blending the foreground color with an appropriate percentage of the background, depending on how much of the pixel in question is actually within the boundaries of the line being drawn. All line-drawing methods, such as line() and polygon, will draw antialiased lines if the special "color" B is used when calling them. setAntiAliased() is used to specify the actual foreground color to be used when drawing antialiased lines. You may set any color to be the foreground, however as of libgd version 2.0.12 an alpha channel component is not supported. Antialiased lines can be drawn on both truecolor and palette-based images. However, attempts to draw antialiased lines on highly complex palette-based backgrounds may not give satisfactory results, due to the limited number of colors available in the palette. Antialiased line-drawing on simple backgrounds should work well with palette-based images; otherwise create or fetch a truecolor image instead. When using palette-based images, be sure to allocate a broad spectrum of colors in order to have sufficient colors for the antialiasing to use. =item B<$image-EsetAntiAliasedDontBlend($color,[$flag])> Normally, when drawing lines with the special B "color," blending with the background to reduce jagged edges is the desired behavior. However, when it is desired that lines not be blended with one particular color when it is encountered in the background, the setAntiAliasedDontBlend() method can be used to indicate the special color that the foreground should stand out more clearly against. Once turned on, you can turn this feature off by calling setAntiAliasedDontBlend() with a second argument of 0: $image->setAntiAliasedDontBlend($color,0); =back =head2 Drawing Commands These methods allow you to draw lines, rectangles, and ellipses, as well as to perform various special operations like flood-fill. =over 4 =item B<$image-EsetPixel($x,$y,$color)> This sets the pixel at (x,y) to the specified color index. No value is returned from this method. The coordinate system starts at the upper left at (0,0) and gets larger as you go down and to the right. You can use a real color, or one of the special colors gdBrushed, gdStyled and gdStyledBrushed can be specified. Example: # This assumes $peach already allocated $myImage->setPixel(50,50,$peach); =item B<$image-Eline($x1,$y1,$x2,$y2,$color)> This draws a line from (x1,y1) to (x2,y2) of the specified color. You can use a real color, or one of the special colors gdBrushed, gdStyled and gdStyledBrushed. Example: # Draw a diagonal line using the currently defined # paintbrush pattern. $myImage->line(0,0,150,150,gdBrushed); =item B<$image-EdashedLine($x1,$y1,$x2,$y2,$color)> DEPRECATED: The libgd library provides this method solely for backward compatibility with libgd version 1.0, and there have been reports that it no longer works as expected. Please use the setStyle() and gdStyled methods as described below. This draws a dashed line from (x1,y1) to (x2,y2) in the specified color. A more powerful way to generate arbitrary dashed and dotted lines is to use the setStyle() method described below and to draw with the special color gdStyled. Example: $myImage->dashedLine(0,0,150,150,$blue); =item B<$image-Erectangle($x1,$y1,$x2,$y2,$color)> This draws a rectangle with the specified color. (x1,y1) and (x2,y2) are the upper left and lower right corners respectively. Both real color indexes and the special colors gdBrushed, gdStyled and gdStyledBrushed are accepted. Example: $myImage->rectangle(10,10,100,100,$rose); =item B<$image-EfilledRectangle($x1,$y1,$x2,$y2,$color)> =item B<$image-EsetTile($otherimage)> This draws a rectangle filled with the specified color. You can use a real color, or the special fill color gdTiled to fill the polygon with a pattern. Example: # read in a fill pattern and set it $tile = GD::Image->newFromPng('happyface.png'); $myImage->setTile($tile); # draw the rectangle, filling it with the pattern $myImage->filledRectangle(10,10,150,200,gdTiled); =item B<$image-EopenPolygon($polygon,$color)> This draws a polygon with the specified color. The polygon must be created first (see below). The polygon must have at least three vertices. If the last vertex doesn't close the polygon, the method will close it for you. Both real color indexes and the special colors gdBrushed, gdStyled and gdStyledBrushed can be specified. Example: $poly = GD::Polygon->new; $poly->addPt(50,0); $poly->addPt(99,99); $poly->addPt(0,99); $myImage->openPolygon($poly,$blue); =item B<$image-EunclosedPolygon($polygon,$color)> This draws a sequence of connected lines with the specified color, without connecting the first and last point to a closed polygon. The polygon must be created first (see below). The polygon must have at least three vertices. Both real color indexes and the special colors gdBrushed, gdStyled and gdStyledBrushed can be specified. You need libgd 2.0.33 or higher to use this feature. Example: $poly = GD::Polygon->new; $poly->addPt(50,0); $poly->addPt(99,99); $poly->addPt(0,99); $myImage->unclosedPolygon($poly,$blue); =item B<$image-EfilledPolygon($poly,$color)> This draws a polygon filled with the specified color. You can use a real color, or the special fill color gdTiled to fill the polygon with a pattern. Example: # make a polygon $poly = GD::Polygon->new; $poly->addPt(50,0); $poly->addPt(99,99); $poly->addPt(0,99); # draw the polygon, filling it with a color $myImage->filledPolygon($poly,$peachpuff); =item B<$image-Eellipse($cx,$cy,$width,$height,$color)> =item B<$image-EfilledEllipse($cx,$cy,$width,$height,$color)> These methods() draw ellipses. ($cx,$cy) is the center of the arc, and ($width,$height) specify the ellipse width and height, respectively. filledEllipse() is like Ellipse() except that the former produces filled versions of the ellipse. =item B<$image-Earc($cx,$cy,$width,$height,$start,$end,$color)> This draws arcs and ellipses. (cx,cy) are the center of the arc, and (width,height) specify the width and height, respectively. The portion of the ellipse covered by the arc are controlled by start and end, both of which are given in degrees from 0 to 360. Zero is at the right end of the ellipse, and angles increase clockwise. To specify a complete ellipse, use 0 and 360 as the starting and ending angles. To draw a circle, use the same value for width and height. You can specify a normal color or one of the special colors B, B, or B. Example: # draw a semicircle centered at 100,100 $myImage->arc(100,100,50,50,0,180,$blue); =item B<$image-EfilledArc($cx,$cy,$width,$height,$start,$end,$color [,$arc_style])> This method is like arc() except that it colors in the pie wedge with the selected color. $arc_style is optional. If present it is a bitwise OR of the following constants: gdArc connect start & end points of arc with a rounded edge gdChord connect start & end points of arc with a straight line gdPie synonym for gdChord gdNoFill outline the arc or chord gdEdged connect beginning and ending of the arc to the center gdArc and gdChord are mutually exclusive. gdChord just connects the starting and ending angles with a straight line, while gdArc produces a rounded edge. gdPie is a synonym for gdArc. gdNoFill indicates that the arc or chord should be outlined, not filled. gdEdged, used together with gdNoFill, indicates that the beginning and ending angles should be connected to the center; this is a good way to outline (rather than fill) a "pie slice." Example: $image->filledArc(100,100,50,50,0,90,$blue,gdEdged|gdNoFill); =item B<$image-Efill($x,$y,$color)> This method flood-fills regions with the specified color. The color will spread through the image, starting at point (x,y), until it is stopped by a pixel of a different color from the starting pixel (this is similar to the "paintbucket" in many popular drawing toys). You can specify a normal color, or the special color gdTiled, to flood-fill with patterns. Example: # Draw a rectangle, and then make its interior blue $myImage->rectangle(10,10,100,100,$black); $myImage->fill(50,50,$blue); =item B<$image-EfillToBorder($x,$y,$bordercolor,$color)> Like C, this method flood-fills regions with the specified color, starting at position (x,y). However, instead of stopping when it hits a pixel of a different color than the starting pixel, flooding will only stop when it hits the color specified by bordercolor. You must specify a normal indexed color for the bordercolor. However, you are free to use the gdTiled color for the fill. Example: # This has the same effect as the previous example $myImage->rectangle(10,10,100,100,$black); $myImage->fillToBorder(50,50,$black,$blue); =back =head2 Image Copying Commands Two methods are provided for copying a rectangular region from one image to another. One method copies a region without resizing it. The other allows you to stretch the region during the copy operation. With either of these methods it is important to know that the routines will attempt to flesh out the destination image's color table to match the colors that are being copied from the source. If the destination's color table is already full, then the routines will attempt to find the best match, with varying results. =over 4 =item B<$image-Ecopy($sourceImage,$dstX,$dstY,$srcX,$srcY,$width,$height)> This is the simplest of the several copy operations, copying the specified region from the source image to the destination image (the one performing the method call). (srcX,srcY) specify the upper left corner of a rectangle in the source image, and (width,height) give the width and height of the region to copy. (dstX,dstY) control where in the destination image to stamp the copy. You can use the same image for both the source and the destination, but the source and destination regions must not overlap or strange things will happen. Example: $myImage = GD::Image->new(100,100); ... various drawing stuff ... $srcImage = GD::Image->new(50,50); ... more drawing stuff ... # copy a 25x25 pixel region from $srcImage to # the rectangle starting at (10,10) in $myImage $myImage->copy($srcImage,10,10,0,0,25,25); =item B<$image-Eclone()> Make a copy of the image and return it as a new object. The new image will look identical. However, it may differ in the size of the color palette and other nonessential details. Example: $myImage = GD::Image->new(100,100); ... various drawing stuff ... $copy = $myImage->clone; =item B<$image-EcopyMerge($sourceImage,$dstX,$dstY,> B< $srcX,$srcY,$width,$height,$percent)> This copies the indicated rectangle from the source image to the destination image, merging the colors to the extent specified by percent (an integer between 0 and 100). Specifying 100% has the same effect as copy() -- replacing the destination pixels with the source image. This is most useful for highlighting an area by merging in a solid rectangle. Example: $myImage = GD::Image->new(100,100); ... various drawing stuff ... $redImage = GD::Image->new(50,50); ... more drawing stuff ... # copy a 25x25 pixel region from $srcImage to # the rectangle starting at (10,10) in $myImage, merging 50% $myImage->copyMerge($srcImage,10,10,0,0,25,25,50); =item B<$image-EcopyMergeGray($sourceImage,$dstX,$dstY,> B< $srcX,$srcY,$width,$height,$percent)> This is identical to copyMerge() except that it preserves the hue of the source by converting all the pixels of the destination rectangle to grayscale before merging. =item B<$image-EcopyResized($sourceImage,$dstX,$dstY,> B< $srcX,$srcY,$destW,$destH,$srcW,$srcH)> This method is similar to copy() but allows you to choose different sizes for the source and destination rectangles. The source and destination rectangle's are specified independently by (srcW,srcH) and (destW,destH) respectively. copyResized() will stretch or shrink the image to accommodate the size requirements. Example: $myImage = GD::Image->new(100,100); ... various drawing stuff ... $srcImage = GD::Image->new(50,50); ... more drawing stuff ... # copy a 25x25 pixel region from $srcImage to # a larger rectangle starting at (10,10) in $myImage $myImage->copyResized($srcImage,10,10,0,0,50,50,25,25); =item B<$image-EcopyResampled($sourceImage,$dstX,$dstY,> B< $srcX,$srcY,$destW,$destH,$srcW,$srcH)> This method is similar to copyResized() but provides "smooth" copying from a large image to a smaller one, using a weighted average of the pixels of the source area rather than selecting one representative pixel. This method is identical to copyResized() when the destination image is a palette image. =item B<$image-EcopyRotated($sourceImage,$dstX,$dstY,> B< $srcX,$srcY,$width,$height,$angle)> Like copyResized() but the $angle argument specifies an arbitrary amount to rotate the image counter clockwise (in degrees). In addition, $dstX and $dstY species the B
of the destination image, and not the top left corner. =item B<$image-EtrueColorToPalette([$dither], [$colors])> This method converts a truecolor image to a palette image. The code for this function was originally drawn from the Independent JPEG Group library code, which is excellent. The code has been modified to preserve as much alpha channel information as possible in the resulting palette, in addition to preserving colors as well as possible. This does not work as well as might be hoped. It is usually best to simply produce a truecolor output image instead, which guarantees the highest output quality. Both the dithering (0/1, default=0) and maximum number of colors used (<=256, default = gdMaxColors) can be specified. =item B<$image = $sourceImage-EcreatePaletteFromTrueColor([$dither], [$colors])> Creates a new palette image from a truecolor image. Same as above, but returns a new image. Don't use these function -- write real truecolor PNGs and JPEGs. The disk space gain of conversion to palette is not great (for small images it can be negative) and the quality loss is ugly. =item B<$error = $image-EcolorMatch($otherimage)> Bring the palette colors in $otherimage to be closer to truecolor $image. A negative return value is a failure. -1 image must be True Color -2 otherimage must be indexed -3 the images are meant to be the same dimensions -4 At least 1 color in otherimage must be allocated This method is only available with libgd >= 2.1.0 =item B<$image = $sourceImage-EneuQuant($maxcolor=256,$samplefactor=5)> Creates a new palette image from a truecolor image. =over 4 =item samplefactor The quantization precision between 1 (highest quality) and 10 (fastest). =item maxcolor The number of desired palette entries. =back This is the same as createPaletteFromTrueColor with the quantization method GD_QUANT_NEUQUANT. This does not support dithering. This method is only available with libgd >= 2.1.0 =back =head2 Image Transformation Commands Gd provides these simple image transformations, non-interpolated. =over 4 =item B<$image = $sourceImage-EcopyRotate90()> =item B<$image = $sourceImage-EcopyRotate180()> =item B<$image = $sourceImage-EcopyRotate270()> =item B<$image = $sourceImage-EcopyFlipHorizontal()> =item B<$image = $sourceImage-EcopyFlipVertical()> =item B<$image = $sourceImage-EcopyTranspose()> =item B<$image = $sourceImage-EcopyReverseTranspose()> These methods can be used to rotate, flip, or transpose an image. The result of the method is a copy of the image. =item B<$image-Erotate180()> =item B<$image-EflipHorizontal()> =item B<$image-EflipVertical()> These methods are similar to the copy* versions, but instead modify the image in place. =back =head2 Image Interpolation Methods Since libgd 2.1.0 there are better transformation methods, with these interpolation methods: GD_BELL - Bell GD_BESSEL - Bessel GD_BILINEAR_FIXED - fixed point bilinear GD_BICUBIC - Bicubic GD_BICUBIC_FIXED - fixed point bicubic integer GD_BLACKMAN - Blackman GD_BOX - Box GD_BSPLINE - BSpline GD_CATMULLROM - Catmullrom GD_GAUSSIAN - Gaussian GD_GENERALIZED_CUBIC - Generalized cubic GD_HERMITE - Hermite GD_HAMMING - Hamming GD_HANNING - Hannig GD_MITCHELL - Mitchell GD_NEAREST_NEIGHBOUR - Nearest neighbour interpolation GD_POWER - Power GD_QUADRATIC - Quadratic GD_SINC - Sinc GD_TRIANGLE - Triangle GD_WEIGHTED4 - 4 pixels weighted bilinear interpolation GD_LINEAR - bilinear interpolation =over 4 =item B<$image-EinterpolationMethod( [$method] )> Gets or sets the interpolation methods for all subsequent interpolations. See above for the valid values. Only available since libgd 2.2.0 =item B<$image-EcopyScaleInterpolated( width, height )> Returns a copy, using interpolation. =item B<$image-EcopyRotateInterpolated( angle, bgcolor )> Returns a copy, using interpolation. =back =head2 Image Filter Commands Gd also provides some common image filters, they modify the image in place and return TRUE if modified or FALSE if not. Most of them need libgd >= 2.1.0, with older versions those functions are undefined. =over 4 =item B<$ok = $image-Escatter($sub, $plus)> if $sub and $plus are 0, nothing is changed, TRUE is returned. if $sub >= $plus, nothing is changed, FALSE is returned. else random pixels are changed. =item B<$ok = $image-EscatterColor($sub, $plus, @colors)> Similar to scatter, but using the given array of colors, i.e. palette indices. =item B<$ok = $image-Epixelate($blocksize, $mode)> if $blocksize <= 0, nothing is changed, FALSE is returned. if $blocksize == 1, nothing is changed, TRUE is returned. else the following modes are observed: GD_PIXELATE_UPPERLEFT GD_PIXELATE_AVERAGE =item B<$ok = $image-Enegate()> =item B<$ok = $image-Egrayscale()> =item B<$ok = $image-Ebrightness($add)> $add: -255..255 =item B<$ok = $image-Econtrast($contrast)> $contrast: a double value. The contrast adjustment value. Negative values increase, positive values decrease the contrast. The larger the absolute value, the stronger the effect. =item B<$ok = $image-Ecolor($red,$green,$blue,$alpha)> Change channel values of an image. $red - The value to add to the red channel of all pixels. $green - The value to add to the green channel of all pixels. $blue - The value to add to the blue channel of all pixels. $alpha - The value to add to the alpha channel of all pixels. =item B<$ok = $image-EselectiveBlur()> =item B<$ok = $image-EedgeDetectQuick()> =item B<$ok = $image-EgaussianBlur()> =item B<$ok = $image-Eemboss()> =item B<$ok = $image-EmeanRemoval()> =item B<$ok = $image-Esmooth($weight)> =item B<$image = $sourceImage-EcopyGaussianBlurred($radius, $sigma)> $radius: int, the blur radius (*not* diameter--range is 2*radius + 1) a radius, not a diameter so a radius of 2 (for example) will blur across a region 5 pixels across (2 to the center, 1 for the center itself and another 2 to the other edge). $sigma: the sigma value or a value <= 0.0 to use the computed default. represents the "fatness" of the curve (lower == fatter). The result is always truecolor. =back =head2 Character and String Drawing GD allows you to draw characters and strings, either in normal horizontal orientation or rotated 90 degrees. These routines use a GD::Font object, described in more detail below. There are four built-in monospaced fonts, available in the global variables B, B, B, B and B. In addition, you can use the load() method to load GD-formatted bitmap font files at runtime. You can create these bitmap files from X11 BDF-format files using the bdf2gd.pl script, which should have been installed with GD (see the bdf_scripts directory if it wasn't). The format happens to be identical to the old-style MSDOS bitmap ".fnt" files, so you can use one of those directly if you happen to have one. For writing proportional scalable fonts, GD offers the stringFT() method, which allows you to load and render any TrueType font on your system. =over 4 =item B<$image-Estring($font,$x,$y,$string,$color)> This method draws a string starting at position (x,y) in the specified font and color. Your choices of fonts are gdSmallFont, gdMediumBoldFont, gdTinyFont, gdLargeFont and gdGiantFont. Example: $myImage->string(gdSmallFont,2,10,"Peachy Keen",$peach); =item B<$image-EstringUp($font,$x,$y,$string,$color)> Just like the previous call, but draws the text rotated counterclockwise 90 degrees. =item B<$image-Echar($font,$x,$y,$char,$color)> =item B<$image-EcharUp($font,$x,$y,$char,$color)> These methods draw single characters at position (x,y) in the specified font and color. They're carry-overs from the C interface, where there is a distinction between characters and strings. Perl is insensible to such subtle distinctions. =item $font = Bload($fontfilepath)> This method dynamically loads a font file, returning a font that you can use in subsequent calls to drawing methods. For example: my $courier = GD::Font->load('./courierR12.fnt') or die "Can't load font"; $image->string($courier,2,10,"Peachy Keen",$peach); Font files must be in GD binary format, as described above. =item B<@bounds = $image-EstringFT($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string)> =item B<@bounds = GD::Image-EstringFT($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string)> =item B<@bounds = $image-EstringFT($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string,\%options)> This method uses TrueType to draw a scaled, antialiased string using the TrueType vector font of your choice. It requires that libgd to have been compiled with TrueType support, and for the appropriate TrueType font to be installed on your system. The arguments are as follows: fgcolor Color index to draw the string in fontname A path to the TrueType (.ttf) font file or a font pattern. ptsize The desired point size (may be fractional) angle The rotation angle, in radians (positive values rotate counter clockwise) x,y X and Y coordinates to start drawing the string string The string itself If successful, the method returns an eight-element list giving the boundaries of the rendered string: @bounds[0,1] Lower left corner (x,y) @bounds[2,3] Lower right corner (x,y) @bounds[4,5] Upper right corner (x,y) @bounds[6,7] Upper left corner (x,y) In case of an error (such as the font not being available, or FT support not being available), the method returns an empty list and sets $@ to the error message. The B argument is the name of the font, which can be a full pathname to a F<.ttf> file, or if not the paths in C<$ENV{GDFONTPATH}> will be searched or if empty the libgd compiled DEFAULT_FONTPATH. The TrueType extensions .ttf, .pfa, .pfb or .dfont can be omitted. The string may contain UTF-8 sequences like: "À" You may also call this method from the GD::Image class name, in which case it doesn't do any actual drawing, but returns the bounding box using an inexpensive operation. You can use this to perform layout operations prior to drawing. Using a negative color index will disable antialiasing, as described in the libgd manual page at L. An optional 8th argument allows you to pass a hashref of options to stringFT(). Several hashkeys are recognized: B, B, B, and B. The value of B is supposed to be a multiple of the character height, so setting linespacing to 2.0 will result in double-spaced lines of text. However the current version of libgd (2.0.12) does not do this. Instead the linespacing seems to be double what is provided in this argument. So use a spacing of 0.5 to get separation of exactly one line of text. In practice, a spacing of 0.6 seems to give nice results. Another thing to watch out for is that successive lines of text should be separated by the "\r\n" characters, not just "\n". The value of B is one of "Unicode", "Shift_JIS" and "Big5". The interaction between Perl, Unicode and libgd is not clear to me, and you should experiment a bit if you want to use this feature. The value of B is the vertical and horizontal resolution, in DPI, in the format "hdpi,vdpi". If present, the resolution will be passed to the Freetype rendering engine as a hint to improve the appearance of the rendered font. The value of B is a flag. Set it to false to turn off the default kerning of text. Example: $gd->stringFT($black,'/c/windows/Fonts/pala.ttf',40,0,20,90, "hi there\r\nbye now", {linespacing=>0.6, charmap => 'Unicode', }); If GD was compiled with fontconfig support, and the fontconfig library is available on your system, then you can use a font name pattern instead of a path. Patterns are described in L and will look something like this "Times:italic". For backward compatibility, this feature is disabled by default. You must enable it by calling useFontConfig(1) prior to the stringFT() call. $image->useFontConfig(1); For backward compatibility with older versions of the FreeType library, the alias stringTTF() is also recognized. =item B<$hasfontconfig = $image-EuseFontConfig($flag)> Call useFontConfig() with a value of 1 in order to enable support for fontconfig font patterns (see stringFT). Regardless of the value of $flag, this method will return a true value if the fontconfig library is present, or false otherwise. This method can also be called as a class method of GD::Image; =item B<$result = $image-EstringFTCircle($cx,$cy,$radius,$textRadius,$fillPortion,$font,$points,$top,$bottom,$fgcolor)> This draws text in a circle. Currently (libgd 2.0.33) this function does not work for me, but the interface is provided for completeness. The call signature is somewhat complex. Here is an excerpt from the libgd manual page: Draws the text strings specified by top and bottom on the image, curved along the edge of a circle of radius radius, with its center at cx and cy. top is written clockwise along the top; bottom is written counterclockwise along the bottom. textRadius determines the "height" of each character; if textRadius is 1/2 of radius, characters extend halfway from the edge to the center. fillPortion varies from 0 to 1.0, with useful values from about 0.4 to 0.9, and determines how much of the 180 degrees of arc assigned to each section of text is actually occupied by text; 0.9 looks better than 1.0 which is rather crowded. font is a freetype font; see gdImageStringFT. points is passed to the freetype engine and has an effect on hinting; although the size of the text is determined by radius, textRadius, and fillPortion, you should pass a point size that "hints" appropriately -- if you know the text will be large, pass a large point size such as 24.0 to get the best results. fgcolor can be any color, and may have an alpha component, do blending, etc. Returns a true value on success. =back =head2 Alpha channels The alpha channel methods allow you to control the way drawings are processed according to the alpha channel. When true color is turned on, colors are encoded as four bytes, in which the last three bytes are the RGB color values, and the first byte is the alpha channel. Therefore the hexadecimal representation of a non transparent RGB color will be: C=0x00(rr)(bb)(bb) When alpha blending is turned on, you can use the first byte of the color to control the transparency, meaning that a rectangle painted with color 0x00(rr)(bb)(bb) will be opaque, and another one painted with 0x7f(rr)(gg)(bb) will be transparent. The Alpha value must be >= 0 and <= 0x7f. =over 4 =item B<$image-EalphaBlending($integer)> The alphaBlending() method allows for two different modes of drawing on truecolor images. In blending mode, which is on by default (libgd 2.0.2 and above), the alpha channel component of the color supplied to all drawing functions, such as C, determines how much of the underlying color should be allowed to shine through. As a result, GD automatically blends the existing color at that point with the drawing color, and stores the result in the image. The resulting pixel is opaque. In non-blending mode, the drawing color is copied literally with its alpha channel information, replacing the destination pixel. Blending mode is not available when drawing on palette images. Pass a value of 1 for blending mode, and 0 for non-blending mode. =item B<$image-EsaveAlpha($saveAlpha)> By default, GD (libgd 2.0.2 and above) does not attempt to save full alpha channel information (as opposed to single-color transparency) when saving PNG images. (PNG is currently the only output format supported by gd which can accommodate alpha channel information.) This saves space in the output file. If you wish to create an image with alpha channel information for use with tools that support it, call C to turn on saving of such information, and call C to turn off alpha blending within the library so that alpha channel information is actually stored in the image rather than being composited immediately at the time that drawing functions are invoked. =back =head2 Miscellaneous Image Methods These are various utility methods that are useful in some circumstances. =over 4 =item B<$image-Einterlaced([$flag])> This method sets or queries the image's interlaced setting. Interlace produces a cool venetian blinds effect on certain viewers. Provide a true parameter to set the interlace attribute. Provide undef to disable it. Call the method without parameters to find out the current setting. =item B<($width,$height) = $image-EgetBounds()> This method will return a two-member list containing the width and height of the image. You query but not change the size of the image once it's created. =item B<$width = $image-Ewidth> =item B<$height = $image-Eheight> Return the width and height of the image, respectively. =item B<$is_truecolor = $image-EisTrueColor()> This method will return a Boolean representing whether the image is true color or not. =item B<$flag = $image1-Ecompare($image2)> Compare two images and return a bitmap describing the differences found, if any. The return value must be logically AND'ed with one or more constants in order to determine the differences. The following constants are available: GD_CMP_IMAGE The two images look different GD_CMP_NUM_COLORS The two images have different numbers of colors GD_CMP_COLOR The two images' palettes differ GD_CMP_SIZE_X The two images differ in the horizontal dimension GD_CMP_SIZE_Y The two images differ in the vertical dimension GD_CMP_TRANSPARENT The two images have different transparency GD_CMP_BACKGROUND The two images have different background colors GD_CMP_INTERLACE The two images differ in their interlace GD_CMP_TRUECOLOR The two images are not both true color The most important of these is GD_CMP_IMAGE, which will tell you whether the two images will look different, ignoring differences in the order of colors in the color palette and other invisible changes. The constants are not imported by default, but must be imported individually or by importing the :cmp tag. Example: use GD qw(:DEFAULT :cmp); # get $image1 from somewhere # get $image2 from somewhere if ($image1->compare($image2) & GD_CMP_IMAGE) { warn "images differ!"; } =item B<$image-Eclip($x1,$y1,$x2,$y2)> =item B<($x1,$y1,$x2,$y2) = $image-Eclip> Set or get the clipping rectangle. When the clipping rectangle is set, all drawing will be clipped to occur within this rectangle. The clipping rectangle is initially set to be equal to the boundaries of the whole image. Change it by calling clip() with the coordinates of the new clipping rectangle. Calling clip() without any arguments will return the current clipping rectangle. =item B<$flag = $image-EboundsSafe($x,$y)> The boundsSafe() method will return true if the point indicated by ($x,$y) is within the clipping rectangle, or false if it is not. If the clipping rectangle has not been set, then it will return true if the point lies within the image boundaries. =back =head2 Grouping Methods GD does not support grouping of objects, but GD::SVG does. In that subclass, the following methods declare new groups of graphical objects: =over 4 =item $image-EstartGroup([$id,\%style]) =item $image-EendGroup() =item $group = $image-EnewGroup See L for information. =back =head1 Polygons A few primitive polygon creation and manipulation methods are provided. They aren't part of the Gd library, but I thought they might be handy to have around (they're borrowed from my qd.pl Quickdraw library). Also see L. =over 3 =item B<$poly = GD::Polygon-Enew> Create an empty polygon with no vertices. $poly = GD::Polygon->new; =item B<$poly-EaddPt($x,$y)> Add point (x,y) to the polygon. $poly->addPt(0,0); $poly->addPt(0,50); $poly->addPt(25,25); $myImage->fillPoly($poly,$blue); =item B<($x,$y) = $poly-EgetPt($index)> Retrieve the point at the specified vertex. ($x,$y) = $poly->getPt(2); =item B<$poly-EsetPt($index,$x,$y)> Change the value of an already existing vertex. It is an error to set a vertex that isn't already defined. $poly->setPt(2,100,100); =item B<($x,$y) = $poly-EdeletePt($index)> Delete the specified vertex, returning its value. ($x,$y) = $poly->deletePt(1); =item B<$poly-Eclear()> Delete all vertices, restoring the polygon to its initial empty state. =item B<$poly-EtoPt($dx,$dy)> Draw from current vertex to a new vertex, using relative (dx,dy) coordinates. If this is the first point, act like addPt(). $poly->addPt(0,0); $poly->toPt(0,50); $poly->toPt(25,-25); $myImage->fillPoly($poly,$blue); =item B<$vertex_count = $poly-Elength> Return the number of vertices in the polygon. $points = $poly->length; =item B<@vertices = $poly-Evertices> Return a list of all the vertices in the polygon object. Each member of the list is a reference to an (x,y) array. @vertices = $poly->vertices; foreach $v (@vertices) print join(",",@$v),"\n"; } =item B<@rect = $poly-Ebounds> Return the smallest rectangle that completely encloses the polygon. The return value is an array containing the (left,top,right,bottom) of the rectangle. ($left,$top,$right,$bottom) = $poly->bounds; =item B<$poly-Eoffset($dx,$dy)> Offset all the vertices of the polygon by the specified horizontal (dh) and vertical (dy) amounts. Positive numbers move the polygon down and to the right. $poly->offset(10,30); =item B<$poly-Emap($srcL,$srcT,$srcR,$srcB,$destL,$dstT,$dstR,$dstB)> Map the polygon from a source rectangle to an equivalent position in a destination rectangle, moving it and resizing it as necessary. See polys.pl for an example of how this works. Both the source and destination rectangles are given in (left,top,right,bottom) coordinates. For convenience, you can use the polygon's own bounding box as the source rectangle. # Make the polygon really tall $poly->map($poly->bounds,0,0,50,200); =item B<$poly-Escale($sx,$sy, [$tx,$ty])> Scale each vertex of the polygon by the X and Y factors indicated by sx and sy. For example scale(2,2) will make the polygon twice as large. For best results, move the center of the polygon to position (0,0) before you scale, then move it back to its previous position. Accepts an optional offset vector. =item B<$poly-Etransform($sx,$rx,$ry,$sy, $tx,$ty)> Run each vertex of the polygon through a 2D affine transformation matrix, where sx and sy are the X and Y scaling factors, rx and ry are the X and Y rotation factors, and tx and ty are X and Y offsets. See the Adobe PostScript Reference, page 154 for a full explanation, or experiment. libgd: The transformation matrix is created using 6 numbers: matrix[0] == xx matrix[1] == yx matrix[2] == xy matrix[3] == xy (probably meaning yy here) matrix[4] == x0 matrix[5] == y0 where the transformation of a given point (x,y) is given by: x_new = xx * x + xy * y + x0; y_new = yx * x + yy * y + y0; =back =head2 GD::Polyline Please see L for information on creating open polygons and splines. =head1 Font Utilities The libgd library (used by the Perl GD library) has built-in support for about half a dozen fonts, which were converted from public-domain X Windows fonts. For more fonts, compile libgd with TrueType support and use the stringFT() call. If you wish to add more built-in fonts, the directory bdf_scripts contains two contributed utilities that may help you convert X-Windows BDF-format fonts into the format that libgd uses internally. However these scripts were written for earlier versions of GD which included its own mini-gd library. These scripts will have to be adapted for use with libgd, and the libgd library itself will have to be recompiled and linked! Please do not contact me for help with these scripts: they are unsupported. Each of these fonts is available both as an imported global (e.g. B) and as a package method (e.g. BSmall>). =over 5 =item B =item BSmall> This is the basic small font, "borrowed" from a well known public domain 6x12 font. =item B =item BLarge> This is the basic large font, "borrowed" from a well known public domain 8x16 font. =item B =item BMediumBold> This is a bold font intermediate in size between the small and large fonts, borrowed from a public domain 7x13 font; =item B =item BTiny> This is a tiny, almost unreadable font, 5x8 pixels wide. =item B =item BGiant> This is a 9x15 bold font converted by Jan Pazdziora from a sans serif X11 font. =item B<$font-Enchars> This returns the number of characters in the font. print "The large font contains ",gdLargeFont->nchars," characters\n"; =item B<$font-Eoffset> This returns the ASCII value of the first character in the font =item B<$width = $font-Ewidth> =item B<$height = $font-Eheight> =item C These return the width and height of the font. ($w,$h) = (gdLargeFont->width,gdLargeFont->height); =back =head1 Helper Functions =over =item GD::LIBGD_VERSION Returns a number of the libgd VERSION, like 2.0204, 2.0033 or 2.01. =item GD::VERSION_STRING Returns the string of the libgd VERSION, like "2.2.4". =item GD::constant =back =head1 Obtaining the C-language version of gd libgd, the C-language version of gd, can be obtained at URL http://libgd.org/ Directions for installing and using it can be found at that site. Please do not contact me for help with libgd. =head1 AUTHOR The GD.pm interface is copyright 1995-2010, Lincoln D. Stein. This package and its accompanying libraries is free software; you can redistribute it and/or modify it under the terms of the GPL (either version 1, or at your option, any later version) or the Artistic License 2.0. Refer to LICENSE for the full license text. package for details. The latest versions of GD.pm are available at https://github.com/lstein/Perl-GD =head1 SEE ALSO L, L, L, L =cut 1; __END__ GD-2.78/lib/GD/0000755000175000017500000000000014450761210012350 5ustar rurbanrurbanGD-2.78/lib/GD/Polyline.pm0000644000175000017500000005342414174320547014520 0ustar rurbanrurban############################################################################ # # Polyline.pm # # Author: Dan Harasty # Email: harasty@cpan.org # Version: 0.2 # Date: 2002/08/06 # # For usage documentation: see POD at end of file # # For changes: see "Changes" file included with distribution # use strict; package GD::Polyline; ############################################################################ # # GD::Polyline # ############################################################################ # # What's this? A class with nothing but a $VERSION and @ISA? # Below, this module overrides and adds several modules to # the parent class, GD::Polygon. Those updated/new methods # act on polygons and polylines, and sometimes those behaviours # vary slightly based on whether the object is a polygon or polyline. # use vars qw($VERSION @ISA); $VERSION = "0.2"; @ISA = qw(GD::Polygon); package GD::Polygon; ############################################################################ # # new methods on GD::Polygon # ############################################################################ use GD; use Carp 'croak','carp'; use vars qw($bezSegs $csr); $bezSegs = 20; # number of bezier segs -- number of segments in each portion of the spline produces by toSpline() $csr = 1/3; # control seg ratio -- the one possibly user-tunable parameter in the addControlPoints() algorithm sub rotate { my ($self, $angle, $cx, $cy) = @_; $self->offset(-$cx,-$cy) if $cx or $cy; $self->transform(cos($angle),sin($angle),-sin($angle),cos($angle),$cx,$cy); } sub centroid { my ($self, $scale) = @_; my ($cx,$cy); $scale = 1 unless defined $scale; map {$cx += $_->[0]; $cy += $_->[1]} $self->vertices(); $cx *= $scale / $self->length(); $cy *= $scale / $self->length(); return ($cx, $cy); } sub segLength { my $self = shift; my @points = $self->vertices(); my ($p1, $p2, @segLengths); $p1 = shift @points; # put the first vertex on the end to "close" a polygon, but not a polyline push @points, $p1 unless $self->isa('GD::Polyline'); while ($p2 = shift @points) { push @segLengths, _len($p1, $p2); $p1 = $p2; } return @segLengths if wantarray; my $sum; map {$sum += $_} @segLengths; return $sum; } sub segAngle { my $self = shift; my @points = $self->vertices(); my ($p1, $p2, @segAngles); $p1 = shift @points; # put the first vertex on the end to "close" a polygon, but not a polyline push @points, $p1 unless $self->isa('GD::Polyline'); while ($p2 = shift @points) { push @segAngles, _angle_reduce2(_angle($p1, $p2)); $p1 = $p2; } return @segAngles; } sub vertexAngle { my $self = shift; my @points = $self->vertices(); my ($p1, $p2, $p3, @vertexAngle); $p1 = $points[$#points]; # last vertex $p2 = shift @points; # current point -- the first vertex # put the first vertex on the end to "close" a polygon, but not a polyline push @points, $p2 unless $self->isa('GD::Polyline'); while ($p3 = shift @points) { push @vertexAngle, _angle_reduce2(_angle($p1, $p2, $p3)); ($p1, $p2) = ($p2, $p3); } $vertexAngle[0] = undef if defined $vertexAngle[0] and $self->isa("GD::Polyline"); return @vertexAngle if wantarray; } sub toSpline { my $self = shift; my @points = $self->vertices(); # put the first vertex on the end to "close" a polygon, but not a polyline push @points, [$self->getPt(0)] unless $self->isa('GD::Polyline'); unless (@points > 1 and @points % 3 == 1) { carp "Attempt to call toSpline() with invalid set of control points"; return undef; } my ($ap1, $dp1, $dp2, $ap2); # ap = anchor point, dp = director point $ap1 = shift @points; my $bez = new ref($self); $bez->addPt(@$ap1); while (@points) { ($dp1, $dp2, $ap2) = splice(@points, 0, 3); for (1..$bezSegs) { my ($t0, $t1, $c1, $c2, $c3, $c4, $x, $y); $t1 = $_/$bezSegs; $t0 = (1 - $t1); # possible optimization: # these coefficient could be calculated just once and # cached in an array for a given value of $bezSegs $c1 = $t0 * $t0 * $t0; $c2 = 3 * $t0 * $t0 * $t1; $c3 = 3 * $t0 * $t1 * $t1; $c4 = $t1 * $t1 * $t1; $x = $c1 * $ap1->[0] + $c2 * $dp1->[0] + $c3 * $dp2->[0] + $c4 * $ap2->[0]; $y = $c1 * $ap1->[1] + $c2 * $dp1->[1] + $c3 * $dp2->[1] + $c4 * $ap2->[1]; $bez->addPt($x, $y); } $ap1 = $ap2; } # remove the last anchor point if this is a polygon -- since it will autoclose without it $bez->deletePt($bez->length()-1) unless $self->isa('GD::Polyline'); return $bez; } sub addControlPoints { my $self = shift; my @points = $self->vertices(); unless (@points > 1) { carp "Attempt to call addControlPoints() with too few vertices in polyline"; return undef; } my $points = scalar(@points); my @segAngles = $self->segAngle(); my @segLengths = $self->segLength(); my ($prevLen, $nextLen, $prevAngle, $thisAngle, $nextAngle); my ($controlSeg, $pt, $ptX, $ptY, @controlSegs); # this loop goes about creating polylines -- here called control segments -- # that hold the control points for the final set of control points # each control segment has three points, and these are colinear # the first and last will ultimately be "director points", and # the middle point will ultimately be an "anchor point" for my $i (0..$#points) { $controlSeg = new GD::Polyline; $pt = $points[$i]; ($ptX, $ptY) = @$pt; if ($self->isa('GD::Polyline') and ($i == 0 or $i == $#points)) { $controlSeg->addPt($ptX, $ptY); # director point $controlSeg->addPt($ptX, $ptY); # anchor point $controlSeg->addPt($ptX, $ptY); # director point next; } $prevLen = $segLengths[$i-1]; $nextLen = $segLengths[$i]; $prevAngle = $segAngles[$i-1]; $nextAngle = $segAngles[$i]; # make a control segment with control points (director points) # before and after the point from the polyline (anchor point) $controlSeg->addPt($ptX - $csr * $prevLen, $ptY); # director point $controlSeg->addPt($ptX , $ptY); # anchor point $controlSeg->addPt($ptX + $csr * $nextLen, $ptY); # director point # note that: # - the line is parallel to the x-axis, as the points have a common $ptY # - the points are thus clearly colinear # - the director point is a distance away from the anchor point in proportion to the length of the segment it faces # now, we must come up with a reasonable angle for the control seg # first, "unwrap" $nextAngle w.r.t. $prevAngle $nextAngle -= 2*pi() until $nextAngle < $prevAngle + pi(); $nextAngle += 2*pi() until $nextAngle > $prevAngle - pi(); # next, use seg lengths as an inverse weighted average # to "tip" the control segment toward the *shorter* segment $thisAngle = ($nextAngle * $prevLen + $prevAngle * $nextLen) / ($prevLen + $nextLen); # rotate the control segment to $thisAngle about it's anchor point $controlSeg->rotate($thisAngle, $ptX, $ptY); } continue { # save the control segment for later push @controlSegs, $controlSeg; } # post process my $controlPoly = new ref($self); # collect all the control segments' points in to a single control poly foreach my $cs (@controlSegs) { foreach my $pt ($cs->vertices()) { $controlPoly->addPt(@$pt); } } # final clean up based on poly type if ($controlPoly->isa('GD::Polyline')) { # remove the first and last control point # since they are director points ... $controlPoly->deletePt(0); $controlPoly->deletePt($controlPoly->length()-1); } else { # move the first control point to the last control point # since it is supposed to end with two director points ... $controlPoly->addPt($controlPoly->getPt(0)); $controlPoly->deletePt(0); } return $controlPoly; } # The following helper functions are for internal # use of this module. Input arguments of "points" # refer to an array ref of two numbers, [$x, $y] # as is used internally in the GD::Polygon # # _len() # Find the length of a segment, passing in two points. # Internal function; NOT a class or object method. # sub _len { # my ($p1, $p2) = @_; # return sqrt(($p2->[0]-$p1->[0])**2 + ($p2->[1]-$p1->[1])**2); my $pt = _subtract(@_); return sqrt($pt->[0] ** 2 + $pt->[1] **2); } use Math::Trig; # _angle() # Find the angle of... well, depends on the number of arguments: # - one point: the angle from x-axis to the point (origin is the center) # - two points: the angle of the vector defined from point1 to point2 # - three points: # Internal function; NOT a class or object method. # sub _angle { my ($p1, $p2, $p3) = @_; my $angle = undef; if (@_ == 1) { return atan2($p1->[1], $p1->[0]); } if (@_ == 2) { return _angle(_subtract($p1, $p2)); } if (@_ == 3) { return _angle(_subtract($p2, $p3)) - _angle(_subtract($p2, $p1)); } } # _subtract() # Find the difference of two points; returns a point. # Internal function; NOT a class or object method. # sub _subtract { my ($p1, $p2) = @_; # print(_print_point($p2), "-", _print_point($p1), "\n"); return [$p2->[0]-$p1->[0], $p2->[1]-$p1->[1]]; } # _print_point() # Returns a string suitable for displaying the value of a point. # Internal function; NOT a class or object method. # sub _print_point { my ($p1) = @_; return "[" . join(", ", @$p1) . "]"; } # _angle_reduce1() # "unwraps" angle to interval -pi < angle <= +pi # Internal function; NOT a class or object method. # sub _angle_reduce1 { my ($angle) = @_; $angle += 2 * pi() while $angle <= -pi(); $angle -= 2 * pi() while $angle > pi(); return $angle; } # _angle_reduce2() # "unwraps" angle to interval 0 <= angle < 2 * pi # Internal function; NOT a class or object method. # sub _angle_reduce2 { my ($angle) = @_; $angle += 2 * pi() while $angle < 0; $angle -= 2 * pi() while $angle >= 2 * pi(); return $angle; } ############################################################################ # # new methods on GD::Image # ############################################################################ sub GD::Image::polyline { my $self = shift; # the GD::Image my $p = shift; # the GD::Polyline (or GD::Polygon) my $c = shift; # the color my @points = $p->vertices(); my $p1 = shift @points; my $p2; while ($p2 = shift @points) { $self->line(@$p1, @$p2, $c); $p1 = $p2; } } sub GD::Image::polydraw { my $self = shift; # the GD::Image my $p = shift; # the GD::Polyline or GD::Polygon my $c = shift; # the color return $self->polyline($p, $c) if $p->isa('GD::Polyline'); return $self->polygon($p, $c); } 1; __END__ =pod =head1 NAME GD::Polyline - Polyline object and Polygon utilities (including splines) for use with GD =head1 SYNOPSIS use GD; use GD::Polyline; # create an image $image = GD::Image->new (500,300); $white = $image->colorAllocate(255,255,255); $black = $image->colorAllocate( 0, 0, 0); $red = $image->colorAllocate(255, 0, 0); # create a new polyline $polyline = GD::Polyline->new; # add some points $polyline->addPt( 0, 0); $polyline->addPt( 0,100); $polyline->addPt( 50,125); $polyline->addPt(100, 0); # polylines can use polygon methods (and vice versa) $polyline->offset(200,100); # rotate 60 degrees, about the centroid $polyline->rotate(3.14159/3, $polyline->centroid()); # scale about the centroid $polyline->scale(1.5, 2, $polyline->centroid()); # draw the polyline $image->polydraw($polyline,$black); # create a spline, which is also a polyine $spline = $polyline->addControlPoints->toSpline; $image->polydraw($spline,$red); # output the png binmode STDOUT; print $image->png; =head1 DESCRIPTION B extends the GD module by allowing you to create polylines. Think of a polyline as "an open polygon", that is, the last vertex is not connected to the first vertex (unless you expressly add the same value as both points). For the remainder of this doc, "polyline" will refer to a GD::Polyline, "polygon" will refer to a GD::Polygon that is not a polyline, and "polything" and "$poly" may be either. The big feature added to GD by this module is the means to create splines, which are approximations to curves. =head1 The Polyline Object GD::Polyline defines the following class: =over 5 =item C A polyline object, used for storing lists of vertices prior to rendering a polyline into an image. =item C Cnew> I Create an empty polyline with no vertices. $polyline = GD::Polyline->new; $polyline->addPt( 0, 0); $polyline->addPt( 0,100); $polyline->addPt( 50,100); $polyline->addPt(100, 0); $image->polydraw($polyline,$black); In fact GD::Polyline is a subclass of GD::Polygon, so all polygon methods (such as B and B) may be used on polylines. Some new methods have thus been added to GD::Polygon (such as B) and a few updated/modified/enhanced (such as B) I. See section "New or Updated GD::Polygon Methods" for more info. =back Note that this module is very "young" and should be considered subject to change in future releases, and/or possibly folded in to the existing polygon object and/or GD module. =head1 Updated Polygon Methods The following methods (defined in GD.pm) are OVERRIDDEN if you use this module. All effort has been made to provide 100% backward compatibility, but if you can confirm that has not been achieved, please consider that a bug and let the the author of Polyline.pm know. =over 5 =item C C<$poly-Escale($sx, $sy, $cx, $cy)> I Scale a polything in along x-axis by $sx and along the y-axis by $sy, about centery point ($cx, $cy). Center point ($cx, $cy) is optional -- if these are omitted, the function will scale about the origin. To flip a polything, use a scale factor of -1. For example, to flip the polything top to bottom about line y = 100, use: $poly->scale(1, -1, 0, 100); =back =head1 New Polygon Methods The following methods are added to GD::Polygon, and thus can be used by polygons and polylines. Don't forget: a polyline is a GD::Polygon, so GD::Polygon methods like offset() can be used, and they can be used in GD::Image methods like filledPolygon(). =over 5 =item C C<$poly-Erotate($angle, $cx, $cy)> I Rotate a polything through $angle (clockwise, in radians) about center point ($cx, $cy). Center point ($cx, $cy) is optional -- if these are omitted, the function will rotate about the origin In this function and other angle-oriented functions in GD::Polyline, positive $angle corresponds to clockwise rotation. This is opposite of the usual Cartesian sense, but that is because the raster is opposite of the usual Cartesian sense in that the y-axis goes "down". =item C C<($cx, $cy) = $poly-Ecentroid($scale)> I Calculate and return ($cx, $cy), the centroid of the vertices of the polything. For example, to rotate something 180 degrees about it's centroid: $poly->rotate(3.14159, $poly->centroid()); $scale is optional; if supplied, $cx and $cy are multiplied by $scale before returning. The main use of this is to shift an polything to the origin like this: $poly->offset($poly->centroid(-1)); =item C C<@segLengths = $poly-EsegLength()> I In array context, returns an array the lengths of the segments in the polything. Segment n is the segment from vertex n to vertex n+1. Polygons have as many segments as vertices; polylines have one fewer. In a scalar context, returns the sum of the array that would have been returned in the array context. =item C C<@segAngles = $poly-EsegAngle()> I Returns an array the angles of each segment from the x-axis. Segment n is the segment from vertex n to vertex n+1. Polygons have as many segments as vertices; polylines have one fewer. Returned angles will be on the interval 0 <= $angle < 2 * pi and angles increase in a clockwise direction. =item C C<@vertexAngles = $poly-EvertexAngle()> I Returns an array of the angles between the segment into and out of each vertex. For polylines, the vertex angle at vertex 0 and the last vertex are not defined; however $vertexAngle[0] will be undef so that $vertexAngle[1] will correspond to vertex 1. Returned angles will be on the interval 0 <= $angle < 2 * pi and angles increase in a clockwise direction. Note that this calculation does not attempt to figure out the "interior" angle with respect to "inside" or "outside" the polygon, but rather, just the angle between the adjacent segments in a clockwise sense. Thus a polygon with all right angles will have vertex angles of either pi/2 or 3*pi/2, depending on the way the polygon was "wound". =item C C<$poly-EtoSpline()> I Create a new polything which is a reasonably smooth curve using cubic spline algorithms, often referred to as Bezier curves. The "source" polything is called the "control polything". If it is a polyline, the control polyline must have 4, 7, 10, or some number of vertices of equal to 3n+1. If it is a polygon, the control polygon must have 3, 6, 9, or some number of vertices of equal to 3n. $spline = $poly->toSpline(); $image->polydraw($spline,$red); In brief, groups of four points from the control polyline are considered "control points" for a given portion of the spline: the first and fourth are "anchor points", and the spline passes through them; the second and third are "director points". The spline does not pass through director points, however the spline is tangent to the line segment from anchor point to adjacent director point. The next portion of the spline reuses the previous portion's last anchor point. The spline will have a cusp (non-continuous slope) at an anchor point, unless the anchor points and its adjacent director point are colinear. In the current implementation, toSpline() return a fixed number of segments in the returned polyline per set-of-four control points. In the future, this and other parameters of the algorithm may be configurable. =item C C<$polyline-EaddControlPoints()> I So you say: "OK. Splines sound cool. But how can I get my anchor points and its adjacent director point to be colinear so that I have a nice smooth curves from my polyline?" Relax! For The Lazy: addControlPoints() to the rescue. addControlPoints() returns a polyline that can serve as the control polyline for toSpline(), which returns another polyline which is the spline. Is your head spinning yet? Think of it this way: =over 5 =item + If you have a polyline, and you have already put your control points where you want them, call toSpline() directly. Remember, only every third vertex will be "on" the spline. You get something that looks like the spline "inscribed" inside the control polyline. =item + If you have a polyline, and you want all of its vertices on the resulting spline, call addControlPoints() and then toSpline(): $control = $polyline->addControlPoints(); $spline = $control->toSpline(); $image->polyline($spline,$red); You get something that looks like the control polyline "inscribed" inside the spline. =back Adding "good" control points is subjective; this particular algorithm reveals its author's tastes. In the future, you may be able to alter the taste slightly via parameters to the algorithm. For The Hubristic: please build a better one! And for The Impatient: note that addControlPoints() returns a polyline, so you can pile up the call like this, if you'd like: $image->polyline($polyline->addControlPoints()->toSpline(),$mauve); =back =head1 New GD::Image Methods =over 5 =item C C<$image-Epolyline(polyline,color)> I $image->polyline($polyline,$black) This draws a polyline with the specified color. Both real color indexes and the special colors gdBrushed, gdStyled and gdStyledBrushed can be specified. Neither the polyline() method or the polygon() method are very picky: you can call either method with either a GD::Polygon or a GD::Polyline. The I determines if the shape is "closed" or "open" as drawn, I the object type. =item C C<$image-Epolydraw(polything,color)> I $image->polydraw($poly,$black) This method draws the polything as expected (polygons are closed, polylines are open) by simply checking the object type and calling either $image->polygon() or $image->polyline(). =back =head1 Examples Please see file "polyline-examples.pl" that is included with the distribution. =head1 See Also For more info on Bezier splines, see http://www.webreference.com/dlab/9902/bezier.html. =head1 Future Features On the drawing board are additional features such as: - polygon winding algorithms (to determine if a point is "inside" or "outside" the polygon) - new polygon from bounding box - find bounding polygon (tightest fitting simple convex polygon for a given set of vertices) - addPts() method to add many points at once - clone() method for polygon - functions to interwork GD with SVG Please provide input on other possible features you'd like to see. =head1 Author This module has been written by Daniel J. Harasty. Please send questions, comments, complaints, and kudos to him at harasty@cpan.org. Thanks to Lincoln Stein for input and patience with me and this, my first CPAN contribution. =head1 Copyright Information The Polyline.pm module is copyright 2002, Daniel J. Harasty. It is distributed under the same terms as Perl itself. See the "Artistic License" in the Perl source code distribution for licensing terms. The latest version of Polyline.pm is available at your favorite CPAN repository and/or along with GD.pm by Lincoln D. Stein at http://stein.cshl.org/WWW/software/GD. =cut # future: # addPts # boundingPolygon # addControlPoints('method' => 'fitToSegments', 'numSegs' => 10) # toSpline('csr' => 1/4); # GD::Color # colorMap('x11' | 'svg' | ) # colorByName($image, 'orange'); # setImage($image); # cbn('orange'); # # # GD-2.78/lib/GD/Image.pm0000644000175000017500000001415314450761142013740 0ustar rurbanrurban# DO NOT EDIT! THIS FILE IS AUTOGENERATED BY lib/GD/Image_pm.PL package GD::Image; use strict; use GD; use Symbol 'gensym','qualify_to_ref'; use vars '$VERSION'; $VERSION = '2.77'; =head1 NAME GD::Image - Image class for the GD image library =head1 SYNOPSIS See L =head1 DESCRIPTION Supported Image formats: =over 4 =item Png =item Gif =item Jpeg =item Tiff =item WBMP =item Webp =item Heif =item Avif =item BMP =back Unsupported Image formats: =over 4 =item Gd =item Gd2 =item Xpm =item GifAnim =back See L =head1 AUTHOR The GD.pm interface is copyright 1995-2005, Lincoln D. Stein. It is distributed under the same terms as Perl itself. See the "Artistic License" in the Perl source code distribution for licensing terms. The latest versions of GD.pm are available on CPAN: http://www.cpan.org =head1 SEE ALSO L L, L, L, L =cut # Copyright 1995 Lincoln D. Stein. See accompanying README file for # usage information *stringTTF = \&GD::Image::stringFT; sub _make_filehandle { shift; # get rid of class no strict 'refs'; my $thing = shift; return $thing if defined(fileno $thing); # otherwise try qualifying it into caller's package my $fh; { local $^W = 0; # to avoid uninitialized variable warning from Symbol.pm my $pkg = caller(2) ? caller(2) : "main"; $fh = qualify_to_ref($thing,$pkg); } return $fh if defined(fileno $fh); # otherwise treat it as a file to open $fh = gensym; if (!open($fh,$thing)) { die "$thing not found: $!"; return undef; } return $fh; } sub new { my $pack = shift; if (@_ == 1) { if (my $type = _image_type($_[0])) { my $method = "newFrom${type}Data"; return unless $pack->can($method); return $pack->$method($_[0]); } return unless my $fh = $pack->_make_filehandle($_[0]); my $magic; return unless read($fh,$magic,4); return unless my $type = _image_type($magic); seek($fh,0,0); my $method = "newFrom${type}"; return $pack->$method($fh); } return $pack->_new(@_); } sub newTrueColor { my $pack = shift; return $pack->_new(@_, 1); } sub newPalette { my $pack = shift; return $pack->_new(@_, 0); } sub ellipse ($$$$$) { my ($self,$cx,$cy,$width,$height,$color) = @_; $self->arc($cx,$cy,$width,$height,0,360,$color); } # draws closed polygon with the specified color sub polygon { my $self = shift; my($p,$c) = @_; $self->openPolygon($p, $c); $self->line( @{$p->{'points'}->[0]}, @{$p->{'points'}->[$p->{'length'}-1]}, $c); } sub width { my $self = shift; my @bounds = $self->getBounds; $bounds[0]; } sub height { my $self = shift; my @bounds = $self->getBounds; $bounds[1]; } sub _image_type { my $data = shift; my $magic = substr($data,0,4); return 'Png' if $magic eq "\x89PNG"; return 'Jpeg' if ((substr($data,0,3) eq "\377\330\377") && ord(substr($data,3,1)) >= 0xc0); return 'Gif' if $magic eq "GIF8"; return 'Gd2' if $magic eq "gd2\000"; return 'Tiff' if $magic eq "\x4d\x4d\x00\x2a" or $magic eq "\x49\x49\x2a\x00" or $magic eq "IIN1"; return 'Webp' if substr($data,0,12) eq "RIFF2\0\0\0WEBP"; return 'Heif' if $magic eq '\000\000\000\030' and substr($data,4,4) eq "ftyp" and (substr($data,8,4) eq "heic" or substr($data,8,4) eq "heix"); return 'Avif' if $magic eq '\000\000\000\030' and substr($data,4,4) eq "ftyp" and (substr($data,8,4) eq "avif" or substr($data,8,4) eq "mif1"); return 'Xpm' if substr($data,0,9) eq "/* XPM */" or $magic eq '/* X'; return 'Xbm' if substr($data,0,8) eq "#define " or $magic eq "#def"; return; } sub clone { croak("Usage: clone(\$image)") unless @_ == 1; my $self = shift; my ($x,$y) = $self->getBounds; my $new = $self->new($x,$y); return unless $new; $new->copy($self,0,0,0,0,$x,$y); return $new; } sub newFromPng { croak("Usage: newFromPng(class,filehandle,[truecolor])") unless @_>=2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromPng($fh,@_); } sub newFromJpeg { croak("Usage: newFromJpeg(class,filehandle,[truecolor])") unless @_>=2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromJpeg($fh,@_); } sub newFromGif { croak("Usage: newFromGif(class,filehandle)") unless @_==2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromGif($fh,@_); } sub newFromTiff { croak("Usage: newFromTiff(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromTiff($fh); } sub newFromXbm { croak("Usage: newFromXbm(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromXbm($fh); } sub newFromWebp { croak("Usage: newFromWebp(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromWebp($fh); } sub newFromHeif { croak("Usage: newFromHeif(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromHeif($fh); } sub newFromAvif { croak("Usage: newFromAvif(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromAvif($fh); } sub newFromWBMP { croak("Usage: newFromWBMP(class,filehandle)") unless @_==2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromWBMP($fh,@_); } sub newFromBmp { croak("Usage: newFromBmp(class,filehandle)") unless @_==2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromBmp($fh,@_); } # Autoload methods go after __END__, and are processed by the autosplit program. 1; __END__ GD-2.78/lib/GD/Polygon.pm0000644000175000017500000001037214435047450014346 0ustar rurbanrurbanpackage GD::Polygon; use strict; use Carp 'carp'; use GD; use vars '$VERSION'; $VERSION = '2.77'; # old documentation error *GD::Polygon::delete = \&deletePt; =head1 NAME GD::Polygon - Polygon class for the GD image library =head1 SYNOPSIS See L =head1 DESCRIPTION See L =head1 AUTHOR The GD.pm interface is copyright 1995-2005, Lincoln D. Stein. It is distributed under the same terms as Perl itself. See the "Artistic License" in the Perl source code distribution for licensing terms. The latest versions of GD.pm are available on CPAN: http://www.cpan.org =head1 SEE ALSO L L, L, L, L =cut ### The polygon object ### # create a new polygon sub new { my $class = shift; return bless { 'length'=>0,'points'=>[] },$class; } # automatic destruction of the polygon sub DESTROY { my $self = shift; undef $self->{'points'}; } sub clear { my $self = shift; $self->{'points'} = []; $self->{'length'} = 0; } # add an x,y vertex to the polygon sub addPt { my($self,$x,$y) = @_; push(@{$self->{'points'}},[$x,$y]); $self->{'length'}++; } # get a vertex sub getPt { my($self,$index) = @_; return () unless ($index >= 0) && ($index < $self->{'length'}); return @{$self->{'points'}->[$index]}; } # change the value of a vertex sub setPt { my($self,$index,$x,$y) = @_; unless (($index>=0) && ($index<$self->{'length'})) { carp "Attempt to set an undefined polygon vertex"; return undef; } @{$self->{'points'}->[$index]} = ($x,$y); 1; } # return the total number of vertices sub length { shift->{'length'} } # return the array of vertices. # each vertex is an two-member (x,y) array sub vertices { @{shift->{'points'}} } # return the bounding box of the polygon # (smallest rectangle that contains it) sub bounds { my $self = shift; my($top,$bottom,$left,$right) = @_; $top = 99999999; $bottom =-99999999; $left = 99999999; $right = -99999999; my $v; foreach $v ($self->vertices) { $left = $v->[0] if $left > $v->[0]; $right = $v->[0] if $right < $v->[0]; $top = $v->[1] if $top > $v->[1]; $bottom = $v->[1] if $bottom < $v->[1]; } return ($left,$top,$right,$bottom); } # delete a vertex, returning it, just for fun sub deletePt { my($self,$index) = @_; unless (($index>=0) && ($index<@{$self->{'points'}})) { carp "Attempt to delete an undefined polygon vertex"; return undef; } my($vertex) = splice(@{$self->{'points'}},$index,1); $self->{'length'}--; return @$vertex; } # translate the polygon in space by deltaX and deltaY sub offset { my($self,$dh,$dv) = @_; my $size = $self->length; my($i); for ($i=0;$i<$size;$i++) { my($x,$y)=$self->getPt($i); $self->setPt($i, $x+$dh, $y+$dv); } } # map the polygon from sourceRect to destRect, # translating and resizing it if necessary sub map { my($self,$srcL,$srcT,$srcR,$srcB,$destL,$destT,$destR,$destB) = @_; my($factorV) = ($destB-$destT)/($srcB-$srcT); my($factorH) = ($destR-$destL)/($srcR-$srcL); my($vertices) = $self->length; my($i); for ($i=0;$i<$vertices;$i++) { my($x,$y) = $self->getPt($i); $x = int($destL + ($x - $srcL) * $factorH); $y = int($destT + ($y - $srcT) * $factorV); $self->setPt($i,$x,$y); } } # These routines added by Winfriend Koenig. sub toPt { my($self, $dx, $dy) = @_; unless ($self->length > 0) { $self->addPt($dx,$dy); return; } my ($x, $y) = $self->getPt($self->length-1); $self->addPt($x+$dx,$y+$dy); } sub transform($$$$$$$) { # see PostScript Ref. page 154 # documented as the affine transformation matrix: (xx,yx,xy,yy,x0,y0) # note that even the libgd doc is wrong here for yy. my($self, $sx, $rx, $sy, $ry, $tx, $ty) = @_; my $size = $self->length; for (my $i=0;$i<$size;$i++) { my($x,$y)=$self->getPt($i); # gdAffineApplyToPointF: # dst->x = x * affine[0] + y * affine[2] + affine[4]; # dst->y = x * affine[1] + y * affine[3] + affine[5]; $self->setPt($i, $x*$sx + $y*$ry + $tx, $x*$rx + $y*$sy + $ty); } } sub scale { my($self, $sx, $sy, $cx, $cy) = @_; $self->offset(-$cx,-$cy) if defined $cx or defined $cy; # sx, rx, ry, sy $self->transform($sx,0,0,$sy,$cx,$cy); } 1; GD-2.78/lib/GD/Simple.pm0000644000175000017500000011201214174320547014143 0ustar rurbanrurbanpackage GD::Simple; =head1 NAME GD::Simple - Simplified interface to GD library =head1 SYNOPSIS For a nice tutorial on using this module, see Gabor Szabo's article at http://perlmaven.com/drawing-images-using-gd-simple. use GD::Simple; # create a new image $img = GD::Simple->new(400,250); # draw a red rectangle with blue borders $img->bgcolor('red'); $img->fgcolor('blue'); $img->rectangle(10,10,50,50); # draw an empty rectangle with green borders $img->bgcolor(undef); $img->fgcolor('green'); $img->rectangle(30,30,100,100); # move to (80,80) and draw a green line to (100,190) $img->moveTo(80,80); $img->lineTo(100,190); # draw a solid orange ellipse $img->moveTo(110,100); $img->bgcolor('orange'); $img->fgcolor('orange'); $img->ellipse(40,40); # draw a black filled arc $img->moveTo(150,150); $img->fgcolor('black'); $img->arc(50,50,0,100,gdNoFill|gdEdged); # draw a string at (10,180) using the default # built-in font $img->moveTo(10,180); $img->string('This is very simple'); # draw a string at (280,210) using 20 point # times italic, angled upward 90 degrees $img->moveTo(280,210); $img->font('Times:italic'); $img->fontsize(20); $img->angle(-90); $img->string('This is very fancy'); # some turtle graphics $img->moveTo(300,100); $img->penSize(3,3); $img->angle(0); $img->line(20); # 20 pixels going to the right $img->turn(30); # set turning angle to 30 degrees $img->line(20); # 20 pixel line $img->line(20); $img->line(20); $img->turn(-90); # set turning angle to -90 degrees $img->line(50); # 50 pixel line # draw a cyan polygon edged in blue my $poly = GD::Polygon->new; $poly->addPt(150,100); $poly->addPt(199,199); $poly->addPt(100,199); $img->bgcolor('cyan'); $img->fgcolor('blue'); $img->penSize(1,1); $img->polygon($poly); # convert into png data print $img->png; =head1 DESCRIPTION GD::Simple is a subclass of the GD library that shortens many of the long GD method calls by storing information about the pen color, size and position in the GD object itself. It also adds a small number of "turtle graphics" style calls for those who prefer to work in polar coordinates. In addition, the library allows you to use symbolic names for colors, such as "chartreuse", and will manage the colors for you. =head2 The Pen GD::Simple maintains a "pen" whose settings are used for line- and shape-drawing operations. The pen has the following properties: =over 4 =item fgcolor The pen foreground color is the color of lines and the borders of filled and unfilled shapes. =item bgcolor The pen background color is the color of the contents of filled shapes. =item pensize The pen size is the width of the pen. Larger sizes draw thicker lines. =item position The pen position is its current position on the canvas in (X,Y) coordinates. =item angle When drawing in turtle mode, the pen angle determines the current direction of lines of relative length. =item turn When drawing in turtle mode, the turn determines the clockwise or counterclockwise angle that the pen will turn before drawing the next line. =item font The font to use when drawing text. Both built-in bitmapped fonts and TrueType fonts are supported. =item fontsize The size of the font to use when drawing with TrueType fonts. =back One sets the position and properties of the pen and then draws. As the drawing progresses, the position of the pen is updated. =head2 Methods GD::Simple introduces a number of new methods, a few of which have the same name as GD::Image methods, and hence change their behavior. In addition to these new methods, GD::Simple objects support all of the GD::Image methods. If you make a method call that isn't directly supported by GD::Simple, it refers the request to the underlying GD::Image object. Hence one can load a JPEG image into GD::Simple and declare it to be TrueColor by using this call, which is effectively inherited from GD::Image: my $img = GD::Simple->newFromJpeg('./myimage.jpg',1); The rest of this section describes GD::Simple-specific methods. =cut use strict; use GD; use GD::Group; use Math::Trig; use Carp 'croak'; our @ISA = 'Exporter'; our @EXPORT = @GD::EXPORT; our @EXPORT_OK = @GD::EXPORT_OK; our $AUTOLOAD; my $IMAGECLASS = 'GD::Image'; my $TRANSPARENT; my %COLORS = ( white => [ 0xFF, 0xFF, 0xFF ], black => [ 0x00, 0x00, 0x00 ], aliceblue => [ 0xF0, 0xF8, 0xFF ], antiquewhite => [ 0xFA, 0xEB, 0xD7 ], aqua => [ 0x00, 0xFF, 0xFF ], aquamarine => [ 0x7F, 0xFF, 0xD4 ], azure => [ 0xF0, 0xFF, 0xFF ], beige => [ 0xF5, 0xF5, 0xDC ], bisque => [ 0xFF, 0xE4, 0xC4 ], blanchedalmond => [ 0xFF, 0xEB, 0xCD ], blue => [ 0x00, 0x00, 0xFF ], blueviolet => [ 0x8A, 0x2B, 0xE2 ], brown => [ 0xA5, 0x2A, 0x2A ], burlywood => [ 0xDE, 0xB8, 0x87 ], cadetblue => [ 0x5F, 0x9E, 0xA0 ], chartreuse => [ 0x7F, 0xFF, 0x00 ], chocolate => [ 0xD2, 0x69, 0x1E ], coral => [ 0xFF, 0x7F, 0x50 ], cornflowerblue => [ 0x64, 0x95, 0xED ], cornsilk => [ 0xFF, 0xF8, 0xDC ], crimson => [ 0xDC, 0x14, 0x3C ], cyan => [ 0x00, 0xFF, 0xFF ], darkblue => [ 0x00, 0x00, 0x8B ], darkcyan => [ 0x00, 0x8B, 0x8B ], darkgoldenrod => [ 0xB8, 0x86, 0x0B ], darkgray => [ 0xA9, 0xA9, 0xA9 ], darkgreen => [ 0x00, 0x64, 0x00 ], darkkhaki => [ 0xBD, 0xB7, 0x6B ], darkmagenta => [ 0x8B, 0x00, 0x8B ], darkolivegreen => [ 0x55, 0x6B, 0x2F ], darkorange => [ 0xFF, 0x8C, 0x00 ], darkorchid => [ 0x99, 0x32, 0xCC ], darkred => [ 0x8B, 0x00, 0x00 ], darksalmon => [ 0xE9, 0x96, 0x7A ], darkseagreen => [ 0x8F, 0xBC, 0x8F ], darkslateblue => [ 0x48, 0x3D, 0x8B ], darkslategray => [ 0x2F, 0x4F, 0x4F ], darkturquoise => [ 0x00, 0xCE, 0xD1 ], darkviolet => [ 0x94, 0x00, 0xD3 ], deeppink => [ 0xFF, 0x14, 0x100 ], deepskyblue => [ 0x00, 0xBF, 0xFF ], dimgray => [ 0x69, 0x69, 0x69 ], dodgerblue => [ 0x1E, 0x90, 0xFF ], firebrick => [ 0xB2, 0x22, 0x22 ], floralwhite => [ 0xFF, 0xFA, 0xF0 ], forestgreen => [ 0x22, 0x8B, 0x22 ], fuchsia => [ 0xFF, 0x00, 0xFF ], gainsboro => [ 0xDC, 0xDC, 0xDC ], ghostwhite => [ 0xF8, 0xF8, 0xFF ], gold => [ 0xFF, 0xD7, 0x00 ], goldenrod => [ 0xDA, 0xA5, 0x20 ], gray => [ 0x80, 0x80, 0x80 ], green => [ 0x00, 0x80, 0x00 ], greenyellow => [ 0xAD, 0xFF, 0x2F ], honeydew => [ 0xF0, 0xFF, 0xF0 ], hotpink => [ 0xFF, 0x69, 0xB4 ], indianred => [ 0xCD, 0x5C, 0x5C ], indigo => [ 0x4B, 0x00, 0x82 ], ivory => [ 0xFF, 0xFF, 0xF0 ], khaki => [ 0xF0, 0xE6, 0x8C ], lavender => [ 0xE6, 0xE6, 0xFA ], lavenderblush => [ 0xFF, 0xF0, 0xF5 ], lawngreen => [ 0x7C, 0xFC, 0x00 ], lemonchiffon => [ 0xFF, 0xFA, 0xCD ], lightblue => [ 0xAD, 0xD8, 0xE6 ], lightcoral => [ 0xF0, 0x80, 0x80 ], lightcyan => [ 0xE0, 0xFF, 0xFF ], lightgoldenrodyellow => [ 0xFA, 0xFA, 0xD2 ], lightgreen => [ 0x90, 0xEE, 0x90 ], lightgrey => [ 0xD3, 0xD3, 0xD3 ], lightpink => [ 0xFF, 0xB6, 0xC1 ], lightsalmon => [ 0xFF, 0xA0, 0x7A ], lightseagreen => [ 0x20, 0xB2, 0xAA ], lightskyblue => [ 0x87, 0xCE, 0xFA ], lightslategray => [ 0x77, 0x88, 0x99 ], lightsteelblue => [ 0xB0, 0xC4, 0xDE ], lightyellow => [ 0xFF, 0xFF, 0xE0 ], lime => [ 0x00, 0xFF, 0x00 ], limegreen => [ 0x32, 0xCD, 0x32 ], linen => [ 0xFA, 0xF0, 0xE6 ], magenta => [ 0xFF, 0x00, 0xFF ], maroon => [ 0x80, 0x00, 0x00 ], mediumaquamarine => [ 0x66, 0xCD, 0xAA ], mediumblue => [ 0x00, 0x00, 0xCD ], mediumorchid => [ 0xBA, 0x55, 0xD3 ], mediumpurple => [ 0x100, 0x70, 0xDB ], mediumseagreen => [ 0x3C, 0xB3, 0x71 ], mediumslateblue => [ 0x7B, 0x68, 0xEE ], mediumspringgreen => [ 0x00, 0xFA, 0x9A ], mediumturquoise => [ 0x48, 0xD1, 0xCC ], mediumvioletred => [ 0xC7, 0x15, 0x85 ], midnightblue => [ 0x19, 0x19, 0x70 ], mintcream => [ 0xF5, 0xFF, 0xFA ], mistyrose => [ 0xFF, 0xE4, 0xE1 ], moccasin => [ 0xFF, 0xE4, 0xB5 ], navajowhite => [ 0xFF, 0xDE, 0xAD ], navy => [ 0x00, 0x00, 0x80 ], oldlace => [ 0xFD, 0xF5, 0xE6 ], olive => [ 0x80, 0x80, 0x00 ], olivedrab => [ 0x6B, 0x8E, 0x23 ], orange => [ 0xFF, 0xA5, 0x00 ], orangered => [ 0xFF, 0x45, 0x00 ], orchid => [ 0xDA, 0x70, 0xD6 ], palegoldenrod => [ 0xEE, 0xE8, 0xAA ], palegreen => [ 0x98, 0xFB, 0x98 ], paleturquoise => [ 0xAF, 0xEE, 0xEE ], palevioletred => [ 0xDB, 0x70, 0x100 ], papayawhip => [ 0xFF, 0xEF, 0xD5 ], peachpuff => [ 0xFF, 0xDA, 0xB9 ], peru => [ 0xCD, 0x85, 0x3F ], pink => [ 0xFF, 0xC0, 0xCB ], plum => [ 0xDD, 0xA0, 0xDD ], powderblue => [ 0xB0, 0xE0, 0xE6 ], purple => [ 0x80, 0x00, 0x80 ], red => [ 0xFF, 0x00, 0x00 ], rosybrown => [ 0xBC, 0x8F, 0x8F ], royalblue => [ 0x41, 0x69, 0xE1 ], saddlebrown => [ 0x8B, 0x45, 0x13 ], salmon => [ 0xFA, 0x80, 0x72 ], sandybrown => [ 0xF4, 0xA4, 0x60 ], seagreen => [ 0x2E, 0x8B, 0x57 ], seashell => [ 0xFF, 0xF5, 0xEE ], sienna => [ 0xA0, 0x52, 0x2D ], silver => [ 0xC0, 0xC0, 0xC0 ], skyblue => [ 0x87, 0xCE, 0xEB ], slateblue => [ 0x6A, 0x5A, 0xCD ], slategray => [ 0x70, 0x80, 0x90 ], snow => [ 0xFF, 0xFA, 0xFA ], springgreen => [ 0x00, 0xFF, 0x7F ], steelblue => [ 0x46, 0x82, 0xB4 ], tan => [ 0xD2, 0xB4, 0x8C ], teal => [ 0x00, 0x80, 0x80 ], thistle => [ 0xD8, 0xBF, 0xD8 ], tomato => [ 0xFF, 0x63, 0x47 ], turquoise => [ 0x40, 0xE0, 0xD0 ], violet => [ 0xEE, 0x82, 0xEE ], wheat => [ 0xF5, 0xDE, 0xB3 ], whitesmoke => [ 0xF5, 0xF5, 0xF5 ], yellow => [ 0xFF, 0xFF, 0x00 ], yellowgreen => [ 0x9A, 0xCD, 0x32 ], gradient1 => [ 0x00, 0xFF, 0x00 ], gradient2 => [ 0x0A, 0xFF, 0x00 ], gradient3 => [ 0x14, 0xFF, 0x00 ], gradient4 => [ 0x1E, 0xFF, 0x00 ], gradient5 => [ 0x28, 0xFF, 0x00 ], gradient6 => [ 0x32, 0xFF, 0x00 ], gradient7 => [ 0x3D, 0xFF, 0x00 ], gradient8 => [ 0x47, 0xFF, 0x00 ], gradient9 => [ 0x51, 0xFF, 0x00 ], gradient10 => [ 0x5B, 0xFF, 0x00 ], gradient11 => [ 0x65, 0xFF, 0x00 ], gradient12 => [ 0x70, 0xFF, 0x00 ], gradient13 => [ 0x7A, 0xFF, 0x00 ], gradient14 => [ 0x84, 0xFF, 0x00 ], gradient15 => [ 0x8E, 0xFF, 0x00 ], gradient16 => [ 0x99, 0xFF, 0x00 ], gradient17 => [ 0xA3, 0xFF, 0x00 ], gradient18 => [ 0xAD, 0xFF, 0x00 ], gradient19 => [ 0xB7, 0xFF, 0x00 ], gradient20 => [ 0xC1, 0xFF, 0x00 ], gradient21 => [ 0xCC, 0xFF, 0x00 ], gradient22 => [ 0xD6, 0xFF, 0x00 ], gradient23 => [ 0xE0, 0xFF, 0x00 ], gradient24 => [ 0xEA, 0xFF, 0x00 ], gradient25 => [ 0xF4, 0xFF, 0x00 ], gradient26 => [ 0xFF, 0xFF, 0x00 ], gradient27 => [ 0xFF, 0xF4, 0x00 ], gradient28 => [ 0xFF, 0xEA, 0x00 ], gradient29 => [ 0xFF, 0xE0, 0x00 ], gradient30 => [ 0xFF, 0xD6, 0x00 ], gradient31 => [ 0xFF, 0xCC, 0x00 ], gradient32 => [ 0xFF, 0xC1, 0x00 ], gradient33 => [ 0xFF, 0xB7, 0x00 ], gradient34 => [ 0xFF, 0xAD, 0x00 ], gradient35 => [ 0xFF, 0xA3, 0x00 ], gradient36 => [ 0xFF, 0x99, 0x00 ], gradient37 => [ 0xFF, 0x8E, 0x00 ], gradient38 => [ 0xFF, 0x84, 0x00 ], gradient39 => [ 0xFF, 0x7A, 0x00 ], gradient40 => [ 0xFF, 0x70, 0x00 ], gradient41 => [ 0xFF, 0x65, 0x00 ], gradient42 => [ 0xFF, 0x5B, 0x00 ], gradient43 => [ 0xFF, 0x51, 0x00 ], gradient44 => [ 0xFF, 0x47, 0x00 ], gradient45 => [ 0xFF, 0x3D, 0x00 ], gradient46 => [ 0xFF, 0x32, 0x00 ], gradient47 => [ 0xFF, 0x28, 0x00 ], gradient48 => [ 0xFF, 0x1E, 0x00 ], gradient49 => [ 0xFF, 0x14, 0x00 ], gradient50 => [ 0xFF, 0x0A, 0x00 ], ); sub AUTOLOAD { my $self = shift; my($pack,$func_name) = $AUTOLOAD=~/(.+)::([^:]+)$/; return if $func_name eq 'DESTROY'; if (ref $self && exists $self->{gd}) { $self->{gd}->$func_name(@_); } else { my @result = $IMAGECLASS->$func_name(@_); if (UNIVERSAL::isa($result[0],'GD::Image')) { return $self->new($result[0]); } else { return @result; } } } =over 4 =item $img = GD::Simple->new($x,$y [,$truecolor]) =item $img = GD::Simple->new($gd) Create a new GD::Simple object. There are two forms of new(). In the first form, pass the width and height of the desired canvas, and optionally a boolean flag to request a truecolor image. In the second form, pass a previously-created GD::Image object. =cut # dual-purpose code - beware sub new { my $pack = shift; unshift @_,(100,100) if @_ == 0; if (@_ >= 2) { # traditional GD::Image->new() call my $gd = $IMAGECLASS->new(@_); my $self = $pack->new($gd); $self->clear; return $self; } if (@_ == 1) { # initialize from existing image my $gd = shift; my $self = bless { gd => $gd, xy => [0,0], font => gdSmallFont, fontsize => 9, turningangle => 0, angle => 0, pensize => 1, },$pack; $self->{bgcolor} = $self->translate_color(255,255,255); $self->{fgcolor} = $self->translate_color(0,0,0); return $self; } } =item GD::Simple->class('GD'); =item GD::Simple->class('GD::SVG'); Select whether new() should use GD or GD::SVG internally. Call GD::Simple->class('GD::SVG') before calling new() if you wish to generate SVG images. If future GD subclasses are created, this method will subport them. =cut sub class { my $pack = shift; if (@_) { $IMAGECLASS = shift; eval "require $IMAGECLASS; 1" or die $@; $IMAGECLASS = "$IMAGECLASS\:\:Image" if $IMAGECLASS eq 'GD::SVG'; } $IMAGECLASS; } =item $img->moveTo($x,$y) This call changes the position of the pen without drawing. It moves the pen to position ($x,$y) on the drawing canvas. =cut sub moveTo { my $self = shift; croak 'Usage GD::Simple->moveTo($x,$y)' unless @_ == 2; my ($x,$y) = @_; $self->{xy} = [$x,$y]; } =item $img->move($dx,$dy) =item $img->move($dr) This call changes the position of the pen without drawing. When called with two arguments it moves the pen $dx pixels to the right and $dy pixels downward. When called with one argument it moves the pen $dr pixels along the vector described by the current pen angle. =cut sub move { my $self = shift; if (@_ == 1) { # polar coordinates -- this is r $self->{angle} += $self->{turningangle}; my $angle = deg2rad($self->{angle}); $self->{xy}[0] += $_[0] * cos($angle); $self->{xy}[1] += $_[0] * sin($angle); } elsif (@_ == 2) { # cartesian coordinates $self->{xy}[0] += $_[0]; $self->{xy}[1] += $_[1]; } else { croak 'Usage GD::Simple->move($dx,$dy) or move($r)'; } } =item $img->lineTo($x,$y) The lineTo() call simultaneously draws and moves the pen. It draws a line from the current pen position to the position defined by ($x,$y) using the current pen size and color. After drawing, the position of the pen is updated to the new position. =cut sub lineTo { my $self = shift; croak 'Usage GD::Simple->lineTo($x,$y)' unless @_ == 2; $self->gd->line($self->curPos,@_,$self->fgcolor); $self->moveTo(@_); } =item $img->line($x1,$y1,$x2,$y2 [,$color]) =item $img->line($dx,$dy) =item $img->line($dr) The line() call simultaneously draws and moves the pen. When called with two arguments it draws a line from the current position of the pen to the position $dx pixels to the right and $dy pixels down. When called with one argument, it draws a line $dr pixels long along the angle defined by the current pen angle. When called with four or five arguments, line() behaves like GD::Image->line(). =cut sub line { my $self = shift; if (@_ >= 4) { my ($x1,$x2,$y1,$y2,$color) = @_; $color ||= $self->fgcolor; return $self->gd->line($x1,$x2,$y1,$y2,$color); } croak 'Usage GD::Simple->line($dx,$dy) or line($r) or line($x1,$y1,$x2,$y2 [,$color])' unless @_ >= 1; my @curPos = $self->curPos; $self->move(@_); my @newPos = $self->curPos; return $self->gd->line(@curPos,@newPos,$self->fgcolor); } =item $img->clear This method clears the canvas by painting over it with the current background color. =cut sub clear { my $self = shift; $self->gd->filledRectangle(0,0,$self->getBounds,$self->bgcolor); } =item $img->rectangle($x1,$y1,$x2,$y2) This method draws the rectangle defined by corners ($x1,$y1), ($x2,$y2). The rectangle's edges are drawn in the foreground color and its contents are filled with the background color. To draw a solid rectangle set bgcolor equal to fgcolor. To draw an unfilled rectangle (transparent inside), set bgcolor to undef. =cut sub rectangle { my $self = shift; return $self->gd->rectangle(@_) if @_ == 5; croak 'Usage GD::Simple->rectangle($x1,$y1,$x2,$y2)' unless @_ == 4; my $gd = $self->gd; my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); $gd->filledRectangle(@_,$bg) if defined $bg; $gd->rectangle(@_,$fg) if defined $fg && (!defined $bg || $bg != $fg); } =item $img->ellipse($width,$height) This method draws the ellipse centered at the current location with width $width and height $height. The ellipse's border is drawn in the foreground color and its contents are filled with the background color. To draw a solid ellipse set bgcolor equal to fgcolor. To draw an unfilled ellipse (transparent inside), set bgcolor to undef. =cut sub ellipse { my $self = shift; return $self->gd->ellipse(@_) if @_ == 5; croak 'Usage GD::Simple->ellipse($width,$height)' unless @_ == 2; my $gd = $self->gd; my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); $gd->filledEllipse($self->curPos,@_,$bg) if defined $bg; $gd->ellipse($self->curPos,@_,$fg) if defined $fg && (!defined $bg || $bg != $fg); } =item $img->arc([$cx,$cy,] $width,$height,$start,$end [,$style]) This method draws filled and unfilled arcs, at the current position, with the current fore- and background colors. See L for a description of the arguments. To draw a solid arc (such as a pie wedge) set bgcolor equal to fgcolor. To draw an unfilled arc, set bgcolor to undef. =cut sub arc { my $self = shift; return $self->gd->arc(@_) if @_ == 7; croak 'Usage GD::Simple->arc($width,$height,$start,$end[,$style])' unless @_ >= 4; my ($width,$height,$start,$end,$style) = @_; my $gd = $self->gd; my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); my ($cx,$cy) = $self->curPos; if ($bg) { my @args = ($cx,$cy,$width,$height,$start,$end,$bg); push @args,$style if defined $style; $gd->filledArc(@args); } else { my @args = ($cx,$cy,$width,$height,$start,$end,$fg); $gd->arc(@args); } } =item $img->polygon($poly) This method draws filled and unfilled polygon using the current settings of fgcolor for the polygon border and bgcolor for the polygon fill color. See L for a description of creating polygons. To draw a solid polygon set bgcolor equal to fgcolor. To draw an unfilled polygon, set bgcolor to undef. =cut sub polygon { my $self = shift; croak 'Usage GD::Simple->polygon($poly)' unless @_ == 1; my $gd = $self->gd; my ($bg,$fg) = ($self->bgcolor,$self->fgcolor); $gd->filledPolygon(@_,$bg) if defined $bg; $gd->openPolygon(@_,$fg) if defined $fg && (!defined $bg || $bg != $fg); } =item $img->polyline($poly) This method draws polygons without closing the first and last vertices (similar to GD::Image->unclosedPolygon()). It uses the fgcolor to draw the line. =cut sub polyline { my $self = shift; croak 'Usage GD::Simple->polyline($poly)' unless @_ == 1; my $gd = $self->gd; my $fg = $self->fgcolor; $gd->unclosedPolygon(@_,$fg); } =item $img->string($string) This method draws the indicated string starting at the current position of the pen. The pen is moved to the end of the drawn string. Depending on the font selected with the font() method, this will use either a bitmapped GD font or a TrueType font. The angle of the pen will be consulted when drawing the text. For TrueType fonts, any angle is accepted. For GD bitmapped fonts, the angle can be either 0 (draw horizontal) or -90 (draw upwards). For consistency between the TrueType and GD font behavior, the string is always drawn so that the current position of the pen corresponds to the bottom left of the first character of the text. This is different from the GD behavior, in which the first character of bitmapped fonts hangs down from the pen point. This method returns a polygon indicating the bounding box of the rendered text. If an error occurred (such as invalid font specification) it returns undef and an error message in $@. =cut sub string { my $self = shift; return $self->gd->string(@_) if @_ == 5; my $string = shift; my $font = $self->font; my @bounds; if (ref $font && $font->isa('GD::Font')) { my ($x,$y) = $self->curPos; if ($self->angle == -90) { $x -= $font->height; $y -= $font->width; $self->gd->stringUp($font,$x,$y,$string,$self->fgcolor); $self->{xy}[1] -= length($string) * $font->width; @bounds = ( ($self->{xy}[0],$y), ($x,$y), ($x,$self->{xy}[1]-$font->width), ($self->{xy}[0],$self->{xy}[1]-$font->width) ); } else { $y -= $font->height; $self->gd->string($font,$x,$y,$string,$self->fgcolor); $self->{xy}[0] += length($string) * $font->width; @bounds = ( ($x,$self->{xy}[1]), ($self->{xy}[0],$self->{xy}[1]), ($self->{xy}[0],$y), ($x,$y) ); } } else { $self->useFontConfig(1); @bounds = $self->stringFT($self->fgcolor,$font, $self->fontsize,-deg2rad($self->angle), # -pi * $self->angle/180, $self->curPos,$string); return unless @bounds; my ($delta_x,$delta_y) = $self->_string_width(@bounds); $self->{xy}[0] += $delta_x; $self->{xy}[1] += $delta_y; } my $poly = GD::Polygon->new; while (@bounds) { $poly->addPt(splice(@bounds,0,2)); } return $poly; } =item $metrics = $img->fontMetrics =item ($metrics,$width,$height) = GD::Simple->fontMetrics($font,$fontsize,$string) This method returns information about the current font, most commonly a TrueType font. It can be invoked as an instance method (on a previously-created GD::Simple object) or as a class method (on the 'GD::Simple' class). When called as an instance method, fontMetrics() takes no arguments and returns a single hash reference containing the metrics that describe the currently selected font and size. The hash reference contains the following information: xheight the base height of the font from the bottom to the top of a lowercase 'm' ascent the length of the upper stem of the lowercase 'd' descent the length of the lower step of the lowercase 'j' lineheight the distance from the bottom of the 'j' to the top of the 'd' leading the distance between two adjacent lines This description and code was changed with 2.75. =cut # return %$fontmetrics # keys: 'ascent', 'descent', 'lineheight', 'xheight', 'leading' sub fontMetrics { my $self = shift; unless (ref $self) { #class invocation -- create a scratch $self = $self->new; $self->font(shift) if defined $_[0]; $self->fontsize(shift) if defined $_[0]; } my $font = $self->font; my $metrics; if (ref $font && $font->isa('GD::Font')) { my $height = $font->height; $metrics = {ascent => 0, descent => 0, lineheight => $height, xheight => $height, leading => 0}; } else { $self->useFontConfig(1); my @mbounds = GD::Image->stringFT($self->fgcolor,$font, $self->fontsize,0, 0,0,'m'); my $xheight = $mbounds[3]-$mbounds[5]; my @jbounds = GD::Image->stringFT($self->fgcolor,$font, $self->fontsize,0, 0,0,'j'); my $ascent = $mbounds[7]-$jbounds[7]; my $descent = $jbounds[3]-$mbounds[3]; my @mmbounds = GD::Image->stringFT($self->fgcolor,$font, $self->fontsize,0, 0,0,"m\nm"); my $twolines = $mmbounds[3]-$mmbounds[5]; my $lineheight = $twolines - 2*$xheight; my $leading = $lineheight - $ascent - $descent; $metrics = {ascent => $ascent, descent => $descent, lineheight => $lineheight, xheight => $xheight, leading => $leading}; } if ((my $string = shift) && wantarray) { my ($width,$height) = $self->stringBounds($string); return ($metrics,abs($width),abs($height)); } return $metrics; } =item ($delta_x,$delta_y)= $img->stringBounds($string) This method indicates the X and Y offsets (which may be negative) that will occur when the given string is drawn using the current font, fontsize and angle. When the string is drawn horizontally, it gives the width and height of the string's bounding box. =cut sub stringBounds { my $self = shift; my $string = shift; my $font = $self->font; if (ref $font && $font->isa('GD::Font')) { if ($self->angle == -90) { return ($font->height,-length($string) * $font->width); } else { return (length($string) * $font->width,$font->height); } } else { $self->useFontConfig(1); my @bounds = GD::Image->stringFT($self->fgcolor,$font, $self->fontsize,-deg2rad($self->angle), $self->curPos,$string); return $self->_string_width(@bounds); } } =item $delta_x = $img->stringWidth($string) This method indicates the width of the string given the current font, fontsize and angle. It is the same as ($img->stringBounds($string))[0] =cut sub stringWidth { return ((shift->stringBounds(@_))[0]); } sub _string_width { my $self = shift; my @bounds = @_; my $delta_x = abs($bounds[2]-$bounds[0]); my $delta_y = abs($bounds[5]-$bounds[3]); my $angle = $self->angle % 360; if ($angle >= 0 && $angle < 90) { return ($delta_x,$delta_y); } elsif ($angle >= 90 && $angle < 180) { return (-$delta_x,$delta_y); } elsif ($angle >= 180 && $angle < 270) { return (-$delta_x,-$delta_y); } elsif ($angle >= 270 && $angle < 360) { return ($delta_x,-$delta_y); } } =item ($x,$y) = $img->curPos Return the current position of the pen. Set the current position using moveTo(). =cut sub curPos { @{shift->{xy}}; } =item $font = $img->font([$newfont] [,$newsize]) Get or set the current font. Fonts can be GD::Font objects, TrueType font file paths, or fontconfig font patterns like "Times:italic" (see L). The latter feature requires that you have the fontconfig library installed and are using libgd version 2.0.33 or higher. As a shortcut, you may pass two arguments to set the font and the fontsize simultaneously. The fontsize is only valid when drawing with TrueType fonts. =cut sub font { my $self = shift; $self->{font} = shift if @_; $self->{fontsize} = shift if @_; $self->{font}; } =item $size = $img->fontsize([$newfontsize]) Get or set the current font size. This is only valid for TrueType fonts. =cut sub fontsize { my $self = shift; $self->{fontsize} = shift if @_; $self->{fontsize}; } =item $size = $img->penSize([$newpensize]) Get or set the current pen width for use during line drawing operations. =cut sub penSize { my $self = shift; if (@_) { $self->{pensize} = shift; $self->gd->setThickness($self->{pensize}); } $self->{pensize}; } =item $angle = $img->angle([$newangle]) Set the current angle for use when calling line() or move() with a single argument. Here is an example of using turn() and angle() together to draw an octagon. The first line drawn is the downward-slanting top right edge. The last line drawn is the horizontal top of the octagon. $img->moveTo(200,50); $img->angle(0); $img->turn(360/8); for (1..8) { $img->line(50) } =cut sub angle { my $self = shift; $self->{angle} = shift if @_; $self->{angle}; } =item $angle = $img->turn([$newangle]) Get or set the current angle to turn prior to drawing lines. This value is only used when calling line() or move() with a single argument. The turning angle will be applied to each call to line() or move() just before the actual drawing occurs. Angles are in degrees. Positive values turn the angle clockwise. =cut # degrees, not radians sub turn { my $self = shift; $self->{turningangle} = shift if @_; $self->{turningangle}; } =item $color = $img->fgcolor([$newcolor]) Get or set the pen's foreground color. The current pen color can be set by (1) using an (r,g,b) triple; (2) using a previously-allocated color from the GD palette; or (3) by using a symbolic color name such as "chartreuse." The list of color names can be obtained using color_names(). The special color name 'transparent' will create a completely transparent color. =cut sub fgcolor { my $self = shift; $self->{fgcolor} = $self->translate_color(@_) if @_; $self->{fgcolor}; } =item $color = $img->bgcolor([$newcolor]) Get or set the pen's background color. The current pen color can be set by (1) using an (r,g,b) triple; (2) using a previously-allocated color from the GD palette; or (3) by using a symbolic color name such as "chartreuse." The list of color names can be obtained using color_names(). The special color name 'transparent' will create a completely transparent color. =cut sub bgcolor { my $self = shift; $self->{bgcolor} = $self->translate_color(@_) if @_; $self->{bgcolor}; } =item $index = $img->translate_color(@args) Translates a color into a GD palette or TrueColor index. You may pass either an (r,g,b) triple or a symbolic color name. If you pass a previously-allocated index, the method will return it unchanged. =cut sub translate_color { my $self = shift; return unless defined $_[0]; my ($r,$g,$b); if (@_ == 1 && $_[0] =~ /^-?\d+/) { # previously allocated index return $_[0]; } elsif (@_ == 3) { # (rgb triplet) ($r,$g,$b) = @_; } elsif (lc $_[0] eq 'transparent') { return $TRANSPARENT ||= $self->alphaColor('white',127); } else { die "unknown color $_[0]" unless exists $COLORS{lc $_[0]}; ($r,$g,$b) = @{$COLORS{lc $_[0]}}; } return $self->colorResolve($r,$g,$b); } sub transparent { my $self = shift; my $index = $self->translate_color(@_); $self->gd->transparent($index); } =item $index = $img->alphaColor(@args,$alpha) Creates an alpha color. You may pass either an (r,g,b) triple or a symbolic color name, followed by an integer indicating its opacity. The opacity value ranges from 0 (fully opaque) to 127 (fully transparent). =cut sub alphaColor { my $self = shift; return unless defined $_[0]; my ($r,$g,$b,$a); if (@_ == 4) { # (rgb triplet) ($r,$g,$b,$a) = @_; } else { die "unknown color $_[0]" unless exists $COLORS{lc $_[0]}; ($r,$g,$b) = @{$COLORS{lc $_[0]}}; $a = $_[1]; } return $self->colorAllocateAlpha($r,$g,$b,$a); } =item @names = GD::Simple->color_names =item $translate_table = GD::Simple->color_names Called in a list context, color_names() returns the list of symbolic color names recognized by this module. Called in a scalar context, the method returns a hash reference in which the keys are the color names and the values are array references containing [r,g,b] triples. =cut sub color_names { my $self = shift; return wantarray ? sort keys %COLORS : \%COLORS; } =item $gd = $img->gd Return the internal GD::Image object. Usually you will not need to call this since all GD methods are automatically referred to this object. =cut sub gd { shift->{gd} } sub setBrush { my $self = shift; my $brush = shift; if ($brush->isa('GD::Simple')) { $self->gd->setBrush($brush->gd); } else { $self->gd->setBrush($brush); } } =item ($red,$green,$blue) = GD::Simple->HSVtoRGB($hue,$saturation,$value) Convert a Hue/Saturation/Value (HSV) color into an RGB triple. The hue, saturation and value are integers from 0 to 255. =cut sub HSVtoRGB { my $self = shift; @_ == 3 or croak "Usage: GD::Simple->HSVtoRGB(\$hue,\$saturation,\$value)"; my ($h,$s,$v)=@_; my ($r,$g,$b,$i,$f,$p,$q,$t); if( $s == 0 ) { ## achromatic (grey) return ($v,$v,$v); } $h %= 255; $s /= 255; ## scale saturation from 0.0-1.0 $h /= 255; ## scale hue from 0 to 1.0 $h *= 360; ## and now scale it to 0 to 360 $h /= 60; ## sector 0 to 5 $i = $h % 6; $f = $h - $i; ## factorial part of h $p = $v * ( 1 - $s ); $q = $v * ( 1 - $s * $f ); $t = $v * ( 1 - $s * ( 1 - $f ) ); if($i<1) { $r = $v; $g = $t; $b = $p; } elsif($i<2){ $r = $q; $g = $v; $b = $p; } elsif($i<3){ $r = $p; $g = $v; $b = $t; } elsif($i<4){ $r = $p; $g = $q; $b = $v; } elsif($i<5){ $r = $t; $g = $p; $b = $v; } else { $r = $v; $g = $p; $b = $q; } return (int($r+0.5),int($g+0.5),int($b+0.5)); } =item ($hue,$saturation,$value) = GD::Simple->RGBtoHSV($red,$green,$blue) Convert a Red/Green/Blue (RGB) value into a Hue/Saturation/Value (HSV) triple. The hue, saturation and value are integers from 0 to 255. =back =cut sub RGBtoHSV { my $self = shift; my ($r, $g ,$bl) = @_; my ($min,undef,$max) = sort {$a<=>$b} ($r,$g,$bl); return (0,0,0) unless $max > 0; my $v = $max; my $s = 255 * ($max - $min)/$max; my $h; my $range = $max - $min; if ($range == 0) { # all colors are equal, so monochrome return (0,0,$max); } if ($max == $r) { $h = 60 * ($g-$bl)/$range; } elsif ($max == $g) { $h = 60 * ($bl-$r)/$range + 120; } else { $h = 60 * ($r-$g)/$range + 240; } $h += 360 if $h < 0; $h = int($h*255/360 + 0.5); return ($h, $s, $v); } sub newGroup { my $self = shift; return $self->GD::newGroup(@_); } 1; =head1 COLORS This script will create an image showing all the symbolic colors. #!/usr/bin/perl use strict; use GD::Simple; my @color_names = GD::Simple->color_names; my $cols = int(sqrt(@color_names)); my $rows = int(@color_names/$cols)+1; my $cell_width = 100; my $cell_height = 50; my $legend_height = 16; my $width = $cols * $cell_width; my $height = $rows * $cell_height; my $img = GD::Simple->new($width,$height); $img->font(gdSmallFont); for (my $c=0; $c<$cols; $c++) { for (my $r=0; $r<$rows; $r++) { my $color = $color_names[$c*$rows + $r] or next; my @topleft = ($c*$cell_width,$r*$cell_height); my @botright = ($topleft[0]+$cell_width,$topleft[1]+$cell_height-$legend_height); $img->bgcolor($color); $img->fgcolor($color); $img->rectangle(@topleft,@botright); $img->moveTo($topleft[0]+2,$botright[1]+$legend_height-2); $img->fgcolor('black'); $img->string($color); } } print $img->png; =head1 AUTHOR The GD::Simple module is copyright 2004, Lincoln D. Stein. It is distributed under the same terms as Perl itself. See the "Artistic License" in the Perl source code distribution for licensing terms. The latest versions of GD.pm are available at https://github.com/lstein/Perl-GD =head1 SEE ALSO L, L, L, L =cut GD-2.78/lib/GD/Image_pm.PL0000644000175000017500000002217614450761142014337 0ustar rurbanrurban#!perl use Config; use File::Basename qw(&basename &dirname); use Cwd; my $DEFINES = ''; my $VERSION = ''; if (open F,".config.cache") { chomp($DEFINES = ); close F; } my $origdir = cwd; chdir dirname($0); my $file = 'Image.pm'; open OUT,">",$file or die "Can't create $file: $!"; print "Extracting $file (with variable substitutions)\n"; print OUT <<"!GROK!THIS!"; # DO NOT EDIT! THIS FILE IS AUTOGENERATED BY $0 !GROK!THIS! print OUT << '!NO!SUBS!'; package GD::Image; use strict; use GD; use Symbol 'gensym','qualify_to_ref'; use vars '$VERSION'; $VERSION = '2.77'; =head1 NAME GD::Image - Image class for the GD image library =head1 SYNOPSIS See L =head1 DESCRIPTION Supported Image formats: =over 4 !NO!SUBS! print OUT "=item Png\n\n" if $DEFINES =~ /HAVE_PNG/; print OUT "=item Gif\n\n" if $DEFINES =~ /HAVE_GIF/; print OUT "=item Gd\n\n=item Gd2\n\n" if $DEFINES =~ /HAVE_GD2/; print OUT "=item Jpeg\n\n" if $DEFINES =~ /HAVE_JPEG/; print OUT "=item Tiff\n\n" if $DEFINES =~ /HAVE_TIFF/; print OUT "=item Xpm\n\n" if $DEFINES =~ /HAVE_XPM/; print OUT "=item WBMP\n\n" if 1 or $DEFINES =~ /HAVE_WBMP/; print OUT "=item GifAnim\n\n" if $DEFINES =~ /HAVE_GIFANIM/; print OUT "=item Webp\n\n" if $DEFINES =~ /HAVE_WEBP/; print OUT "=item Heif\n\n" if $DEFINES =~ /HAVE_HEIF/; print OUT "=item Avif\n\n" if $DEFINES =~ /HAVE_AVIF/; print OUT "=item BMP\n\n" if $DEFINES =~ /HAVE_BMP/; print OUT << '!NO!SUBS!'; =back Unsupported Image formats: =over 4 !NO!SUBS! print OUT "=item Png\n\n" if $DEFINES !~ /HAVE_PNG/; print OUT "=item Gif\n\n" if $DEFINES !~ /HAVE_GIF/; print OUT "=item Gd\n\n=item Gd2\n\n" if $DEFINES !~ /HAVE_GD2/; print OUT "=item Jpeg\n\n" if $DEFINES !~ /HAVE_JPEG/; print OUT "=item Tiff\n\n" if $DEFINES !~ /HAVE_TIFF/; print OUT "=item Xpm\n\n" if $DEFINES !~ /HAVE_XPM/; print OUT "=item GifAnim\n\n" if $DEFINES !~ /HAVE_GIFANIM/; print OUT "=item Webp\n\n" if $DEFINES !~ /HAVE_WEBP/; print OUT "=item Heif\n\n" if $DEFINES !~ /HAVE_HEIF/; print OUT "=item Avif\n\n" if $DEFINES !~ /HAVE_AVIF/; print OUT "=item BMP\n\n" if $DEFINES !~ /HAVE_BMP/; print OUT << '!NO!SUBS!'; =back See L =head1 AUTHOR The GD.pm interface is copyright 1995-2005, Lincoln D. Stein. It is distributed under the same terms as Perl itself. See the "Artistic License" in the Perl source code distribution for licensing terms. The latest versions of GD.pm are available on CPAN: http://www.cpan.org =head1 SEE ALSO L L, L, L, L =cut # Copyright 1995 Lincoln D. Stein. See accompanying README file for # usage information *stringTTF = \&GD::Image::stringFT; sub _make_filehandle { shift; # get rid of class no strict 'refs'; my $thing = shift; return $thing if defined(fileno $thing); # otherwise try qualifying it into caller's package my $fh; { local $^W = 0; # to avoid uninitialized variable warning from Symbol.pm my $pkg = caller(2) ? caller(2) : "main"; $fh = qualify_to_ref($thing,$pkg); } return $fh if defined(fileno $fh); # otherwise treat it as a file to open $fh = gensym; if (!open($fh,$thing)) { die "$thing not found: $!"; return undef; } return $fh; } sub new { my $pack = shift; if (@_ == 1) { if (my $type = _image_type($_[0])) { my $method = "newFrom${type}Data"; return unless $pack->can($method); return $pack->$method($_[0]); } return unless my $fh = $pack->_make_filehandle($_[0]); my $magic; return unless read($fh,$magic,4); return unless my $type = _image_type($magic); seek($fh,0,0); my $method = "newFrom${type}"; return $pack->$method($fh); } return $pack->_new(@_); } sub newTrueColor { my $pack = shift; return $pack->_new(@_, 1); } sub newPalette { my $pack = shift; return $pack->_new(@_, 0); } sub ellipse ($$$$$) { my ($self,$cx,$cy,$width,$height,$color) = @_; $self->arc($cx,$cy,$width,$height,0,360,$color); } # draws closed polygon with the specified color sub polygon { my $self = shift; my($p,$c) = @_; $self->openPolygon($p, $c); $self->line( @{$p->{'points'}->[0]}, @{$p->{'points'}->[$p->{'length'}-1]}, $c); } sub width { my $self = shift; my @bounds = $self->getBounds; $bounds[0]; } sub height { my $self = shift; my @bounds = $self->getBounds; $bounds[1]; } sub _image_type { my $data = shift; my $magic = substr($data,0,4); return 'Png' if $magic eq "\x89PNG"; return 'Jpeg' if ((substr($data,0,3) eq "\377\330\377") && ord(substr($data,3,1)) >= 0xc0); return 'Gif' if $magic eq "GIF8"; return 'Gd2' if $magic eq "gd2\000"; return 'Tiff' if $magic eq "\x4d\x4d\x00\x2a" or $magic eq "\x49\x49\x2a\x00" or $magic eq "IIN1"; return 'Webp' if substr($data,0,12) eq "RIFF2\0\0\0WEBP"; return 'Heif' if $magic eq '\000\000\000\030' and substr($data,4,4) eq "ftyp" and (substr($data,8,4) eq "heic" or substr($data,8,4) eq "heix"); return 'Avif' if $magic eq '\000\000\000\030' and substr($data,4,4) eq "ftyp" and (substr($data,8,4) eq "avif" or substr($data,8,4) eq "mif1"); return 'Xpm' if substr($data,0,9) eq "/* XPM */" or $magic eq '/* X'; return 'Xbm' if substr($data,0,8) eq "#define " or $magic eq "#def"; return; } sub clone { croak("Usage: clone(\$image)") unless @_ == 1; my $self = shift; my ($x,$y) = $self->getBounds; my $new = $self->new($x,$y); return unless $new; $new->copy($self,0,0,0,0,$x,$y); return $new; } !NO!SUBS! if ($DEFINES =~ /HAVE_PNG/) { print OUT <<'!NO!SUBS!' sub newFromPng { croak("Usage: newFromPng(class,filehandle,[truecolor])") unless @_>=2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromPng($fh,@_); } !NO!SUBS! } if ($DEFINES =~ /HAVE_GD2/) { print OUT <<'!NO!SUBS!' sub newFromGd { croak("Usage: newFromGd(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromGd($fh); } sub newFromGd2 { croak("Usage: newFromGd2(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromGd2($fh); } sub newFromGd2Part { croak("Usage: newFromGd2(class,filehandle,srcX,srcY,width,height)") unless @_==6; my($class,$f) = splice(@_,0,2); my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromGd2Part($fh,@_); } !NO!SUBS! } if ($DEFINES =~ /HAVE_JPEG/) { print OUT <<'!NO!SUBS!' sub newFromJpeg { croak("Usage: newFromJpeg(class,filehandle,[truecolor])") unless @_>=2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromJpeg($fh,@_); } !NO!SUBS! } if ($DEFINES =~ /HAVE_GIF/) { print OUT <<'!NO!SUBS!' sub newFromGif { croak("Usage: newFromGif(class,filehandle)") unless @_==2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromGif($fh,@_); } !NO!SUBS! } if ($DEFINES =~ /HAVE_TIFF/) { print OUT <<'!NO!SUBS!' sub newFromTiff { croak("Usage: newFromTiff(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromTiff($fh); } !NO!SUBS! } print OUT <<'!NO!SUBS!'; sub newFromXbm { croak("Usage: newFromXbm(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromXbm($fh); } !NO!SUBS! if ($DEFINES =~ /HAVE_WEBP/) { print OUT <<'!NO!SUBS!' sub newFromWebp { croak("Usage: newFromWebp(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromWebp($fh); } !NO!SUBS! } if ($DEFINES =~ /HAVE_HEIF/) { print OUT <<'!NO!SUBS!' sub newFromHeif { croak("Usage: newFromHeif(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromHeif($fh); } !NO!SUBS! } if ($DEFINES =~ /HAVE_AVIF/) { print OUT <<'!NO!SUBS!' sub newFromAvif { croak("Usage: newFromAvif(class,filehandle)") unless @_==2; my($class,$f) = @_; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromAvif($fh); } !NO!SUBS! } if (1 or $DEFINES =~ /HAVE_WBMP/) { print OUT <<'!NO!SUBS!'; sub newFromWBMP { croak("Usage: newFromWBMP(class,filehandle)") unless @_==2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromWBMP($fh,@_); } !NO!SUBS! } if ($DEFINES =~ /HAVE_BMP/) { print OUT <<'!NO!SUBS!'; sub newFromBmp { croak("Usage: newFromBmp(class,filehandle)") unless @_==2; my($class) = shift; my($f) = shift; my $fh = $class->_make_filehandle($f); binmode($fh); $class->_newFromBmp($fh,@_); } !NO!SUBS! } print OUT <<'!NO!SUBS!'; # Autoload methods go after __END__, and are processed by the autosplit program. 1; __END__ !NO!SUBS! close OUT or die "Can't close $file: $!"; chdir $origdir; GD-2.78/lib/GD/Group.pm0000644000175000017500000000123713415647142014014 0ustar rurbanrurbanpackage GD::Group; =head1 NAME GD::Group - Simple object for recursive grouping =head1 DESCRIPTION Does absolutely nothing with GD, but works nicely with GD::SVG. =cut use strict; our $AUTOLOAD; our $VERSION = 1.00; sub AUTOLOAD { my ($pack,$func_name) = $AUTOLOAD =~ /(.+)::([^:]+)$/; my $this = shift; $this->{gd}->currentGroup($this->{group}); $this->{gd}->$func_name(@_); } sub new { my $this = shift; my ($gd,$group) = @_; return bless {gd => $gd, group => $group},ref $this || $this; } sub DESTROY { my $this = shift; my $gd = $this->{gd}; my $grp = $this->{group}; $gd->endGroup($grp); } 1;