bulia byak wrote:
... If we agree that a default totally without scrolling is not feasible, then what is the profit in reducing its length slightly? Can't we just extend the primaries and leave the rest as is?
Because this is an opportunity to make it better :) But you are right that if we fix scrolling to be a lot nicer it won't be such an issue to add some more colors (especially if the most basic part can be accessed directly).
And even if we must reduce the h/s/l, you are going too far IMHO. The old grouping was 11/9/7, yours is 9/6/3. I might perhaps agree to a compromise like 10/8/6, but again, I just don't see why we must reduce this at all.
Fair point, but if adding so many colors I would prefer them to be distributed a bit more perceptually uniform, as I can then take the n-th step of red and the same of step of blue and trust that the lightness and saturation are more or less matched). Of course this is definitely not trivial to do well, but still.
And I also strongly object to dropping the light grays (5% and 2.5%). They are useful.
Assuming you mean they are useful because of gamma and such I've now chosen the values to be linear in "linearRGB" and then transformed them to sRGB, this gives finer steps in the high regions and coarser steps in the low regions.
Also, instead of adding back in the old HSL sequences I've used some color space transformations (using CIE Lab with the same whitepoint as sRGB) to create a similar series of sequences (using the same hues as in the first part). This should make it easier to select different hues with the same (perceived) saturation and lightness. I've attached the generator, so feel free to vary on the theme (for instance, I've chosen to still let HSL determine the hue, but this can also be done in Lab, giving less emphasis on green).
So this palette tries to give: - A slightly smaller, but "fairer" range of grays. - Easy access to a wider variety of hues and also some lighter colors than the original inkscape default. - Hopefully more perceptually uniform sequences of varying lightness and saturation for the same set of hues.
Do people indeed perceive these colors as more perceptually uniform than in the old Inkscape default? Is this perceived as an advantage? Is the distribution of hues reasonable? Any constructive feedback is appreciated.
GIMP Palette Name: Inkscape default Columns: 3 # generated by PaletteGen.py 0 0 0 Black 89 89 89 90% Gray 124 124 124 80% Gray 149 149 149 70% Gray 170 170 170 60% Gray 188 188 188 50% Gray 203 203 203 40% Gray 218 218 218 30% Gray 231 231 231 20% Gray 243 243 243 10% Gray 255 255 255 White 128 0 0 Maroon (#800000) 255 0 0 Red (#FF0000) 255 128 128 #FF8080 128 64 0 #804000 255 128 0 #FF8000 255 191 128 #FFBF80 128 128 0 Olive (#808000) 255 255 0 Yellow (#FFFF00) 255 255 128 #FFFF80 64 128 0 #408000 127 255 0 Chartreuse (#7FFF00) 191 255 128 #BFFF80 0 128 0 Green (#008000) 0 255 0 Lime (#00FF00) 128 255 128 #80FF80 0 128 64 #008040 0 255 127 Spring green (#00FF7F) 128 255 191 #80FFBF 0 128 128 Teal (#008080) 0 255 255 Aqua (#00FFFF) 128 255 255 #80FFFF 0 64 128 #004080 0 128 255 #0080FF 128 191 255 #80BFFF 0 0 128 Navy (#000080) 0 0 255 Blue (#0000FF) 128 128 255 #8080FF 64 0 128 #400080 128 0 255 #8000FF 191 128 255 #BF80FF 128 0 128 Purple (#800080) 255 0 255 Fuchsia (#FF00FF) 255 128 255 #FF80FF 128 0 64 #800040 255 0 128 #FF0080 255 128 191 #FF80BF 43 0 0 #2B0000 79 0 0 #4F0000 116 0 0 #740000 155 0 0 #9B0000 197 0 0 #C50000 239 0 0 #EF0000 255 79 49 #FF4F31 255 130 101 #FF8265 255 170 148 #FFAA94 255 205 192 #FFCDC0 255 239 234 #FFEFEA 47 0 0 #2F0000 91 0 0 #5B0000 138 0 0 #8A0000 182 24 9 #B61809 217 62 36 #D93E24 253 94 63 #FD5E3F 255 148 122 #FF947A 255 193 177 #FFC1B1 255 235 230 #FFEBE6 48 7 0 #300700 83 39 28 #53271C 120 71 59 #78473B 159 106 92 #9F6A5C 199 142 128 #C78E80 240 181 165 #F0B5A5 255 229 222 #FFE5DE 43 0 0 #2B0000 66 20 0 #421400 89 41 0 #592900 113 62 0 #713E00 139 84 0 #8B5400 166 106 0 #A66A00 194 129 0 #C28100 223 152 0 #DF9800 252 177 0 #FCB100 255 209 132 #FFD184 255 240 219 #FFF0DB 43 4 0 #2B0400 66 33 0 #422100 94 58 0 #5E3A00 125 84 0 #7D5400 158 110 0 #9E6E00 192 138 0 #C08A00 228 167 0 #E4A700 255 199 90 #FFC75A 255 237 211 #FFEDD3 35 18 0 #231200 66 49 12 #42310C 102 81 43 #66512B 139 115 76 #8B734C 178 152 111 #B2986F 219 191 148 #DBBF94 255 231 197 #FFE7C5 29 11 0 #1D0B00 43 34 0 #2B2200 53 57 0 #353900 69 80 0 #455000 88 103 0 #586700 111 126 0 #6F7E00 135 150 0 #879600 161 175 0 #A1AF00 188 200 0 #BCC800 216 226 0 #D8E200 244 252 0 #F4FC00 28 16 0 #1C1000 44 43 0 #2C2B00 65 69 0 #414500 91 96 0 #5B6000 120 124 0 #787C00 151 153 0 #979900 183 183 0 #B7B700 216 214 49 #D8D631 249 245 83 #F9F553 27 22 0 #1B1600 54 53 12 #36350C 88 86 43 #58562B 124 121 76 #7C794C 162 158 111 #A29E6F 202 196 148 #CAC494 242 236 186 #F2ECBA 0 20 0 #001400 17 40 0 #112800 18 63 0 #123F00 27 87 0 #1B5700 38 111 0 #266F00 50 136 0 #328800 75 161 0 #4BA100 101 187 0 #65BB00 127 213 0 #7FD500 153 239 0 #99EF00 221 255 136 #DDFF88 2 23 0 #021700 24 47 0 #182F00 35 75 0 #234B00 58 103 0 #3A6700 86 132 0 #568400 115 162 0 #73A200 145 192 32 #91C020 177 223 68 #B1DF44 211 255 104 #D3FF68 18 24 0 #121800 44 56 16 #2C3810 77 89 47 #4D592F 112 124 80 #707C50 149 161 115 #95A173 188 200 152 #BCC898 228 240 191 #E4F0BF 0 20 0 #001400 2 42 0 #022A00 0 64 0 #004000 0 88 0 #005800 0 113 0 #007100 0 139 0 #008B00 0 166 0 #00A600 0 193 0 #00C100 0 222 0 #00DE00 0 251 0 #00FB00 208 255 192 #D0FFC0 0 23 0 #001700 1 49 0 #013100 0 77 0 #004D00 0 107 0 #006B00 0 139 0 #008B00 55 169 40 #37A928 91 200 71 #5BC847 124 232 101 #7CE865 195 255 176 #C3FFB0 1 27 0 #011B00 31 58 24 #1F3A18 63 91 55 #3F5B37 98 127 88 #627F58 134 164 124 #86A47C 172 203 161 #ACCBA1 211 244 200 #D3F4C8 0 20 0 #001400 0 42 0 #002A00 0 64 8 #004008 0 88 20 #005814 0 112 39 #007027 0 138 58 #008A3A 0 164 79 #00A44F 0 191 100 #00BF64 0 219 123 #00DB7B 0 247 150 #00F796 195 255 228 #C3FFE4 0 23 0 #001700 0 49 8 #003108 0 77 32 #004D20 0 106 56 #006A38 0 137 81 #008951 0 169 108 #00A96C 0 202 136 #00CA88 0 236 165 #00ECA5 179 255 222 #B3FFDE 0 27 5 #001B05 0 60 40 #003C28 36 94 72 #245E48 73 130 106 #49826A 109 168 143 #6DA88F 147 207 181 #93CFB5 186 248 220 #BAF8DC 0 18 23 #001217 0 39 51 #002733 0 60 76 #003C4C 0 82 99 #005263 0 106 122 #006A7A 0 131 146 #008392 0 157 170 #009DAA 0 184 196 #00B8C4 0 211 222 #00D3DE 0 240 240 #00F0F0 183 255 254 #B7FFFE 0 22 22 #001616 0 46 53 #002E35 0 73 80 #004950 0 102 108 #00666C 0 132 137 #008489 0 164 168 #00A4A8 0 197 200 #00C5C8 0 231 233 #00E7E9 162 255 254 #A2FFFE 0 26 25 #001A19 0 58 59 #003A3B 0 94 94 #005E5E 48 131 130 #308382 89 169 168 #59A9A8 128 208 207 #80D0CF 168 249 247 #A8F9F7 0 0 75 #00004B 0 19 114 #001372 0 40 150 #002896 0 66 176 #0042B0 0 94 194 #005EC2 0 122 209 #007AD1 0 150 222 #0096DE 0 179 235 #00B3EB 107 201 255 #6BC9FF 176 222 255 #B0DEFF 230 244 255 #E6F4FF 0 9 68 #000944 0 36 104 #002468 0 63 139 #003F8B 0 91 175 #005BAF 0 121 211 #0079D3 0 155 235 #009BEB 34 189 255 #22BDFF 155 215 255 #9BD7FF 224 241 255 #E0F1FF 0 23 46 #00172E 0 55 83 #003753 21 90 122 #155A7A 67 125 159 #437D9F 107 162 198 #6BA2C6 146 201 239 #92C9EF 215 238 255 #D7EEFF 0 0 75 #00004B 0 0 132 #000084 0 0 190 #0000BE 26 8 245 #1A08F5 91 51 255 #5B33FF 129 85 255 #8155FF 159 116 255 #9F74FF 184 147 255 #B893FF 206 177 255 #CEB1FF 227 208 255 #E3D0FF 246 239 255 #F6EFFF 0 0 82 #000052 30 12 133 #1E0C85 68 40 163 #4428A3 101 66 194 #6542C2 133 94 226 #855EE2 165 123 255 #A57BFF 194 160 255 #C2A0FF 220 198 255 #DCC6FF 244 236 255 #F4ECFF 26 15 49 #1A0F31 58 45 82 #3A2D52 92 77 117 #5C4D75 128 112 154 #80709A 165 148 193 #A594C1 205 187 233 #CDBBE9 240 230 255 #F0E6FF 4 0 73 #040049 43 0 111 #2B006F 79 0 146 #4F0092 114 0 183 #7200B7 151 0 221 #9700DD 189 17 255 #BD11FF 205 87 255 #CD57FF 220 130 255 #DC82FF 232 167 255 #E8A7FF 242 203 255 #F2CBFF 251 238 255 #FBEEFF 29 0 62 #1D003E 68 0 105 #440069 107 8 146 #6B0892 138 48 176 #8A30B0 169 78 207 #A94ECF 201 108 239 #C96CEF 225 147 255 #E193FF 239 191 255 #EFBFFF 250 234 255 #FAEAFF 35 11 44 #230B2C 67 42 77 #432A4D 102 74 111 #664A6F 138 109 148 #8A6D94 176 145 186 #B091BA 216 184 226 #D8B8E2 249 228 255 #F9E4FF 34 0 43 #22002B 66 0 76 #42004C 99 0 108 #63006C 134 0 141 #86008D 171 0 176 #AB00B0 209 0 213 #D100D5 250 0 250 #FA00FA 255 104 251 #FF68FB 255 156 249 #FF9CF9 255 198 250 #FFC6FA 255 237 253 #FFEDFD 39 0 43 #27002B 78 0 81 #4E0051 120 0 121 #780079 159 25 159 #9F199F 191 64 189 #BF40BD 224 96 220 #E060DC 255 129 250 #FF81FA 255 185 249 #FFB9F9 255 232 252 #FFE8FC 41 8 40 #290828 73 39 72 #492748 108 72 106 #6C486A 145 106 142 #916A8E 184 143 180 #B88FB4 224 181 220 #E0B5DC 255 226 252 #FFE2FC 41 0 11 #29000B 76 0 40 #4C0028 110 0 65 #6E0041 147 0 93 #93005D 185 0 123 #B9007B 224 0 161 #E000A1 255 48 190 #FF30BE 255 117 203 #FF75CB 255 162 216 #FFA2D8 255 201 231 #FFC9E7 255 237 247 #FFEDF7 45 0 22 #2D0016 86 0 54 #560036 129 0 88 #810058 175 0 126 #AF007E 214 41 159 #D6299F 248 80 190 #F850BE 255 138 208 #FF8AD0 255 188 226 #FFBCE2 255 233 245 #FFE9F5 46 4 32 #2E0420 80 36 63 #50243F 116 69 97 #744561 154 104 132 #9A6884 193 141 170 #C18DAA 233 179 209 #E9B3D1 255 227 242 #FFE3F2
import math import numpy as np import numpy.linalg as la
# This method is more consistent than colorsys.hls_to_rgb # Specifically, hls_to_rgb sometimes returns a value that is rounded # to 0x7F and sometimes a value that is rounded to 0x80 when it should # output 0.5*255=127.5. def rgbFromHSL(H,S=None,L=None): if S is None and L is None and type(H) is tuple: H,S,L = H C = 2.0*L*S if L<=0.5 else (2.0-2.0*L)*S H1 = (float(H)%1.0)*6.0 X = C*(1-abs(H1 % 2 - 1)) if 0<=H1<1: c1 = (C,X,0) elif 1<=H1<2: c1 = (X,C,0) elif 2<=H1<3: c1 = (0,C,X) elif 3<=H1<4: c1 = (0,X,C) elif 4<=H1<5: c1 = (X,0,C) elif 5<=H1<6: c1 = (C,0,X) m = L - C/2.0 return tuple(map(lambda c:c+m,c1))
# Conversion from Lab and more RGB2XYZ = np.array([[0.4124,0.3576,0.1805],[0.2126,0.7152,0.0722],[0.0193,0.1192,0.9505]]) XYZ2RGB = np.array([[3.2410,-1.5374,-0.4986],[-0.9692,1.8760,0.0416],[0.0556,-0.2040,1.0570]]) iters = 0 while max(np.max(np.max(np.abs(la.inv(RGB2XYZ)-XYZ2RGB))),np.max(np.max(np.abs(la.inv(XYZ2RGB)-RGB2XYZ))))>1e-14 and iters<1e6: iters += 1 XYZ2RGBn = XYZ2RGB + (1/16.0)*(la.inv(RGB2XYZ)-XYZ2RGB) RGB2XYZ += (1/16.0)*(la.inv(XYZ2RGB)-RGB2XYZ) XYZ2RGB = XYZ2RGBn #Xn, Yn, Zn = 0.94811, 1.0, 1.07304 Xn, Yn, Zn = tuple(np.sum(RGB2XYZ,axis=1)) # This makes the sRGB gray axis align exactly with the Lab gray axis
def LabFromXYZ(X,Y=None,Z=None): if Y is None and Z is None and type(X) is tuple: X,Y,Z = X delta = 6/29.0 f = lambda t: t**(1/3.0) if t>delta**3 else t/(3.0*delta**2)+2*delta/3.0 L = 116*f(Y/Yn)-16 a = 500*(f(X/Xn)-f(Y/Yn)) b = 200*(f(Y/Yn)-f(Z/Zn)) return (L,a,b)
def XYZFromLab(L,a=None,b=None): if a is None and b is None and type(L) is tuple: L,a,b = L fy = (L+16)/116.0 fx = fy + a/500.0 fz = fy - b/200.0 delta = 6/29.0 X = (fx**3) if fx>delta else (fx-16/116.0)*3*delta*delta Y = (fy**3) if fy>delta else (fy-16/116.0)*3*delta*delta Z = (fz**3) if fz>delta else (fz-16/116.0)*3*delta*delta return (X*Xn,Y*Yn,Z*Zn)
def XYZFromLinearRGB(R,G=None,B=None): if G is None and B is None and type(R) is tuple: R,G,B = R return tuple(np.dot(RGB2XYZ,np.array([R,G,B])))
def linearRGBFromXYZ(X,Y=None,Z=None): if Y is None and Z is None and type(X) is tuple: X,Y,Z = X C = tuple(np.dot(XYZ2RGB,np.array([X,Y,Z]))) return tuple(map(lambda c:max(0,min(1,c)), C))
def linearCFromSC(C): a = 0.055 return C/19.92 if C<=0.04045 else ((C+a)/(1+a))**2.4
def sCFromLinearC(C): a = 0.055 return 12.92*C if C<=0.0031308 else (1+a)*(C**(1/2.4))-a
def linearRGBFromSRGB(R,G=None,B=None): if G is None and B is None and type(R) is tuple: R,G,B = R R,G,B = tuple(map(lambda c:max(0,min(1,c)), (R,G,B))) return tuple(map(linearCFromSC, (R,G,B)))
def sRGBFromLinearRGB(R,G=None,B=None): if G is None and B is None and type(R) is tuple: R,G,B = R R,G,B = tuple(map(lambda c:max(0,min(1,c)), (R,G,B))) return tuple(map(sCFromLinearC, (R,G,B)))
def LabFromLinearRGB(R,G=None,B=None): return LabFromXYZ(XYZFromLinearRGB(R,G,B))
def linearRGBFromLab(L,a=None,b=None): return linearRGBFromXYZ(XYZFromLab(L,a,b))
def LabFromSRGB(R,G=None,B=None): return LabFromXYZ(XYZFromLinearRGB(linearRGBFromSRGB(R,G,B)))
def sRGBFromLab(L,a=None,b=None): return sRGBFromLinearRGB(linearRGBFromXYZ(XYZFromLab(L,a,b)))
def sRGBFromLCH(L,C=None,H=None): return sRGBFromLinearRGB(linearRGBFromXYZ(XYZFromLab(LabFromLCH(L,C,H))))
# Helpers def sRGBFromLabIterL1(Lo,ao=None,bo=None): if ao is None and bo is None and type(Lo) is tuple: Lo,ao,bo = Lo L,a,b = Lo,ao,bo iters = 0 while True: iters += 1 if iters>10000 or math.sqrt(a*a+b*b)<1e-6: return sRGBFromLab(L,a,b) Ln,an,bn = LabFromLinearRGB(linearRGBFromLab(L,a,b)) if (math.sqrt((Ln-L)**2+(an-a)**2+(bn-b)**2)<1e-2): break a,b = a*0.99,b*0.99 return sRGBFromLab(L,a,b)
def sRGBFromLabIterL2(Lo,ao=None,bo=None): if ao is None and bo is None and type(Lo) is tuple: Lo,ao,bo = Lo L,a,b = Lo,ao,bo iters = 0 while True: iters += 1 if iters>10000: print "bailout (%f,%f,%f)" % (L,a,b) break if math.sqrt(a*a+b*b)<1e-6: break Ln,an,bn = LabFromLinearRGB(linearRGBFromLab(L,a,b)) Ln,an,bn = (2*L+3*Lo+Ln)/6.0,(2*a+3*ao+an)/6.0,(2*b+3*bo+bn)/6.0 if (math.sqrt((Ln-L)**2+(an-a)**2+(bn-b)**2)<1e-2): break L,a,b = Ln,an,bn return sRGBFromLab(L,a,b)
def sRGBFromLabIterL4(Lo,ao=None,bo=None): if ao is None and bo is None and type(Lo) is tuple: Lo,ao,bo = Lo L,a,b = Lo,ao,bo iters = 0 while True: iters += 1 if iters>10000 or math.sqrt(a*a+b*b)<1e-6: return sRGBFromLab(L,a,b) Ln,an,bn = LabFromLinearRGB(linearRGBFromLab(L,a,b)) if (math.sqrt((Ln-L)**2+(an-a)**2+(bn-b)**2)<1e-3): break l = (an*a + bn*b)/(a*a+b*b) a,b = l*a,l*b a,b = (a+2*an)/3.0,(b+2*bn)/3.0 return sRGBFromLab(L,a,b)
def sRGBFromLabIterL5(Lo,ao=None,bo=None): if ao is None and bo is None and type(Lo) is tuple: Lo,ao,bo = Lo L,a,b = Lo,ao,bo iters = 0 while True: iters += 1 if iters>10000 or math.sqrt(a*a+b*b)<1e-6: return sRGBFromLab(L,a,b) Ln,an,bn = LabFromLinearRGB(linearRGBFromLab(L,a,b)) if (math.sqrt((Ln-L)**2+(an-a)**2+(bn-b)**2)<1e-3): break l = (an*a + bn*b)/(a*a+b*b) a,b = 0.5*(l+1)*a,0.5*(l+1)*b return sRGBFromLab(L,a,b)
# Initialization # Note that the numbers of colors used make the palette align nicely in # the swatches dialog with three columns. Ncols = 3 # The number of columns Ngrays = 10+1 # In increments of 10% Nhues = 4 # The number of hues "per side" Nlights = 11 # Number of lightness values Nsats = 3 # The number of saturation values colors = []
# Gray values for i in range(0,Ngrays): colors.append(sRGBFromLinearRGB(rgbFromHSL(0.0,0.0,i/(Ngrays-1.0))))
# Hues (S=1, L=0.25,0.5,0.75) for h in range(0,3*Nhues): for L in (0.25,0.5,0.75): colors.append(rgbFromHSL(h/(3.0*Nhues),1.0,L))
# HSL palette (hue and saturation are controlled by HSL, lightness is done using Lab) sStepSize = 1.0/(Nsats-0.5) #Lo,ao,bo = LabFromXYZ(XYZFromLinearRGB(1,0,0)) #baseAngle = math.atan2(bo,ao) for h in range(0, 3*Nhues): Lo,ao,bo = LabFromXYZ(XYZFromLinearRGB(rgbFromHSL(h/(3.0*Nhues),1.0,0.5))) Co = math.sqrt(ao*ao+bo*bo) #H = 2*math.pi*h/(3*Nhues)+baseAngle for s in range(0, Nsats): sVal = 1-(s*sStepSize) a = ao*sVal*128.0/Co b = bo*sVal*128.0/Co #a = sVal*128.0*math.cos(H) #b = sVal*128.0*math.asinhsin(H) lSteps = Nlights - 2*s lStepSize = 1.0 / lSteps for l in range(0, lSteps): L = (l+0.5)*lStepSize if 100*L<=Lo: colors.append(sRGBFromLabIterL4(100*L,a,b)) else: colors.append(sRGBFromLabIterL5(100*L,a,b))
# Print colors print """GIMP Palette Name: Inkscape default Columns: %u # generated by PaletteGen.py""" % Ncols knownColors = [ # HTML colors ((128,0,0),"Maroon"), ((255,0,0),"Red"), ((128,128,0),"Olive"), ((255,255,0),"Yellow"), ((0,128,0),"Green"), ((0,255,0),"Lime"), ((0,128,128),"Teal"), ((0,255,255),"Aqua"), ((0,0,128),"Navy"), ((0,0,255),"Blue"), ((128,0,128),"Purple"), ((255,0,255),"Fuchsia"), # SVG colors (capitalized and spaced when actually used in the result) ((0,0,0),"black"), ((105,105,105),"dimgray"), ((128,128,128),"gray"), ((169,169,169),"darkgray"), ((192,192,192),"silver"), ((211,211,211),"lightgray"), ((220,220,220),"gainsboro"), ((245,245,245),"whitesmoke"), ((255,255,255),"white"), ((188,143,143),"rosybrown"), ((205,92,92),"indianred"), ((165,42,42),"brown"), ((178,34,34),"firebrick"), ((240,128,128),"lightcoral"), ((128,0,0),"maroon"), ((139,0,0),"darkred"), ((255,0,0),"red"), ((255,250,250),"snow"), ((255,228,225),"mistyrose"), ((250,128,114),"salmon"), ((255,99,71),"tomato"), ((233,150,122),"darksalmon"), ((255,127,80),"Coral"), ((255,69,0),"orangered"), ((255,160,122),"lightsalmon"), ((160,82,45),"sienna"), ((255,245,238),"Seashell"), ((210,105,30),"chocolate"), ((139,69,19),"saddlebrown"), ((244,164,96),"sandybrown"), ((255,218,185),"peachpuff"), ((205,133,63),"peru"), ((250,240,230),"Linen"), ((255,228,196),"bisque"), ((255,140,0),"darkorange"), ((222,184,135),"burlywood"), ((210,180,140),"tan"), ((250,235,215),"antiquewhite"), ((255,222,173),"navajowhite"), ((255,235,205),"blanchedalmond"), ((255,239,213),"Papaya Whip"), ((255,228,181),"moccasin"), ((255,165,0),"orange"), ((245,222,179),"wheat"), ((253,245,230),"oldlace"), ((255,250,240),"floralwhite"), ((184,134,11),"darkgoldenrod"), ((218,165,32),"goldenrod"), ((255,248,220),"cornsilk"), ((255,215,0),"Gold"), ((240,230,140),"khaki"), ((255,250,205),"lemonchiffon"), ((238,232,170),"palegoldenrod"), ((189,183,107),"darkkhaki"), ((245,245,220),"beige"), ((250,250,210),"lightgoldenrodyellow"), ((128,128,0),"olive"), ((255,255,0),"yellow"), ((255,255,224),"lightyellow"), ((255,255,240),"ivory"), ((107,142,35),"olivedrab"), ((154,205,50),"yellowgreen"), ((85,107,47),"darkolivegreen"), ((173,255,47),"greenyellow"), ((127,255,0),"Chartreuse"), ((124,252,0),"lawngreen"), ((143,188,143),"darkseagreen"), ((34,139,34),"forestgreen"), ((50,205,50),"limegreen"), ((144,238,144),"lightgreen"), ((152,251,152),"palegreen"), ((0,100,0),"Dark Green"), ((0,128,0),"green"), ((0,255,0),"lime"), ((240,255,240),"honeydew"), ((46,139,87),"seagreen"), ((60,179,113),"mediumseagreen"), ((0,255,127),"Spring green"), ((245,255,250),"mintcream"), ((0,250,154),"mediumspringgreen"), ((102,205,170),"mediumaquamarine"), ((127,255,212),"aquamarine"), ((64,224,208),"turquoise"), ((32,178,170),"lightseagreen"), ((72,209,204),"mediumturquoise"), ((47,79,79),"darkslategray"), ((175,238,238),"paleturquoise"), ((0,128,128),"teal"), ((0,139,139),"darkcyan"), ((0,255,255),"cyan"), ((224,255,255),"lightcyan"), ((240,255,255),"Azure"), ((0,206,209),"darkturquoise"), ((95,158,160),"cadetblue"), ((176,224,230),"powderblue"), ((173,216,230),"lightblue"), ((0,191,255),"deepskyblue"), ((135,206,235),"skyblue"), ((135,206,250),"lightskyblue"), ((70,130,180),"steelblue"), ((240,248,255),"aliceblue"), ((30,144,255),"dodgerblue"), ((112,128,144),"slategray"), ((119,136,153),"lightslategray"), ((176,196,222),"lightsteelblue"), ((100,149,237),"cornflowerblue"), ((65,105,225),"royalblue"), ((25,25,112),"midnightblue"), ((230,230,250),"Lavender"), ((0,0,128),"navy"), ((0,0,139),"darkblue"), ((0,0,205),"Medium Blue"), ((0,0,255),"blue"), ((248,248,255),"ghostwhite"), ((106,90,205),"slateblue"), ((72,61,139),"darkslateblue"), ((123,104,238),"mediumslateblue"), ((147,112,219),"mediumpurple"), ((138,43,226),"blueviolet"), ((75,0,130),"indigo"), ((153,50,204),"darkorchid"), ((148,0,211),"darkviolet"), ((186,85,211),"mediumorchid"), ((216,191,216),"thistle"), ((221,160,221),"plum"), ((238,130,238),"violet"), ((128,0,128),"purple"), ((139,0,139),"darkmagenta"), ((255,0,255),"magenta"), ((218,112,214),"orchid"), ((199,21,133),"mediumvioletred"), ((255,20,147),"deeppink"), ((255,105,180),"hotpink"), ((255,240,245),"lavenderblush"), ((219,112,147),"palevioletred"), ((220,20,60),"crimson"), ((255,192,203),"pink"), ((255,182,193),"lightpink"), ] eps = 1.0/255.0 for i,c in enumerate(colors): ci = None name = None if max(c)-min(c)<eps and i<Ngrays: # Gray value if c[0]<eps: ci = (0,0,0) name = "Black" elif c[0]>1-eps: ci = (255,255,255) name = "White" else: ci = 3*(round(sum(c)*(255.0/3)),) name = "%u%% Gray" % round(100.0-100.0*linearCFromSC(sum(c)/3.0)) else: for kc,kn in knownColors: diff = (abs(kc[0]-255*c[0]),abs(kc[1]-255*c[1]),abs(kc[2]-255*c[2])) if max(diff)<255*eps: ci = kc name = kn + (" (#%02X%02X%02X)" % ci) break if ci is None: ci = tuple(map(lambda v:round(255*v), c)) name = "#%02X%02X%02X" % ci print "%3u %3u %3u %s" % (ci+(name,))