imagecolorclosest

(PHP 4、PHP 5、PHP 7、PHP 8)

imagecolorclosest获取最接近指定颜色的颜色索引

描述

imagecolorclosest(
    GdImage $image,
    int $red,
    int $green,
    int $blue
): int

返回图像调色板中“最接近”指定 RGB 值的颜色索引。

所需颜色与调色板中每个颜色之间的“距离”计算方式如同 RGB 值表示三维空间中的点。

如果您从文件创建图像,则只解析图像中使用的颜色。只有调色板中存在的颜色不会被解析。

参数

image

一个 GdImage 对象,由一个图像创建函数返回,例如 imagecreatetruecolor()

red

红色分量的值。

green

绿色分量的值。

blue

蓝色分量的值。

颜色参数是 0 到 255 之间的整数或 0x00 到 0xFF 之间的十六进制数。

返回值

返回图像调色板中与指定颜色最接近的颜色索引。

变更日志

版本 描述
8.0.0 image 现在期望一个 GdImage 实例;以前,期望的是一个有效的 gd resource

示例

示例 #1 在图像中搜索一组颜色

<?php
// 从一个图像开始,并将其转换为基于调色板的图像
$im = imagecreatefrompng('figures/imagecolorclosest.png');
imagetruecolortopalette($im, false, 255);

// 搜索颜色 (RGB)
$colors = array(
array(
254, 145, 154),
array(
153, 145, 188),
array(
153, 90, 145),
array(
255, 137, 92)
);

// 循环遍历每个搜索,并在调色板中找到最接近的颜色。
// 返回搜索编号、搜索 RGB 和转换后的 RGB 匹配
foreach($colors as $id => $rgb)
{
$result = imagecolorclosest($im, $rgb[0], $rgb[1], $rgb[2]);
$result = imagecolorsforindex($im, $result);
$result = "({$result['red']}, {$result['green']}, {$result['blue']})";

echo
"#$id: Search ($rgb[0], $rgb[1], $rgb[2]); Closest match: $result.\n";
}

imagedestroy($im);
?>

上面的示例将输出类似于以下内容

#0: Search (254, 145, 154); Closest match: (252, 150, 148).
#1: Search (153, 145, 188); Closest match: (148, 150, 196).
#2: Search (153, 90, 145); Closest match: (148, 90, 156).
#3: Search (255, 137, 92); Closest match: (252, 150, 92).

参见

添加笔记

用户贡献笔记 4 笔记

4
info at codeworx dot ch
12 年前
这是一个比较两个 HEX 颜色的相似度的函数。如果您想检测肉眼无法区分的颜色,这将很有用。它返回一个布尔值:如果颜色彼此相似(在容差范围内)则为 TRUE,如果颜色差异足够大则为 FALSE。
我测试了一些颜色,得出了 35 的容差(rgb 值 - 应该在 0 到 255 之间),但您可以通过将第三个参数传递给函数来更改该容差。

