Как и перед авторами недавнего топика, передо мной возник вопрос генерации дефолтных аватаров. Тут же вспомнил о «фрактальных» аватарах.
Основной принцип — генерируем примитивами 1/4 изображения и дублируем с поворотом на 90°. Пробовал сделать свой вариант:
Как и любой дизайнер, «поиграл цветами и формами», но все было не то. Тогда и родилась идея сделать случайно генерируемые лица. Подумывал даже об ан$%е, но вовремя отдумал. В планах была только генерация лиц в стиле «мульт» — с разноцветными глазами, волосами и карикатурными чертами, а после задумался и об аксессуарах — очки, румяна, веснушки и т.д…
На скорую руку набросал мордочки,
и принялся за различные части лица. Начнем с глаз.
Базовая форма для глаза — капля.
В общем-то, эта форма является базовой для многих частей аватарки — ноздри, губы и т.д. Получить ее довольно просто — из параболы. Точнее — из четырех:
/*
$width, $height - высота, ширина поработы
$quality - обратное качеству
*/
$color = imageColorAllocate($image,45,45,45)
$points = array();
for($x=0; $x<=$width/2; $x+=$quality)
{
$y=($x*$x) / (($width)*($width)) * $height;
array_push($points, $x, $y);
}
imagefilledpolygon($image, $points, count($points)/2, $color);
А imagefilledpolygon заполняет многоугольник выбранным цветом в контуре, заданным массивом точек в декартовой системе координат. Подробнее о рисовании средствами PHP можно почитать здесь.
Делаем тонкую обводку глаза черным цветом. imagepolygon — как раз подходит — обвод многоугольника без заливки.
Обводка, тень от века, тени, белОк.
Зрачок и блики рисуем с помощью imagefilledellipse.
Зрачок, блики.
Кастомизация глаз происхоит с помощью rand
<?php
/*
Не для слабонервных. Давно бросил пхп, но иногда балуюсь. Данный код - сырое превью.
Новичкам - лучше вообще не смотреть.
*/
$Width=500;
$Height=300;
$img = imageCreate($Width,$Height);
$r = rand(5,200);$g = rand(5,200);$b = rand(5,200);
$c = imageColorAllocate($img, 255,255,255);
imagefilledrectangle($img, 0, 0, $Width, $Height, $c);
//-------------------го дотан------------------------//
$w = rand(100,150);
$h = rand(100,100);
$zsize=rand(20,50);
$max = rand(2,7)/10;
$max2= 0.5;
$zxr = rand(-$w/5,$w/5);
$zyr = rand(-$h/5,$h/5);
$zform = rand(3,8)/10;
$mejg = rand($w/2,$w);
$zc = imageColorAllocate($img,rand(5,150),rand(5,150),rand(5,150));
$ec = imageColorAllocate($img,$r,$g,$b);
$ebc = imageColorAllocate($img,rand(235,255),rand(235,255),rand(230,255));
$eform = rand(90,100)/100;
$eform2 = rand(70,100)/100;
$rznglaz = rand(80,120)/100;
$rznglaz2 = rand(80,120)/100;
$smeshx = (500 - ($w*2+$mejg))/2;
DrawEye($img, $smeshx+0,0, $w*$rznglaz,$h ,$ec, $ebc, $eform, $eform2, $zxr, $zyr, $zc, $max, $max2, $zform, $zsize);
if(rand(0,5)==0) $zc = imageColorAllocate($img,rand(5,150),rand(5,150),rand(5,150));
DrawEye($img, $smeshx+$w + $mejg, 0, $w*$rznglaz2, $h, $ec, $ebc, $eform, $eform2, $zxr, $zyr, $zc, 1-$max, $max2, $zform, $zsize);
//imageellipse ( $img , 100 , 100 ,100 , 100 , imageColorAllocate($img,45,45,45) );
//imagefilledellipse ( $img , 200 , 200 ,100 , 100 , imageColorAllocate($img,45,45,45) );
//-----------------и пили симфоню уже-----------------------//
header('Content-type: image/png');
imagepng($img);
imagedestroy($img);
//-------------------------------------------------------//
function DrawEye($image, $xx, $yy, $w, $h, $ec, $ebc, $eform, $eform2, $zxr,$zyr, $zc, $max, $max2, $zform, $zsize)
{
/*
if($w<$h)
$zsize = $w/3;
else
$zsize = $h/3;
*/
DrawEyePoligon($image,$xx-5,95-5,$w+10,$h+10, imageColorAllocate($image,5,5,5), 1, $max, $max2, 0);
DrawEyePoligon($image,$xx,95,$w,$h, imageColorAllocate($image,5,5,5), 1, $max, $max2, 1);
DrawEyePoligon($image,$xx,100,$w,$h*$eform, $ec, 1, $max, $max2, 1);
DrawEyePoligon($image,$xx+10,100+$zform*10,$w-20,$h*$eform2, $ebc, 1, $max2,$max2, 1);
DrawEyePoligon($image,$xx+10,100+$zform*10,$w-20,$h*$eform2, $ebc, 1, $max2,$max2, 1);
imagefilledellipse ( $image, $xx+$w/2+$zxr,140+$zyr, $zsize, $zsize, $zc);
imagefilledellipse ( $image, $xx+$w/2+$zxr,140+$zyr, $zsize * $zform, $zsize*(1-$zform), imageColorAllocate($image,5,5,5));
imagefilledellipse ( $image, $xx+$w/2+$zxr+10,140+$zyr-10, $zsize * 0.5, $zsize*0.5, imageColorAllocate($image,255,255,255));
}
//-------------------------------------------------------//
function DrawEyePoligon($image, $xx, $yy, $width, $height, $color, $quality, $max, $max2, $fill)
{
$height/=2;
if($quality>$width/2)
$quality=$width/2;
$points = array();
for($i=0; $i<=$width; $i+=$quality)
{
$x = $i-$width;
$y=($x*$x) / (($width)*($width)) * $height;
array_push($points, $i*$max, $y);
}
for($i=0; $i<=$width; $i+=$quality)
{
$x = $i;
$y=($x*$x) / (($width)*($width)) * $height;
//$y=(($width*$width)-($x*$x)) / (($width)*($width)) * $height;
array_push($points, $i*(1-$max)+($width*$max), $y);
}
for($i=0; $i<=$width; $i+=$quality)
{
$x = $i-$width;
$y=-($x*$x) / (($width)*($width)) * $height;
array_push($points, $i*$max2, 2*$height+$y);
}
for($i=0; $i<=$width; $i+=$quality)
{
$x = $i;
$y=-($x*$x) / (($width)*($width)) * $height;
//$y=(($width*$width)-($x*$x)) / (($width)*($width)) * $height;
array_push($points, $i*(1-$max2)+($width*$max2), 2*$height+$y);
}
DrawPoligon($image, $xx, $yy, $points, $color, $fill);
}
//-------------------------------------------------------//
function DrawPoligon($image, $x, $y, $points, $color, $fill)
{
for($i=0; $i<count($points); $i+=2)
{
$points[$i]+=$x;
$points[$i+1]+=$y;
}
if($fill)
imagefilledpolygon($image, $points, count($points)/2, $color);
else
imagepolygon($image, $points, count($points)/2, $color);
}
Остальные части лица (кроме волос и аксессуаров) рисуются аналогичным образом. Получается красиво, но есть большой и жирный минус — это очень затратно даже если оптимизировать. А накладывать друг на друга готовые паттерны может и лучше, но скучно и однообразно. Засим откланиваюсь, с наступающим и спасибо за рыбу.
Автор: eximap