PHP convert 24-bit colors to 4-bit

我只是一个虾纸丫 提交于 2019-12-31 06:08:05

问题


Background, I am converting images to ascii art. This works perfectly and even works with 24-bit color, converting the colors to the right rgb values. However, I now want to render the ascii art in 4-bit color palette rather than 24-bit.

How do I convert 24-bit colors to 4-bit with PHP?

More specifically, I have the standard IRC color pallet which I need to convert any given Hexidecimal or RGB value to. It is preferred that the colors match as best as possible when converted to the 4-bit color.

Other ideas I have had on this are to convert the image itself to a 4-bit palette (using GD, which is what I use to read in the colors right now) before trying to grab colors off of it. And another idea might be to define a color range for each of the following color and just check that the given 24-bit color is in the range, however I wouldn't know how to get the ranges for all colors into that palette.


回答1:


imagetruecolortopalette allows you to reduce the colours, but results can vary wildly and I don't know if there is a way of 'mapping' the colours correctly or specifying the palette.

Test image (24-bit):

Reduced to 4-bit (without dithering):

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

Reduced to 4-bit (with dithering):

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

As you can see, results are far from perfect. But perhaps this is a good start for you.




回答2:


I think ImageMagick (or GraphicsMagick) can do this with the -depth option. There's a discussion of it here: http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=15395

UPDATE: I should add that ImageMagick is not a PHP library, however there's a PECL wrapper (imagick) for it at http://pecl.php.net/package/imagick.




回答3:


I think you need to use remap to map the colours in the image to the palette of colours in your swatch. I do it at the command line like this:

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

You may, or may not want the dither option - check it out.

Original image is here:

and this is my palette.jpg (you only need a really small image, this is way too big - I will address this shortly)

and the result

You can also create your palette according to the colours you want using ImageMagick. I hand-coded the following and didn't pay too much attention, so you would want to check the RGB values in here before assuming they are correct:

#/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

Basically, the script above gives ImageMagick the RGB values as text and asks it to make small 8x2 image that looks like this:

Then you would use this palette with your remap operation.




回答4:


In the end, despite the wonderful suggestions surrounding imagemagick I found a good solution using straight php. I was able to calculate the closest color through the use of delta E 2000 with a modified version of php-color-difference library found on github, here is my fork: https://github.com/nalipaz/php-color-difference

The pertinent example is:

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

I am pretty happy with this solution and smaller amount of overhead. Thanks for the suggestions guys.



来源:https://stackoverflow.com/questions/26225594/php-convert-24-bit-colors-to-4-bit

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!