Special FX, Interlacing

In image terms, "interlacing" means two quite different things. One is a special effect, and the other is a form of progressive image download that allows users to see part of the image before it is fully downloaded. As this is the special effects section, we will be looking at the former meaning: interlacing is when an image is only visible on alternate lines. Although this might sound odd, it has a very cinematic look to it and you will often see it in movies and games where they try to depict electronic viewing devices such as sniper aiming scopes.

In code terms, we need to loop through the image row by row, and, if the row is odd-numbered (i.e. row 1, 3, 5, 7, etc) we should colour all pixels on that row black. As with the imagetruecolortopalette() function, our interlacing function should accept the image to interlace as a reference so that all changes are made directly onto the image.

Here is how that looks in PHP:

<?php
    function interlace (&$image) {
        $imagex = imagesx($image);
        $imagey = imagesy($image);
        GLOBAL $black;
        // loop through all rows in the image

        for ($y = 0; $y < $imagey; ++$y) {
            // if it is even...
            if ($y % 2) {
                // loop through all pixels in this row
                for ($x = 0; $x < $imagex; ++$x) {
                    // set them to black
                    ImageSetPixel($image, $x, $y, $black);
                }
            }
        }
    }

    $image = imagecreatefrompng("space.png");
    $black = imagecolorallocate($image, 0, 0, 0);
    interlace($image);

    header("image/png");
    imagepng($image);
    imagedestroy($image);
?>

Note that the decision whether to blacken a row is dependent on the $y % 2 condition, which means, "if the remainder of $y divided by 2 is equal to 1". As $y is set to the current row, then this will evaluate as true for all odd rows - 0 / 2 = remainder 0, 1 / 2 = remainder 1, 2 / 2 = remainder 0, 3 / 2 = remainder 1, etc.

Now, although the script above is quite fast, you can make it faster by eliminating the $x loop. Rather than individually setting all pixels on a row to black, it would be easier to change the entire row at once by drawing a line. For even more speed, you can drop the if statement altogether and just change the loop to $y = $y + 2 rather than ++$y - this means PHP will always draw the black lines, but skips a line in the loop automatically. These two changes would make the interlace() function look like this:

function interlace (&$image) {
    $imagex = imagesx($image);
    $imagey = imagesy($image);
    GLOBAL $black;

    for ($y = 1; $y < $imagey; $y += 2) {
        imageline($image, 0, $y, $imagex, $y, $black);
    }
}

If you recall, the parameters to imageline() are the image to draw on, the starting X and Y co-ordinates, and the ending X and Y co-ordinates. As such, that above line of code draws from X = 0 to X = the width of the image, all in black - just like our loop did, except much faster.

Keep the previous code in mind, however - looping through rows and columns is a skill that will be heavily used in later image effects.

 

Want to learn PHP 7?

Hacking with PHP has been fully updated for PHP 7, and is now available as a downloadable PDF. Get over 1200 pages of hands-on PHP learning today!

If this was helpful, please take a moment to tell others about Hacking with PHP by tweeting about it!

Next chapter: Special FX, Screen >>

Previous chapter: Special FX, Colour reduction

Jump to:

 

Home: Table of Contents

Copyright ©2015 Paul Hudson. Follow me: @twostraws.