Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use PHP to split an image into pixel divs

This is tricky to explain, but for curiosities sake, I'd like to grab an image with PHP, split it into 1 pixel parts and do a foreach and assign each pixel to a div as an image/background image. So when the picture is displayed on the screen it looks whole, but its actually lots of 1px divs.

Using GD or a similar library, is this possible?

(Also, if this is easier with Javascript and Canvas then i'd be interested to know)

like image 328
benhowdle89 Avatar asked Nov 06 '11 20:11

benhowdle89


3 Answers

As others have said, you'd need to use the imagecolorat function to select the image at each pixel, then loop through and render the elements as necessary.

Just because I found this interesting more so than practical I had a play around with it.

Below is some quickly thrown together code which demonstrates a couple of outputs from this. image.jpg is a 50x39px image of a monkey which amounts to 1950 1x1px images. The image below shows the output- the first image is the original, the second is the one with a matrix of 1x1px images as div backgrounds, the third is the hex colour picked from the original then background:#xxxxxx; on that 1x1px div. Be warned, if you test this use a small image! as obviously it generates an image for each pixel in the original image.

For future readers, this is more a proof of concept and should not be used in a production environment!

Edit: The third image in the screenshot obviously isn't rendered correctly- however this now works thanks to a suggestion by minitech. The code below has been amended to reflect this change.

Original, 1px rendered, 1px hex colour rendered

<?php

$im = imagecreatefromjpeg("image.jpg");
$w = imagesx($im);
$h = imagesy($im);

?>

<div style="background:url(image.jpg);float:left;width:50px;height:39px;"></div>
<div style="clear:both;"></div>
-------<br />
<div style="clear:both;"></div>

<?php

/*
 * Do it with image creation, image per pixel
 */

for( $i = 0; $i < $w; $i++ ) {
    for( $j = 0; $j < $h; $j++ ) {      
        if( !file_exists( "dots/{$i}_{$j}.jpg" ) ) {
            $dot = imagecreatetruecolor(1, 1);
            imagefill($dot, 0, 0, imagecolorat($im, $i, $j));
            imagejpeg($dot, "dots/{$i}_{$j}.jpg", 100); 
            imagedestroy($dot);
        }

        $dots[$j][$i] = "dots/{$i}_{$j}.jpg";
    }
}

foreach( $dots as $column ) {
    foreach( $column as $row ) {
        echo '<div style="background:url('.$row.');float:left;width:1px;height:1px;"></div>';
    }
    echo '<div style="clear:both;"></div>';
}

/*
 * Do it with picking the hex colour
 */

?>

<div style="clear:both;"></div>
-------<br />
<div style="clear:both;"></div>

<?php

for( $i = 0; $i < $w; $i++ ) {
    for( $j = 0; $j < $h; $j++ ) {
        $array[$j][$i] = get_hex(imagecolorat($im, $i, $j));
    }
}

foreach( $array as $column ) {
    foreach( $column as $row ) {
        echo '<div style="background:'.$row.';float:left;width:1px;height:1px;"></div>';
    }
    echo '<div style="clear:both;"></div>';
}

function get_hex( $dec ) {
    $r = ($dec >> 16) & 0xFF;
    $g = ($dec >> 8) & 0xFF;
    $b = $dec & 0xFF;

    return '#' . pad_hex( dechex( $r ) ) . pad_hex( dechex( $g ) ) . pad_hex( dechex( $b ) ) ;
}

function pad_hex( $val ) {  
    return strlen( $val ) == 1 ? str_pad(dechex( $val ), 2, '0', STR_PAD_LEFT) : $val;
}

?>

Just had a bit more of a play around with it and here's the same achieved with canvas and jQuery. It could easily be done without jQuery though.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Test</title>
    <script src="http://code.jquery.com/jquery-1.7.min.js"></script>
    <script type="text/javascript">
    $(document).ready(function() {  
        var canvas = document.getElementById("myCanvas");  
        var ctx = canvas.getContext("2d");  

        var image = new Image();  
        image.src = "image.jpg";  
        $(image).load(function() {  
            ctx.drawImage(image, 0, 0);

            var imageData = ctx.getImageData(0, 0, 50, 39);  
            var pixels = imageData.data;

            ctx.clearRect(0, 0, canvas.width, canvas.height);
            $('canvas').remove();

            for (var i = 0, n = pixels.length; i < n; i += 4) {
                var r = pixels[i  ] // red
                var g = pixels[i+1] // green
                var b = pixels[i+2] // blue

                // i+3 is alpha (the fourth element)
                $('body').append('<div style="width:1px;background:rgb('+pixels[i  ]+','+g+','+b+');height:1px;float:left;"></div>');
                if( i % ( 4 * imageData.width ) == 0) {
                    //alert(i);
                    $('body').append('<div style="clear:both;"></div>');
                }
            }
        });
    });  
    </script>
  </head>
  <body>
    <p><canvas style="display:none;" id="myCanvas" width="350" height="250"></canvas></p>
  </body>
</html>
like image 168
Ben Swinburne Avatar answered Nov 09 '22 21:11

Ben Swinburne


Sure. All you need is GD's imagecolorat(). The result is just going to be a really, really big file, making this impractical for almost everything beyond an experiment.

like image 21
Pekka Avatar answered Nov 09 '22 23:11

Pekka


I was intrigued with your question so I had a go at making something that would create an image with html tags but the size was so huge it was unusable. I spent the rest of the day making it as small as possible by creating a dynamic stylesheet compressing any web safe hex colors into 3 character versions, adjusting the width of multiple consecutive pixels to span that number of columns and removing the border of an image and replacing it with css padding.

<?

echo number_format(create_cssi('myimage.png')/1024) .' kb';

function create_cssi($file,$link=false){
    set_time_limit(60);
    $a = get_array($file);
    arsort($a['p']);//sort the color counter high to low
    foreach($a['p'] as $col => $count){//create css pallete .cRGB or .cRRGGBB
        $css[] = '.c'.substr($col,1).'{background:'.$col.'}';
    }

    foreach($a['xy'] as $x => $xy){//create image pixels with css
        foreach($xy as $y => $color){
            if($color==$a['cb']['c']){//if the pixel is the same as the border color (top left pixel) then don't use a class
                $cssi[] = '<i></i>';
            }else{//otherwise apply the color class
                $cssi[] = '<i class=c'.substr($color,1).'></i>';
            }
        }
        $cssi[] = '<div class="cb"></div>';//new line: .cb{clear:both;}
    }

    //now it gets a bit more messy, I did this part after to further compress the html
    //this finds all of the consecutive empty tags (<i></i><i></i><i></i>) and replaced them with single tags of the same width:
    //<i></i><i></i><i></i>
    //<i class="s3"></i>

    $cssi = implode('',$cssi);
    $counters = array();
    preg_match_all('%(<i></i>)+%', $cssi, $result, PREG_SET_ORDER);
    for ($matchi = 0; $matchi < count($result); $matchi++) {
        for ($backrefi = 0; $backrefi < count($result[$matchi]); $backrefi++) {
            $count = substr_count($result[$matchi][0], '/');
            if($count>2){//3 or more consecutive tags
                $counters[$result[$matchi][0]] = substr_count($result[$matchi][0], '/');
            }
        }
    }
    $counters = array_unique($counters);
    $keys = array_map('strlen', array_keys($counters));//sort counters by key length ensuring the longest is first
    array_multisort($keys, SORT_DESC, $counters);
    $find = array();
    $replace = array();
    foreach($counters as $i => $c){
        $css[] = '.s'.$c.'{width:'.$c.'px}';//create a css class for the width
        $find[] = $i;                           //e.g. <i></i><i></i><i></i><i></i><i></i><i></i>
        $replace[] = '<i class="s'.$c.'"></i>'; //e.g. <i class="s6"></i>
    }
    $cssi = str_replace($find,$replace,$cssi);//do the highly inefficient find and replace!


    //still with me?
    //OK, now for all of the other colors - essentially the same thing but we're also saving the color in the counter array

    foreach($a['p'] as $span_color => $ct){
        $counters = array();
        if($ct>10){
            preg_match_all('%(<i class=c'.substr($span_color,1).'></i>)+%', $cssi, $result, PREG_SET_ORDER);
            for ($matchi = 0; $matchi < count($result); $matchi++) {
                for ($backrefi = 0; $backrefi < count($result[$matchi]); $backrefi++) {
                    $count = substr_count($result[$matchi][0], '/');
                    if($count>2){
                        $counters[$result[$matchi][0]] = array(substr_count($result[$matchi][0], '/'),'c'.substr($span_color,1));
                    }
                }
            }

            $keys = array_map('strlen', array_keys($counters));
            array_multisort($keys, SORT_DESC, $counters);

            $find = array();
            $replace = array();
            foreach($counters as $i => $c){
                $css[] = '.s'.$c[0].'{width:'.$c[0].'px}';
                $find[] = $i;
                $replace[] = '<i class="s'.$c[0].' '.$c[1].'"></i>';//$c[0] is the span width and $c[1] is the color class
            }

            $cssi = str_replace($find,$replace,$cssi);
        }
    }
    $css = array_unique($css);//strip out any diplicated css
    $style = '<style>.cb{clear:both;}i{width:1px;height:1px;float:left;}'.implode('',$css).'</style>';//build the style tag

    if($link!==false){//do we want this image linked?
        $pic = '<a href="'.$link.'">'.$cssi.'</a>';
    }else{
        $pic = $cssi;
    }

    //combine css pallete, image divs and wrapper and use the border removal valued as padding
    $tofile = $style.'<div style="width:'.$a['w'].'px;height:'.$a['h'].'px; padding:'.$a['cb']['t'].'px '.$a['cb']['r'].'px '.$a['cb']['b'].'px '.$a['cb']['l'].'px;background:'.$a['cb']['c'].';">'.$pic.'</div>';

    echo $tofile;//output to screen
    file_put_contents('logo.htm',$tofile);//store in a file
    return(strlen($tofile));//return the file size

}

function get_array($path){
    $img = imagecreatefromfile($path);//create the image from the path or remote uri
    $cb['t'] = 0;
    $cb['b'] = 0;
    $cb['l'] = 0;
    $cb['r'] = 0;
    $cb['c'] = imagecolorat($img, 0, 0);//get the top left pixel color (used for removing borders

    for(; $cb['t'] < imagesy($img); ++$cb['t']) {
        for($x = 0; $x < imagesx($img); ++$x) {
            if(imagecolorat($img, $x, $cb['t']) != $cb['c']) {
                break 2;
            }
        }
    }

    //find a pizel that is not the top left corner color on the bottom
    for(; $cb['b'] < imagesy($img); ++$cb['b']) {
        for($x = 0; $x < imagesx($img); ++$x) {
            if(imagecolorat($img, $x, imagesy($img) - $cb['b']-1) != $cb['c']) {
                break 2;
            }
        }
    }

    //find a pizel that is not the top left corner color on the left
    for(; $cb['l'] < imagesx($img); ++$cb['l']) {
        for($y = 0; $y < imagesy($img); ++$y) {
            if(imagecolorat($img, $cb['l'], $y) != $cb['c']) {
                break 2;
            }
        }
    }

    //find a pizel that is not the top left corner color on the right
    for(; $cb['r'] < imagesx($img); ++$cb['r']) {
        for($y = 0; $y < imagesy($img); ++$y) {
            if(imagecolorat($img, imagesx($img) - $cb['r']-1, $y) != $cb['c']) {
                break 2;
            }
        }
    }
    $r = ($cb['c'] >> 16) & 0xFF;
    $g = ($cb['c'] >> 8) & 0xFF;
    $b = $cb['c'] & 0xFF;
    $cb['c'] = rgb2hex($r,$g,$b);//convert the top left pixel color to hex

    $newimg = imagecreatetruecolor(//create a new image the size of the none bordered image
        imagesx($img)-($cb['l']+$cb['r']),
        imagesy($img)-($cb['t']+$cb['b'])
    );

    imagecopy($newimg, $img, 0, 0, $cb['l'], $cb['t'], imagesx($newimg), imagesy($newimg));//copt the section of the image without the border to the new image

    $newimg = imagerotate($newimg, 270, 0);//don't ask, something drove me nots with my pixerl array so I just hacked it with a rotate and flip
    $newimg = ImageFlip($newimg);
    $imagew = imagesx($newimg);
    $imageh = imagesy($newimg);
    $xy = array();
    $p = array();

    for ($x = 0; $x <= $imagew-1; $x++) {//cycle through every pixel of the image to build and array $xy
        for ($y = 0;$y <= $imageh-1; $y++){
            $rgb = imagecolorat($newimg, $x, $y);
            $r = ($rgb >> 16) & 0xFF;
            $g = ($rgb >> 8) & 0xFF;
            $b = $rgb & 0xFF;
            $h = rgb2hex($r,$g,$b);
            $xy[$x][$y] = $h;
            @$p[$h]++;//count the occurences of each color
        }
    }
    return(array('xy'=>$xy,'p'=>$p,'w'=>$imageh,'h'=>$imagew,'cb'=>$cb));//return the pizel array ($xy), the color count ($p), the original height ($h), the original width ($w) and the crop box with color at the top left corner ($cb)
}

function rgb2hex($r,$g,$b) {
    $r = dechex($r);
    $g = dechex($g);
    $b = dechex($b);
    $rp = str_pad($r, 2, "0", STR_PAD_LEFT);
    $gp = str_pad($g, 2, "0", STR_PAD_LEFT);
    $bp = str_pad($b, 2, "0", STR_PAD_LEFT);
    $rr = str_split($rp);
    $gg = str_split($gp);
    $bb = str_split($bp);
    if($rr[0]==$rr[1]&&$gg[0]==$gg[1]&&$bb[0]==$bb[1]){//compress web safe colors to 3 character equivalent
        return('#'.$rr[0].$gg[0].$bb[0]);
    }else{
        return('#'.$rp.$gp.$bp);
    }
}

function imagecreatefromfile($path){//my fave imagecreate function
    $info = @getimagesize($path);
    if(!$info){
        return false;
    }
    $functions = array(
        IMAGETYPE_GIF => 'imagecreatefromgif',
        IMAGETYPE_JPEG => 'imagecreatefromjpeg',
        IMAGETYPE_PNG => 'imagecreatefrompng',
        IMAGETYPE_WBMP => 'imagecreatefromwbmp',
        IMAGETYPE_XBM => 'imagecreatefromwxbm',
    );
    return $functions[$info[2]]($path);
}

function ImageFlip($img){//image flip because I'm not great at arrays.
    $width = imagesx($img);
    $height = imagesy($img);
    $src_x = 0;
    $src_y = 0;
    $src_width = $width;
    $src_height = $height;
    $src_x = $width -1;
    $src_width = -$width;
    $imgdest =  imagecreatetruecolor($width, $height );
    if(imagecopyresampled($imgdest, $img, 0, 0, $src_x, $src_y , $width, $height, $src_width, $src_height)){
        return $imgdest;
    }
    return $img;
}

function pre($a){//just useful for outputting arrays in a <pre> tag, not used
    echo '<pre>';
    print_r($a);
    echo '</pre>';
}
?>

png input

From a 300x300 pixel png 86kb it creates a 1.1mb html equivalent

html output

Far better results can be made with images containing only a few colors like the twitter logo which "only" comes out at 78kb

twitter logo 300x300 pixels

Here's the output of a 40x40 pixel twitter logo

<style>.cb{clear:both;}i{width:1px;height:1px;float:left;}.c00aced{background:#00aced}.cfff{background:#fff}.c00a7ec{background:#00a7ec}.c00abed{background:#00abed}.c00a8ec{background:#00a8ec}.c00a9ed{background:#00a9ed}.c00a6ec{background:#00a6ec}.c00aaed{background:#00aaed}.c00a8ed{background:#00a8ed}.cf8fdfe{background:#f8fdfe}.c00a9ec{background:#00a9ec}.cfeffff{background:#feffff}.cfdfeff{background:#fdfeff}.cf4fbfe{background:#f4fbfe}.c02aced{background:#02aced}.c5cc9f2{background:#5cc9f2}.c09aeed{background:#09aeed}.cf6fcfe{background:#f6fcfe}.c6fcff4{background:#6fcff4}.c00aaec{background:#00aaec}.cebf8fd{background:#ebf8fd}.c04abed{background:#04abed}.c4ec5f2{background:#4ec5f2}.c07aeed{background:#07aeed}.c2bb8ef{background:#2bb8ef}.c63cbf3{background:#63cbf3}.c03aced{background:#03aced}.c11b1ee{background:#11b1ee}.c33bcf0{background:#33bcf0}.cc1ebfb{background:#c1ebfb}.cb1e5f9{background:#b1e5f9}.c04abec{background:#04abec}.cd8f2fc{background:#d8f2fc}.cd0effb{background:#d0effb}.ce1f5fc{background:#e1f5fc}.cf5fcfe{background:#f5fcfe}.ce2f5fc{background:#e2f5fc}.ccfeffb{background:#cfeffb}.c18b1ed{background:#18b1ed}.c3ebfef{background:#3ebfef}.ce3f5fc{background:#e3f5fc}.c20b4ee{background:#20b4ee}.c03abec{background:#03abec}.c42c0f1{background:#42c0f1}.c0bafed{background:#0bafed}.cb0e5f9{background:#b0e5f9}.ce8f7fd{background:#e8f7fd}.cfafdfe{background:#fafdfe}.c05adec{background:#05adec}.c30baf0{background:#30baf0}.c04aced{background:#04aced}.c45c2f0{background:#45c2f0}.cade4f9{background:#ade4f9}.cd4f0fb{background:#d4f0fb}.c85d6f4{background:#85d6f4}.c7fd4f5{background:#7fd4f5}.c6ecff4{background:#6ecff4}.ca7e2f8{background:#a7e2f8}.c46c1f1{background:#46c1f1}.ccdeefa{background:#cdeefa}.c54c6f1{background:#54c6f1}.c7cd3f4{background:#7cd3f4}.c8cd8f5{background:#8cd8f5}.c42c1f0{background:#42c1f0}.cb9e7f8{background:#b9e7f8}.cd1effb{background:#d1effb}.c62cbf3{background:#62cbf3}.cdff4fc{background:#dff4fc}.c5dc9f3{background:#5dc9f3}.cc3ebfa{background:#c3ebfa}.cd2f0fc{background:#d2f0fc}.c8dd9f6{background:#8dd9f6}.c13b1ee{background:#13b1ee}.c3dbef1{background:#3dbef1}.c4ec4f2{background:#4ec4f2}.ccceefb{background:#cceefb}.c9ddef7{background:#9ddef7}.c4dc4f2{background:#4dc4f2}.c22b6ef{background:#22b6ef}.ce0f4fc{background:#e0f4fc}.cc3ebfb{background:#c3ebfb}.cc8edfb{background:#c8edfb}.cd7f2fc{background:#d7f2fc}.cf7fcfe{background:#f7fcfe}.ce6f7fd{background:#e6f7fd}.c03aded{background:#03aded}.c13b2ee{background:#13b2ee}.ca8e2f8{background:#a8e2f8}.c00a4eb{background:#00a4eb}.c00a2eb{background:#00a2eb}.c0dafee{background:#0dafee}.c3dbef0{background:#3dbef0}.cdef4fc{background:#def4fc}.ccaecf9{background:#caecf9}.c64cbf3{background:#64cbf3}.cbee9fa{background:#bee9fa}.c6bcef4{background:#6bcef4}.c0baeed{background:#0baeed}.c1fb4ee{background:#1fb4ee}.c98ddf7{background:#98ddf7}.ca2e1f8{background:#a2e1f8}.cf9fdfe{background:#f9fdfe}.cecf9fd{background:#ecf9fd}.c8fdaf6{background:#8fdaf6}.c1ab2ee{background:#1ab2ee}.c7ad3f5{background:#7ad3f5}.c07aced{background:#07aced}.c96ddf7{background:#96ddf7}.c7dd4f5{background:#7dd4f5}.c20b6ef{background:#20b6ef}.cdcf3fc{background:#dcf3fc}.c77d1f3{background:#77d1f3}.ce8f7fc{background:#e8f7fc}.c1db4ee{background:#1db4ee}.c0fafed{background:#0fafed}.cd9f2fb{background:#d9f2fb}.c00a4ec{background:#00a4ec}.c35bdf0{background:#35bdf0}.c77d3f5{background:#77d3f5}.c2fbbf0{background:#2fbbf0}.c23b6ee{background:#23b6ee}.ce7f7fd{background:#e7f7fd}.c0db0ee{background:#0db0ee}.c5fcaf2{background:#5fcaf2}.cb5e5f7{background:#b5e5f7}.cd1f0fb{background:#d1f0fb}.cbce9fa{background:#bce9fa}.ca5e1f8{background:#a5e1f8}.c47c2f1{background:#47c2f1}.c66ccf2{background:#66ccf2}.c1cb3ee{background:#1cb3ee}.c8ddaf6{background:#8ddaf6}.c16b1ee{background:#16b1ee}.cb0e4f9{background:#b0e4f9}.cfbfeff{background:#fbfeff}.ce9f7fd{background:#e9f7fd}.c3fc0f1{background:#3fc0f1}.c37bef1{background:#37bef1}.cbce8fa{background:#bce8fa}.c6acdf4{background:#6acdf4}.c41c0f1{background:#41c0f1}.cf3fbfd{background:#f3fbfd}.c47c1f1{background:#47c1f1}.c87d7f5{background:#87d7f5}.c3fbeef{background:#3fbeef}.cc8edfa{background:#c8edfa}.ca2dff6{background:#a2dff6}.c4ac2f1{background:#4ac2f1}.c37bcf0{background:#37bcf0}.cc6ecfa{background:#c6ecfa}.cc1eafa{background:#c1eafa}.c01aced{background:#01aced}.cc7ecfa{background:#c7ecfa}.c7ed4f5{background:#7ed4f5}.c46c2f1{background:#46c2f1}.c4cc5f2{background:#4cc5f2}.ce9f8fd{background:#e9f8fd}.cd1f0fc{background:#d1f0fc}.c3bbef1{background:#3bbef1}.c78d2f5{background:#78d2f5}.cace4f9{background:#ace4f9}.cb1e4f9{background:#b1e4f9}.cf2fbfe{background:#f2fbfe}.c85d6f6{background:#85d6f6}.cf3fbfe{background:#f3fbfe}.c18b4ee{background:#18b4ee}.c0fb0ee{background:#0fb0ee}.c51c6f2{background:#51c6f2}.c5dcaf3{background:#5dcaf3}.c63ccf3{background:#63ccf3}.c26b7ef{background:#26b7ef}.c02aaec{background:#02aaec}.ccaedfa{background:#caedfa}.cdaf3fc{background:#daf3fc}.c05aded{background:#05aded}.c08aced{background:#08aced}.c62caf2{background:#62caf2}.c00a3eb{background:#00a3eb}.c0aaeed{background:#0aaeed}.c16b3ee{background:#16b3ee}.c19b4ef{background:#19b4ef}.c82d5f5{background:#82d5f5}.ca0dff8{background:#a0dff8}.c71d0f4{background:#71d0f4}.c88d7f6{background:#88d7f6}.c40c0f1{background:#40c0f1}.c76d2f4{background:#76d2f4}.ca3e0f8{background:#a3e0f8}.c00a5ec{background:#00a5ec}.c1db5ef{background:#1db5ef}.c2cb8ef{background:#2cb8ef}.c5fcaf3{background:#5fcaf3}.s24{width:24px}.s23{width:23px}.s19{width:19px}.s18{width:18px}.s17{width:17px}.s16{width:16px}.s15{width:15px}.s14{width:14px}.s13{width:13px}.s12{width:12px}.s11{width:11px}.s10{width:10px}.s9{width:9px}.s8{width:8px}.s7{width:7px}.s6{width:6px}.s5{width:5px}.s4{width:4px}.s3{width:3px}.s29{width:29px}.s28{width:28px}.s27{width:27px}.s26{width:26px}.s22{width:22px}</style><div style="width:40px;height:33px; padding:3px 0px 4px 0px;background:#fff;"><i class="s24"></i><i class=cbce8fa></i><i class=c6acdf4></i><i class=c41c0f1></i><i class=c37bef1></i><i class=c3fc0f1></i><i class=c63cbf3></i><i class=cb0e4f9></i><i class=cfbfeff></i><i class="s6"></i><i class=ce9f7fd></i><i></i><div class="cb"></div><i></i><i></i><i class=cf4fbfe></i><i class=cf3fbfd></i><i class="s18"></i><i class=cd8f2fc></i><i class=c47c1f1></i><i class=c00a9ec></i><i class=c00a7ec></i><i class=c00a8ec></i><i class=c00a9ed></i><i class=c00a9ec></i><i class=c00a7ec></i><i class=c00a8ec></i><i class=c37bcf0></i><i class=cc6ecfa></i><i></i><i></i><i class=cfdfeff></i><i class=cc1eafa></i><i class=c4ac2f1></i><i class=ca2dff6></i><i></i><div class="cb"></div><i></i><i></i><i class=c87d7f5></i><i class=c3fbeef></i><i class=cf8fdfe></i><i class="s16"></i><i class=cc8edfa></i><i class=c16b1ee></i><i class=c00a7ec></i><i class="s7 c00aced"></i><i class=c00a8ec></i><i class=c09aeed></i><i class=c8ddaf6></i><i class=c77d3f5></i><i class=c2fbbf0></i><i class=c00a6ec></i><i class=c23b6ee></i><i class=cf6fcfe></i><i></i><div class="cb"></div><i></i><i class=cfeffff></i><i class=c35bdf0></i><i class=c00a4ec></i><i class=c4ec5f2></i><i class=cf8fdfe></i><i class="s14"></i><i class=ce8f7fc></i><i class=c1db4ee></i><i class=c00a8ed></i><i class="s9 c00aced"></i><i class=c00abed></i><i class=c00a8ec></i><i class=c00a7ec></i><i class=c00a7ec></i><i class=c0fafed></i><i class=cd9f2fb></i><i></i><i class=cf4fbfe></i><div class="cb"></div><i></i><i class=ce7f7fd></i><i class=c0db0ee></i><i class=c00abed></i><i class=c00a7ec></i><i class=c47c2f1></i><i class=cebf8fd></i><i class="s13"></i><i class=c66ccf2></i><i class=c00a6ec></i><i class="s12 c00aced"></i><i class=c00abed></i><i class=c1cb3ee></i><i class=ca5e1f8></i><i class=cbce9fa></i><i class=c5fcaf2></i><i class=cb5e5f7></i><div class="cb"></div><i></i><i class=cd1f0fb></i><i class=c01aced></i><i class=c00aced></i><i class=c00aced></i><i class=c00a7ec></i><i class=c2bb8ef></i><i class=cc7ecfa></i><i class="s11"></i><i class=ce2f5fc></i><i class=c0aaeed></i><i class=c00abed></i><i class="s12 c00aced"></i><i class=c00abed></i><i class=c16b3ee></i><i class=c19b4ef></i><i class=c00a3eb></i><i class=c62caf2></i><i class=cfdfeff></i><div class="cb"></div><i></i><i class=cdaf3fc></i><i class=c05aded></i><i class=c00abed></i><i class=c00aced></i><i class=c00aced></i><i class=c00a9ed></i><i class=c08aced></i><i class=c82d5f5></i><i class=cf5fcfe></i><i class="s9"></i><i class=ca0dff8></i><i class=c00a7ec></i><i class="s14 c00aced"></i><i class=c00abed></i><i class=c00a5ec></i><i class=c5cc9f2></i><i class=cfeffff></i><i></i><div class="cb"></div><i></i><i class=cf6fcfe></i><i class=c1db5ef></i><i class=c00aaed></i><i class="s3 c00aced"></i><i class=c00abed></i><i class=c00a7ec></i><i class=c2cb8ef></i><i class=ca3e0f8></i><i class=cf8fdfe></i><i class="s7"></i><i class=c76d2f4></i><i class=c00a7ec></i><i class="s14 c00aced"></i><i class=c04abed></i><i class=c71d0f4></i><i class=cfeffff></i><i></i><i></i><div class="cb"></div><i></i><i></i><i class=c5cc9f2></i><i class=c00a7ec></i><i class="s5 c00aced"></i><i class=c00a9ed></i><i class=c00a8ec></i><i class=c2bb8ef></i><i class=c88d7f6></i><i class=cd8f2fc></i><i class="s5"></i><i class=c6fcff4></i><i class=c00a7ec></i><i class="s13 c00aced"></i><i class=c00a9ec></i><i class=c40c0f1></i><i class="s4"></i><div class="cb"></div><i></i><i></i><i class=ccaedfa></i><i class=c02aaec></i><i class=c00abed></i><i class="s6 c00aced"></i><i class=c00a9ed></i><i class=c00a7ec></i><i class=c07aeed></i><i class=c3bbef1></i><i class=c78d2f5></i><i class=cace4f9></i><i class=cd1f0fc></i><i class=ce9f8fd></i><i class=c7ed4f5></i><i class=c00a8ec></i><i class="s13 c00aced"></i><i class=c00a8ec></i><i class=c46c2f1></i><i class="s4"></i><div class="cb"></div><i class="s3"></i><i class=c77d1f3></i><i class=c00a6ec></i><i class="s8 c00aced"></i><i class=c00abed></i><i class=c00a9ed></i><i class=c00a7ec></i><i class=c00a8ec></i><i class=c00aced></i><i class=c11b1ee></i><i class=c11b1ee></i><i class="s14 c00aced"></i><i class=c00a8ec></i><i class=c4cc5f2></i><i class="s4"></i><div class="cb"></div><i></i><i class=ce1f5fc></i><i class=cb1e4f9></i><i class=cf2fbfe></i><i class=c5dcaf3></i><i class=c04abed></i><i class="s12 c00aced"></i><i class=c00abed></i><i class=c00abed></i><i class="s14 c00aced"></i><i class=c00a8ec></i><i class=c63ccf3></i><i class="s4"></i><div class="cb"></div><i></i><i class=cd0effb></i><i class=c00a9ec></i><i class=c26b7ef></i><i class=c51c6f2></i><i class=c0fb0ee></i><i class=c00abed></i><i class="s27 c00aced"></i><i class=c00a7ec></i><i class=c85d6f6></i><i class="s4"></i><div class="cb"></div><i></i><i class=cf3fbfe></i><i class=c18b4ee></i><i class=c00a8ed></i><i class=c00a9ed></i><i class="s29 c00aced"></i><i class=c00a8ec></i><i class=cb1e5f9></i><i class="s4"></i><div class="cb"></div><i></i><i></i><i class=c5fcaf3></i><i class=c00a7ec></i><i class="s29 c00aced"></i><i class=c00abed></i><i class=c07aeed></i><i class=cdef4fc></i><i class="s4"></i><div class="cb"></div><i></i><i></i><i class=cd0effb></i><i class=c04abec></i><i class=c00abed></i><i class="s28 c00aced"></i><i class=c00a9ed></i><i class=c33bcf0></i><i class=cfeffff></i><i class="s4"></i><div class="cb"></div><i class="s3"></i><i class=c85d6f4></i><i class=c00a6ec></i><i class="s28 c00aced"></i><i class=c00a7ec></i><i class=c7fd4f5></i><i class="s5"></i><div class="cb"></div><i class="s4"></i><i class=c6ecff4></i><i class=c00a7ec></i><i class=c00a9ed></i><i class="s26 c00aced"></i><i class=c03aced></i><i class=cd4f0fb></i><i class="s5"></i><div class="cb"></div><i class="s5"></i><i class=cade4f9></i><i class=c30baf0></i><i class=c04aced></i><i class="s24 c00aced"></i><i class=c00a8ed></i><i class=c45c2f0></i><i class="s6"></i><div class="cb"></div><i class="s4"></i><i class=ce1f5fc></i><i class=cb1e5f9></i><i class=ca7e2f8></i><i class=c46c1f1></i><i class=c02aced></i><i class="s23 c00aced"></i><i class=c00a8ec></i><i class=cb9e7f8></i><i class="s6"></i><div class="cb"></div><i class="s4"></i><i class=ce2f5fc></i><i class=c05adec></i><i class=c00a8ed></i><i class="s24 c00aced"></i><i class=c00a8ed></i><i class=c42c1f0></i><i class="s7"></i><div class="cb"></div><i class="s5"></i><i class=c8cd8f5></i><i class=c00a6ec></i><i class="s23 c00aced"></i><i class=c00abed></i><i class=c04abec></i><i class=ccdeefa></i><i class="s7"></i><div class="cb"></div><i class="s5"></i><i class=cfdfeff></i><i class=c54c6f1></i><i class=c00a6ec></i><i class="s22 c00aced"></i><i class=c00a6ec></i><i class=c7cd3f4></i><i class="s8"></i><div class="cb"></div><i class="s6"></i><i class=cf8fdfe></i><i class=c62cbf3></i><i class=c00a8ec></i><i class=c00a8ec></i><i class=c00abed></i><i class="s18 c00aced"></i><i class=c00a8ed></i><i class=c3ebfef></i><i class=cfafdfe></i><i class="s8"></i><div class="cb"></div><i class="s8"></i><i class=cb0e5f9></i><i class=c42c0f1></i><i class=c0bafed></i><i class=c02aced></i><i class="s16 c00aced"></i><i class=c00a9ed></i><i class=c20b4ee></i><i class=ce3f5fc></i><i class="s9"></i><div class="cb"></div><i class="s10"></i><i class=ce8f7fd></i><i class=c6fcff4></i><i class=c03abec></i><i class="s14 c00aced"></i><i class=c00a9ed></i><i class=c18b1ed></i><i class=cd1effb></i><i class="s10"></i><div class="cb"></div><i class="s9"></i><i class=cdcf3fc></i><i class=c6bcef4></i><i class=c0baeed></i><i class=c00abed></i><i class="s13 c00aced"></i><i class=c00a7ec></i><i class=c1fb4ee></i><i class=ccfeffb></i><i class="s11"></i><div class="cb"></div><i class="s6"></i><i class=cf5fcfe></i><i class=cbee9fa></i><i class=c64cbf3></i><i class=c0dafee></i><i class=c00a7ec></i><i class="s13 c00aced"></i><i class=c00abed></i><i class=c00a7ec></i><i class=c3dbef0></i><i class=cdff4fc></i><i class="s12"></i><div class="cb"></div><i class=ccaecf9></i><i class=c98ddf7></i><i class=ca2e1f8></i><i class=c96ddf7></i><i class=c7dd4f5></i><i class=c4ec5f2></i><i class=c20b6ef></i><i class=c00aaec></i><i class=c00a7ec></i><i class=c00abed></i><i class="s13 c00aced"></i><i class=c00a8ec></i><i class=c07aced></i><i class=c7ad3f5></i><i class=cf9fdfe></i><i class="s13"></i><div class="cb"></div><i class=cecf9fd></i><i class=c8fdaf6></i><i class=c1ab2ee></i><i class=c00a2eb></i><i class=c00a4eb></i><i class=c00a7ec></i><i class=c00aaed></i><i class="s13 c00aced"></i><i class=c00abed></i><i class=c00a7ec></i><i class=c00aaec></i><i class=c4ec4f2></i><i class=ccceefb></i><i class="s15"></i><div class="cb"></div><i></i><i></i><i class=cf4fbfe></i><i class=c9ddef7></i><i class=c3dbef1></i><i class=c03aced></i><i class=c00a7ec></i><i class=c00a8ec></i><i class=c00aaed></i><i class=c00abed></i><i class="s5 c00aced"></i><i class=c00abed></i><i class=c00abed></i><i class=c00a9ed></i><i class=c00a7ec></i><i class=c00a8ec></i><i class=c13b1ee></i><i class=c5dc9f3></i><i class=cc3ebfa></i><i class="s17"></i><div class="cb"></div><i class="s5"></i><i class=cd2f0fc></i><i class=c8dd9f6></i><i class=c4dc4f2></i><i class=c22b6ef></i><i class=c09aeed></i><i class=c00aced></i><i class=c00aaed></i><i class=c00aaed></i><i class=c00aaed></i><i class=c00abed></i><i class=c03aded></i><i class=c13b2ee></i><i class=c33bcf0></i><i class=c63cbf3></i><i class=ca8e2f8></i><i class=ce6f7fd></i><i class="s19"></i><div class="cb"></div><i class="s8"></i><i class=cf7fcfe></i><i class=ce0f4fc></i><i class=ccfeffb></i><i class=cc3ebfb></i><i class=cc1ebfb></i><i class=cc1ebfb></i><i class=cc8edfb></i><i class=cd7f2fc></i><i class=cebf8fd></i><i class="s23"></i><div class="cb"></div></div>
like image 1
Andy Gee Avatar answered Nov 09 '22 22:11

Andy Gee