Comunidad de diseño web y desarrollo en internet online

Crear avatares aleatorios en PHP con GD e imágenes PNG

Es muy común cuando uno tiene un sistema de usuarios, con avatares incluidos, poner una imagen de reemplazo cuando el usuario aún no ha creado su avatar.

El problema es que cuando trabajamos con clientes, a veces queda más profesional que nuestra aplicación le cree un avatar a medida a cada usuario. De esta forma se puede identificar en la plataforma al usuario, aunque el mismo sea un vago que no ha subido nada. (Muy común en sistemas de empleados o círculos de intranets, dónde se requiere identificar roles fácilmente).

Además de crearlo dinámico, es probable tengamos que:

  • Hacerlo a varias medidas
  • Incluirle texto ("No Image" o algo)
  • Logo de la Web o Cliente


Para hacerlo usaremos: PHP, la librería GD y algo de ingenio.

Mezclando colores


Lo primero que debemos hacer, es crear una matriz de colores aleatorios, que seleccione por nosotros uno o más colores para armar el avatar.

Para hacerlo, debemos saber que una imagen se compone de 3 valores básicos:

Código :

R (Red) + G (Green) + B (Blue)

Para cada slot (R/G/B) tenemos dos espacios disponibles, que indican la saturación de dicho color en la imagen. El valor se expresa de 0 a 256 (Cantidad Máxima). Como tenemos dos slots, sería 16 x 16.

But.. wait! Tenemos números del 0 al 9 nada más, como poner en dos lugares un 1616. Es por eso que se usa la escala hexagesimal, la cual cuenta así:

Código :

0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F

Siendo, por ejemplo F, el valor 16.

Si queremos hacer un verde saturado hacemos:

Código :

00FF00

Sabiendo esto podemos armar una matriz de colores aleatoria así:

Código :

//Los valores permitidos, nuestro esquema hexagesimal
$accepted_vals = array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F");
// Cuantos colores queremos diferentes en nuestra matriz de colores
$cant_colors = 2;
// La matriz de Resultado que tendrá nuestros colores aleatorios
$colors = array();
// Mezclamos los colores para las 6 posiciones de RGB
for($n=0;$n<$cant_colors;$n++){
   $q = count($accepted_vals) - 1;
   $r = $accepted_vals[rand(0,$q)].$accepted_vals[rand(0,$q)];
   $g = $accepted_vals[rand(0,$q)].$accepted_vals[rand(0,$q)];
   $b = $accepted_vals[rand(0,$q)].$accepted_vals[rand(0,$q)];    
   array_push($colors,$r.$g.$b);
}

Esto nos dará como resultado el array $colors, con 2 colores (O los que le digamos en la variable $cant_colors). ¿Pero como creamos la imagen?

Creando el fondo de nuestro avatar


Comenzaremos por crear el fondo de colores diferentes para cada usuario. Para hacerlo nos valdremos de la librería GD.

Primero debemos setear lo siguiente:

Código :

//Ancho que tendrá nuestra imagen
$w = 100;
//Alto que tendrá nuestra imagen
$h = 100;
//Dónde alojaremos la imagen
$uploadDir = '';
// Que nombre le pondremos
$imageName = "testing.jpg";
//Path Final
$uploadFile = $uploadDir . $imageName;
// Creamos una imagen vacía
$img = imagecreatetruecolor($w, $h);
// La pintamos de blanco
imagefill($img, 0, 0, 0xFFFFFF);

Para crear la imagen de fondo, usaremos dos bucles, uno que recorra el alto de la imagen y otro el ancho. Y le pediremos que use en la línea 0 el color 1, en la línea 1 el color 2, en la línea 2 el color 1, y así. O sea, uno y uno.

En realidad, iremos más lejos, le pediremos que haga ese recorrido, según cuantos colores máximo tengamos en el array de $colors.

Para hacerlo usaremos la siguiente expresión:

Código :

$alto % $cantidad_colors

Luego usaremos la librería GD para crear la imagen Pixel por Pixel:

Código :

for($i = 0; $i < $h; $i++){
   for($j = 0; $j < $w; $j++){
      $hex = $colors[$i%count($colors)];
      $r = hexdec(substr($hex, 0, 2));
      $g = hexdec(substr($hex, 2, 2));
      $b = hexdec(substr($hex, 4, 2));
      $imgResult = imagecolorallocate($img, $r, $g, $b);
      imagesetpixel($img, $j, $i, $imgResult);      
   }
}

