2010-09-16 27 views
5

In PHP GD come si può convertire l'immagine di un truecolor ad un palette senza perdere eventuali colori. Con imagetruecolortopallete lo non funziona. Ho una funzione che attraversa tutti i colori e li filtra (ad esempio in scala di grigi). e Esso non conserva tutti i colori, come questa immagine di un Lamborghini-PHP GD colori della tavolozza

Immagine

alt text

Questo è il mio codice

$im = imagecreatefrompng("lamborghini.png"); 
$degrees = 0; 

$img = imagecreatetruecolor(imagesx($im), imagesy($im)); 
imagecopy($img, $im, 0, 0, 0, 0, imagesx($im), imagesy($im)); 
imagetruecolortopalette($img, true, 256); 
$t = imagecolorstotal($img); 
for ($i = 0; $i < $t; $i++) { 
    $rgb = imagecolorsforindex($img, $i); 
    $hsv =rgbtohsv($rgb['red'], $rgb['green'], $rgb['blue']); 
    $h = $degrees; 
    $s = $hsv['s']; 
    $v = $hsv['v']; 
    while ($h > 360) {$h -= 360;}; 
     $nrgb = hsvtorgb($h, $s, $v); 
    imagecolorset($img, $i, $nrgb['r'], $nrgb['g'], $nrgb['b']); 
} 
imagecopy($im, $img, 0, 0, 0, 0, imagesx($img), imagesy($img)); 

header('Content-type: image/png'); 

imagepng($im); 
imagedestroy($im); 

Ed assomiglia a questo

alt text

Si può vedere perde i colori. C'è qualsiasi soluzione?

Anche io non credo che abbia a che fare con il mio codice, ma come imagetruecolortopalette uscite è

+0

La conversione della tavolozza della libreria GD è veloce, ma molto imprecisa. Se vuoi usare la palette, ti consiglio di usare commandline [pngquant] (https://github.com/pornel/improved-pngquant) tramite [popen()] (http://php.net/popen) - mentre questo perdere * alcuni * colori, la perdita non sarà così male. – Kornel

risposta

5

Controllare il ritorno su imagecolorstotal, si ottengono sempre 256 colori come il ritorno non importa quanto in alto si imposta il numero di colori su cui eseguire il dithering. PNG-8 & I formati GIF supportano solo palette fino a 256 colori. Quindi, anche se puoi utilizzare più di 256 in una tavolozza, dovresti salvarlo come vero colore affinché chiunque possa usarlo, rendendo così l'intero processo di conversione una perdita di tempo. In altre parole, imagetruecolortopallete ha un limite superiore di 256 colori, non è possibile andare più in alto.

Ecco come è possibile farlo in truecolor, anche se richiede molte risorse. Forse guarda in imagemagick se vuoi farlo in modo più efficiente.

$im = imagecreatefrompng("lamb.png"); 
$img = imagecreatetruecolor(imagesx($im), imagesy($im)); 
$degrees = 0; 
if ($degrees > 360) {$degrees = $degrees % 360 ;} 

foreach (range(0, imagesx($im) - 1) as $x) { 
    foreach (range(0, imagesy($im) - 1) as $y) { 
     $rgb = imagecolorat($im, $x, $y); 
     $r = ($rgb >> 16) & 0xFF; 
     $g = ($rgb >> 8) & 0xFF; 
     $b = $rgb & 0xFF; 
     $hsv = rgbtohsv($r,$g,$b); 
     $rgb = hsvtorgb($degrees, $hsv['s'], $hsv['v']); 
     imagesetpixel($img, $x,$y,imagecolorallocate($img, $rgb['r'], $rgb['g'], $rgb['b'])); 
    } 
} 

imagepng($img, 'lamb2.png'); 

Modifica: Aggiunta rgbtohsv & funzioni hsvtorgb. Non ho scritto queste funzioni.

function rgbtohsv ($R, $G, $B) { 
// HSV Results:Number 0-1 
$HSL = array(); 

$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--; 
} 

$HSL['h'] = $H; 
$HSL['s'] = $S; 
$HSL['v'] = $V; 

return $HSL; 
} 

function hsvtorgb ($H, $S, $V) 
{ 
$RGB = array(); 

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; 
} 

$RGB['r'] = $R; 
$RGB['g'] = $G; 
$RGB['b'] = $B; 

return $RGB; 
} 
+0

cosa è 'rgbtohsv' e' hsvtorgb' – EscoMaji

+0

@EscoMaji Ho aggiunto quelle funzioni al post. – Klinky

0

Che ne dite di questa funzione: http://www.php.net/manual/en/function.imagetruecolortopalette.php. Tuttavia, potrebbe essere necessario qualche problema con il numero di colori per farlo bene.

+0

Che cosa stavo già provando, vedere la mia modifica –

+0

Hai abilitato 'dithering'? E quanti colori hai specificato? –

+0

Questo è ciò che ho 'imagetruecolortopalette ($ img, true, 256);' sì sì –

2

La conversione di truecolor in tavolozza comporta sempre la perdita di colori, a meno che il tavolo per pallette non sia abbastanza grande da contenere ogni colore univoco dell'immagine. I lamborghini possono benissimo avere più di (almeno) 255 sfumature di giallo da solo, e quindi hai ancora bisogno di slot per le palette per il resto dell'immagine. Ecco perché ci sono immagini truecolor. Non c'è tavolozza, ma ogni pixel può avere il suo triplet RGB dedicato per rappresentare più accuratamente la scena originale.

Detto questo, non riesco a vedere come la conversione di un'immagine in truecolor cambierà da gialla a rossa come nelle immagini di esempio. Come stai esattamente facendo questa conversione della tavolozza? Campionare ogni pixel e fare una sorta di trasformazione su di esso?

+0

Fammi modificare per spiegare –

+0

Cosa succede se elimini il round-round rgb-> hsv-> rgb? Vedi cosa produce l'imagetruecolortopalette? Immagino che tu abbia un errore nella funzione rgbtohsv e/o hsvtorgb, in quanto anche un generatore di palette "cattivo" non produrrebbe così tanti rossi da un'immagine sorgente che essenzialmente non ne ha. –

+0

No Ho risolto il problema utilizzando opzionalmente palette (per la velocità) e TrueColor per la qualità. –