2024 日本 PHP 研討會

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 資源

範例

範例 #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: 搜尋 ($rgb[0], $rgb[1], $rgb[2]); 最接近的匹配: $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 則筆記

info at codeworx dot ch
13 年前
這裡有一個函式,用於比較兩個十六進位顏色值的相似度。如果您想要偵測肉眼無法分辨的顏色差異,這個函式會很有用。它會回傳一個布林值:如果顏色彼此相似(在容許範圍內),則為 TRUE;如果顏色差異夠大,則為 FALSE。
我測試了一些顏色,並得出 35 的容許值(rgb 值 - 應介於 0 到 255 之間),但您可以透過傳遞第三個參數給函式來更改此容許值。

<?php
函數 compareColors ($col1, $col2, $tolerance = 35) {
$col1Rgb = 陣列(
"r" => hexdec(substr($col1, 0, 2)),
"g" => hexdec(substr($col1, 2, 2)),
"b" => hexdec(substr($col1, 4, 2))
);
$col2Rgb = 陣列(
"r" => hexdec(substr($col2, 0, 2)),
"g" => hexdec(substr($col2, 2, 2)),
"b" => hexdec(substr($col2, 4, 2))
);
返回 (
$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);
}
?>
Hayley Watson
7 年前
RGB 色彩空間並不是衡量兩種顏色之間距離的最佳選擇,因為它忽略了例如我們將深綠色和淺綠色都視為「綠色」的事實(#000000 和 #7f7f7f 之間的 RGB 距離與 #000000 和 #5443c0(稍微暗一點的青藍色)之間的距離相同)。

一種更符合顏色感知方式的色彩空間是所謂的 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 調色板,而不是像這裡那樣每次都重新生成它。
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);
}
?>

如果在影像中找到*完全相同的*顏色,則會傳回該顏色。如果沒有完全相同的顏色,則會嘗試配置該顏色。如果無法配置,則會傳回影像中最接近的顏色。
Vikrant Korde <vakorde at hotmail dot com>
21 年前
當您處理現有的影像(例如 .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); // 將字串 "Korde" 寫入圖片
imagejpeg($im, "", 150); // 將圖片以 JPEG 格式輸出,品質為 150
imagedestroy($im); // 銷毀圖片資源
To Top