PHP конвертирует 24-битные цвета в 4-битные

Фон, я конвертирую изображения в ascii art. Это работает отлично и даже работает с 24-битным цветом, преобразовывая цвета в правильные значения RGB. Тем не менее, теперь я хочу представить ascii art в 4-битной цветовой палитре, а не в 24-битной.

Как мне преобразовать 24-битные цвета в 4-битные с помощью PHP?

Более конкретно, у меня есть стандартная цветовая палитра IRC, в которую мне нужно преобразовать любое заданное шестнадцатеричное или RGB-значение. Желательно, чтобы цвета совпадали как можно лучше при преобразовании в 4-битный цвет.

Другие идеи, которые у меня были по этому поводу, — преобразовать само изображение в 4-битную палитру (используя GD, который я сейчас и использую для чтения цветов), прежде чем пытаться извлечь из него цвета. И еще одна идея может состоять в том, чтобы определить цветовой диапазон для каждого из следующих цветов и просто проверить, что данный 24-битный цвет находится в диапазоне, однако я не знаю, как получить диапазоны для всех цветов в этой палитре.

введите описание изображения здесь

0

Решение

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

Другие решения

Я думаю, ImageMagick (или GraphicsMagick) может сделать это с опцией -depth. Здесь обсуждается это: http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&т = 15395

ОБНОВЛЕНИЕ: я должен добавить, что ImageMagick не является библиотекой PHP, однако есть обертка PECL (imagick) для этого в http://pecl.php.net/package/imagick.

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 в виде текста и просит его создать небольшое изображение 8×2, которое выглядит следующим образом:

введите описание изображения здесь

Тогда вы бы использовали эту палитру с вашим remap операция.

0

В конце концов, несмотря на замечательные предложения, связанные с imagemagick, я нашел хорошее решение, используя прямой php. Я смог рассчитать ближайший цвет с помощью delta E 2000 с модифицированной версией библиотеки php-color-разности, найденной на github, вот мой форк: 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];

Я очень доволен этим решением и меньшим количеством накладных расходов. Спасибо за предложения, ребята.

0
По вопросам рекламы [email protected]