A text access counter
The Increment subroutine
The complete text access counter script
Seeding the Counter
Adding the Counter to Your HTML Page
With Server Side Includes
Without Server Side Includes
Creating the Template File
Modifying the access.pl Script
A graphical access counter
Incrementing the Counter
Creating the GIF Image
Returning the Graphical Counter Image
The Graphical Counter Script
Calling the Counter with the <IMG> Tag
Creating the GIF Image
Once the counter value has been read in from the count.dat file, the GIF image can be created. Recall that you create the GIF image from the counter value you read in from the file, not from the incremented value. This is because the incremented version is stored in an integer, and it is easier to create the GIF based on a value stored in a string. Remember, a string in C is actually an array of characters. So, if the counter value is 769, the s_count variable contains the string 769. Each individual digit can easily be accessed by addressing the specific array element. For example, the first digit, 7, can be accessed by using the variable s_count[0], which is the first element in the s_count array. In this way, you can loop over each digit in the counter value and append the corresponding GIF image file to the GIF image you are creating. With the 769 example, you would first add the contents of the 7 GIF image file, next the contents of the 6 GIF image file, and then the contents of the 9 GIF image file.
Before looping over the s_count array and creating the new GIF image, you must either create or download the ten GIF images representing each digit. For this example, the ten GIF images have been downloaded from the Digit Mania Web site, http://cervantes.learningco.com/kevin/digits/index.html. This Web site contains many digit styles for use in graphical access counter programs. The style used here is the tiny style, which was created by Muhammad A. Muquit. Each one of these GIF digits is a 9-pixel wide by 13-pixel high image. To implement this example exactly as shown, you need to download these images and place them in a directory that your graphical counter CGI script can access.
Now that you have the ten GIF images, one for each digit, you can write the C code for creating the graphical counter image that will be displayed within your Web page. First you must create a blank version of the graphical counter image that is the same width and height as your final image. By doing this, you allocate the memory necessary to store the final graphical counter image and you create the image to which the individual digit images can be copied. Because the digit images will each be 13 pixels high, your final image will also be 13 pixels high. However, the width must be calculated based on the number of digits the number contains. Remember that the length of the s_count array is also the number of digits your graphical counter image will contain. Therefore, you can calculate the width of your final image by multiplying the length of the s_count array by the width of each individual digit image, which in this case is 9 pixels. You can do this with the code
width = strlen(s_count) * real_width;
where real_width is an integer that is set to 9 earlier in the program. Listings 6.6 and 6.7 later in this article show where the real_width variable is set.
After you have calculated the dimensions of the graphical counter image, you can use the gdImageCreate function from the gd library to create the new graphical counter image. This function takes two parameters, a width and height, and creates a blank GIF image with the specified dimensions. The C statement
im_final = gdImageCreate(width, real_height);
calls the gdImageCreate function, passing it the width value that was just calculated and the height of the individual digit images, which is stored in the variable real_height. Listings 6.7 and 6.8 will show the code that sets the real_height variable to 13, which is the height for the tiny style digit images. Notice that the return value of the function gdImageCreate is assigned to the variable im_final. This variable is a pointer to the image that was just created, and it is through this variable that you will reference the image later on in the code.
Next you need to loop over the array s_count and append the digit image files to the im_final image you just created. The loop you use will be similar to the for loops used in Perl. The line
for (i=Ø; i < strlen(s_count); i++) {
starts the for loop. The loop executes once for every element in the s_count array and the variable i represents the index of the current s_count array element. For example, if s_count holds the string 769, the for loop executes three times. The first time, the i variable is 0, so the first digit of the s_count array can be accessed by using the variable s_count[i]. As i is incremented, the variable s_count[i] moves to the next elements in the array. For each iteration of the loop, you should check the value of the s_count[i] array element, open the digit image file that corresponds to that value, and append the contents of that digit's GIF image file to the graphical counter image you are creating. Listing 6 shows the C code for the entire for loop.
for (i=Ø; i < strlen(s_count); i++) {
switch (s_count[i]) {
case 'Ø':
image = fopen(zero_gif, "rb");
break;
case '1':
image = fopen(one_gif, "rb");
break;
case '2':
image = fopen(two_gif, "rb");
break;
case '3':
image = fopen(three_gif, "rb");
break;
case '4':
image = fopen(four_gif, "rb");
break;
case '5':
image = fopen(five_gif, "rb");
break;
case '6':
image = fopen(six_gif, "rb");
break;
case '7':
image = fopen(seven_gif, "rb");
break;
case '8':
image = fopen(eight_gif, "rb");
break;
case '9':
image = fopen(nine_gif, "rb");
break;
default :
break;
}
if (!image) {
printf("Content-type: text/html\n\nCannot open image file!\n");
return(Ø);
} else {
im_file = gdImageCreateFromGif(image);
fclose(image);
gdImageCopy(im_final, im_file,
destx, Ø, Ø, Ø, real_width, real_height);
destx += real_width;
gdImageDestroy(im_file);
}
}
|
The first section of the for loop uses the switch conditional, which compares the value of the s_count[i] array element with each case until a match is found. When a matching case is found, the code under the case is executed. If no match is found, the code under the default is executed. For example, if the s_count array contains 769, the first iteration of the loop would have the s_count[i] element equal to 7. The switch would execute the code under the case '7': line, which is
image = fopen(seven_gif, "rb"); break;
The first line opens the 7 digit's GIF image file, whose path and file name are stored in the seven_gif variable. The code setting this variable is shown in Listings 6.6 and 6.7. The difference between this fopen statement, and the ones in the previous section is the "rb" string. This string specifies to open the file for binary input.
At the end of the switch statement, an if...else conditional verifies that the image file has been successfully opened. In the else portion of the conditional, the digit image is appended to the graphical counter image being created. This is done with the following lines of code:
im_file = gdImageCreateFromGif(image);
fclose(image);
gdImageCopy(im_final, im_file,
destx, Ø, Ø, Ø, real_width, real_height);
destx += real_width;
gdImageDestroy(im_file);
The first line creates a new gd graphical image from the digit's GIF image file. The pointer im_file points to this image. After the im_file image has been created, you can close the stream to the file with the fclose statement. The statement
gdImageCopy(im_final, im_file,
destx, Ø, Ø, Ø, real_width, real_height);
appends the digit's image just read in from the image file to the graphical counter image that is being constructed. The parameters for gdImageCopy are the following: a pointer to the destination image, a pointer to the source image, the x coordinate in the destination image to start placing the copy, the y coordinate in the destination image to start placing the copy, the x coordinate in the source image to begin the copy, the y coordinate in the source image to begin the copy, the number of pixels to copy in the x direction, the number of pixels to copy in the y direction. In this statement, the destination image is the graphical counter image you are creating, which is pointed to with the im_final variable. The source image is the image that was just read in from the digit's GIF file, and is pointed to with the im_file. The x coordinate for the destination of the copy is a variable, destx. This variable is increased after each iteration of the loop, in the line
destx += real_width;
For example, with the s_count array containing 769, the first iteration copies the 7 digit's GIF image file to the im_final image. Because this is the first image being copied, the x coordinate in the destination image is 0. However, on the next iteration of the loop, the im_final image already contains the 7 digit. So, the x coordinate has to be moved over 9 pixels. Why 9 pixels? Because that is the width of each individual digit's GIF image. After the 6 digit's image file is added to the im_final image, the destx variable is increased by another 9 pixels. So, when the 9 digit is added to the im_final image, the destx variable is 18, which is the sum of the widths of the previous two digits 7 and 6. Finally, after the im_file image is appended to the im_final image, the im_file image is destroyed with the gdImageDestroy command. Listing 7 shows the all of the C code for creating the graphical counter image.
/* Image file handle */
FILE *image;
/* Input and output images */
gdImagePtr im_file, im_final;
/* Image files
All users need to change the paths to the actual
paths for their machines. Windows users need to
use paths in the form "c:\\robertm\\Øtiny.gif" */
char *zero_gif = "/users/robertm/0tiny.gif";
char *one_gif = "/users/robertm/1tiny.gif";
char *two_gif = "/users/robertm/2tiny.gif";
char *three_gif = "/users/robertm/3tiny.gif";
char *four_gif = "/users/robertm/4tiny.gif";
char *five_gif = "/users/robertm/5tiny.gif";
char *six_gif = "/users/robertm/6tiny.gif";
char *seven_gif = "/users/robertm/7tiny.gif";
char *eight_gif = "/users/robertm/8tiny.gif";
char *nine_gif = "/users/robertm/9tiny.gif";
/* string version of counter file value */
char s_count[2Ø];
/* width of image created image,
x position for new image, and loop variable */
int width;
int destx = Ø;
int i;
/* the real_height is the height (in pixels) for all of the image files.
the real_width is the width (in pixels) for all of the image files. */
int real_height = 13;
int real_width = 9;
width = strlen(s_count) * real_width;
im_final = gdImageCreate(width, real_height);
for (i=0; i < strlen(s_count); i++) {
switch (s_count[i]) {
case 'Ø':
image = fopen(zero_gif, "rb");
break;
case '1':
image = fopen(one_gif, "rb");
break;
case '2':
image = fopen(two_gif, "rb");
break;
case '3':
image = fopen(three_gif, "rb");
break;
case '4':
image = fopen(four_gif, "rb");
break;
case '5':
image = fopen(five_gif, "rb");
break;
case '6':
image = fopen(six_gif, "rb");
break;
case '7':
image = fopen(seven_gif, "rb");
break;
case '8':
image = fopen(eight_gif, "rb");
break;
case '9':
image = fopen(nine_gif, "rb");
break;
default :
break;
}
if (!image) {
printf("Content-type: text/html\n\nCannot open image file!\n");
return(0);
} else {
im_file = gdImageCreateFromGif(image);
fclose(image);
gdImageCopy(im_final, im_file,
destx, Ø, Ø, Ø, real_width, real_height);
destx += real_width;
gdImageDestroy(im_file);
}
}
|