在 PHP GD 中,如何将 truecolor 图像转换为调色板,而不会丢失 任何 颜色。使用imagetruecolortopallete
无效。我有一个贯穿所有颜色并过滤它们的功能(例如灰度)。并且它不保留所有颜色,例如兰博基尼的这张照片 -
图片
这是我的代码
$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);
看起来像这样
您可以看到 它失去了颜色 。是 任何解决方案 ?
此外,我不认为它与我的代码有关,但imagetruecolortopalette
如何输出
答案 0 :(得分:5)
检查imagecolorstotal
上的返回值,无论您设置多少要抖动的颜色,总是会得到256种颜色作为返回。 PNG-8&amp; GIF格式仅支持最多256种颜色的调色板。因此,即使您可以在调色板中使用超过256个,您也必须将其保存为真正的颜色,以便任何人都可以使用它,从而使整个转换过程浪费时间。换句话说,imagetruecolortopallete
的上限为256色,你不能更高。
以下是如何在truecolor中完成它,尽管它是资源密集型的。如果你想更有效地做这件事,也许可以看看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&amp; 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;
}
答案 1 :(得分:2)
将truecolor转换为调色板总是会涉及丢失颜色,除非您的调色板足够大以容纳图像中的每种独特颜色。兰博基尼可能只有(比方说)单独使用255种黄色,然后你还需要调色板插槽才能显示剩余的图像。这就是真彩色图像的原因。没有调色板,但每个像素都可以拥有自己的专用RGB三元组,以更准确地表示原始场景。
话虽如此,我无法看到如何转换真彩色图片会像样本图像中那样将黄色变为红色。你究竟是如何进行这种调色板转换的?对每个像素进行采样并对其进行某种转换?
答案 2 :(得分:0)
这个功能怎么样:http://www.php.net/manual/en/function.imagetruecolortopalette.php。但是,为了使它正确,颜色的数量可能会有些混乱。