Rexx/gd is a Rexx extension allowing you to quickly draw images complete with lines, arcs, text, multiple colors, cut and paste from other images, and flood fills, and write out the result as a PNG, BMP, JPEG or GIF file. This is particularly useful in World Wide Web applications, where these image formats are the most common formats accepted for inline images by most browsers. Rexx/gd now also creates animated GIF files.
Rexx/gd is not a paint program. If you are looking for a paint program, you are looking in the wrong place. If you are not a Rexx programmer, you are looking in the wrong place.
Rexx/gd does not provide for every possible desirable graphics operation. Rexx/gd is based on the freely available gd library. Currently Rexx/gd supports the majority of the functionality of gd 2.0.33.
What else do I need to use Rexx/gd?
Well, you obviously need a Rexx interpreter! Rexx/gd will work with any Rexx interpreter that supports the SAA API.
Rexx/gd is dependent on the requirements of the underlying gd library. As such Rexx/gd requires the following:
If you want to see the images you have created, then you will need a PNG and/or JPEG viewer. Most browsers will be able to view these files.
While this all looks daunting, the installer for the Win32 port of Rexx/gd contains the gd library DLL (which contains all of the above packages), so you don't need anything else, other than Rexx/gd. The OS/2 port requires only the gd library package (which at the time of writing was available at: OS/2 gd library 2-0.15. Note that any GIF support in the OS/2 package is NOT supported in Rexx/gd.
On Unix platforms there are packages, deb and rpm available for most popular distributions.
However if you want to build from source things are not as simple :-( You will need
to install (possibly build) the above packages. Once you have done this, then
the configure script that comes with Rexx/gd should find all of the
required libraries. if not, you can always specify where you have installed
the packages. Note that you will need development versions of the
packages; ie. library files and header files!
The basic steps once you have extracted the source is:
% ./configure --with-rexx=xxxx (where xxxx is regina, oorexx, ...) % make % sudo make install
Rexx/gd basics: using Rexx/gd in your program
To use Rexx/gd in your
program, load the library with RxFuncAdd as you would for any other Rexx extensions
and call GdLoadFuncs.
Here is a short example program. (For a more advanced example, see rexxgddemo.rexx, included in the distribution. rexxgddemo.rexx is NOT the same program; it demonstrates additional features!)
/* Load the Rexx/gd library functions */ Call RxFuncAdd 'GdLoadFuncs', 'rexxgd', 'GdLoadFuncs' Call GdLoadFuncs /* Allocate the image: 64 pixels across by 64 pixels tall */ im = gdImageCreate(64, 64) /* Allocate the color black (red, green and blue all minimum). Since this is the first color in a new image, it will be the background color. */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Draw a line from the upper left to the lower right, using white color index. */ Call gdImageLine im, 0, 0, 63, 63, white /* Output the image to the disk file in PNG format. */ gdImagePng(im, 'test.png'); /* Output the same image in JPEG format, using the default JPEG quality setting. */ Call gdImageJpeg im, 'test.jpg', -1 /* Destroy the image in memory. */ Call gdImageDestroy imWhen executed, this program creates an image, allocates two colors (the first color allocated becomes the background color), draws a diagonal line (note that 0, 0 is the upper left corner), writes the image to PNG and JPEG files, and destroys the image.
The above example program should give you an idea of how the package works. Rexx/gd provides many additional functions, which are listed in the following reference chapters, complete with code snippets demonstrating each. There is also an alphabetical index.
Rexx/gd Coordinates System
Rexx/gd uses a coordinates system which has an origin (0,0) in the top-left
corner of the image, with the x axis increasing to the right, and the y axis
increasing to the bottom. No negative coordinates are supported.
im = gdImageCreate(64, 64) /* ... Use the image ... */ Call gdImageDestroy im
Truecolor images are always filled with black at creation time. There is no concept of a "background" color index.
im = gdImageCreateTrueColor(64, 64) /* ... Use the image ... */ Call gdImageDestroy im
If you already have the image file in memory, pass the variable containing the file's data to gdImageCreateFromJpegPtr, which is otherwise identical to gdImageCreateFromJpeg.
im = gdImageCreateFromJpeg("myjpeg.jpg") Say 'Image size:' gdImageGetWidth(im) 'x' gdImageGetHeight(im) Call gdImageDestroy im
If you already have the image file in memory, pass the variable containing the file's data to gdImageCreateFromPngPtr, which is otherwise identical to gdImageCreateFromPng.
If the PNG image being loaded is a truecolor image, the resulting identifier will refer to a truecolor image. If the PNG image being loaded is a palette or grayscale image, the resulting identifier will refer to a palette image. gd retains only 8 bits of resolution for each of the red, green and blue channels, and only 7 bits of resolution for the alpha channel. The former restriction affects only a handful of very rare 48-bit color and 16-bit grayscale PNG images. The second restriction affects all semitransparent PNG images, but the difference is essentially invisible to the eye. 7 bits of alpha channel resolution is, in practice, quite a lot.
im = gdImageCreateFromPng("mypng.png") Say 'Image size:' gdImageGetWidth(im) 'x' gdImageGetHeight(im) Call gdImageDestroy im
If you already have the image file in memory, pass the variable containing the file's data to gdImageCreateFromGifPtr, which is otherwise identical to gdImageCreateFromGif.
im = gdImageCreateFromGif("mygif.gif") Say 'Image size:' gdImageGetWidth(im) 'x' gdImageGetHeight(im) Call gdImageDestroy im
If you already have the image file in memory, pass the variable containing the file's data to gdImageCreateFromGdPtr, which is otherwise identical to gdImageCreateFromGd.
gdImageCreateFromGd returns an internal identifier to the new image, or "" if unable to load the image (most often because the file is corrupt or does not contain a gd format image). The image must eventually be destroyed using gdImageDestroy().
im = gdImageCreateFromGd("mygd.gd") Say 'Image size:' gdImageGetWidth(im) 'x' gdImageGetHeight(im) Call gdImageDestroy im
If you already have the image file in memory, pass the variable containing the file's data to gdImageCreateFromGd2Ptr, which is otherwise identical to gdImageCreateFromGd2.
gdImageCreateFromGd2 returns an internal idetifier to the new image, or "" if unable to load the image (most often because the file is corrupt or does not contain a gd format image). The image must eventually be destroyed using gdImageDestroy().
im = gdImageCreateFromGd2("mygd2.gd2") Say 'Image size:' gdImageGetWidth(im) 'x' gdImageGetHeight(im) Call gdImageDestroy im
If you already have the image file in memory, you may use gdImageCreateFromGd2PartPtr. Pass the variable containing the image file data.
EXAMPLE ???
If you already have the image file in memory, pass the variable containing the file's data to gdImageCreateFromWBMPPtr, which is otherwise identical to gdImageCreateFromWBMP.
im = gdImageCreateFromWBMP("mywbmp.bmp") Say 'Image size:' gdImageGetWidth(im) 'x' gdImageGetHeight(im) Call gdImageDestroy im
im = gdImageCreateFromXbm("myxbm.xbm") Say 'Image size:' gdImageGetWidth(im) 'x' gdImageGetHeight(im) Call gdImageDestroy im
im = gdImageCreateFromXpm("myxpm.xpm") Say 'Image size:' gdImageGetWidth(im) 'x' gdImageGetHeight(im) Call gdImageDestroy im
im = gdImageCreate(10, 10) /* ... Use the image ... */ /* Now destroy it */ Call gdImageDestroy im
If jpeg_quality is negative, the default IJG JPEG quality value (which should yield a good general quality / size tradeoff for most situations) is used. Otherwise, for practical purposes, quality should be a value in the range 0-95, higher quality values usually implying both higher quality and larger image sizes.
If you have set image interlacing using gdImageInterlace, this function will interpret that to mean you wish to output a progressive JPEG. Some programs (e.g., Web browsers) can display progressive JPEGs incrementally; this can be useful when browsing over a relatively slow communications link, for example. Progressive JPEGs can also be slightly smaller than sequential (non-progressive) JPEGs.
/* Create the image */ im = gdImageCreate(100, 100) /* Allocate background */ white = gdImageColorAllocate(im, 255, 255, 255) /* Allocate drawing color */ black = gdImageColorAllocate(im, 0, 0, 0) /* Draw rectangle */ gdImageRectangle(im, 0, 0, 99, 99, black) /* Write JPEG using default quality */ Call gdImageJpeg im, "rect.jpg", -1 /* Destroy image */ Call gdImageDestroy im
GIF does not support true color; GIF images can contain a maximum of 256 colors. If the image to be written is a truecolor image, such as those created with gdImageCreateTrueColor or loaded from a JPEG or a truecolor PNG image file, a palette-based temporary image will automatically be created internally using the gdImageCreatePaletteFromTrueColor function. The original image pixels are not modified. This conversion produces high quality palettes but does require some CPU time. If you are regularly converting truecolor to palette in this way, you should consider creating your image as a palette-based image in the first place.
/* Create the image */ im = gdImageCreate(100, 100) /* Allocate background */ white = gdImageColorAllocate(im, 255, 255, 255) /* Allocate drawing color */ black = gdImageColorAllocate(im, 0, 0, 0) /* Draw rectangle */ Call gdImageRectangle im, 0, 0, 99, 99, black /* Write GIF */ out = "rect.gif" Call gdImageGif im, out /* Destroy image */ Call gdImageDestroy im
The GlobalCM flag indicates if a global color map (or palette) is used in the GIF89A header. A nonzero value specifies that a global color map should be used to reduce the size of the animation. Of course, if the color maps of individual frames differ greatly, a global color map may not be a good idea. GlobalCM=1 means write global color map, GlobalCM=0 means do not, and GlobalCM=-1 means to do the default, which currently is to use a global color map.
If Loops is 0 or greater, the Netscape 2.0 extension for animation loop count is written. 0 means infinite loop count. -1 means that the extension is not added which results in no looping. -1 is the default.
previm
is
passed, the built-in GIF optimizer will always use "GDDISPOSALNONE"
regardless of the Disposal parameter.
Setting the LocalCM flag to 1 adds a local palette for this image to the animation. Otherwise the global palette is assumed and the user must make sure the palettes match. Use gdImagePaletteCopy to do that.
Automatic optimization 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. To achieve good optimization, it is usually best to use a single global color map. To allow gdImageGifAnimAdd to compress unchanged pixels via the use of a transparent color, the image must include a transparent color.
/* Create the image */ im = gdImageCreate(100, 100) /* Allocate background */ white = gdImageColorAllocate(im, 255, 255, 255) /* Allocate drawing color */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate transparent color for animation compression */ trans = gdImageColorAllocate(im, 1, 1, 1) /* Draw rectangle */ Call gdImageRectangle im, 0, 0, 10, 10, black out = "anim.gif" /* Write GIF header. Use global color map. Loop a few times */ Call gdImageGifAnimBegin im, out, 1, 3 /* Write the first frame. No local color map. Delay = 1s */ Call gdImageGifAnimAdd im, out, 0, 0, 0, 100, 1, "" /* construct the second frame */ im2 = gdImageCreate(100, 100) /* Allocate background to make it white */ Call gdImageColorAllocate im2, 255, 255, 255 /* Make sure the palette is identical */ Call gdImagePaletteCopy im2, im /* Draw something */ Call gdImageRectangle im2, 0, 0, 15, 15, black /* Allow animation compression with transparent pixels */ Call gdImageColorTransparent im2, trans /* Add the second frame */ Call gdImageGifAnimAdd im2, out, 0, 0, 0, 100, 1, im /* construct the second frame */ im3 = gdImageCreate(100, 100) /* Allocate background to make it white */ Call gdImageColorAllocate im3, 255, 255, 255 /* Make sure the palette is identical */ Call gdImagePaletteCopy im3, im /* Draw something */ Call gdImageRectangle im3, 0, 0, 15, 20, black /* Allow animation compression with transparent pixels */ Call gdImageColorTransparent im3, trans /* Add the third frame, compressing against the second one */ Call gdImageGifAnimAdd im3, out, 0, 0, 0, 100, 1, im2 /* Write the end marker */ Call gdImageGifAnimEnd out /* Destroy images */ Call gdImageDestroy im Call gdImageDestroy im2 Call gdImageDestroy im3
/* Create the image */ im = gdImageCreate(100, 100) /* Allocate background */ white = gdImageColorAllocate(im, 255, 255, 255) /* Allocate drawing color */ black = gdImageColorAllocate(im, 0, 0, 0) /* Draw rectangle */ gdImageRectangle(im, 0, 0, 99, 99, black) /* Write PNG file */ Call gdImagePng im, "rect.png" /* Destroy image */ Call gdImageDestroy im
For more information, see gdImagePng.
WBMP file support is black and white only. The color index specified by the fg argument is the "foreground," and only pixels of this color will be set in the WBMP file. All other pixels will be considered "background."
/* Create the image */ im = gdImageCreate(100, 100) /* Allocate background */ white = gdImageColorAllocate(im, 255, 255, 255) /* Allocate drawing color */ black = gdImageColorAllocate(im, 0, 0, 0) /* Draw rectangle */ gdImageRectangle(im, 0, 0, 99, 99, black) /* Write PNG file */ Call gdImageWBMP im, "rect.wbmp", black /* Destroy image */ Call gdImageDestroy im
The gd image format is intended for fast reads and writes of images your program will need frequently to build other images. It is not a compressed format, and is not intended for general use.
/* Create the image */ im = gdImageCreate(100, 100) /* Allocate background */ white = gdImageColorAllocate(im, 255, 255, 255) /* Allocate drawing color */ black = gdImageColorAllocate(im, 0, 0, 0) /* Draw rectangle */ gdImageRectangle(im, 0, 0, 99, 99, black) /* Write PNG file */ Call gdImageGd im, "rect.gd", black /* Destroy image */ Call gdImageDestroy im
The gd2 image format is intended for fast reads and writes of parts of images. It is a compressed format, and well suited to retrieving small sections of much larger images.
The file is stored as a series of compressed subimages, and the chunkSize determines the sub-image size - a value of zero causes the GD library to use the default.
It is also possible to store GD2 files in an uncompressed format, in which case the fmt should be GD2RAW. To store GD2 files in compressed format specify GD2COMPRESSED for fmt.
/* Create the image */ im = gdImageCreate(100, 100) /* Allocate background */ white = gdImageColorAllocate(im, 255, 255, 255) /* Allocate drawing color */ black = gdImageColorAllocate(im, 0, 0, 0) /* Draw rectangle */ gdImageRectangle(im, 0, 0, 99, 99, black) /* Write PNG file */ Call gdImageGd im, "rect.gd", 0, "GD2COMPRESSED" /* Destroy image */ Call gdImageDestroy im
gdImageCreatePaletteFromTrueColor returns a new image. gdImageTrueColorToPalette permanently converts the existing image. The two functions are otherwise identical.
The function converts a truecolor image to a palette-based image, using a high-quality two-pass quantization routine. If ditherFlag is set, the image will be dithered to approximate colors better, at the expense of some obvious "speckling." colorsWanted can be anything up to 256. If the original source image includes photographic information or anything that came out of a JPEG, 256 is strongly recommended. 100% transparency of a single transparent color in the original truecolor image will be preserved. There is no other support for preservation of alpha channel or transparency in the destination image.
For best results, don't use this 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. However, the version of this function included in version 2.0.12 and later does do a better job than the version included prior to 2.0.12.
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Set a pixel near the center. */ Call gdImageSetPixel im, 50, 50, white /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Draw a line from the upper left corner to the lower right corner. */ Call gdImageLine im, 0, 0, 99, 99, white /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Draw a triangle. */ x.0 = 3; x.1 = 50; x.2 = 99; x.3 = 0; y.0 = 3; y.1 = 0; y.2 = 99; y.3 = 99; Call gdImagePolygon im, 'x.', 'y.', white /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Draw a rectangle occupying the central area. */ Call gdImageRectangle im, 25, 25, 74, 74, white /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) red = gdImageColorAllocate(im, 255, 0, 0) /* Draw a triangle. */ x.0 = 3; x.1 = 50; x.2 = 99; x.3 = 0; y.0 = 3; y.1 = 0; y.2 = 99; y.3 = 99; /* Paint it in white */ Call gdImageFilledPolygon im, 'x.', 'y.', white /* Outline it in red; must be done second */ Call gdImagePolygon im, 'x.', 'y.', red /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Draw a rectangle occupying the central area. */ Call gdImageRectangle im, 25, 25, 74, 74, white /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreate(100, 50) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Inscribe an ellipse in the image. */ Call gdImageArc im, 50, 25, 98, 48, 0, 360, white /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreate(100, 50) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Inscribe a filled pie slice in the image. */ Call gdImageFilledArc im, 50, 25, 98, 48, 0, 45, white, 'GDARC' /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreate(100, 50) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Inscribe a filled ellipse in the image. */ Call gdImageFilledEllipse im, 50, 25, 98, 48, white /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
The border color cannot be a special color such as GDTILED; it must be a proper solid color. The fill color can be, however.
Note that gdImageFillToBorder is recursive. It is not the most naive implementation possible, and the implementation is expected to improve, but there will always be degenerate cases in which the stack can become very deep. This can be a problem in MSDOS and MS Windows 3.1 environments. (Of course, in a Unix or Windows 95/98/NT environment with a proper stack, this is not a problem at all.)
im = gdImageCreate(100, 50) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 25, 255) /* Allocate the color red. */ red = gdImageColorAllocate(im, 255, 0, 0) /* Inscribe an ellipse in the image. */ Call gdImageArc im, 50, 25, 98, 48, 0, 360, white /* Flood-fill the ellipse. Fill color is red, border color is white (ellipse). */ Call gdImageFillToBorder im, 50, 50, white, red /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
The fill color can be GDTILED, resulting in a tile fill using another image as the tile. However, the tile image cannot be transparent. If the image you wish to fill with has a transparent color index, call gdImageTransparent on the tile image and set the transparent color index to -1 to turn off its transparency.
Note that gdImageFill is recursive. It is not the most naive implementation possible, and the implementation is expected to improve, but there will always be degenerate cases in which the stack can become very deep. This can be a problem in MSDOS and MS Windows environments. (Of course, in a Unix or Windown 96/98/NT environment with a proper stack, this is not a problem at all.)
im = gdImageCreate(100, 50) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Allocate the color red. */ red = gdImageColorAllocate(im, 255, 0, 0) /* Inscribe an ellipse in the image. */ Call gdImageArc im, 50, 25, 98, 48, 0, 360, white /* Flood-fill the ellipse. Fill color is red, and will replace the black interior of the ellipse. */ Call gdImageFill im, 50, 50, red; /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
gdImageSetAntiAliased 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 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.
You need not take any special action when you are finished with antialised line drawing.
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) blue = gdImageColorAllocate(im, 0, 0, 255) Call gdImageSetAntiAliased im, blue /* Draw a smooth line from the upper left corner to the lower right corner. */ Call gdImageLine im, 0, 0, 99, 99, "GDANTIALIASED" /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy imSee also gdAntiAliased and gdSetAntiAliasedDontBlend.
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) blue = gdImageColorAllocate(im, 0, 0, 255) white = gdImageColorAllocate(im, 255, 255, 255) Call gdImageSetAntiAliased im, blue /* The portion of the line that crosses this white rectangle will not be blended smoothly */ Call gdImageSetAntiAliasedDontBlend im, white Call gdImageFilledRectangle im, 25, 25, 75, 75, white /* Draw a smooth line from the upper left corner to the lower right corner. */ Call gdImageLine im, 0, 0, 99, 99, "GDANTIALIASED" /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy imSee also gdAntiAliased and gdSetAntiAliased.
gdImageSetBrush is used to specify the brush to be used in a particular image. You can set any image to be the brush. If the brush image does not have the same color map as the first image, any colors missing from the first image will be allocated. If not enough colors can be allocated, the closest colors already available will be used. This allows arbitrary PNGs to be used as brush images. It also means, however, that you should not set a brush unless you will actually use it; if you set a rapid succession of different brush images, you can quickly fill your color map, and the results will not be optimal.
You need not take any special action when you are finished with a brush. As for any other image, if you will not be using the brush image for any further purpose, you should call gdImageDestroy. You must not use the color GDBRUSHED if the current brush has been destroyed; you can of course set a new brush to replace it.
im = gdImageCreate(100, 100) /* Open the brush PNG. For best results, portions of the brush that should be transparent (ie, not part of the brush shape) should have the transparent color index. */ brush = gdImageCreateFromPng("star.png") /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) Call gdImageSetBrush im, brush /* Draw a line from the upper left corner to the lower right corner using the brush. */ Call gdImageLine im, 0, 0, 99, 99, "GDBRUSHED" /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im /* Destroy the brush image */ Call gdImageDestroy brush
gdImageSetTile is used to specify the tile to be used in a particular image. You can set any image to be the tile. If the tile image does not have the same color map as the first image, any colors missing from the first image will be allocated. If not enough colors can be allocated, the closest colors already available will be used. This allows arbitrary PNGs to be used as tile images. It also means, however, that you should not set a tile unless you will actually use it; if you set a rapid succession of different tile images, you can quickly fill your color map, and the results will not be optimal.
You need not take any special action when you are finished with a tile. As for any other image, if you will not be using the tile image for any further purpose, you should call gdImageDestroy. You must not use the color GDTILED if the current tile has been destroyed; you can of course set a new tile to replace it.
im = gdImageCreate(100, 100) /* Open the tile PNG. For best results, portions of the tile that should be transparent (ie, allowing the background to shine through) should have the transparent color index. */ tile = gdImageCreateFromPng("star.png") /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) Call gdImageSetTile im, tile /* Fill an area using the tile. */ Call gdImageFilledRectangle im, 25, 25, 75, 75, "GDTILED" /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im /* Destroy the tile image */ Call gdImageDestroy tile
To use gdImageSetStyle, create an array of colors to be repeated. You can assign the special color value; GDTRANSPARENT to indicate that the existing color should be left unchanged for that particular pixel (allowing a dashed line to be attractively drawn over an existing image).
Then, to draw a line using the style, use the normal gdImageLine function with the special color value; GDSTYLED.
You can also combine styles and brushes to draw the brush image at intervals instead of in a continuous stroke. When creating a style for use with a brush, the style values are interpreted differently: zero (0) indicates pixels at which the brush should not be drawn, while one (1) indicates pixels at which the brush should be drawn. To draw a styled, brushed line, you must use the special color value; GDSTYLEDBRUSHED. For an example of this feature in use, see rexxgddemo.rexx (provided in the distribution).
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) red = gdImageColorAllocate(im, 255, 0, 0) /* Set up dotted style. Leave every other pixel alone. */ styledotted.1 = red styledotted.2 = "GDTRANSPARENT" styledotted.0 = 2 /* Set up dashed style. Three on, three off. */ styledashed.1 = red styledashed.2 = red styledashed.3 = red styledashed.4 = "GDTRANSPARENT" styledashed.5 = "GDTRANSPARENT" styledashed.6 = "GDTRANSPARENT" styledashed.0 = 6 /* Set dotted style. Note that we have to specify how many pixels are in the style! */ Call gdImageSetStyle im, "STYLEDOTTED." /* Draw a line from the upper left corner to the lower right corner. */ Call gdImageLine im, 0, 0, 99, 99, "GDSTYLED" /* Now the dashed line. */ Call gdImageSetStyle(im, "STYLEDASHED." Call gdImageLine im, 0, 99, 0, 99, "GDSTYLED" /* ... Do something with the image, such as saving it to a file ... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Set thickness. */ Call gdImageSetThickness im, 4 /* Draw a fat line from the upper left corner to the lower right corner. */ Call gdImageLine im, 0, 0, 99, 99, white /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreateTrueColor(100, 100) /* Background color */ red = gdTrueColor(255, 0, 0) Call gdImageFilledRectangle im, 0, 0, 100, 100, red /* Drawing color. Full transparency would be an alpha channel value of 127 (gd has a 7 bit alpha chnanel). 0 is opaque, 127 is transparent. So cut gdAlphaTransparent in half to get 50% blending. */ blue = gdTrueColorAlpha(0, 0, 255, gdAlphaTransparent / 2) /* Draw with blending. Result will be 50% red, 50% blue: yellow (emitted light, remember, not reflected light. What you learned in Kindergarten is wrong here). */ Call gdImageAlphaBlending im, 1 Call gdImageFilledRectangle im, 0, 0, 25, 25, blue /* Draw without blending. Result will be 50% blue, 50% the background color of the image viewer or web browser used; results in browsers that don't support semi-transparent pixels are unpredictable! */ Call gdImageAlphaBlending im, 0 Call gdImageFilledRectangle im, 75, 75, 25, 25, blue /* Write the image to disk, etc. */
If gdImageSetClip is never called, the clipping area will be the entire image.
The parameters passed to gdImageSetClip are checked against the dimensions of the image and limited to "safe" values.
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Set the clipping rectangle. */ Call gdImageSetClip im, 25, 25, 75, 75 /* Draw a line from the upper left corner to the lower right corner. Only the part within the clipping rectangle will appear. */ Call gdImageLine im, 0, 0, 99, 99, white /* ... Do something with the image, such as saving it to a file ... */ /* Destroy it */ Call gdImageDestroy imSee also gdImageGetClip.
im = gdImageCreateTrueColor(100, 100) Call gdImageSetClip im, 25, 25, 75, 75 Parse Value gdImageGetClip(im) With x1 y1 x2 y2 Say 'Boundaries:' x1 y1 x2 y2The above code would print:
25 25 75 75See also gdImageSetClip.
im = gdImageCreateFromPng("mypng.png") c = gdImageGetPixel(im, gdImageGetWidth(im) % 2, gdImageGetHeight(im) % 2) Say "The value of the center pixel is" c Say "RGB values are" gdImageColorRed(im,c)","gdImageColorGreen(im,c)","gdImageColorBlue(im,c) Call gdImageDestroy im
If gdImageBoundsSafe(im, 50, 50) Then Say "50, 50 is within the image bounds" Else Say "50, 50 is outside the image bounds" Call gdImageDestroy im
Say "Large font is" gdFontGetHeight("GDFONTLARGE") "pixels high."
Say "Large font is" gdFontGetWidth("GDFONTLARGE") "pixels wide."
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Draw a character. */ Call gdImageChar im, "GDFONTLARGE", 0, 0, 'Q', white /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Draw a character upwards so it rests against the top of the image. */ Call gdImageCharUp(im, "GDFONTLARGE", 0, gdFontGetHeight("GDFONTLARGE"), 'Q', white /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
/* String to draw. */ string = "Hello." /* Font to use */ font = "GDFONTLARGE" im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Draw a centered string. */ Call gdImageString(im, font, gdImageGetWidth(im) % 2 - ( Length(string) * gdFontGetWidth(font) % 2 ), gdImageGetHeight(im) % 2 - gdFontGetHeight(font) % 2, string, white) /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
This function provides a means of rendering fonts with more than 256 characters for those who have them. A more frequently used routine is gdImageString.
/* String to draw. */ string = "Hello." /* Font to use */ font = "GDFONTLARGE" im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color white (red, green and blue all maximum). */ white = gdImageColorAllocate(im, 255, 255, 255) /* Draw a centered string. */ Call gdImageStringUp(im, font, gdImageGetWidth(im) % 2 - ( Length(string) * gdFontGetWidth(font) % 2 ), gdImageGetHeight(im) % 2 - gdFontGetHeight(font) % 2, string, white) /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
This function provides a means of rendering fonts with more than 256 characters for those who have them. A more frequently used routine is gdImageStringUp.
The string argument is considered to be encoded via the UTF_8 standard; also, HTML entities are supported, including decimal, hexadecimal, and named entities (2.0.26). Those who are passing ordinary ASCII strings may have difficulty with the & character unless encoded correctly as & but should have no other difficulties.
The string may be arbitrarily scaled ptsize and rotated (angle in radians). The direction of rotation is counter-clockwise, with 0 radians (0 degrees) at 3 o'clock and PI/2 radians (90 degrees) at 12 o'clock.
On return, gdImageStringFT returns "" if successful, or an error string if unsuccessful. The brect array is filled on return from gdImageStringFT with the 8 elements representing the 4 corner coordinates of the bounding rectangle:
brect.1 | lower left corner, X position |
brect.2 | lower left corner, Y position |
brect.3 | lower right corner, X position |
brect.4 | lower right corner, Y position |
brect.5 | upper right corner, X position |
brect.6 | upper right corner, Y position |
brect.7 | upper left corner, X position |
brect.8 | upper left corner, Y position |
The points are relative to the text regardless of the angle, so "upper left" means in the top left-hand corner seeing the text horizontally.
Use an empty argument for im to get the bounding rectangle without rendering. This is a relatively cheap operation if followed by a rendering of the same string, because of the caching of the partial rendering during bounding rectangle calculation.
The string is rendered in the color indicated. Use the negative of the desired color index to disable anti-aliasing.
The string may contain UTF-8 sequences like: "À"
string = "Hello." /* String to draw. */ size = 40 fontname = "/usr/local/share/ttf/Times.ttf" /* User supplied font */ /* obtain brect so that we can size the image */ err = gdImageStringFT( ,"brect.",0,fontname,size,0,0,0,string) If err \= "" Then Do Say "Error with gdImageStringFT():" err return 1 End /* create an image big enough for the string plus a little whitespace */ x = brect.3-brect.7 + 6 y = brect.4-brect.8 + 6 im = gdImageCreate(x,y) /* Background color (first allocated) */ white = gdImageColorResolve(im, 255, 255, 255) black = gdImageColorResolve(im, 0, 0, 0) /* render the string, offset origin to center string*/ /* note that we use top-left coordinate for adjustment * since gd origin is in top-left with y increasing downwards. */ x = 3 - brect.7 y = 3 - brect.8 err = gdImageStringFT(im,"brect.",black,fontname,size,0,x,y,string) If err \= "" Then Do Say "Error with gdImageStringFT():" err return 1 End /* Save image */ Call gdImagePng im, "mypng.png" /* Destroy it */ Call gdImageDestroy im
top
and bottom
on im
, 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 0 on success, or an error string otherwise.
/* Create an image of text on a circle, with an alpha channel so that we can copy it onto a background */ in = "mypicture.jpg" If Stream( in, 'C', 'QUERY EXISTS' ) = '' Then im = gdImageCreateTrueColor(300, 300) Else im = gdImageCreateFromJpeg(in) If gdImageGetWidth(im) < gdImageGetHeight(im) Then radius = gdImageGetWidth(im) / 2 Else radius = gdImageGetHeight(im) / 2 Call gdImageStringFTCircle im, gdImageGetWidth(im) / 2, gdImageGetHeight(im) / 2, , radius, radius / 2, 0.8, "arial", 24, "top text", "bottom text", , gdTrueColorAlpha(240, 240, 255, 32) out = "gdfx.png" Call gdImagePng im, out Call gdImageDestroy im return 0For more information, see gdImageSquareToCircle.
In the event that all gdMaxColors colors (256) have already been allocated, gdImageColorAllocate will return -1 to indicate failure. (This is not uncommon when working with existing PNG files that already use 256 colors.) Note that gdImageColorAllocate does not check for existing colors that match your request; see gdImageColorExact, gdImageColorClosest and gdImageColorClosestHWB for ways to locate existing colors that approximate the color desired in situations where a new color is not available. Also see gdImageColorResolve.
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color red. */ red = gdImageColorAllocate(im, 255, 0, 0) /* Draw a dashed line from the upper left corner to the lower right corner. */ Call gdImageLine im, 0, 0, 99, 99, red /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
In the event that all gdMaxColors colors (256) have already been allocated, gdImageColorAllocate will return -1 to indicate failure. (This is not uncommon when working with existing palette-based PNG files that already use 256 colors.) Note that gdImageColorAllocateAlpha does not check for existing colors that match your request; see gdImageColorExactAlpha and gdImageColorClosestAlpha for ways to locate existing colors that approximate the color desired in situations where a new color is not available. Also see gdImageColorResolveAlpha.
im = gdImageCreate(100, 100) /* Background color (first allocated) */ black = gdImageColorAllocate(im, 0, 0, 0) /* Allocate the color red, 50% transparent. */ red = gdImageColorAllocateAlpha(im, 255, 0, 0, 64) /* Draw a dashed line from the upper left corner to the lower right corner. */ Call gdImageDashedLine im, 0, 0, 99, 99, red /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
If no colors have yet been allocated in the image, gdImageColorClosest returns -1.
When applied to a truecolor image, this function always succeeds in returning the desired color.
This function is most useful as a backup method for choosing a drawing color when an image already contains gdMaxColors (256) colors and no more can be allocated. (This is not uncommon when working with existing PNG files that already use many colors.) See gdImageColorExact for a method of locating exact matches only.
/* Let's suppose that photo.png is a scanned photograph with many colors. */ im = gdImageCreateFromPng("photo.png"); /* Try to allocate red directly */ red = gdImageColorAllocate(im, 255, 0, 0) /* If we fail to allocate red... */ If red = -1 Then Do /* Find the closest color instead. */ red = gdImageColorClosest(im, 255, 0, 0) End /* Draw a line from the upper left corner to the lower right corner */ Call gdImageLine im, 0, 0, 99, 99, red /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
If no colors have yet been allocated in the image, gdImageColorClosestAlpha returns -1.
When applied to a truecolor image, this function always succeeds in returning the desired color.
This function is most useful as a backup method for choosing a drawing color when a palette-based image already contains gdMaxColors (256) colors and no more can be allocated. (This is not uncommon when working with existing palette-based PNG files that already use many colors.) See gdImageColorExactAlpha for a method of locating exact matches only.
/* Let's suppose that photo.png is a scanned photograph with many colors. */ in = "photo.png" im = gdImageCreateFromPng(in) /* Try to allocate red, 50% transparent, directly */ red = gdImageColorAllocateAlpha(im, 255, 0, 0, 64) /* If we fail to allocate red... */ If red = -1 Then /* Find the closest color instead. */ red = gdImageColorClosestAlpha(im, 255, 0, 0, 64) } /* Draw a dashed line from the upper left corner to the lower right corner */ Call gdImageDashedLine im, 0, 0, 99, 99, red /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
If no colors have yet been allocated in the image, gdImageColorClosestHWB returns -1.
When applied to a truecolor image, this function always succeeds in returning the desired color.
This function is most useful as a backup method for choosing a drawing color when an image already contains gdMaxColors (256) colors and no more can be allocated. (This is not uncommon when working with existing PNG files that already use many colors.) See gdImageColorExact for a method of locating exact matches only.
/* Let's suppose that photo.png is a scanned photograph with many colors. */ im = gdImageCreateFromPng("photo.png") /* Try to allocate red directly */ red = gdImageColorAllocate(im, 255, 0, 0) /* If we fail to allocate red... */ If red = -1 Then Do /* Find the closest color instead. */ red = gdImageColorClosestHWB(im, 255, 0, 0) End /* Draw a line from the upper left corner to the lower right corner */ Call gdImageLine im, 0, 0, 99, 99, red /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
When applied to a truecolor image, this function always succeeds in returning the desired color.
im = gdImageCreateFromPng("photo.png") /* The image may already contain red; if it does, we'll save a slot in the color table by using that color. */ /* See if red already exists */ red = gdImageColorExact(im, 255, 0, 0) /* If red isn't already present... */ If red = -1 Then Do /* Second best: try to allocate it directly. */ red = gdImageColorAllocate(im, 255, 0, 0) /* Out of colors, so find the closest color instead. */ If red = -1 Then red = gdImageColorClosest(im, 255, 0, 0) End /* Draw a line from the upper left corner to the lower right corner */ Call gdImageLine im, 0, 0, 99, 99, red /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
When applied to a truecolor image, this function always succeeds in returning the desired color.
im = gdImageCreateFromPng("photo.png") /* The image may already contain red; if it does, we'll save a slot in the color table by using that color. */ /* Get index of red, or color closest to red */ red = gdImageColorResolve(im, 255, 0, 0); /* Draw a line from the upper left corner to the lower right corner */ Call gdImageLine im, 0, 0, 99, 99, red /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
When applied to a truecolor image, this function always succeeds in returning the desired color.
in = "photo.png" im = gdImageCreateFromPng(in) /* The image may already contain red; if it does, we'll save a slot in the color table by using that color. */ /* Get index of red, 50% transparent, or the next best thing */ red = gdImageColorResolveAlpha(im, 255, 0, 0, 64) /* Draw a dashed line from the upper left corner to the lower right corner */ Call gdImageDashedLine im, 0, 0, 99, 99, red /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
im = gdImageCreateFromPng("photo.png") /* Look for red in the color table. */ red = gdImageColorExact(im, 255, 0, 0) /* If red is present... */ If red != -1 Then Do /* Deallocate it. */ Call gdImageColorDeallocate im, red /* Allocate blue, reusing slot in table. Existing red pixels will change color. */ blue = gdImageColorAllocate(im, 0, 0, 255) End /* ... Do something with the image, such as saving it to a file... */ /* Destroy it */ Call gdImageDestroy im
The color index used should be an index allocated by gdImageColorAllocate, whether explicitly invoked by your code or implicitly invoked by loading an image. In order to ensure that your image has a reasonable appearance when viewed by users who do not have transparent background capabilities (or when you are writing a JPEG-format file, which does not support transparency), be sure to give reasonable RGB values to the color you allocate for use as a transparent color, even though it will be transparent on systems that support PNG transparency.
im = gdImageCreateFromPng("photo.png") /* Look for black in the color table and make it transparent. */ black = gdImageColorExact(im, 0, 0, 0) /* If black is present... */ If black != -1 Then Do /* Make it transparent */ Call gdImageColorTransparent im, black End /* Save the newly-transparent image back to the file */ Call gdImagePng im, "photo.png" /* Destroy it */ Call gdImageDestroy im
dstX and dstY arguments specify the point in the destination image to which the region will be copied. The srcX and srcY arguments specify the upper left corner of the region in the source image. The width and height arguments specify the width and height of the region.
When you copy a region from one location in an image to another location in the same image, gdImageCopy will perform as expected unless the regions overlap, in which case the result is unpredictable.
Important note on copying between images: since different images do not necessarily have the same color tables, pixels are not simply set to the same color index values to copy them. gdImageCopy will attempt to find an identical RGB value in the destination image for each pixel in the copied portion of the source image by invoking gdImageColorExact. If such a value is not found, gdImageCopy will attempt to allocate colors as needed using gdImageColorAllocate. If both of these methods fail, gdImageCopy will invoke gdImageColorClosest to find the color in the destination image which most closely approximates the color of the pixel being copied.
/* Load a small png to tile the larger one with */ im_in = gdImageCreateFromPng("small.png") /* Get size of im_in for later use */ in_x = gdImageGetWidth(im_in) in_y = gdImageGetHeight(im_in) /* Make the output image four times as large on both axes */ im_out = gdImageCreate(in_x * 4, in_y * 4) /* Now tile the larger image using the smaller one */ Do y = 0 To 3 Do x = 0 To 3 Call gdImageCopy im_out, im_in, x * in_x, y * in_y, 0, 0, in_x, in_y End End Call gdImagePng im_out, "tiled.png" Call gdImageDestroy im_in Call gdImageDestroy im_out
The dstX and dstY arguments specify the point in the destination image to which the region will be copied. The srcX and srcY arguments specify the upper left corner of the region in the source image. The dstW and dstH arguments specify the width and height of the destination region. The srcW and srcH arguments specify the width and height of the source region and can differ from the destination size, allowing a region to be scaled during the copying process.
When you copy a region from one location in an image to another location in the same image, gdImageCopy will perform as expected unless the regions overlap, in which case the result is unpredictable. If this presents a problem, create a scratch image in which to keep intermediate results.
Important note on copying between images: since images do not necessarily have the same color tables, pixels are not simply set to the same color index values to copy them. gdImageCopy will attempt to find an identical RGB value in the destination image for each pixel in the copied portion of the source image by invoking gdImageColorExact. If such a value is not found, gdImageCopy will attempt to allocate colors as needed using gdImageColorAllocate. If both of these methods fail, gdImageCopy will invoke gdImageColorClosest to find the color in the destination image which most closely approximates the color of the pixel being copied.
/* Load a small png to expand in the larger one */ im_in = gdImageCreateFromPng("small.png") in_x = gdImageGetWidth(im_in) in_y = gdImageGetHeight(im_in) /* Make the output image four times as large on both axes */ im_out = gdImageCreate(in_x * 4, in_y * 4) out_x = gdImageGetWidth(im_out) out_y = gdImageGetHeight(im_out) /* Now copy the smaller image, but four times larger */ Call gdImageCopyResized im_out, im_in, 0, 0, 0, 0, out_x, out_y, in_x, in_y Call gdImagePng im_out, "large.png" Call gdImageDestroy im_in Call gdImageDestroy im_out
Pixel values are only interpolated if the destination image is a truecolor image. Otherwise, gdImageCopyResized is automatically invoked.
The dstX and dstY arguments specify the point in the destination image to which the region will be copied. The srcX and srcY arguments specify the upper left corner of the region in the source image. The dstW and dstH arguments specify the width and height of the destination region. The srcW and srcH arguments specify the width and height of the source region and can differ from the destination size, allowing a region to be scaled during the copying process.
When you copy a region from one location in an image to another location in the same image, gdImageCopy will perform as expected unless the regions overlap, in which case the result is unpredictable. If this presents a problem, create a scratch image in which to keep intermediate results.
Important note on copying between images: since images do not necessarily have the same color tables, pixels are not simply set to the same color index values to copy them. If the destination image is a palette image, gd will use the gdImageColorResolve function to determine the best color available.
/* Load a large png to shrink in the smaller one */ in = "large.png" im_in = gdImageCreateFromPng(in) in_x = gdImageGetWidth(im_in) in_y = gdImageGetHeight(im_in) /* Make the output image four times as small on both axes. Use a true color image so that we can interpolate colors. */ im_out = gdImageCreateTrueColor(in_x / 4, in_y / 4) out_x = gdImageGetWidth(im_out) out_y = gdImageGetHeight(im_out) /* Now copy the large image, but four times smaller */ Call gdImageCopyResampled im_out, im_in, 0, 0, 0, 0, out_x, out_y, in_x, in_y out = "large.png" Call gdImagePng im_out, out Call gdImageDestroy im_in Call gdImageDestroy im_out
When you copy a region from one location in an image to another location in the same image, gdImageCopyRotated will perform as expected unless the regions overlap, in which case the result is unpredictable. If this presents a problem, create a scratch image in which to keep intermediate results.
Important note on copying between images: since palette-based images do not necessarily have the same color tables, pixels are not simply set to the same color index values to copy them. If the destination image is not a truecolor image, gdImageColorResolveAlpha is used to choose the destination pixel.
/* Load a small png to rotate in the larger one */ /* you will need a trancendental math's package!! */ in = "small.png" im_in = gdImageCreateFromPng(in) in_x = gdImageGetWidth(im_in) in_y = gdImageGetHeight(im_in) /* Make the output image four times as large on both axes */ im_out = gdImageCreate(n_x * 4, in_y * 4) out_x = gdImageGetWidth(im_out) out_y = gdImageGetHeight(im_out) /* Now rotate the smaller image */ Do a = 0 While a < 360 By 45 x = cos(a * .0174532925) * out_x / 2; y = -sin(a * .0174532925) * out_y / 2; Call gdImageCopyRotated im_out, im_in, out_x / 2 + x, out_y / 2 + y, 0, 0, in_x, in_y, a End out = "large.png" Call gdImagePng im_out, out Call gdImageDestroy im_in Call gdImageDestroy im_out
If, however, pct is less than 100, then the two images are merged. With pct = 0, no action is taken.
This feature is most useful to 'highlight' sections of an image by merging a solid color with pct = 50:
Call gdImageCopyMerge im_out, im_in, 100, 200, 0, 0, 30, 50, 50
Call gdImageCopyMergeGray im_out, im_in, 100, 200, 0, 0, 30, 50, 50
cmpMask = gdImageCompare(im1, im2) If gdImageDifferent(cmpMask) Then Say "Images will display differently" If gdImageDifferentTransparent(cmpMask) Then Say "Images have different transparency indexes"
A nonzero value for the interlace argument turns on interlace; a zero value turns it off. Note that interlace has no effect on other functions, and has no meaning unless you save the image in PNG or JPEG format; the gd and xbm formats do not support interlace.
When a PNG is loaded with gdImageCreateFromPng or a JPEG is loaded with gdImageCreateFromJpeg, interlace will be set according to the setting in the PNG or JPEG file.
Note that many PNG and JPEG viewers and web browsers do not support interlace or the incremental display of progressive JPEGs. However, the interlaced PNG or progressive JPEG should still display; it will simply appear all at once, just as other images do.
/* Load the image */ im_in = gdImageCreateFromPng("test.png") /* Now turn on interlace */ Call gdImageInterlace im, 1 /* And open an output file */ /* Save the image -- could also use gdImageJpeg */ Call gdImagePng im, "test.png" Call gdImageDestroy im
DEBUG (settable) 0 - no debugging 1 - all Rexx variables set by rexx/gd are displayed as they are set 2 - all Rexx/gd functions are traced on entry with argument values and on exit with the return value 4 - all internal Rexx/gd functions are traced with their arguments (really only useful for developers) The values can be added together for a combination of the above details. DEBUGFILE (settable) Where any debugging output is written. By default this goes to the system's error stream; usually 'stderr'. VERSION (readonly) The full version details of Rexx/gd in the format: package version version_date Where: package - the string 'rexxgd' version - package version in n.n format; eg 1.0 version_date - date package was released in DATE('N') format
call rxfuncadd 'GdQueryFunction', 'rexxgd', 'GdQueryFunction' call rxfuncadd 'GdVariable', 'rexxgd', 'GdVariable' say gdqueryfunction( 'stem.', 'A' ) /* returns 0 */ do i = 1 to stem.0 /* 112 items displayed */ say 'stem/A' stem.i end drop stem. say gdqueryfunction( 'stem.', 'R' ) /* returns 0 */ do i = 1 to stem.0 /* 2 items displayed */ say 'stem/R' stem.i end drop stem. say gdqueryfunction( 'gdvariable', 'A' ) /* returns 0 */ drop stem. say gdqueryfunction( 'gdvariable' ) /* returns 0 */ drop stem. say gdqueryfunction( 'gddropfuncs', 'A' ) /* returns 0 */ drop stem. say gdqueryfunction( 'gddropfuncs', 'R' ) /* returns 1 */