<?php
function compareColors ($col1, $col2, $tolerance=35) {
$col1Rgb = array(
"r" => hexdec(substr($col1, 0, 2)),
"g" => hexdec(substr($col1, 2, 2)),
"b" => hexdec(substr($col1, 4, 2))
);
$col2Rgb = array(
"r" => hexdec(substr($col2, 0, 2)),
"g" => hexdec(substr($col2, 2, 2)),
"b" => hexdec(substr($col2, 4, 2))
);
return (
$col1Rgb['r'] >= $col2Rgb['r'] - $tolerance && $col1Rgb['r'] <= $col2Rgb['r'] + $tolerance) && ($col1Rgb['g'] >= $col2Rgb['g'] - $tolerance && $col1Rgb['g'] <= $col2Rgb['g'] + $tolerance) && ($col1Rgb['b'] >= $col2Rgb['b'] - $tolerance && $col1Rgb['b'] <= $col2Rgb['b'] + $tolerance);
}
?>
1
Hayley Watson
7 年前
RGB 空间不是衡量两种颜色之间距离的最佳选择,因为它忽略了一些因素,例如,我们将深绿色和浅绿色都算作“绿色”(#000000 和 #7f7f7f 之间的 RGB 距离与 #000000 和 #5443c0 之间的距离相同 - 一种略微变暗的 SlateBlue)。

一个更好的颜色空间选择,它更符合颜色的感知方式,是所谓的 Lab 空间,它根据颜色的明暗、红绿和黄蓝来测量颜色。(还有更好的模型,但它们是以增加计算量为代价的。)

<?php

function warp1($c)
{
if(
$c > 10.3148)
{
return
pow((561 + 40*$c)/10761, 2.4);
}
else
{
return
$c / 3294.6;
}
}
function
warp2($c)
{
if(
$c > 0.008856)
{
return
pow($c, 1/3);
}
else
{
return
7.787 * $c + 4/29;
}
}
function
rgb2lab($rgb)
{
[
$red, $green, $blue] = array_map('warp1', $rgb);

$x = warp2($red * 0.4339 + $green * 0.3762 + $blue * 0.1899);
$y = warp2($red * 0.2126 + $green * 0.7152 + $blue * 0.0722);
$z = warp2($red * 0.0178 + $green * 0.1098 + $blue * 0.8730);

$l = 116*$y - 16;
$a = 500 * ($x - $y);
$b = 200 * ($y - $z);

return
array_map('intval', [$l, $a, $b]);
}

function
generate_palette_from_image($image)
{
$pal = [];
$width = imagesx($image);
$height = imagesy($image);
for(
$x = 0; $x < $width; ++$x)
{
for(
$y = 0; $y < $height; ++$y)
{
$pal[] = imagecolorat($image, $x, $y);
}
}
return
array_map(function($col)use($image)
{
$rgba = imagecolorsforindex($image, $col);
return [
$rgba['red'], $rgba['green'], $rgba['blue']];
},
array_unique($pal));
}

function
closest_rgb_in_palette($rgb, $palette)
{
// Quick return when the exact
// colour is in the palette.
if(($idx = array_search($rgb, $palette)) !== false)
{
return
$idx;
}
[
$tl, $ta, $tb] = rgb2lab($rgb);
$dists = array_map(function($plab)use($tl, $ta, $tb)
{
[
$pl, $pa, $pb] = $plab;
$dl = $pl - $tl;
$da = $pa - $ta;
$db = $pa - $tb;
return
$dl * $dl + $da * $da + $db * $db;
},
array_map('rgb2lab', $palette));
return
array_search(min($dists), $dists);
}

function
closest_rgb_in_image($rgb, $image)
{
$palette = generate_palette_from_image($image);
return
$palette[closest_rgb_in_palette($rgb, $palette)];
}

$lena = imagecreatefrompng('lena.png');
$red = closest_rgb_in_image([255,0,0],$lena);
echo
join(' ', $red); // 228 71 82

?>

如果你要将许多颜色与调色板匹配,你可能希望预先计算并重用 Lab 调色板,而不是像这里一样每次都重新生成它。
-1
MagicalTux at FF dot st
19 年前
一种每次都能得到答案的方法

<?php
function imagegetcolor($im, $r, $g, $b) {
$c=imagecolorexact($im, $r, $g, $b);
if (
$c!=-1) return $c;
$c=imagecolorallocate($im, $r, $g, $b);
if (
$c!=-1) return $c;
return
imagecolorclosest($im, $r, $g, $b);
}
?>

如果图像中找到了*完全匹配*的颜色,则将返回该颜色。如果我们没有找到完全匹配的颜色,我们将尝试分配它。如果我们无法分配它,我们将返回图像中最接近的颜色。
-1
Vikrant Korde <vakorde at hotmail dot com>
20 年前
当您处理之前存在的图像(如 .png、.jpg 等)时,此函数非常有用。您可以使用此函数在图像上写入文本。

对我来说,函数 imagecolorallocate() 返回 -1 值。经过大量的研究和网站搜索,我找到了一个使用 imagecolorclosest() 函数的方法。这解决了我在图像上用自定义颜色写入文本的问题。

实际上,之前它是在图像上写入文本,但颜色并不明显。它使用了与背景图像相同的颜色。

以下代码段对我来说没问题。

header ("Content-type: image/jpeg");
$im = imagecreatefromjpeg("BlankButton.jpg");
$white = imageColorClosest($im, 255,255,255);
// 这是针对 TTF 字体的
imagettftext ($im, 20, 0, 16, 30, $white, "/usr/X11R6/lib/X11/fonts/TTF/luximb.ttf", "Vikrant");

// 这是针对普通字体的
imagestring($im, 4, 0,0,"Korde", $white);
imagejpeg($im,"",150);
imagedestroy ($im);
To Top