簡體   English   中英

PHP將24位顏色轉換為4位

[英]PHP convert 24-bit colors to 4-bit

背景,我正在將圖像轉換為ASCII藝術。 這可以完美工作,甚至可以使用24位顏色,將顏色轉換為正確的rgb值。 但是,我現在想用4位調色板而不是24位來渲染ascii藝術。

如何使用PHP將24位顏色轉換為4位?

更具體地說,我有標准的IRC顏色托盤,我需要將任何給定的十六進制或RGB值轉換為該顏色。 當轉換為4位顏色時,顏色最好盡可能匹配。

我對此的其他想法是,在嘗試從中獲取顏色之前,將圖像本身轉換為4位調色板(使用GD,這是我現在用來讀取顏色的顏色)。 另一個想法可能是為以下每種顏色定義一個顏色范圍,然后僅檢查給定的24位顏色在該范圍內,但是我不知道如何將所有顏色的范圍都放入該調色板中。

在此處輸入圖片說明

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');

幸福,有抖動

如您所見,結果遠非完美。 但這也許對您來說是一個好的開始。

我認為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)。

我認為您需要使用remap將圖像中的顏色remap到色板中的調色板。 我在這樣的命令行上這樣做:

convert image.jpg -remap palette.jpg out.jpg

您可能想要或不希望使用dither選項-將其簽出。

原始圖片在這里:

在此處輸入圖片說明 這是我的palette.jpg (您只需要一個非常小的圖像,這太大了-我將在短期內解決)

在此處輸入圖片說明

和結果 在此處輸入圖片說明

您還可以使用ImageMagick根據想要的顏色創建調色板。 我對以下內容進行了手工編碼,並且沒有過多注意,因此您在假設它們正確之前,需要在此處檢查R​​GB值:

#/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操作中使用此調色板。

最后,盡管圍繞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];

我對這種解決方案和較少的開銷感到非常滿意。 謝謝你們的建議。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM