PHP将24位颜色转换为4位

PHP将24位颜色转换为4位,php,colors,gd,Php,Colors,Gd,背景,我正在将图像转换为ascii艺术。这非常有效,甚至适用于24位颜色,将颜色转换为正确的rgb值。但是,我现在想在4位调色板而不是24位调色板中渲染ascii艺术 如何使用PHP将24位颜色转换为4位颜色 更具体地说,我有标准的IRC颜色托盘,我需要将任何给定的十六进制或RGB值转换为。最好在转换为4位颜色时,颜色尽可能匹配 我在这方面的其他想法是将图像本身转换为4位调色板(使用GD,这是我现在用来读取颜色的),然后再尝试从中获取颜色。另一个想法可能是为下面的每种颜色定义一个颜色范围,然后检

背景,我正在将图像转换为ascii艺术。这非常有效,甚至适用于24位颜色,将颜色转换为正确的rgb值。但是,我现在想在4位调色板而不是24位调色板中渲染ascii艺术

如何使用PHP将24位颜色转换为4位颜色

更具体地说,我有标准的IRC颜色托盘,我需要将任何给定的十六进制或RGB值转换为。最好在转换为4位颜色时,颜色尽可能匹配

我在这方面的其他想法是将图像本身转换为4位调色板(使用GD,这是我现在用来读取颜色的),然后再尝试从中获取颜色。另一个想法可能是为下面的每种颜色定义一个颜色范围,然后检查给定的24位颜色是否在该范围内,但是我不知道如何将所有颜色的范围放入该调色板

我认为ImageMagick(或GraphicsMagick)可以通过-depth选项实现这一点。这里有一个关于它的讨论:

更新:我应该补充一点,ImageMagick不是一个PHP库,但是它有一个PECL包装器(imagick)

允许您减少颜色,但结果可能差异很大,我不知道是否有一种方法可以正确“映射”颜色或指定调色板

测试图像(24位):

$img = imagecreatefrompng('Bliss.png');
imagetruecolortopalette($img, false, 16);
imagepng($img, 'Bliss2.png');
$img = imagecreatefrompng('Bliss.png');
imagetruecolortopalette($img, true, 16);
imagepng($img, 'Bliss3.png');

减少到4位(无抖动):

$img = imagecreatefrompng('Bliss.png');
imagetruecolortopalette($img, false, 16);
imagepng($img, 'Bliss2.png');
$img = imagecreatefrompng('Bliss.png');
imagetruecolortopalette($img, true, 16);
imagepng($img, 'Bliss3.png');

减少到4位(带抖动):

$img = imagecreatefrompng('Bliss.png');
imagetruecolortopalette($img, false, 16);
imagepng($img, 'Bliss2.png');
$img = imagecreatefrompng('Bliss.png');
imagetruecolortopalette($img, true, 16);
imagepng($img, 'Bliss3.png');


正如你所看到的,结果远非完美。但这可能是一个好的开始。

我认为您需要使用
重新映射
将图像中的颜色映射到样例中的调色板。我在命令行中这样做:

convert image.jpg -remap palette.jpg out.jpg
您可能想要,也可能不想要
抖动
选项-查看它

原图如下:

这是我的
调色板.jpg
(你只需要一个非常小的图像,这太大了-我很快就会解决这个问题)

结果呢

您还可以使用ImageMagick根据需要的颜色创建调色板。我手工编写了以下代码,没有太多注意,因此在假设RGB值正确之前,您需要检查其中的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
#/bin/bash

cat最后,尽管围绕imagemagick提出了很多建议,但我还是找到了一个使用纯php的好解决方案。我能够通过使用delta E 2000计算最接近的颜色,并在github上找到一个修改版本的php色差库,这是我的fork:

相关的例子是:

<?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];

ImageMagick可以成为一种无需太多麻烦的需求。我猜我需要先将任何jpe?g和GIF转换为png,然后再使用这个选项?我认为-depth选项可以跨格式工作-请参阅。查看更改深度。这可能会有帮助,但这并不能说明我需要用上面调色板中的颜色替换这些颜色。生成的图像只需要是上述调色板中的颜色。也许,如果我将深度更改减少到16,然后用上面的颜色替换16种颜色中的每一种,那么它可能会起作用。不过,我需要研究颜色的替换,并将上述每种颜色与生成图像中的合理颜色进行匹配。