2009-12-11 27 views
11

Me gustaría cambiar el "matiz" de una imagen utilizando las funciones de procesamiento de imágenes de PHP. ¿Cuál es el filtro correcto para aplicar?¿Cambiar "HUE" de una imagen con PHP GD Library?

Nota: Soy de un fondo photoshop, por lo que en caso de que mi interpretación de "tono" es diferente de los demás, esto es lo que quiero decir ...

En Photoshop, puede utilizar el "tono" filtrar para cambiar el color de una imagen sin afectar el diseño de la imagen.

Actualmente estoy usando la función siguiente para volver a colorear mis imágenes, pero la función no cumple con mis necesidades debido a que vuelve a pintar completamente la imagen, perdiendo el diseño.

function set_theme_color_header($hex) 
    { 
     $info = hexToRGB($hex); //utility function that converts hex to rgb 
     $token = "header.gif"; 
     $img = imagecreatefromgif("header-template.gif"; 
     $color = imagecolorallocate($img, $info["red"], $info["green"], $info["blue"]); 
     imagecolorset($img, 0, $info["red"], $info["green"], $info["blue"]); 
     imagegif($img, $token); 
    } 
    ?> 
+0

¿Qué función cree que está 'repintando completamente la imagen'? ¿Qué quieres decir con 'pierde el diseño'? –

+0

¿Cuántas preguntas va a publicar y eliminar con respecto a la función set_theme_color_header()? –

Respuesta

32

Estoy bastante seguro de que no hay funciones en PHP que puedan manejar el cambio de matiz. Sin embargo, usted puede escribir su propia función para hacer esto, aquí están los pasos para cambiar la tonalidad de la imagen:

  1. Traverse la imagen píxel a píxel
  2. obtener el color RGB en el píxel utilizando imagecolorat()
  3. Transformar el RGB valor en un valor HSL
  4. Cambiar el valor de matiz, saturación y luminosidad dejar solos (Hue es un valor de 0 a 360)
  5. Transformar el nuevo valor HSL de nuevo a RGB
  6. Cambiar el color en el píxel actual

En realidad, esto parece ser algo muy interesante de probar, así que podría hacerlo yo mismo y publicarlo aquí si no encuentra otra solución.

EDITAR

Has escrito la función. Para cambiar el tono en PHP, necesitará funciones para transformar espacios de color RGB y HSL y una función que atraviese la imagen. Esto podría ser un poco feo, pero funciona muy bien. Bastante lento en imágenes más grandes.

function imagehue(&$image, $angle) { 
    if($angle % 360 == 0) return; 
    $width = imagesx($image); 
    $height = imagesy($image); 

    for($x = 0; $x < $width; $x++) { 
     for($y = 0; $y < $height; $y++) { 
      $rgb = imagecolorat($image, $x, $y); 
      $r = ($rgb >> 16) & 0xFF; 
      $g = ($rgb >> 8) & 0xFF; 
      $b = $rgb & 0xFF;    
      $alpha = ($rgb & 0x7F000000) >> 24; 
      list($h, $s, $l) = rgb2hsl($r, $g, $b); 
      $h += $angle/360; 
      if($h > 1) $h--; 
      list($r, $g, $b) = hsl2rgb($h, $s, $l);    
      imagesetpixel($image, $x, $y, imagecolorallocatealpha($image, $r, $g, $b, $alpha)); 
     } 
    } 
} 

He aquí las funciones auxiliares requeridas para la conversión de espacio de color, descaradamente copiado de http://www.actionscript.org/forums/showthread.php3?t=50746 con alteraciones menores:

function rgb2hsl($r, $g, $b) { 
    $var_R = ($r/255); 
    $var_G = ($g/255); 
    $var_B = ($b/255); 

    $var_Min = min($var_R, $var_G, $var_B); 
    $var_Max = max($var_R, $var_G, $var_B); 
    $del_Max = $var_Max - $var_Min; 

    $v = $var_Max; 

    if ($del_Max == 0) { 
     $h = 0; 
     $s = 0; 
    } else { 
     $s = $del_Max/$var_Max; 

     $del_R = ((($var_Max - $var_R)/6) + ($del_Max/2))/$del_Max; 
     $del_G = ((($var_Max - $var_G)/6) + ($del_Max/2))/$del_Max; 
     $del_B = ((($var_Max - $var_B)/6) + ($del_Max/2))/$del_Max; 

     if  ($var_R == $var_Max) $h = $del_B - $del_G; 
     else if ($var_G == $var_Max) $h = (1/3) + $del_R - $del_B; 
     else if ($var_B == $var_Max) $h = (2/3) + $del_G - $del_R; 

     if ($h < 0) $h++; 
     if ($h > 1) $h--; 
    } 

    return array($h, $s, $v); 
} 

function hsl2rgb($h, $s, $v) { 
    if($s == 0) { 
     $r = $g = $B = $v * 255; 
    } else { 
     $var_H = $h * 6; 
     $var_i = floor($var_H); 
     $var_1 = $v * (1 - $s); 
     $var_2 = $v * (1 - $s * ($var_H - $var_i)); 
     $var_3 = $v * (1 - $s * (1 - ($var_H - $var_i))); 

     if  ($var_i == 0) { $var_R = $v  ; $var_G = $var_3 ; $var_B = $var_1 ; } 
     else if ($var_i == 1) { $var_R = $var_2 ; $var_G = $v  ; $var_B = $var_1 ; } 
     else if ($var_i == 2) { $var_R = $var_1 ; $var_G = $v  ; $var_B = $var_3 ; } 
     else if ($var_i == 3) { $var_R = $var_1 ; $var_G = $var_2 ; $var_B = $v  ; } 
     else if ($var_i == 4) { $var_R = $var_3 ; $var_G = $var_1 ; $var_B = $v  ; } 
     else     { $var_R = $v  ; $var_G = $var_1 ; $var_B = $var_2 ; } 

     $r = $var_R * 255; 
     $g = $var_G * 255; 
     $B = $var_B * 255; 
    }  
    return array($r, $g, $B); 
} 

Y, por último, un ejemplo de uso. En este ejemplo se abre una imagen, cambia su color por 180 ° y salidas al navegador:

header('Content-type: image/png'); 
$image = imagecreatefrompng('image.png'); 
imagehue($image, 180); 
imagepng($image); 

A medida que el ángulo de tono se establece en grados, dando 0, 360, 720 o cualquier múltiplo de 360 ​​dará lugar a ningún cambiar a la imagen.

+1

¡Guau! ¡Te tomo bastante tiempo!:-) Gracias ton ton. –

+0

Tatu, una cosa que me falta, y quizás esto no es posible, pero, digamos, solo quiero cambiar el matiz de la imagen de gris (el valor predeterminado) a algo muy cercano a # cc0000. es posible? Como no puedo proporcionar un hexágono en su función, ¿cómo puedo definir el ángulo necesario para lograr eso? –

+0

Además, en su ejemplo, comienza con un png y luego crea un jpeg a partir de eso. ¿Funcionará esto si en su lugar utilizo un gif indexado para cada paso? –

0

Normalmente convertiría de RGB to HSL espacio de color, en cuyo punto puede manipular el matiz directamente. Una vez que haya hecho lo que quiere, volverá a convertir a RGB.

Cuestiones relacionadas