Introduction to Algorithms and Programming
Graphics and animations using the GD library
Reference documentation about the
GD graphics library and
time and date functions:
Create an image file with a background color
int gdImageColorAllocate( gdImagePtr image, int red, int green, int blue)
Sets the color index for the image using the RGB values red, green, blue and returns the index of the new color index. Then, you can use the returned value as a parameter to drawing functions. The first time you invoke this function, you are setting the background color for that image.
Draw lines
void gdImageSetThickness( gdImagePtr image, int thickness )
Sets the width of the lines used by drawing functions according to the thickness parameter.
void gdImageLine( gdImagePtr image, int x1, int y1, int x2, int y2, int color )
Draw a line from point x1, y1 to point x2, y2 using the color parameter.
#include
#include
int main()
{
/* Declare and initialise variables for a new image.
These steps are done once before using drawing functions. */
gdImagePtr gdImage = gdImageCreate( 100, 100 );
FILE *jpgFile = NULL;
int yellow;
/* The first call to gdImageColorAllocate() always sets the image background.
This step can only be done once before using drawing functions. */
gdImageColorAllocate( gdImage, 0, 0, 0 );
/* Subsequent calls to gdImageColorAllocate() creates new colors for drawing.
It is similar using a paint brush with a specific color. The brush can be
used over and over. This is only needed each time a new color is required. */
yellow = gdImageColorAllocate( gdImage, 255, 255, 0 );
/* Most of the work is done by using drawing functions.
These functions set the line width to 4 and draws a diagonal line. */
gdImageSetThickness( gdImage, 4 );
gdImageLine( gdImage, 0, 0, 100, 100, yellow );
/* These steps save the image in memory out to a physical file on the server.
These steps are done once when the drawing is done. */
jpgFile = fopen( "test.jpg", "wb" );
gdImageJpeg( gdImage, jpgFile, -1 );
/* These steps clear all memory and files used with the image.
These steps are done once when the image is no longer used. */
fclose( jpgFile );
gdImageDestroy( gdImage );
}
Draw filled ellipses and circles
void gdImageFilledEllipse( gdImagePtr image, int cx, int cy, int width, int height, int color)
Draws an ellipse centered at point cx, cy , with the specified width and height in pixels. The ellipse is filled with the color parameter.
#include
#include
int main()
{
/* Declare and initialise variables for a new image.
These steps are done once before using drawing functions. */
gdImagePtr gdImage = gdImageCreate( 100, 100 );
FILE *jpgFile = NULL;
int yellow;
/* The first call to gdImageColorAllocate() always sets the image background.
This step can only be done once before using drawing functions. */
gdImageColorAllocate( gdImage, 0, 0, 0 );
/* Subsequent calls to gdImageColorAllocate() creates new colors for drawing.
It is similar using a paint brush with a specific color. The brush can be
used over and over. This is only needed each time a new color is required. */
yellow = gdImageColorAllocate( gdImage, 255, 255, 0 );
/* Most of the work is done by using drawing functions.
This function draws an ellipse, or circle if the height and width are the equal. */
gdImageFilledEllipse( gdImage, 20, 20, 20, 20, yellow );
/* These steps save the image in memory out to a physical file on the server.
These steps are done once when the drawing is done. */
jpgFile = fopen( "test.jpg", "wb" );
gdImageJpeg( gdImage, jpgFile, -1 );
/* These steps clear all memory and files used with the image.
These steps are done once when the image is no longer used. */
fclose( jpgFile );
gdImageDestroy( gdImage );
}
Draw filled rectangles and squares
void gdImageFilledRectangle( gdImagePtr image, int x1, int y1, int x2, int y2, int color )
Draws a solid rectangle from the upper left corner x1, y1 to the lower right corner x2, y2 . The rectangle is filled with the color parameter.
#include
#include
#define IMAGE_WIDTH 100
#define IMAGE_HEIGHT 100
enum shapes { square, rectangle, circle, ellipse };
int main()
{
gdImagePtr gdImage = gdImageCreate( IMAGE_WIDTH, IMAGE_HEIGHT );
FILE *jpgFile = NULL;
int yellow;
enum shapes choice;
gdImageColorAllocate( gdImage, 0, 0, 0 );
yellow = gdImageColorAllocate( gdImage, 255, 255, 0 );
scanf( "%d", &choice );
switch( choice )
{
case square :
gdImageFilledRectangle( gdImage, 20, 20, IMAGE_WIDTH - 20, IMAGE_HEIGHT - 20, yellow );
break;
case rectangle :
gdImageFilledRectangle( gdImage, 20, 40, IMAGE_WIDTH - 20, IMAGE_HEIGHT - 40, yellow );
break;
case circle :
gdImageFilledEllipse( gdImage, IMAGE_WIDTH / 2, IMAGE_HEIGHT / 2, IMAGE_WIDTH / 2, IMAGE_WIDTH / 2, yellow );
break;
case ellipse :
gdImageFilledEllipse( gdImage, IMAGE_WIDTH / 2, IMAGE_HEIGHT / 2, IMAGE_WIDTH * 0.8, IMAGE_WIDTH / 2, yellow );
break;
}
jpgFile = fopen( "test.jpg", "wb" );
gdImageJpeg( gdImage, jpgFile, -1 );
fclose( jpgFile );
gdImageDestroy( gdImage );
}
0
Static variables
Local variables declared inside functions may also have a
static storage class.
duration : memory is allocated when the program starts and released when the program ends.
scope : variable is accessible only within the function – not outside of it.
#include
#include
#define IMAGE_WIDTH 200
#define IMAGE_HEIGHT 200
void draw( gdImagePtr, int, int );
int main()
{
gdImagePtr gdImage = gdImageCreate( IMAGE_WIDTH, IMAGE_HEIGHT );
FILE *jpgFile = NULL;
int yellow;
gdImageColorAllocate( gdImage, 0, 0, 0 );
yellow = gdImageColorAllocate( gdImage, 255, 255, 0 );
draw( gdImage, yellow, 10 );
draw( gdImage, yellow, 25 );
draw( gdImage, yellow, 40 );
draw( gdImage, yellow, 55 );
jpgFile = fopen( "test.jpg", "wb" );
gdImageJpeg( gdImage, jpgFile, -1 );
fclose( jpgFile );
gdImageDestroy( gdImage );
}
void draw( gdImagePtr image, int color, int inset )
{
int x1 = inset; /* Coordinate of top left corner */
int y1 = inset;
int x2 = IMAGE_WIDTH - inset; /* Coordinate of lower right corner */
int y2 = IMAGE_HEIGHT - inset;
/* The pen thickness increases each time the function is called */
static int penThickness = 0;
penThickness++;
gdImageSetThickness( image, penThickness );
/* The lines form a rectangle or square based on image size and inset value */
gdImageLine( image, x1, y1, x2, y1, color );
gdImageLine( image, x2, y1, x2, y2, color );
gdImageLine( image, x2, y2, x1, y2, color );
gdImageLine( image, x1, y2, x1, x1, color );
}
Drawing text
The GD graphics library may also be used to draw individual chracters or text strings to the image.
#include
#include
#include /* For tiny fonts */
#include /* For small fonts */
#include /* For large fonts */
#include /* For giant fonts */
int main()
{
gdImagePtr gdImage = gdImageCreate( 150, 150 );
FILE *jpgFile = NULL;
int yellow;
gdImageColorAllocate( gdImage, 0, 0, 0 );
yellow = gdImageColorAllocate( gdImage, 255, 255, 0 );
/* Draw one line of text at a time to the image */
gdImageString( gdImage, gdFontGetTiny(), 5, 5, "Line 1", yellow );
gdImageString( gdImage, gdFontGetSmall(), 5, 25, "Line 2", yellow );
gdImageString( gdImage, gdFontGetLarge(), 5, 55, "Line 3", yellow );
gdImageString( gdImage, gdFontGetGiant(), 5, 90, "Line 4", yellow );
/* Draw one character at a time to the image */
gdImageChar( gdImage, gdFontGetTiny(), 5, 120, 'A', yellow );
gdImageChar( gdImage, gdFontGetSmall(), 25, 120, 'B', yellow );
gdImageChar( gdImage, gdFontGetLarge(), 50, 120, 'C', yellow );
gdImageChar( gdImage, gdFontGetGiant(), 80, 120, 'D', yellow );
jpgFile = fopen( "test.jpg", "wb" );
gdImageJpeg( gdImage, jpgFile, -1 );
fclose( jpgFile );
gdImageDestroy( gdImage );
}
Creating animation
The GD graphics library may also be used to create animated GIF images from a sequence of frame images .
#include
#include
#define USE_GLOBAL_COLORMAP 1
#define USE_LOCAL_COLORMAP 0
#define LOOP_ANIMATION_FOREVER 0
#define DO_NOT_LOOP_ANIMATION -1
#define AUTO_FRAME_DISPOSAL 1
#define ANIMATION_DELAY 10 /* in milliseconds */
#define IMAGE_WIDTH 200
#define IMAGE_HEIGHT 200
#define MAX_FRAMES_COUNT 20
#define CIRCLE_DIAMETER 10
#define MOVEMENT_PER_FRAME 10
int main( void )
{
FILE *animatedGIF;
gdImagePtr frameImage;
int frameCounter, yellow;
/* Create first background frame image */
frameImage = gdImageCreate( IMAGE_WIDTH, IMAGE_HEIGHT );
gdImageColorAllocate( frameImage, 0, 0, 0 );
/* Initialize animated GIF with the first background frame */
animatedGIF = fopen( "animation.gif", "wb" );
gdImageGifAnimBegin( frameImage, animatedGIF, USE_GLOBAL_COLORMAP, LOOP_ANIMATION_FOREVER );
/* Start the frame counter at 1 so that it can be used later for movement calculations */
for ( frameCounter = 1; frameCounter <= MAX_FRAMES_COUNT; frameCounter++ )
{
gdImageDestroy( frameImage ); /* Release memory for previous frame image */
frameImage = gdImageCreate( IMAGE_WIDTH, IMAGE_HEIGHT ); /* Create new frame image */
gdImageColorAllocate( frameImage, 0, 0, 0 );
yellow = gdImageColorAllocate( frameImage, 255, 255, 0 );
/* Draw a circle that changes location based on frame counter */
gdImageFilledEllipse( frameImage, frameCounter * MOVEMENT_PER_FRAME, frameCounter * MOVEMENT_PER_FRAME, CIRCLE_DIAMETER, CIRCLE_DIAMETER, yellow );
/* Add frame to the animated gif image */
gdImageGifAnimAdd( frameImage, animatedGIF, USE_GLOBAL_COLORMAP, 0, 0, ANIMATION_DELAY, AUTO_FRAME_DISPOSAL, NULL );
}
/* Save the animated gif and clear memory associated with the animation */
gdImageGifAnimEnd( animatedGIF );
fclose( animatedGIF );
gdImageDestroy( frameImage );
}
Practice exercise
Below is a program that draws one die based on a random number value.
Generate new designs of dice images . For example, try:
Generating 2 dice on the same image
Change the colors of the dice
Change the design of the dice
#include
#include
#include
#include
#define DOT_SIZE 16
void displayDieFace( int, gdImagePtr, int );
int main()
{
/* Declare and initialise variables for a new image.
These steps are done once before using drawing functions. */
gdImagePtr gdImage = gdImageCreate( 80, 80 );
FILE *jpgFile = NULL;
int yellow, dieNumber;
/* The first call to gdImageColorAllocate() always sets the image background.
This step can only be done once before using drawing functions. */
gdImageColorAllocate( gdImage, 0, 0, 0 );
/* Subsequent calls to gdImageColorAllocate() creates new colors for drawing.
It is similar using a paint brush with a specific color. The brush can be
used over and over. This is only needed each time a new color is required. */
yellow = gdImageColorAllocate( gdImage, 255, 255, 0 );
/* Generate random number and call function to display corresponding die face. */
srand( time( 0 ) );
dieNumber = ( rand() % 6 ) + 1;
displayDieFace( dieNumber, gdImage, yellow );
/* These steps save the image in memory out to a physical file on the server.
These steps are done once when the drawing is done. */
jpgFile = fopen( "test.jpg", "wb" );
gdImageJpeg( gdImage, jpgFile, -1 );
/* These steps clear all memory and files used with the image.
These steps are done once when the image is no longer used. */
fclose( jpgFile );
gdImageDestroy( gdImage );
}
/* Draw a die face for a specific number */
void displayDieFace( int number, gdImagePtr image, int brush )
{
/* There are 7 possible dots. Draw dots as required for similar numbers. */
if ( ( number % 2 ) == 1 ) gdImageFilledEllipse( image, 40, 40, DOT_SIZE, DOT_SIZE, brush );
if ( number != 1 )
{
gdImageFilledEllipse( image, 20, 20, DOT_SIZE, DOT_SIZE, brush );
gdImageFilledEllipse( image, 60, 60, DOT_SIZE, DOT_SIZE, brush );
}
if ( number > 3 )
{
gdImageFilledEllipse( image, 60, 20, DOT_SIZE, DOT_SIZE, brush );
gdImageFilledEllipse( image, 20, 60, DOT_SIZE, DOT_SIZE, brush );
}
if ( number == 6 )
{
gdImageFilledEllipse( image, 20, 40, DOT_SIZE, DOT_SIZE, brush );
gdImageFilledEllipse( image, 60, 40, DOT_SIZE, DOT_SIZE, brush );
}
}