Esto nos dará como resultados algo como esto (3 imágenes diferentes):


El resultado es bastante prólijo con 2 colores, sin embargo, podemos crear colores sólidos ($cant_colors = 1), imágenes bastante coloridas ($cant_colors = 4) o MUY coloridas ($cant_colors = $h);

Jugando con la parte de:

Código :

$cant_colors = 2;

y

Código :

$hex = $colors[$i%count($colors)];

Pueden crear resultados MUY variados:


Pero bien, ahora tenemos un control de los fondos, pero como le demos eso como avatar a un cliente y nos joden. Realmente hacer algo pr0 a la mitad es una mierda.

El Avatar


Para terminar la imagen, vamos a crear en Photoshop (O lo que quieran) una imagen PNG-32, en mi caso hice esta:


El fondo negro es en realidad transparente, pero lo sube así L4C.me. So just imagine.

La imagen le agregue bordes y sombras, recuerden que no sabremos que color quedará de fondo, por lo cual ese tipo de truquillos serán ideales.

Ahora vamos a unir el fondo con la muestra:

Código :

//Creamos la imagen del fondo como JPEG
imagejpeg($img, $uploadFile, 100);
// Seteamos las dos imágenes con las que trabajaremos
$avatar = imagecreatefromjpeg($uploadFile);
$no = imagecreatefrompng("no-img.png");
//Las unimos, ¿A que PHP no es genial?
imagecopyresampled($avatar,$no,0,0,0,0,imagesx($avatar),imagesy($avatar),imagesx($avatar),imagesy($avatar));
//Salvamos el resultado en JPEG
imagejpeg($avatar, "salida.jpg", 100);
//Liberamos memoria
imagedestroy($avatar);
imagedestroy($no);

Y así de sencillo, hemos unido las dos partes.

Aquí algunos resultados:


Obviamente esos resultados tienen anotado diferentes cantidades de colores y formula para la creación de diferentes patrones (Solo los primeros 3 son la formula anotada arriba, con dos colores).

Código PHP Final


Código :

//Los valores permitidos, nuestro esquema hexagesimal 
$accepted_vals = array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"); 
// Cuantos colores queremos diferentes en nuestra matriz de colores 
$cant_colors = 2; 
// La matriz de Resultado que tendrá nuestros colores aleatorios 
$colors = array(); 
// Mezclamos los colores para las 6 posiciones de RGB 
for($n=0;$n<$cant_colors;$n++){ 
   $q = count($accepted_vals) - 1; 
   $r = $accepted_vals[rand(0,$q)].$accepted_vals[rand(0,$q)]; 
   $g = $accepted_vals[rand(0,$q)].$accepted_vals[rand(0,$q)]; 
   $b = $accepted_vals[rand(0,$q)].$accepted_vals[rand(0,$q)];     
   array_push($colors,$r.$g.$b); 
}
for($i = 0; $i < $h; $i++){ 
   for($j = 0; $j < $w; $j++){ 
      $hex = $colors[$i%count($colors)]; 
      $r = hexdec(substr($hex, 0, 2)); 
      $g = hexdec(substr($hex, 2, 2)); 
      $b = hexdec(substr($hex, 4, 2)); 
      $imgResult = imagecolorallocate($img, $r, $g, $b); 
      imagesetpixel($img, $j, $i, $imgResult);       
   } 
}
//Creamos la imagen del fondo como JPEG 
imagejpeg($img, $uploadFile, 100); 
// Seteamos las dos imágenes con las que trabajaremos 
$avatar = imagecreatefromjpeg($uploadFile); 
$no = imagecreatefrompng("no-img.png"); 
//Las unimos, ¿A que PHP no es genial? 
imagecopyresampled($avatar,$no,0,0,0,0,imagesx($avatar),imagesy($avatar),imagesx($avatar),imagesy($avatar)); 
//Salvamos el resultado en JPEG 
imagejpeg($avatar, "salida.jpg", 100); 
//Liberamos memoria 
imagedestroy($avatar); 
imagedestroy($no);


Espero les sirva.

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate