~/devlog/procedural-favicon

Procedural favicon

2020/03/11 15:21

10 different icons:
Source code:
favicon.php
mt_srand(); // random seed

$pixel_size = 2;

$width = $mat_w = 16;
$height = $mat_h = 16;

$img = imagecreatetruecolor($width, $height);

$col_min =  60;
$col_max = 200;

// color palette generation
$colors = [];
// starting colors
$num_of_generators = mt_rand(2, 12);
// final palette size
$num_of_colors = mt_rand(8, 16);

while ($num_of_colors <= $num_of_generators) $num_of_colors = mt_rand(8, 16);

$palette = imagecreatetruecolor($num_of_generators, 1);
// generate starting colors
for ($c=0; $c < $num_of_generators; $c++)
{
    imagesetpixel(
        $palette,
        $c,
        0,
        imagecolorallocate(
            $palette,
            mt_rand($col_min, $col_max) / ($c/2 + 1),
           mt_rand($col_min, $col_max) / ($c/2 + 1),
           mt_rand($col_min, $col_max) / ($c/2 + 1)
        )
    );
}

$palette = imagescale($palette, 100 * $num_of_generators, 1,  IMG_BILINEAR_FIXED);
$palette = imagescale($palette, $num_of_colors, 1, IMG_BILINEAR_FIXED);

$rnd = 0;

for ($c=0; $c < $num_of_colors; $c++)
{
    $colors[] = imagecolorat($palette, $c + $rnd, 0);
}

imagefilledrectangle($img, 0, 0, $width, $height, $colors[0]);

$goldColors = array(
    imagecolorallocate($img, 255, 222, 154),
    imagecolorallocate($img, 193, 154, 71),
    imagecolorallocate($img, 159, 126, 54)
);

$pattern_matrix = array(
    0 => array('x','x','x','x','x','x','x','x'),
    1 => array('x','p','p','a','p','a','a','a'),
    2 => array('x','p','p','p','r','r','r','r'),
    3 => array('x','a','p','r','r','r','r','r'),
    4 => array('x','p','r','r','r','r','r','r'),
    5 => array('x','a','r','r','r','r','r','r'),
    6 => array('x','a','r','r','r','r','r','r'),
    7 => array('x','a','r','r','r','r','r','r'),
);

$gold = false;

for($x = 0; $x < 8; $x++)
{
    for($y = 0; $y < 8; $y++)
    {
        $gold = false;
        $selcol = 0;
        switch($pattern_matrix[$x][$y])
        {
            case 'o': $selcol = 0; break;
            case 'r': $selcol = mt_rand(0, $num_of_colors - 1); break;
            case 'x': $selcol = $gold = true; break;
            case 'p': $selcol = $num_of_colors - 1; $gold = mt_rand(0, 2) === 0; break;
            default: $selcol = $num_of_colors - 1; break;
        }
        if($gold){
            $goldColor = $goldColors[mt_rand(0, 2)];
            imagesetpixel($img, $x, $y, $goldColor);
            imagesetpixel($img, $width - 1 - $x, $y, $goldColor);
            imagesetpixel($img, $x, $height - 1 - $y, $goldColor);
            imagesetpixel($img, $width - 1 - $x, $height - 1 - $y, $goldColor);
        }else{
            imagesetpixel($img, $x, $y, $colors[$selcol]);
            imagesetpixel($img, $width - 1 - $x, $y, $colors[$selcol]);
            imagesetpixel($img, $x, $height - 1 - $y, $colors[$selcol]);
            imagesetpixel($img, $width - 1 - $x, $height - 1 - $y, $colors[$selcol]);
        }
    }
}

// apply resolution multiplier (pixel size)
$img = imagescale($img, $width * $pixel_size, $height * $pixel_size, IMG_NEAREST_NEIGHBOUR);

// set content header: this file will not load like a normal html page, it will output a png file
header("Content-type: image/png");
// output image
imagepng($img);
// destroy images
imagedestroy($img);
imagedestroy($palette);

.procedural