Foros del Web » Programando para Internet » PHP »

Problema con paleta de colores PHP

Estas en el tema de Problema con paleta de colores PHP en el foro de PHP en Foros del Web. Buenas, Estoy tratando de extraer el color de los pixels de una imagen y me está volviendo loco. La parte de recorrer los pixels de ...
  #1 (permalink)  
Antiguo 04/12/2013, 16:05
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 1 mes
Puntos: 20
Problema con paleta de colores PHP

Buenas,

Estoy tratando de extraer el color de los pixels de una imagen y me está volviendo loco.

La parte de recorrer los pixels de la imagen y tal la tengo clara, mi problema radica en que despues de varias pruebas los colores que me pilla el script no son los colores reales, sino que los transforma y me saca el color más próximo a los Web Safe Colors, que son 216 exactamente.

Ejemplo:
http://www.techbomb.com/websafe/
http://es.html.net/tutorials/html/le...olourchart.php

La parte de identificar el color la hago de la siguiente manera

Código PHP:
Ver original
  1. $thisColor = imagecolorat($img, $x, $y);
  2.  
  3. $rgb = imagecolorsforindex($img, $thisColor);
  4.            
  5. $red = round(round(($rgb['red'] / 0x33)) * 0x33);
  6. $green = round(round(($rgb['green'] / 0x33)) * 0x33);
  7. $blue = round(round(($rgb['blue'] / 0x33)) * 0x33);
  8. $thisRGB = sprintf('%02X%02X%02X', $red, $green, $blue);

Pero no sé si es la función imagecolorat o imagecolorsforindex la que "distorsiona" el color verdadero y me muestra uno de los Web Safe Colors.

Sabéis como puedo mostrar el color verdadero del pixel? tengo que hacer algo antes o aplicar otro comando?

Muchas gracias de antemano
  #2 (permalink)  
Antiguo 04/12/2013, 16:21
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 3 meses
Puntos: 206
Respuesta: Problema con paleta de colores PHP

Lo que creo que hace lo que dices es tu doble redondeo a 0x33.
  #3 (permalink)  
Antiguo 04/12/2013, 17:20
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 1 mes
Puntos: 20
Respuesta: Problema con paleta de colores PHP

Ostras, es verdad.

Si le quito el doble redondeo, me muestra el valor del pixel real. Ahora lo que pasa es que hay imagenes que igual varía unos números el color pero sigue siendo el mismo color. No existe ninguna función que haga como un poco de tolerancia y que por ejemplo estos colores los simplique?



Hay 7 pixeles de color diferente, pero en verdad son solo 3 colores diferentes
El negro el verde claro y el verde oscuro

#2B2B2B
#50AEC0
#82E0F2

Sabéis a lo que me refiero, verdad?

Muchas gracias de antemano
  #4 (permalink)  
Antiguo 04/12/2013, 18:20
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 3 meses
Puntos: 206
Respuesta: Problema con paleta de colores PHP

Sí, a crear tu propio algoritmo de compresión de imágenes con paleta dinámica.

Por ejemplo:
Código PHP:
Ver original
  1. <?php
  2. header( "Content-type: image/png" );
  3. $imageName="cat.jpg";
  4. $size  = getimagesize($imageName);
  5. $img = imagecreatefromjpeg($imageName);
  6.  
  7. for ($x=0;$x<$size[0];$x++)
  8. {
  9.     for ($y=0;$y<$size[1];$y++)
  10.     {
  11.         $pixel = imagecolorat($img, $x, $y);
  12.         $pixelColor = imagecolorsforindex($img, $pixel);
  13.  
  14.         $rango=51;
  15.         $r=(int)floor($pixelColor["red"]/$rango)*$rango;
  16.         $g=(int)floor($pixelColor["green"]/$rango)*$rango;
  17.         $b=(int)floor($pixelColor["blue"]/$rango)*$rango;
  18.  
  19.         $index=imagecolorexact($img,$r,$g,$b);
  20.         imagesetpixel($img, $x, $y, $index);
  21.     }
  22. }
  23.  
  24. imagepng($img);
  25.  
  26. ?>

