Team LiB
Previous Section Next Section

General Image Manipulation

The GD extension, as you might expect, supports a number of general image- manipulation functions. These functions include copying portions of one image to another, resizing images, and rotating images (to name a few). For most circumstances, these are the types of functions you will most likely use when working with preexisting images to do things such as creating thumbnails. This section of the chapter will discuss all these manipulation functions and provide examples of their use.

Copying One Image to Another

The first topic I will discuss in this section is copying a portion (or all) of one image in memory to another canvas. In fact, six (technically seven) functions accomplish this taskeach with a slightly different behavior. The most general of these functions is the imagecopy() function, which has the following syntax:

imagecopy($dest_img_r, $src_img_r, $dest_x,
                  $dest_y, $src_x, $src_y, $src_w, $src_h);

$dest_img_r/$src_img_r are the image resources for the destination and source canvases, respectively; $dest_x/$dest_y is the coordinate on the destination canvas on which to place the copied portion of the source image, and $src_x, $src_y, $src_w, and $src_h define the region to be copied from the source image.

Although this function has many uses, one particular application that seems to stand out is the tried-and-true Web page counter script. The reason is that most counter images you find online are distributed as a single image containing all the digits 09. To generate a dynamic number from this image, you'll need to copy the appropriate portions of it into a new image. For your reference, Listing 27.18 uses the imagecopy() function to do just that (the file name is again a placeholder):

NOTE

The following script relies on a specific digit image to function properly. The specific image can be found at http://www.digitmania.holowww.com/single.cgi?sbgs, and many more can be found at http://www.digitmania.holowww.com. Also note that different digit images may require the DIGIT_WIDTH and DIGIT_HEIGHT constants to be changed.


Listing 27.18. Using imagecopy() to Make a Graphical Counter
<?php
    define("C_DIGITS", "sbgs.gif");
    define("DIGIT_WIDTH", 12);
    define("DIGIT_HEIGHT", 13);

    $number = 123412341234;
    settype($number, "string");
    $t_digits = strlen($number);

    $width = ($t_digits * DIGIT_WIDTH) + 3;
    $height = DIGIT_HEIGHT + 3;

    $img = imagecreate($width, $height);
    $digits = imagecreatefromgif(C_DIGITS);

    $background = $black = imagecolorallocate($img, 0, 0, 0);

    $dest_x_offset = 1;
    for($i = 0; $i < $t_digits; $i++) {

         $cur_digit = (int)$number[$i];
         $digit_offset = (DIGIT_WIDTH * $cur_digit) - 1;
         imagecopy($img, $digits,
                   $dest_x_offset, 1,
                   $digit_offset,
                   0,
                   DIGIT_WIDTH + 1,
                   DIGIT_HEIGHT + 1);
         $dest_x_offset += DIGIT_WIDTH;
    }

    header("Content-Type: image/png");
    imagepng($img);
?>

Notice that in Listing 27.18, this script takes the number stored in the variable $number and creates a graphical representation of it using the digit image found in the filename pointed to by the C_DIGITS constant. To determine the number of digits in the number, I've used settype() to convert the integer to a string and used strlen(). The width of the destination image is then calculated by multiplying the number of digits in the number by the digit width stored in DIGIT_WIDTH and adding 3 (we add 3 to create a border around the image). The digit image is then loaded, and we enter the for loop, which creates the actual image.

Because we need to keep track of the starting coordinate for the next digit, the $dest_x_offset variable is created (there is no need for keeping track of the y offset, because it is constant). After we start creating the image, we determine the X offset within the digit image by multiplying the current digit by the DIGIT_WIDTH constant and subtracting 1 (because all canvases start at 0,0 not 1,1). At this point we have all the information we need to copy the appropriate digit from the digit image into our destination canvas, which is exactly what is done using the imagecopy() function. After the current digit image has been copied to the destination canvas, we advance the $dest_x_offset variable by DIGIT_WIDTH (to the start of the next spot in the canvas). This process continues until the number has been completely generated, at which point it is displayed to the user. When it is all completed, the canvas $img contains the appropriate pieces of the digit image arranged to create the number stored in the $number variable. All that is needed now is to keep track of the number of hits and you'd have a PHP-based graphical hit counter.

Figure 27.18. A graphical counter using PHP.


