背景,我正在将图像转换为ascii艺术。这非常有效,甚至可以使用24位颜色,将颜色转换为正确的rgb值。但是,我现在想要用4位调色板而不是24位渲染ascii艺术。
如何使用PHP将24位颜色转换为4位?
更具体地说,我有标准的IRC颜色托盘,我需要将任何给定的十六进制或RGB值转换为。当转换为4位颜色时,颜色最好尽可能匹配。
我对此的其他想法是将图像本身转换为4位调色板(使用GD,这是我现在用来读取颜色的颜色),然后再尝试抓取它的颜色。另一个想法可能是为以下每种颜色定义一个颜色范围,并检查给定的24位颜色是否在该范围内,但是我不知道如何将所有颜色的范围放入该调色板中
答案 0 :(得分:1)
imagetruecolortopalette
可以让你减少颜色,但结果可能会有很大差异,我不知道是否有一种“映射”的方法。正确的颜色或指定调色板。
测试图片(24位):
减少到4位(没有抖动):
$img = imagecreatefrompng('Bliss.png');
imagetruecolortopalette($img, false, 16);
imagepng($img, 'Bliss2.png');
减少到4位(带抖动):
$img = imagecreatefrompng('Bliss.png');
imagetruecolortopalette($img, true, 16);
imagepng($img, 'Bliss3.png');
正如您所看到的,结果远非完美。但也许这对你来说是一个好的开始。
答案 1 :(得分:0)
我认为ImageMagick(或GraphicsMagick)可以使用-depth选项执行此操作。这里有一个讨论:http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=15395
更新:我应该补充一点,ImageMagick不是一个PHP库,但在http://pecl.php.net/package/imagick有一个PECL包装器(imagick)。
答案 2 :(得分:0)
我认为你需要使用remap
将图像中的颜色映射到样本中的颜色调色板。我在命令行这样做:
convert image.jpg -remap palette.jpg out.jpg
您可能或可能不想要dither
选项 - 请查看。
原始图片在这里:
这是我的palette.jpg
(你只需要一个非常小的图片,这太大了 - 我会尽快解决这个问题)
和结果
您还可以使用ImageMagick根据您想要的颜色创建调色板。我手动编码以下内容并没有太多关注,所以在假设它们是正确的之前你需要检查这里的RGB值:
#/bin/bash
cat<<EOF | convert txt:- palette.png
# ImageMagick pixel enumeration: 8,2,256,rgb
0,0: (255,255,255)
1,0: (0,0,0)
2,0: (0,0,255)
3,0: (255,255,0)
4,0: (255,0,0)
5,0: (128,128,128)
6,0: (255,105,180)
7,0: (173,216,230)
0,1: (50,205,50)
1,1: (139,0,0)
2,1: (255,165,0)
3,1: (128,0,128)
4,1: (0,0,139)
5,1: (0,128,128)
6,1: (0,128,0)
7,1: (211,211,211)
EOF
基本上,上面的脚本为ImageMagick提供了RGB值作为文本,并要求它生成小的8x2图像,如下所示:
然后,您可以将此调色板与remap
操作一起使用。
答案 3 :(得分:0)
最后,尽管有关于imagemagick的精彩建议,我发现使用直接php的一个很好的解决方案。我能够通过使用delta E 2000计算最接近的颜色,并在github上找到修改后的php-color-difference库,这是我的分叉:https://github.com/nalipaz/php-color-difference
相关的例子是:
<?php
include('lib/color_difference.class.php');
$palette = array(
'00' => array(255, 255, 255),
'01' => array(0, 0, 0),
'02' => array(0, 0, 139),
'03' => array(0, 128, 0),
'04' => array(255, 0, 0),
'05' => array(139, 0, 0),
'06' => array(128, 0, 128),
'07' => array(255, 165, 0),
'08' => array(255, 255, 0),
'09' => array(50, 205, 50),
'10' => array(0, 128, 128),
'11' => array(173, 216, 230),
'12' => array(0, 0, 255),
'13' => array(255, 105, 180),
'14' => array(128, 128, 128),
'15' => array(211, 211, 211),
);
$color_rgb = array(255, 255, 128);
$color_delta_e = new color_difference($color_rgb);
$match_index = $color_delta_e->getClosestMatch($palette);
$color = $palette[$match_index];
我很满意这个解决方案和少量的开销。谢谢你的建议。