He creado una paleta de 216 colores (51 es divisor de 255, aunque en realidad puedes poner cualquier cifra entre 0 y 255; si no son divisores, habrá un insignificante e indetectable error en el redondeo de colores cercanos al blanco absolto), cada componente de color puede coger valores de 0, 51, 102, 153, 205 y 255. Seis colores. Tres componentes=6*6*6=216.

El límite es tu imaginación. Puedes crear tú en un array la paleta, y hacer una función que escoja el color aproximado (por ejemplo sumando la diferencia de cada componente del pixel de la imagen con el componente de cada color de la paleta, y quedarse el menor).

Última edición por marlanga; 04/12/2013 a las 18:28
  #5 (permalink)  
Antiguo 06/12/2013, 08:27
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 1 mes
Puntos: 20
Respuesta: Problema con paleta de colores PHP

Gracias de nuevo marlanga, lo que indicas suena muy bien pero no veo la forma de hacerlo

En el ejemplo anterior, me salian 7 colores diferentes en la imagen, cuando en verdad solo necesitaba 3 colores.

La imagen de pruebas es la siguiente, (no tengas en cuenta el fondo blanco, que para subirla online necesitaba que fuese de 150x150, cuenta que la imagen son las 6 redonditas con el fondo negro :D)



Si mi paleta fuese los 3 colores siguientes:

#2B2B2B
#50AEC0
#82E0F2

Me interesa saber el número de pixeles que hay de cada color, considerando que los que no sean esos colores, me los cuente como si lo fueran (acercandose a color más próximo de mi paleta y contandolos como tal).

Para sacar los colores de mi imagen de ejemplo, sigo un patron y cojo los pixels de las siguientes posiciones:

Posicion X: 13 | Y: 7
Red: 129 | Green: 222 | Blue: 239
Posicion X: 13 | Y: 13
Red: 43 | Green: 43 | Blue: 43
Posicion X: 25 | Y: 7
Red: 75 | Green: 160 | Blue: 174
Posicion X: 25 | Y: 13
Red: 43 | Green: 43 | Blue: 43
Posicion X: 37 | Y: 7
Red: 71 | Green: 149 | Blue: 162
Posicion X: 37 | Y: 13
Red: 43 | Green: 43 | Blue: 43
Posicion X: 49 | Y: 7
Red: 73 | Green: 160 | Blue: 174
Posicion X: 49 | Y: 13
Red: 43 | Green: 43 | Blue: 43
Posicion X: 61 | Y: 7
Red: 80 | Green: 174 | Blue: 192
Posicion X: 61 | Y: 13
Red: 43 | Green: 43 | Blue: 43
Posicion X: 73 | Y: 7
Red: 78 | Green: 176 | Blue: 193
Posicion X: 73 | Y: 13
Red: 43 | Green: 43 | Blue: 43

En total me saca 7 colores, pero el resultado que busco es, sin contar el fondo negro, imagina que solo cojes el pixel central de cada redonda (en eso no tengo dificultades), y te salen los 6 colores de verde diferente, pero en verdad solo necesitas 2 colores de verde, los dos de mi paleta.

Me debería decir que ha encontrado
2 bolas #82E0F2
4 bolas #50AEC0

Mi código

