GD(3)
๐
GD(3) โ like, the whole entire GD.pm situation ๐จโจ
okay so before we even get into it โ this is GD(3) from the User Contributed Perl Documentation, and it's the page for GD.pm, which is your Interface to Gd Graphics Library. yes bestie, the one Thomas Boutell made. we're getting into it. buckle up ๐ซถ
โจ NAME โจ
GD.pm โ Interface to Gd Graphics Library. that's it, that's the name, she's iconic and she knows it ๐
๐ธ SYNOPSIS ๐ธ
okay so here's the vibe in one code block. don't panic, we'll walk through it:
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;
like... she's serving. move over Photoshop, the group chat makes art now ๐
๐ฆ DESCRIPTION ๐ฆ
so GD.pm is a Perl interface to Thomas Boutell's gd graphics library (version 2.01 or higher; see below โ yes, "below", it's a whole thing). GD lets you create color drawings using a large number of graphics primitives, and then emit those drawings as PNG files. no cap, that's the whole pitch. ๐
GD defines these four classes:
GD::Imageโ the image class ๐ it holds the image data and accepts graphic primitive method calls. she's the main character fr.GD::Fontโ a font class, which holds static font information and is used for text rendering. the quiet supportive bestie of the classes.GD::Polygonโ a simple polygon object, used for storing lists of vertices prior to rendering a polygon into an image. lil list of points, living her life.GD::Simpleโ a "simple" class that simplifies theGD::ImageAPI 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 seeGD::Simplefor a description of these methods. lowkey she's the overachiever of the group ๐
โญ A Simple Example โญ
same energy as the synopsis but as a full script this time, with the shebang and everything:
#!/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 ๐ง
- To create a new, empty image, send a
new()message toGD::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. so she can be born blank or born from a file, both valid. - 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. like, write them down bestie, you'll need them ๐ - 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. okay so it's giving arts and crafts hour and we're obsessed โจ
- Polygons are created with a
new()message toGD::Polygon. You can add points to the returned polygon one at a time using theaddPt()method. The polygon can then be passed to an image for rendering. assemble the squad point by point, then let the image render them ๐ฅ - 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 callbinmode()on the file you are writing the image to. this one matters, do not skip thebinmode()โ platforms that care about the text/binary distinction will absolutely ruin your day otherwise ๐
๐ Object Constructors: Creating Images ๐
See GD::Image for the current list of supported Image formats.
Okay bestie, the following class methods are literally your factory line for new GD::Image objects. ๐
$image = GD::Image->new([$width,$height],[$truecolor]) + friends
$image = GD::Image->new([$width,$height],[$truecolor])
$image = GD::Image->new(*FILEHANDLE)
$image = GD::Image->new($filename)
$image = GD::Image->new($data)
The new() method is the main constructor for the GD::Image class, no cap. 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. Cute, tiny, default.
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, only by filename.
If something goes wrong (e.g. insufficient memory), this call will return undef. Sad but true. ๐ญ
$image = GD::Image->trueColor([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);
$image = GD::Image->newPalette([$width,$height])
$image = GD::Image->newTrueColor([$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(). Iconic override energy. โจ
$image = GD::Image->newFromPng($file, [$truecolor])
$image = GD::Image->newFromPngData($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 binmode(FILEHANDLE) for you, on platforms where this matters. Teamwork, lowkey.
You may use any of the following as the argument:
- a simple filehandle, such as
STDIN - a filehandle glob, such as
*PNG - a reference to a glob, such as
\*PNG - an
IO::Handleobject - 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 data contained in $data.
$image = GD::Image->newFromJpeg($file, [$truecolor])
$image = GD::Image->newFromJpegData($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. So yes, same vibe, different file type. ๐ฆ
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.
$image = GD::Image->newFromGif($file, [$truecolor])
$image = GD::Image->newFromGifData($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. No shortcuts there, bestie.
$image = GD::Image->newFromXbm($file, [$truecolor])
This works in exactly the same way as "newFromPng", 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.
$image = GD::Image->newFromWBMP($file)
This works in exactly the same way as "newFromPng", 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.
$image = GD::Image->newFromBmp($file)
This works in exactly the same way as "newFromPng", 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.
$image = GD::Image->newFromGd($file)
$image = GD::Image->newFromGdData($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 BIG. Not cute, but factual.
$myImage = GD::Image->newFromGd("godzilla.gd") || die;
close GDF;
$image = GD::Image->newFromGd2($file)
$image = GD::Image->newFromGd2Data($data)
โ ๏ธ NOTE: GD and GD2 support was dropped witn libgd 2.3.2.
This works in exactly the same way as newFromGd() and newFromGdData, but use the new compressed GD2 image format.
$image = GD::Image->newFromGd2Part($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). Slice it, bestie. ๐
$image = GD::Image->newFromXpm($filename)
This creates a new GD::Image object starting from a filename. 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. We don't make the rules, we just document them. ๐
$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.
$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 >= 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.
๐ 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. Main character lifecycle, honestly. ๐
โจ Image Data Output Methods โจ
The following methods convert the internal drawing format into standard output file formats.
$pngdata = $image->png([$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 binmode(). This is crucial for portability to DOSish platforms. Do not skip it, fr fr. ๐ซถ
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). Different scale, different vibe โ iykyk. ๐
$gifdata = $image->gifanimbegin([$GlobalCM [, $Loops]])โ okay bestie, for libgd version 2.0.33 and higher, this call begins an animated GIF by returning the data that makes up the animated gif image file header. After you call this method, callgifanimadd()one or more times to add the frames of the image. Then callgifanimend(). Every single frame has to be the same width and height, no exceptions, periodt.
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. Lowkey a vibe if you ask me ๐
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 โ infinite slay ๐โจ
$gifdata = $image->gifanimadd([$LocalCM [, $LeftOfs [, $TopOfs [, $Delay [, $Disposal [, $previm]]]]]])โ returns the data that makes up one animated gif image frame. You can then print it, pipe it to a display program, or write it to a file. With$LeftOfsand$TopOfsyou 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 default1. 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 to1, also for the first frame.$LeftOfsand$TopOfsparameters are ignored for optimized frames. (Yeah, they just get ghosted ๐ซฅ)$gifdata = $image->gifanimend()โ 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. She's independent, she don't need the image ๐$jpegdata = $image->jpeg([$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 tojpeg()in order to control the JPEG quality. This should be an integer between0and100. Higher quality scores give larger files and better image quality. If you don't specify the quality,jpeg()will choose a good default. Trust her, she knows ๐$gifdata = $image->gif().โ 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.$gddata = $image->gdโ 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;
$gd2data = $image->gd2โ same asgd(), except that it returns the data in compressed GD2 format. Glow-up edition โจ$bmpdata = $image->bmp([$compression])โ this returns the image data in BMP format, which is a Windows Bitmap. If compression is set to1, it will use RLE compression on the pixel data; otherwise, setting it to0(the default) will leave the BMP pixel data uncompressed.$wbmpdata = $image->wbmp([$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. Very minimal, very demure ๐ค๐ค$tiffdata = $image->tiff()โ this returns the image data in TIFF format.$webpdata = $image->webp([$quality])โ this returns the image data in WEBP format, with the optional quality argument. The default is80, also chosen by the value-1. A quality value of>= 101is considered Lossless. No cap, lossless is the dream ๐$webpdata = $image->heif([$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 is80, also chosen by the value-1. A quality value of200is considered Lossless.
Heads up bestie โ that $webpdata variable name on the HEIF one is exactly what the page says. Not a typo on my end, fr fr ๐
$webpdata = $image->avif([$quality,$speed])โ this returns the truecolor image data in AVIF format, with the AVif encoder and444chroma, and the optional quality argument. If truecolor is not set, this fails. The default compression quality1-100is-1, the default speed0-10is6.$success = $image->_file($filename)โ writes an image to a file in the format indicated by the filename, with libgd versions>= gd-2.1.1.
File type is determined by the extension of the file name. See "supportsFiletype" for an overview of the parsing.
For file types that require extra arguments, "_file" attempts to use sane defaults:
C<gdImageGd2> chunk size = 0, compression is enabled.
C<gdImageJpeg> quality = -1 (i.e. the reasonable default)
C<gdImageWBMP> foreground is the darkest available color
C<gdImageWEBP> quality default
C<gdImageHEIF> quality default, codes = HEVC, chroma = 444
C<gdImageAVIF> quality default, speed = 6
Everything else is called with the two-argument function and so will use the default values.
"_file" and the underlying libgd "gdImageFile" 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. ๐ซ Like... she tries her best but she can't promise everything, y'know? Do not trust the TRUE. Read that again. DO NOT TRUST THE TRUE.
๐จ Color Control ๐จ
These methods allow you to control and manipulate the GD::Image color table for palette, non-truecolor images. (Truecolor girlies, this section is not for you, sorry bestie ๐
)
$index = $image->colorAllocate(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);
Peachpuff is iconic, she said it herself ๐๐
$index = $image->colorAllocateAlpha(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 from0(opaque) to127(transparent). The"alphaBlending"function changes the way this alpha channel affects the resulting image.
Yes, the original really does sayregnotredin that signature. Copying it exactly, bestie, don't come for me ๐
$image->colorDeallocate(colorIndex)โ this marks the color at the specified index as being ripe for reallocation. The next timecolorAllocateis 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);
Out with the old, in with the peachy ๐โจ
$index = $image->colorClosest(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);
$index = $image->colorClosestAlpha(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);
$index = $image->colorClosestHWB(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. She's literally matching vibes, not just numbers, and honestly? Queen behavior ๐
If no colors have yet been allocated, then this call returns -1.
Example:
$mostred = $myImage->colorClosestHWB(255,0,0);
$index = $image->colorExact(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;
$index = $image->colorExactAlpha(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;
$index = $image->colorResolve(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. She's flexible like that ๐โโ๏ธ
$rosey = $myImage->colorResolve(255,100,80);
warn "Everything's coming up roses.\n" if $rosey >= 0;
$index = $image->colorResolveAlpha(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;
$colorsTotal = $image->colorsTotal object methodโ 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. (TrueColor girlies stay losing ๐ญ it's giving "no thoughts, head empty")
$index = $image->getPixel(x,y) โ object method ๐ this one hands you back the color table index sitting underneath the point you picked. Stack it with rgb() and boom, you've got the actual rgb color hiding under that pixel.
Example:
$index = $myImage->getPixel(20,100);
($r,$g,$b) = $myImage->rgb($index);
($red,$green,$blue) = $image->rgb($index) โ gives you a list with the red, green and blue components of whatever color index you toss at it ๐
Example:
@RGB = $myImage->rgb($peachy);
($alpha) = $image->alpha($index) โ returns an item holding the alpha component of the color index you name โจ
Example:
@RGB = $myImage->rgb($peachy);
$image->transparent($colorIndex) โ flags the color at that index as transparent, so any part of the image drawn in that color justโฆ isn't there ๐ป invisible. Iconic for making paintbrushes of weird shapes, and for making PNG backgrounds see-through so they play nice on the Web. Only one color can be transparent at a time, no cap. Want transparency gone? Pass -1 for the index.
Call this method with no parameters and it'll return the current index of the transparent color, or -1 if there isn't one ๐ซถ
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;
๐ซ Special Colors ๐ซ
GD ships a whole lil' cast of special colors for pulling off special effects ๐ They're constants defined in the GD:: namespace, but they get automatically exported into your namespace when the GD module is loaded. So convenient, honestly.
$image->setBrush($image) โ lets you draw lines and shapes using a brush pattern ๐๏ธ Brushes are just palette images โ not TrueColor โ that you can create and manipulate the usual way. When you draw with one, its contents become the color and shape of your lines.
To make a brushed line you gotta create or load the brush first, then assign it to the image with setBrush(). Then you draw using the gdBrushed special color. Pro tip that's genuinely useful: set the background of the brush to transparent so the non-colored parts don't stomp all over the rest 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);
$image->setThickness($thickness) โ lines drawn with line(), rectangle(), arc(), and so forth come out 1 pixel thick by default ๐ call setThickness() to change the line drawing width. Chowky.
$image->setStyle(@colors) โ styled lines are an arbitrary series of repeated colors, and they're the moment for dotted and dashed lines โจ To create one, use setStyle() to specify a repeating series of colors. It takes an array made of one or more color indexes. Then draw using the gdStyled special color. There's another special color, gdTransparent, that punches actual holes in the line โ the example shows it off:
# 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 "gdStyled" and "gdBrushed" behaviors, you specify "gdStyledBrushed" ๐ In that case, a pixel from the current brush pattern gets rendered wherever the color specified in setStyle() is neither gdTransparent nor 0.
gdTiled โ draws filled shapes and flood fills using a pattern ๐ the pattern is just another image. It gets tiled multiple times to fill the space you need, giving you full-on wallpaper effects. You must call "setTile" to define the particular tile pattern you'll use for drawing when you specify the gdTiled color. details.
gdStyled โ the gdStyled color is what you use for creating dashed and dotted lines ๐ a styled line can contain any series of colors and is created using the setStyled() command.
gdAntiAliased โ the "gdAntiAliased" color draws lines with antialiasing turned on โจ antialiasing blends the jagged edges of lines with the background for a smoother look. The actual color drawn is set with setAntiAliased().
$image->setAntiAliased($color) โ "Antialiasing" is a process where the jagged edges that come with line drawing get reduced by blending the foreground color with an appropriate percentage of the background, depending on how much of the pixel in question is actually inside the boundaries of the line being drawn ๐ฆ Every line-drawing method โ line(), polygon, all of them โ will draw antialiased lines if you use the special "color" gdAntiAliased when calling them.
setAntiAliased() is what specifies the actual foreground color used when drawing antialiased lines. You can set any color as 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. But attempts to draw antialiased lines on highly complex palette-based backgrounds may not give satisfactory results, thanks 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. And when you're using palette-based images, be sure to allocate a broad spectrum of colors so antialiasing has enough colors to work with.
$image->setAntiAliasedDontBlend($color,[$flag]) โ normally, when drawing lines with the special gdAntiAliased "color," blending with the background to reduce jagged edges is exactly the behavior you want. But when you want lines to not blend with one particular color when it shows up in the background, setAntiAliasedDontBlend() is the method that tells it which special color the foreground should stand out more clearly against ๐
Once it's turned on, you turn the feature off by calling setAntiAliasedDontBlend() with a second argument of 0:
$image->setAntiAliasedDontBlend($color,0);
๐๏ธ Drawing Commands ๐๏ธ
These methods let you draw lines, rectangles, and ellipses, plus pull off various special operations like flood-fill ๐ฅ main character energy, honestly.
$image->setPixel($x,$y,$color) โ sets the pixel at (x,y) to the specified color index. Nothing gets returned from this method, it just does the thing. 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.
Example:
# This assumes $peach already allocated
$myImage->setPixel(50,50,$peach);
$image->line($x1,$y1,$x2,$y2,$color) โ draws a line from (x1,y1) to (x2,y2) in the specified color โ๏ธ real color works, 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);
$image->dashedLine($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 draw with the special color gdStyled.
Example:
$myImage->dashedLine(0,0,150,150,$blue);
$image->rectangle($x1,$y1,$x2,$y2,$color) โ draws a rectangle in 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);
$image->filledRectangle($x1,$y1,$x2,$y2,$color) / $image->setTile($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);
$image->openPolygon($polygon,$color) โ draws a polygon in the specified color ๐บ the polygon has to be created first (see below). It must have at least three vertices. If the last vertex doesn't close the polygon, the method closes it for you, so sweet of it. 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);
$image->unclosedPolygon($polygon,$color) โ draws a sequence of connected lines in the specified color, without connecting the first and last point into a closed polygon ๐ฆ the polygon must be created first (see below). It 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, just so you know ๐
Example:
$poly = GD::Polygon->new;
$poly->addPt(50,0);
$poly->addPt(99,99);
$poly->addPt(0,99);
$myImage->unclosedPolygon($poly,$blue);
$image->filledPolygon($poly,$color)โ fills that whole polygon with a color, no outline vibes. Bestie you can pass a real color OR the special fill colorgdTiledand the polygon gets filled with a pattern instead. Obsessed honestly.
Example, because we love a demo:
# 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);
$image->ellipse($cx,$cy,$width,$height,$color)$image->filledEllipse($cx,$cy,$width,$height,$color)โ these two draw ellipses, periodt.($cx,$cy)is the center of the arc, and($width,$height)set the ellipse width and height respectively (yes, in that order, don't come for me).filledEllipse()is literallyEllipse()'s louder sister โ the former makes filled versions of the ellipse. ๐$image->arc($cx,$cy,$width,$height,$start,$end,$color)โ draws arcs and ellipses.(cx,cy)= the center of the arc,(width,height)= width and height respectively. Which chunk of the ellipse you actually get is controlled bystartandend, and both are given in degrees from 0 to 360. Zero sits at the right end of the ellipse and the angles increase clockwise. Want the whole ellipse? Use0and360as your starting and ending angles. Want a circle? Use the same value for width and height. ๐
You can hand it a normal color or one of the special colors gdBrushed, gdStyled, or gdStyledBrushed.
Example โ a semicircle, centered at 100,100:
# draw a semicircle centered at 100,100
$myImage->arc(100,100,50,50,0,180,$blue);
$image->filledArc($cx,$cy,$width,$height,$start,$end,$color [,$arc_style])โ same energy asarc()except it colors in the pie wedge with whatever color you picked.$arc_styleis optional. If you do pass it, it's a bitwise OR of these constants:gdArcโ connect start & end points of arc with a rounded edgegdChordโ connect start & end points of arc with a straight linegdPieโ synonym forgdChordgdNoFillโ outline the arc or chordgdEdgedโ connect beginning and ending of the arc to the center
So here's the tea: gdArc and gdChord are mutually exclusive โ pick one, not both. gdChord just connects the starting and ending angles with a straight line, while gdArc produces a rounded edge. gdPie is a synonym for gdArc ๐คจ (yes the list above says gdChord and the paragraph says gdArc โ the docs literally say both, iykyk ๐). gdNoFill means the arc or chord should be outlined, not filled. gdEdged, used together with gdNoFill, means the beginning and ending angles get connected to the center โ which is a genuinely good way to outline (rather than fill) a "pie slice." ๐ฅง
Example:
$image->filledArc(100,100,50,50,0,90,$blue,gdEdged|gdNoFill);
$image->fill($x,$y,$color)โ the flood-fill. It spreads the color through the image starting at point(x,y)until it gets stopped by a pixel that's a different color from the starting pixel. It's giving paintbucket in every drawing app you've ever used, no cap. ๐ชฃ You can specify a normal color, or the special colorgdTiledto flood-fill with patterns.
Example โ draw a rectangle then make its insides blue:
# Draw a rectangle, and then make its interior blue
$myImage->rectangle(10,10,100,100,$black);
$myImage->fill(50,50,$blue);
$image->fillToBorder($x,$y,$bordercolor,$color)โ likefill, it flood-fills regions with the specified color starting at position(x,y). BUT ๐ instead of stopping when it hits a pixel of a different color than the starting pixel, the flooding only stops when it hits the color specified bybordercolor. You must specify a normal indexed color for thebordercolor. The fill color though? Free to begdTiled, go off.
Example โ same effect as the previous one, just a different route:
# This has the same effect as the previous example
$myImage->rectangle(10,10,100,100,$black);
$myImage->fillToBorder(50,50,$black,$blue);
๐จ IMAGE COPYING COMMANDS ๐ซ
Two methods are provided for copying a rectangular region from one image to another. One copies a region without resizing it. The other lets you stretch the region mid-copy, main character behavior.
With either of these methods it is important to know that the routines will attempt to flesh out the destination image's color table so it matches the colors 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 ๐ญ. (Read: it might look a little cursed. You've been warned.)
$image->copy($sourceImage,$dstX,$dstY,$srcX,$srcY,$width,$height)โ the simplest of the several copy operations: it copies the specified region from the source image to the destination image (the one performing the method call, obvs).(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 as both source and destination โ but the source and destination regions must not overlap, or strange things will happen. ๐ซ Not "fun strange." Just don't.
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);
$image->clone()โ makes a copy of the image and returns it as a new object. The new image looks identical. However, it may differ in the size of the color palette and other nonessential details. Twins, not clones clones. ๐ฏ
Example:
$myImage = GD::Image->new(100,100);
... various drawing stuff ...
$copy = $myImage->clone;
$image->copyMerge($sourceImage,$dstX,$dstY,$srcX,$srcY,$width,$height,$percent)โ copies the indicated rectangle from the source image to the destination image, merging the colors to the extent specified bypercent(an integer between0and100). Specifying100% has the same effect ascopy()โ 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);
$image->copyMergeGray($sourceImage,$dstX,$dstY,$srcX,$srcY,$width,$height,$percent)โ identical tocopyMerge()except that it preserves the hue of the source by converting all the pixels of the destination rectangle to grayscale before merging. Moody aesthetic unlocked. ๐ค$image->copyResized($sourceImage,$dstX,$dstY,$srcX,$srcY,$destW,$destH,$srcW,$srcH)โ similar tocopy()but it lets you choose different sizes for the source and destination rectangles. The source and destination rectangles 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);
$image->copyResampled($sourceImage,$dstX,$dstY,$srcX,$srcY,$destW,$destH,$srcW,$srcH)โ similar tocopyResized()but it gives you "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. That's the good shit. This method is identical tocopyResized()when the destination image is a palette image, fyi.$image->copyRotated($sourceImage,$dstX,$dstY,$srcX,$srcY,$width,$height,$angle)โ likecopyResized()but the$angleargument specifies an arbitrary amount to rotate the image counter clockwise (in degrees). Plus,$dstXand$dstYspecify the center of the destination image, not the top left corner. Yes, different origin than the others โ don't get caught slipping. ๐$image->trueColorToPalette([$dither], [$colors])โ 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.$image = $sourceImage->createPaletteFromTrueColor([$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. Like, genuinely. Just don't.
$error = $image->colorMatch($otherimage)โ brings the palette colors in$otherimagecloser to truecolor$image. A negative return value is a failure. Here's the lil error menu:-1image must be True Color-2otherimage must be indexed-3the images are meant to be the same dimensions-4At least 1 color in otherimage must be allocated
This method is only available with libgd >= 2.1.0 โ check your version bestie, don't be out here calling methods that ghost you. ๐ป
$image = $sourceImage->neuQuant($maxcolor=256,$samplefactor=5)โ creates a new palette image from a truecolor image.samplefactorโ The quantization precision between1(highest quality) and10(fastest).maxcolorโ The number of desired palette entries.
This one's basically createPaletteFromTrueColor but locked into the GD_QUANT_NEUQUANT quantization method. Heads up bestie: no dithering here, she doesn't support it ๐
โโ๏ธ. And plot twist โ this method is only available with libgd >= 2.1.0.
๐ Image Transformation Commands
Gd gives you these simple, non-interpolated transformations. Basics but make it iconic.
$image = $sourceImage->copyRotate90()
$image = $sourceImage->copyRotate180()
$image = $sourceImage->copyRotate270()
$image = $sourceImage->copyFlipHorizontal()
$image = $sourceImage->copyFlipVertical()
$image = $sourceImage->copyTranspose()
$image = $sourceImage->copyReverseTranspose()
These rotate, flip, or transpose an image, and the result is a copy of the image. Original stays unbothered, main character energy ๐ .
$image->rotate180()
$image->flipHorizontal()
$image->flipVertical()
Same vibe as the copy* versions, except these modify the image in place. No copy, just ~transformation~ โจ.
๐ฆ Image Interpolation Methods
Since libgd 2.1.0 we got better transformation methods, and they come with these interpolation options:
GD_BELLโ BellGD_BESSELโ BesselGD_BILINEAR_FIXEDโ fixed point bilinearGD_BICUBICโ BicubicGD_BICUBIC_FIXEDโ fixed point bicubic integerGD_BLACKMANโ BlackmanGD_BOXโ BoxGD_BSPLINEโ BSplineGD_CATMULLROMโ CatmullromGD_GAUSSIANโ GaussianGD_GENERALIZED_CUBICโ Generalized cubicGD_HERMITEโ HermiteGD_HAMMINGโ HammingGD_HANNINGโ HannigGD_MITCHELLโ MitchellGD_NEAREST_NEIGHBOURโ Nearest neighbour interpolationGD_POWERโ PowerGD_QUADRATICโ QuadraticGD_SINCโ SincGD_TRIANGLEโ TriangleGD_WEIGHTED4โ 4 pixels weighted bilinear interpolationGD_LINEARโ bilinear interpolation
$image->interpolationMethod( [$method] )
Gets or sets the interpolation method for all subsequent interpolations. Valid values are the list right above ๐. Only available since libgd 2.2.0.
$image->copyScaleInterpolated( width, height )
Returns a copy, using interpolation ๐ซ.
$image->copyRotateInterpolated( angle, bgcolor )
Returns a copy, using interpolation. Rotation + glow-up, love that for you ๐.
๐ธ Image Filter Commands
Gd also has some common image filters. These 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 simply undefined (so like, don't call them, she won't exist ๐ญ).
$ok = $image->scatter($sub, $plus)
If $sub and $plus are 0, nothing changes and TRUE is returned. If $sub >= $plus, nothing changes and FALSE is returned. Otherwise, random pixels get changed. Chaos, but controlled โจ.
$ok = $image->scatterColor($sub, $plus, @colors)
Like scatter, but using the given array of colors โ i.e., palette indices.
$ok = $image->pixelate($blocksize, $mode)
If $blocksize <= 0, nothing changes and FALSE is returned. If $blocksize == 1, nothing changes and TRUE is returned. Otherwise the following modes are observed:
GD_PIXELATE_UPPERLEFT
GD_PIXELATE_AVERAGE
$ok = $image->negate()
$ok = $image->grayscale()
$ok = $image->brightness($add)
$add: -255..255. Serving range, periodt ๐
.
$ok = $image->contrast($contrast)
$contrast: a double value โ the contrast adjustment value. Negative values increase contrast, positive values decrease it. The larger the absolute value, the stronger the effect. Note the flip, bestie โ negative is not "less" here, it's literally the opposite direction ๐.
$ok = $image->color($red,$green,$blue,$alpha)
Changes 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.
$ok = $image->selectiveBlur()
$ok = $image->edgeDetectQuick()
$ok = $image->gaussianBlur()
$ok = $image->emboss()
$ok = $image->meanRemoval()
$ok = $image->smooth($weight)
$image = $sourceImage->copyGaussianBlurred($radius, $sigma)
$radius: int, the blur radius (not diameter โ range is2*radius + 1). A radius, not a diameter, so a radius of2(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). Math check ๐งฎโจ$sigma: the sigma value, or a value<= 0.0to use the computed default. Represents the "fatness" of the curve (lower == fatter).
The result is always truecolor. No palette era for this one ๐ .
๐ Character and String Drawing
GD lets you 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 gdGiantFont, gdLargeFont, gdMediumBoldFont, gdSmallFont and gdTinyFont.
On top of that, 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 (check 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 lying around.
For writing proportional scalable fonts, GD offers the stringFT() method, which lets you load and render any TrueType font on your system. Obsessed honestly ๐ซถ.
$image->string($font,$x,$y,$string,$color)
Draws a string starting at position (x,y) in the specified font and color. Font choices are gdSmallFont, gdMediumBoldFont, gdTinyFont, gdLargeFont and gdGiantFont.
Example:
$myImage->string(gdSmallFont,2,10,"Peachy Keen",$peach);
$image->stringUp($font,$x,$y,$string,$color)
Just like the previous call, but draws the text rotated counterclockwise 90 degrees. Sideways era ๐.
$image->char($font,$x,$y,$char,$color)
$image->charUp($font,$x,$y,$char,$color)
These draw single characters at position (x,y) in the specified font and color. They're carry-overs from the C interface, where there's a distinction between characters and strings. Perl is insensible to such subtle distinctions โ she literally does not care ๐.
$font = GD::Font->load($fontfilepath)
Dynamically loads a font file, returning a font 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 โ๏ธ.
@bounds =
$image->stringFT($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string)
@bounds =
GD::Image->stringFT($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string)
@bounds =
$image->stringFT($fgcolor,$fontname,$ptsize,$angle,$x,$y,$string,\%options)
This one uses TrueType to draw a scaled, antialiased string using the TrueType vector font of your choice. It requires that libgd was compiled with TrueType support, and that the appropriate TrueType font is installed on your system. Two prerequisites, no shortcuts ๐ฅ.
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. So always check$@, bestie ๐ญ.
The fontname argument is the name of the font, which can be a full pathname to a .ttf file, or if not, the paths in $ENV{GDFONTPATH} will be searched โ or if that's 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 โ big brain move ๐ง โจ.
Using a negative color index will disable antialiasing, as described in the libgd manual page at <https://libgd.github.io/manuals/2.0.35/#gdImageStringFT>.
An optional 8th argument lets you pass a hashref of options to stringFT(). Several hashkeys are recognized: linespacing, charmap, resolution, and kerning.
The value of linespacing 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". Careful, the line spacing is lying to you ๐.
The value of charmap is one of "Unicode", "Shift_JIS" and "Big5". The interaction between Perl, Unicode and libgd is not clear to the author, and you should experiment a bit if you want to use this feature. Vibes-based feature, honestly ๐งช.
The value of resolution 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 kerning 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',
});
okay so 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 fontconfig 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. ๐ซ
$hasfontconfig = $image->useFontConfig($flag)โ calluseFontConfig()with a value of1in order to enable support for fontconfig font patterns (seestringFT). 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 ofGD::Image;$result = $image->stringFTCircle($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. โจ
๐ 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. ๐ฅ
$image->alphaBlending($integer)โ thealphaBlending()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"setPixel", 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. ๐
$image->saveAlpha($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, callsaveAlpha(1)to turn on saving of such information, and callalphaBlending(0)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. ๐ธ
๐ Miscellaneous Image Methods ๐
These are various utility methods that are useful in some circumstances. ๐ฆ
$image->interlaced([$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. Provideundefto disable it. Call the method without parameters to find out the current setting. ๐($width,$height) = $image->getBounds()โ 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. ๐$width = $image->widthand$height = $image->heightโ return the width and height of the image, respectively. ๐$is_truecolor = $image->isTrueColor()โ this method will return a Boolean representing whether the image is true color or not. ๐จ$flag = $image1->compare($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!";
}
$image->clip($x1,$y1,$x2,$y2)and($x1,$y1,$x2,$y2) = $image->clipโ 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 callingclip()with the coordinates of the new clipping rectangle. Callingclip()without any arguments will return the current clipping rectangle. โ๏ธ$flag = $image->boundsSafe($x,$y)โ theboundsSafe()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. ๐
๐ซถ 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:
$image->startGroup([$id,\%style])$image->endGroup()$group = $image->newGroup
See GD::SVG for information. ๐ซ
โจ Polygons โจ
okay so there are a few primitive polygon creation and manipulation methods here, and the tea is: they aren't part of the Gd library, but the author thought they might be handy to have around (they're borrowed from the qd.pl Quickdraw library). Also see GD::Polyline. ๐ฆ
$poly = GD::Polygon->new
Create an empty polygon with no vertices. A blank canvas, literally. ๐
$poly = GD::Polygon->new;
$poly->addPt($x,$y)
Add point (x,y) to the polygon. Drop that vertex in, bestie. ๐
$poly->addPt(0,0);
$poly->addPt(0,50);
$poly->addPt(25,25);
$myImage->fillPoly($poly,$blue);
($x,$y) = $poly->getPt($index)
Retrieve the point at the specified vertex. Gimme the coordinates, please. โจ
($x,$y) = $poly->getPt(2);
$poly->setPt($index,$x,$y)
Change the value of an already existing vertex. It is an error to set a vertex that isn't already defined โ so don't try to be cute with a vertex that doesn't exist, bestie. ๐
$poly->setPt(2,100,100);
($x,$y) = $poly->deletePt($index)
Delete the specified vertex, returning its value. Bye-bye, point! ๐
($x,$y) = $poly->deletePt(1);
$poly->clear()
Delete all vertices, restoring the polygon to its initial empty state. Clean slate energy. ๐งผ
$poly->toPt($dx,$dy)
Draw from the 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);
$vertex_count = $poly->length
Return the number of vertices in the polygon. Count 'em up. ๐ข
$points = $poly->length;
@vertices = $poly->vertices
Return a list of all the vertices in the polygon object. Each member of the list is a reference to an (x,y) array. Yes, the closing brace is right there in the example โ we keep it exactly. ๐
@vertices = $poly->vertices;
foreach $v (@vertices)
print join(",",@$v),"\n";
}
@rect = $poly->bounds
Return the smallest rectangle that completely encloses the polygon. The return value is an array containing the (left,top,right,bottom) of the rectangle. It's giving bounding-box realness. ๐ฆ
($left,$top,$right,$bottom) = $poly->bounds;
$poly->offset($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. Slay that position shift. ๐ซ
$poly->offset(10,30);
$poly->rotate($rad)
Rotate all the vertices of the polygon by the specified clockwise radian angle. Spin it, bestie. ๐
use Math::Trig;
$poly->rotate(deg2rad(180));
$poly->map($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. Iconic remix behavior. ๐ฅ
# Make the polygon really tall
$poly->map($poly->bounds,0,0,50,200);
$poly->scale($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.
Undefined $sy defaults to $sx, ie. scale(2.0) scales the polyon by 2. Yes, polyon โ we keep the typo, no cap. ๐ญ
$poly->transform($sx,$sy, $rx,$ry, $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. Math girl summer. ๐โจ
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;
Thus offset by ($tx,$ty) is "transform(1,1,0,0,$tx,$ty)", scale by ($sx,$sy) is "transform($sx,$sy,0,0,0,0)", and rotation by clockwise radians ($r) is
($s,$c) = (sin($r),cos($r));
$poly->transform($c,$s,-$s,$c,0,0);
๐ GD::Polyline ๐
Please see GD::Polyline for information on creating open polygons and splines. Go check the sibling page, bestie. ๐ซถ
๐ค 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. Font glow-up potential: unlocked. โจ
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. gdSmallFont) and as a package method (e.g. GD::Font->Small). So cute, two ways to summon the same font. ๐
gdSmallFont / GD::Font->Small
This is the basic small font, "borrowed" from a well known public domain 6x12 font. Tiny but classic. ๐
gdLargeFont / GD::Font->Large
This is the basic large font, "borrowed" from a well known public domain 8x16 font. Big-font energy. ๐
gdMediumBoldFont / GD::Font->MediumBold
This is a bold font intermediate in size between the small and large fonts, borrowed from a public domain 7x13 font; yes, that semicolon is staying. ๐
gdTinyFont / GD::Font->Tiny
This is a tiny, almost unreadable font, 5x8 pixels wide. Microscopic legend behavior. ๐ฌ
gdGiantFont / GD::Font->Giant
This is a 9x15 bold font converted by Jan Pazdziora from a sans serif X11 font. Giant and iconic. ๐
$font->nchars
This returns the number of characters in the font. Count those glyphs, bestie. ๐ข
print "The large font contains ",gdLargeFont->nchars," characters\n";
$font->offset
This returns the ASCII value of the first character in the font. Little ASCII fact drop. โญ
$width = $font->width / $height = $font->height / "height"
These return the width and height of the font. Yes, "height" is literally hanging out there too โ we keep it. ๐
($w,$h) = (gdLargeFont->width,gdLargeFont->height);
๐งฐ Helper Functions ๐งฐ
GD::LIBGD_VERSIONโ Returns a number of the libgd VERSION, like2.0204,2.0033or2.01. ๐GD::VERSION_STRINGโ Returns the string of the libgd VERSION, like"2.2.4". โจGD::constantโ this one is literally just listed, bestie; the original gives no description, so I'm not inventing one. ๐ซถ
๐ 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. ๐
๐ 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. Then it literally says package for details. โ yes, that is the text, bestie. ๐ญ
The latest versions of GD.pm are available at
https://github.com/lstein/Perl-GD
๐ SEE ALSO ๐
GD::PolylineGD::SVGGD::SimpleImage::Magick
That's the whole page, bestie! This masterpiece comes from perl v5.42.0, dated 2024-06-23, and it's GD(3) โ iconic, mwah ๐โจ
๐ฆ where this page comes from
- opensuse-leap 16.0: perl-GD 2.830.0-160000.1.1 ยท Artistic-1.0 OR GPL-1.0-or-later
- opensuse-leap 16.0: perl-GD 2.830.0-160000.1.1 ยท Artistic-1.0 OR GPL-1.0-or-later
- opensuse-leap 16.0: perl-GD 2.830.0-160000.1.1 ยท Artistic-1.0 OR GPL-1.0-or-later
- opensuse-leap 16.0: perl-GD 2.830.0-160000.1.1 ยท Artistic-1.0 OR GPL-1.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms