5

I want to convert a color either in RGB/Hex format to its nearest web-safe color.

Details about a websafe color can be found here: http://en.wikipedia.org/wiki/Web_safe_color

This website(http://www.colortools.net/color_make_web-safe.html) is able to do the way I want to, but I am not sure how to go about it in Python. Can anyone help me out here?

user2864740
  • 60,010
  • 15
  • 145
  • 220
meemee
  • 129
  • 1
  • 2
  • 9
  • 2
    You know 'web safe' colors aren't really important anymore, right? And weren't all they were cracked up to be in the first place. I bet that Wikipedia link you put here explains that, too. – Andrew Barber Nov 05 '13 at 06:23
  • 1
    I think the general task is interesting (who cares if the colors are from the "web safe" palette?) - step #1 is to find out: "How to compute the difference (and by what metric?) between two RGB values?" *Once such a difference function is defined, this task is easily solved trivially with a map and sort* (which is very boring). – user2864740 Nov 05 '13 at 06:27
  • 1
    Start by [color difference](http://en.wikipedia.org/wiki/Color_difference) to see just how complicated coming up with such a difference function can be! (And this is also very device and color-space dependent.) Anyway, with these new search terms, should be able to explore more. Good luck! – user2864740 Nov 05 '13 at 06:30
  • e.g. see http://stackoverflow.com/questions/4754506/color-similarity-distance-in-rgba-color-space – user2864740 Nov 05 '13 at 06:34
  • 1
    Unlike other palettes, web safe colors don't need any complex comparison algorithms, because each channel is simply a multiple of 51. So you can take the channels of your own color and just do `R = Round( ( R / 255 ) * 5 ) * 51`. Fast and simple cross-platform color quantization. So much for being "not really important anymore"! ;-) – Beejor Mar 12 '15 at 05:42

3 Answers3

9

Despite being somewhat of a misnomer, the web safe color palette is indeed quite useful for color quantization. It's simple, fast, flexible, and ubiquitous. It also allows for RGB hex shorthand such as #369 instead of #336699. Here's a walkthrough:

  1. Web safe colors are RGB triplets, with each value being one of the following six: 00, 33, 66, 99, CC, FF. So we can divide the max RGB value 255 by five (one less than the total possible values) to get a multiple value, 51.
  2. Normalize the channel value by dividing by 255 (this makes it a value from 0-1 instead of 0-255).
  3. Multiply by 5, and round the result to make sure it stays exact.
  4. Multiply by 51 to get the final web safe value. All together, this looks something like:

    def getNearestWebSafeColor(r, g, b):
        r = int(round( ( r / 255.0 ) * 5 ) * 51)
        g = int(round( ( g / 255.0 ) * 5 ) * 51)
        b = int(round( ( b / 255.0 ) * 5 ) * 51)
        return (r, g, b)
    
    print getNearestWebSafeColor(65, 135, 211)
    

No need to go crazy comparing colors or creating huge lookup tables, as others have suggested. :-)

Community
  • 1
  • 1
Beejor
  • 8,606
  • 1
  • 41
  • 31
  • Thanks for this extremely useful and well working method! I've translated your generic code description into a Python function. However, the markup doesn't seem to be working. – Simon Steinberger Dec 02 '17 at 23:23
  • @SimonSteinberger: the problem with the markdown is that to insert a code block in an ordered list, we need to put 8 spaces instead of 4. :-/ – 0x2b3bfa0 Apr 19 '18 at 10:02
2
import scipy.spatial as sp

input_color = (100, 50, 25)
websafe_colors = [(200, 100, 50), ...] # list of web-save colors
tree = sp.KDTree(websafe_colors) # creating k-d tree from web-save colors
ditsance, result = tree.query(input_color) # get Euclidean distance and index of web-save color in tree/list
nearest_color = websafe_colors[result]

Or add loop for several input_colors

About k-dimensional tree

Pylyp
  • 404
  • 1
  • 7
  • 15
0

You can use colorir for this:

>>> from colorir import Palette
>>> css = Palette.load("css")
>>> web_safe = css.most_similar("fe0000") # input can be in any format
>>> web_safe
HexColor(#ff0000)

If you need its name:

>>> css.get_names(web_safe)
['red']

If you need it as RGB:

>>> web_safe.rgb()
sRGB(255, 0, 0)
aleferna
  • 136
  • 6