php - Encapsulate ImageMagick in a PHP class to find the closest colour from a predefined palette
问题描述
I am trying to make a class with a method that will accept a single colour as an argument and return the closest colour to it from a predefined palette of colours.
I am aware that there are many ways to calculate the distance between two colours, but I would like to use ImageMagick's implementation, which I have tried to figure out from the source code, but not had any luck. Unfortunately, ImageMagick for PHP is not documented very well. There is lots of documentation, but much of it is vague.
So far, I have some up with 3 different methods, but only one is working. I'm curious as to why the other two methods aren't working and I would also be keen to know if anyone else has a better way to encapsulate ImageMagick in a PHP class that will allow me to achieve my goal.
The code below runs on PHPFiddle.org. Unfortunately, it seems to be broken at the moment and won't let me save it and link to it, so you will need to copy and paste it yourself.
Thanks in advance.
<?php
class ImagickTest
{
protected function createPalette()
{
// Just a limited palette to use as an example.
$colors = [
'#ffffff',
'#000000',
'#d2d3d1',
'#efecf2',
];
// Create a new Imagick object. 4 pixels on a single row.
$im = new \Imagick();
$im->newImage(1, 4, 'white');
// Add the colours.
$i = 0;
$iterator = $im->getPixelIterator();
foreach ($iterator as $pixels) {
foreach ($pixels as $pixel) {
$pixel->setColor($colors[$i++]);
}
$iterator->syncIterator();
}
return $im;
}
public function run()
{
$tests = [
['withBackgroundColor', "// Why doesn't this work?"],
['withPixelIterator', "// This is a really close match. Good result!"],
['withDirectPixelModification', "// Why hasn't the pixel colour changed?"]
];
$palette = $this->createPalette();
$color = '#cfcfcf';
echo "<table><tbody>\n";
foreach ($tests as $test) {
echo sprintf("<tr><td>%s</td><td>%s</td><td>%s</td></tr>\n",
$test[0],
$this->{$test[0]}($color, $palette),
$test[1]
);
}
echo '</tbody></table>';
}
protected function withBackgroundColor($newColor, $palette)
{
$im = new \Imagick();
// WTH does the fourth parameter do, anyway??
$im->newImage(1, 1, 'white' /*, $format*/);
$im->setImageBackgroundColor($newColor);
$im->remapImage($palette, 0); // Remap has no effect at all.
return $this->pixelToHex($im->getImageBackgroundColor());
}
protected function withPixelIterator($newColor, $palette)
{
$im = new \Imagick();
$im->newImage(1, 1, 'white');
$iterator = $im->getPixelIterator();
$pixel = $iterator->getCurrentIteratorRow()[0];
$pixel->setColor($newColor);
$iterator->syncIterator();
$im->remapImage($palette, 0);
return $this->pixelToHex($im->getImagePixelColor(1, 1));
}
protected function withDirectPixelModification($newColor, $palette)
{
$im = new \Imagick();
$im->newImage(2, 2, 'white');
$pixel = $im->getImagePixelColor(1, 1);
$pixel->setColor($newColor); // Seems to be ignored.
$im->remapImage($palette, 0);
return $this->pixelToHex($im->getImagePixelColor(1, 1));
}
protected function pixelToHex($pixel)
{
$color = $pixel->getColor();
return sprintf('#%s%s%s',
str_pad(dechex($color['r']), 2, '0', STR_PAD_LEFT),
str_pad(dechex($color['g']), 2, '0', STR_PAD_LEFT),
str_pad(dechex($color['b']), 2, '0', STR_PAD_LEFT)
);
}
}
(new ImagickTest)->run();
解决方案
推荐阅读
- c# - 大摇大摆的 IAuthorizationFilter 和 IOperationFilter
- filter - Splunk 如何从列表中排除某个值(如果存在)
- javascript - 如何将数据 url 转换为有效 url,以便它可以通过 Graph API 发布在 Facebook 页面上?
- javascript - 无法使用 puppeteer 将绑定/curried/closure 函数从节点传递到浏览器
- c# - Microsoft Graph SDK 请求批处理响应的下一个链接
- excel - 通过 VBA 更新表
- c++ - 静态库的链接和加载
- javascript - 在JS中将数组语句的第一个字母大写
- javascript - 未捕获的语法错误:导出和导入类时无法在模块外部使用导入语句
- c++ - 关于在嵌入式系统上使用 std::filesystem 的建议