Цвета палитры PHP GD - PullRequest
       44

Цвета палитры PHP GD

5 голосов
/ 17 сентября 2010

In PHP GD как конвертировать truecolor изображение в палитру без потери любого цветов,С imagetruecolortopallete это не работает .У меня есть функция, которая проходит через все цвета и фильтрует их (например, оттенки серого).и не сохраняет все цвета , например, это изображение Lamborghini -

Изображение

alt text

Это мой код

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

И это выглядит так

alt text

Вы можете видеть теряет цвета .Есть ли какое-либо решение ?

Также я не думаю, что это связано с моим кодом, но как imagetruecolortopalette выводит его

Ответы [ 3 ]

5 голосов
/ 17 сентября 2010

Проверьте возврат на imagecolorstotal, вы всегда получаете 256 цветов в качестве возврата, независимо от того, насколько высоко вы устанавливаете количество цветов, на которые нужно смешаться. Форматы PNG-8 и GIF поддерживают только палитры до 256 цветов. Таким образом, даже если вы можете использовать более 256 в палитре, вам придется сохранить его обратно как настоящий цвет, чтобы любой мог его использовать, тем самым делая весь процесс преобразования пустой тратой времени. Другими словами, imagetruecolortopallete имеет верхний предел 256 цветов, вы не можете идти выше.

Вот как вы можете сделать это в истинном цвете, хотя это требует значительных ресурсов. Может быть, посмотрите на imagemagick, если вы хотите сделать это более эффективно.

$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');

Редактирование: добавление функций rgbtohsv & hsvtorgb. Я не писал эти функции.

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;
}
2 голосов
/ 17 сентября 2010

преобразование истинного цвета в палитру всегда приводит к потере цветов, если только таблица ваших палитр не достаточно велика, чтобы вместить каждый уникальный цвет в изображении. Ламборджини вполне может иметь более (скажем) 255 оттенков одного желтого, и тогда вам все еще понадобятся палитры для оставшейся части изображения поверх этого. Вот почему есть цветные изображения. Там нет палитры, но каждый пиксель может иметь свой собственный выделенный триплет RGB для более точного представления исходной сцены.

При этом я не вижу, как преобразование изображения в истинном цвете изменит желтый на красный, как на ваших образцах изображений. Как именно вы делаете это преобразование палитры? Выборка каждого пикселя и его преобразование?

0 голосов
/ 17 сентября 2010

Как насчет этой функции: http://www.php.net/manual/en/function.imagetruecolortopalette.php. Однако для правильной настройки может потребоваться некоторое количество цветов

...