Código PHP:
Ver original
  1. function colorPalette($imageFile, $numColors, $granularity = 12) {
  2.     $granularity = max(1, abs((int)$granularity));
  3.     $colors = array();
  4.     $size = @getimagesize($imageFile);
  5.  
  6.     if( $size === false ){
  7.         user_error("Unable to get image size data");
  8.         return false;
  9.     }
  10.  
  11.     $img = @imagecreatefromstring(file_get_contents($imageFile));
  12.  
  13.     if( !$img ){
  14.         user_error("Unable to open image file");
  15.         return false;
  16.     }
  17.  
  18.     echo "<br/>size0: ".$size[0].'<br/>';
  19.     echo "size1: ".$size[1].'<br/>';
  20.  
  21.     for($x = 13; $x < $size[0]; $x += $granularity){ // Horizontal 
  22.  
  23.         for($y = 7; $y < $size[1]; $y += $granularity/2){ // Vertical
  24.        
  25.             echo "Posicion X: $x | Y: $y<br/>";
  26.             $thisColor = imagecolorat($img, $x, $y);
  27.             $rgb = imagecolorsforindex($img, $thisColor);
  28.                
  29.             $red = $rgb['red'];
  30.             $green = $rgb['green'];
  31.             $blue = $rgb['blue'];
  32.            
  33.             $result = imagecolorclosest($img, $red, $green, $blue);
  34.             $result = imagecolorsforindex($img, $result);
  35.             $result = "({$result['red']}, {$result['green']}, {$result['blue']})";
  36.            
  37.             $thisRGB = sprintf('%02X%02X%02X', $red, $green, $blue);
  38.             echo "Red: $red | Green: $green | Blue: $blue<br/>";
  39.             if(array_key_exists($thisRGB, $colors)){
  40.                 $colors[$thisRGB]++;
  41.             }else{
  42.                 $colors[$thisRGB] = 1;
  43.             }
  44.         }
  45.     }
  46.     arsort($colors);
  47.     return array_slice(array_keys($colors), 0, $numColors);
  48. }
  49.  
  50. /* PRINCIPAL */
  51.  
  52. $archivo = 'espada3.png';
  53.  
  54. echo '<img src="'.$archivo.'"/>';
  55.  
  56. $palette = colorPalette($archivo,32, 12);
  57.  
  58. echo "<table>\n";
  59. foreach($palette as $color){
  60.    echo "<tr><td style='background-color:#$color;width:2em;'>&nbsp;</td><td>#$color</td></tr>\n";
  61. }
  62. echo "</table>\n";

Muchas gracias de antemano!!!!
  #6 (permalink)  
Antiguo 08/12/2013, 06:19
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 1 mes
Puntos: 20
Respuesta: Problema con paleta de colores PHP

Os dejo el código actualizado.

Tengo definida una paleta de verdes y cuando analizo la siguiente imagen de cuadrados soy capaz de contar cuantos cuadrados hay de cada color.

Hasta aquí bien.

Pero quiero dar uso a mi paleta de verdes.
Me gustaría ser capaz de saber a qué verde se acerca más, el verde de la imagen de cuadrados.

No encuentro una forma de seleccionar el verde de mi paleta de colores que se acerca más al verde encontrado en la imagen.



Código PHP:
Ver original
  1. <?php
  2.  
  3. function HexToRGB($hex) { $hex = str_replace("#", "", $hex); $color = array(); if(strlen($hex)==3) { $color['r'] = hexdec(substr($hex, 0, 1).substr($hex, 0, 1)); $color['g'] = hexdec(substr($hex, 1, 1).substr($hex, 1, 1)); $color['b'] = hexdec(substr($hex, 2, 1).substr($hex, 2, 1)); }elseif(strlen($hex)==6){ $color['r'] = hexdec(substr($hex, 0, 2)); $color['g'] = hexdec(substr($hex, 2, 2)); $color['b'] = hexdec(substr($hex, 4, 2)); } return $color; }
  4.  
  5. // Mi paleta verde
  6. $paleta_verde=array('0F8A49','5CCF97','87DDAD','79E633','57BE00','BCF25E');
  7.  
  8. $imageName="cuadrados2.png";
  9. $size  = getimagesize($imageName);
  10. $img = imagecreatefrompng($imageName);
  11. $colors = array();
  12. $granularity = 12; // Defino el tamaño del Pixel
  13.  
  14. //Imprimo mi Paleta de Verdes
  15. echo "<p>Mi Paleta</p>";
  16. echo "<table>\n";
  17. foreach($paleta_verde as $color){
  18.     $rgb = HexToRGB($color);
  19.     echo "<tr><td style='background-color:#$color;width:2em;'>&nbsp;</td><td>#$color</td><td>| RGB (".$rgb['r'].' , '.$rgb['g'].' , '.$rgb['b'].')'."</td></tr>";
  20. }
  21. echo "</table>\n";
  22.  
  23. // Imprimo la imagen
  24. echo '<br/><img src="'.$imageName.'"/><br/>';
  25.  echo "Size: ".$size[0].' x '.$size[1].'<br/><br/>';
  26. // Recorro la imagen
  27.  
  28. for ($x=12;$x<$size[0];$x += $granularity)
  29. {
  30.     for ($y=12;$y<$size[1];$y += $granularity)
  31.     {
  32.         $pixel = imagecolorat($img, $x, $y);
  33.         $pixelColor = imagecolorsforindex($img, $pixel);
  34.  
  35.         $rango=1;
  36.         $r=(int)floor($pixelColor["red"]/$rango)*$rango;
  37.         $g=(int)floor($pixelColor["green"]/$rango)*$rango;
  38.         $b=(int)floor($pixelColor["blue"]/$rango)*$rango;
  39.        
  40.         $index=imagecolorexact($img,$r,$g,$b);
  41.        
  42.         $thisRGB = sprintf('%02X%02X%02X', $r, $g, $b);
  43.         echo "Red: $r | Green: $g | Blue: $b | Posicion X: $x | Y: $y<br/>";
  44.  
  45.         if(array_key_exists($thisRGB, $colors)){
  46.             $colors[$thisRGB]++;
  47.         }else{
  48.             $colors[$thisRGB] = 1;
  49.         }
  50.     }
  51. }
  52.  
  53. // RESUMEN
  54.  
  55. echo "<br/>Colores encontrados<br/>";
  56. arsort($colors); // Ordeno los colores obtenidos de mayor a menor.
  57.  
  58. //Imprimo los colores encontrados
  59. echo "<table>\n";
  60. foreach($colors as $color=>$numero){
  61.     $rgb = HexToRGB($color);
  62.     echo "<tr><td>$numero</td><td style='background-color:#$color;width:2em;'>&nbsp;</td><td>#$color</td><td>| RGB (".$rgb['r'].' , '.$rgb['g'].' , '.$rgb['b'].')'."</td></tr>";
  63. }
  64. echo "</table>\n";
  65.  
  66. ?>