Now that you have been introduced to the imagecopy() function, I'll discuss the other functions in the imagecopy() family. The first of these functions is the imagecopymerge() function, which uses the following syntax:

imagecopymerge($dest_img_r, $src_img_r, $dest_x,
                      $dest_y, $src_x, $src_y, $src_w,
                      $src_h, $percent);

The first eight parameters are identical to those found in the imagecopy() function, and $percent is a percentage (1 = 1%) indicating how much of the source image should be merged with the destination image. If $percent is 100, this function behaves exactly as imagecopy(). A common percentage to use is 50%, which is what I have chosen to use in Listing 27.19 (me.png is a placeholder):

Listing 27.19. Using the imagecopymerge() Function
<?php
    define("SRC_FILE", "me.png");

    $img = imagecreatefrompng(SRC_FILE);
    $img_copy = imagecreatefrompng(SRC_FILE);

    imagecopymerge($img_copy, $img, 10, 10, 0,
                   0, imagesx($img), imagesy($img), 50);

    header("Content-Type: image/png");
    imagepng($img_copy);
?>

Figure 27.19. Merging images using GD.


As you can see, the imagecopymerge() function is quite similar to the alpha-blending functions that I described earlier in the chapter. However, instead of blending solid colors, images are blended. For situations where you would like the hue of the source image to be preserved, the GD extension also provides the imagecopymergegray() function. This function's syntax and usage is identical to the imagecopymerge() function, with the one significant difference that the source image will be converted to a grayscale image prior to copying.

There are times (when dynamically creating thumbnails, for instance) when it is desirable to resize an image to a different width or height. For these purposes the GD extension provides two functions that enable you to duplicate and resize a given image: imagecopyresized() and imagecopyresampled(). The syntax for imagecopyresized() is as follows:

imagecopyresized($dest_img_r, $src_img_r, $dest_x,
                        $dest_y, $src_x, $src_y, $dest_w,
                        $dest_h, $src_w, $src_h);

$dest_img_r and $src_img_r represent the destination and source image resources, and the region to copy is defined by a rectangle starting from the coordinate ($src_x, $src_y) with a width of $src_w and height of $src_h. The region being copied will be resized as necessary to fit into the destination rectangle starting from the coordinate ($dest_x, $dest_y) with a width of $dest_w and $dest_h. An example of using imagecopyresized() to create a thumbnail image dynamically is shown in Listing 27.20:

Listing 27.20. Using the imagecopyresized() Function
<?php

        define("T_WIDTH", 100);
        define("T_HEIGHT", 100);

        $img = imagecreatefrompng("me.png");
        $img_copy = imagecreate(T_WIDTH, T_HEIGHT);

        $width = imagesx($img);
        $height = imagesy($img);

        imagecopyresized($img_copy, $img, 0, 0, 0, 0,
                         T_WIDTH, T_HEIGHT, $width, $height);

        header("Content-type: image/png");
        imagepng($img_copy);
?>

As an alternative to imagecopyresized(), the GD extension provides the imagecopyresampled() function. Although these two functions are identical in syntax (in terms of the parameters each accepts), the imagecopyresampled() function will not only copy and resize the image, it will interpolate the pixels of the resized image, allowing it to retain a considerable amount of detail compared to its counterpart.

Figure 27.20. Resizing images using GD.


NOTE

When working with either the imagecopyresized() or imagecopyresampled() functions, it is important to note that the results may not be as expected when working with palette images. Because palette images are restricted to 256 colors, certain resized images may not appear as expected (or even be visually present at all). To correct this problem, true-color images must be used (for instance, those created with imagecreatetruecolor()).


Duplicating Palettes

The last function related to copying image data from one image canvas to another is the imagepalettecopy() function. This function enables you to duplicate the palette from the source image in the destination image. The syntax for the imagepalettecopy() function is as follows:

imagepalettecopy($dest_img_r, $src_img_r);

$dest_img_r and $src_img_r are the destination and source image resources, respectively. Because palettes can be restricted to 256 colors, when attempting to copy a palette the GD extension will follow the same rules as applied when using the imagecolorresolve() function. This means that if the color does not already exist in the destination palette, or the palette of the destination image is full, the closest alternative will be used.

    Team LiB
    Previous Section Next Section