Una ayuda??

Muchas gracias de antemano!
  #7 (permalink)  
Antiguo 08/12/2013, 09:32
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 3 meses
Puntos: 206
Respuesta: Problema con paleta de colores PHP

Ya te puse cómo obtener la distancia entre dos colores para elegir el más próximo. No se casi nada de la teoría de color, así que es probable que exista otra fórmula de proximidad que de mejores resultados.

Código PHP:
Ver original
  1. <?php
  2. header( "Content-type: image/png" );
  3. $imageName="cat2 - copia.jpg";
  4. $size  = getimagesize($imageName);
  5. $img = imagecreatefromjpeg($imageName);
  6.  
  7. $paleta=array(
  8.     array(15, 138, 73),
  9.     array(92, 207, 151),
  10.     array(135, 221, 173),
  11.     array(121, 230, 51),
  12.     array(87, 190, 0),
  13.     array(188, 242, 94)
  14. );
  15.  
  16. function colorCercano($color, $paleta){
  17.     $n=count($paleta);
  18.     $distancia=INF;
  19.     $mejor=0;
  20.     for ($i=0;$i<$n;$i++)
  21.     {
  22.         $actual=abs($color[0]-$paleta[$i][0])+abs($color[1]-$paleta[$i][1])+abs($color[2]-$paleta[$i][2]);
  23.         //$actual=sqrt(pow($color[0]-$paleta[$i][0],2)+pow($color[1]-$paleta[$i][1],2)+pow($color[2]-$paleta[$i][2],2));
  24.         if ($distancia>$actual)
  25.         {
  26.             $distancia=$actual;
  27.             $mejor=$i;
  28.         }
  29.     }
  30.     return $paleta[$mejor];
  31. }
  32.  
  33. for ($x=0;$x<$size[0];$x++)
  34. {
  35.     for ($y=0;$y<$size[1];$y++)
  36.     {
  37.         $pixel = imagecolorat($img, $x, $y);
  38.         $pixelColor = imagecolorsforindex($img, $pixel);
  39.  
  40.         $colorFinal=colorCercano(array($pixelColor["red"],$pixelColor["green"],$pixelColor["blue"]),$paleta);
  41.  
  42.         $index=imagecolorexact($img,$colorFinal[0],$colorFinal[1],$colorFinal[2]);
  43.         imagesetpixel($img, $x, $y, $index);
  44.     }
  45. }
  46.  
  47. imagepng($img);
  #8 (permalink)  
Antiguo 08/12/2013, 17:17
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 1 mes
Puntos: 20
Respuesta: Problema con paleta de colores PHP

Muchas gracias marlanga,

Gracias, me ha sido de gran utilidad tu ejemplo.

Etiquetas: colores, html, paleta
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 04:28.