|
|
@@ -28,7 +28,7 @@ parser.add_option("-a", "--author", |
|
|
|
help="author name") |
|
|
|
parser.add_option("-b", "--hue-blend", |
|
|
|
action="store", |
|
|
|
dest="rainbowBlend", |
|
|
|
dest="hueBlend", |
|
|
|
default=0.0, |
|
|
|
help="mix ratio between hues and background") |
|
|
|
parser.add_option("-e", "--equiluminant", |
|
|
@@ -36,6 +36,11 @@ parser.add_option("-e", "--equiluminant", |
|
|
|
dest="equiluminant", |
|
|
|
default=0.0, |
|
|
|
help="use the same luminance for last hues") |
|
|
|
parser.add_option("-c", "--contrast", |
|
|
|
action="store", |
|
|
|
dest="foreContrast", |
|
|
|
default=7.0, |
|
|
|
help="use highest possible contrast between foreground and background") |
|
|
|
parser.add_option("--hsl", |
|
|
|
action="store_true", |
|
|
|
dest="hsl", |
|
|
@@ -93,6 +98,7 @@ def toSRGB(col): |
|
|
|
def luminance(col): |
|
|
|
return col[0]*0.2126+col[1]*0.7152+col[2]*0.0722 |
|
|
|
|
|
|
|
foreContrast = floatOrDie(options.foreContrast, "foreground contrast must be a number") |
|
|
|
bgHue, bgSat, origLum = parseTuple(args[0]) |
|
|
|
bgLum = luminance(toLinear(colorsys.hls_to_rgb(bgHue, origLum, bgSat))) if options.hsl else origLum |
|
|
|
|
|
|
@@ -100,7 +106,7 @@ accentHue, accentSat = parseTuple(args[1]) |
|
|
|
|
|
|
|
foreHue, foreSat = parseTuple(args[2]) if len(args) > 2 else (0.0, 0.0) |
|
|
|
|
|
|
|
rainbowBlend = floatOrDie(options.rainbowBlend, "rainbow blend must be a number") |
|
|
|
hueBlend = floatOrDie(options.hueBlend, "rainbow blend must be a number") |
|
|
|
|
|
|
|
def lerp(a, b, t): |
|
|
|
return a + (b - a) * t |
|
|
@@ -121,13 +127,21 @@ def saturation(col): |
|
|
|
return colorsys.rgb_to_hls(*col)[2] |
|
|
|
|
|
|
|
def contrast(a, b): |
|
|
|
lo, hi = min(a, b), max(a, b) |
|
|
|
return (hi + 0.05) / (lo + 0.05) |
|
|
|
return (max(a, b) + 0.05) / (min(a, b) + 0.05) |
|
|
|
|
|
|
|
def getContrast(lum, ratio): |
|
|
|
def lumFromContrast(lum, ratio): |
|
|
|
hi = ratio*lum + (ratio - 1)*0.05 |
|
|
|
lo = (lum + 0.05 - ratio * 0.05) / ratio |
|
|
|
return hi if hi < 0.99 or lo < 0.0 else lo |
|
|
|
|
|
|
|
if hi == min(1.0, hi): return hi |
|
|
|
if lo == max(0.0, lo): return lo |
|
|
|
|
|
|
|
hiCon = 1.05 / (lum + 0.05) |
|
|
|
loCon = (lum + 0.05) / 0.05 |
|
|
|
return hi if hiCon > loCon else lo |
|
|
|
|
|
|
|
def clamp(x): |
|
|
|
return min(1.0, max(x, 0.0)) |
|
|
|
|
|
|
|
def makeColor(hue, lum, sat = 1.0): |
|
|
|
orig = luminance(colorsys.hls_to_rgb(hue, 0.5, sat)) |
|
|
@@ -136,17 +150,23 @@ def makeColor(hue, lum, sat = 1.0): |
|
|
|
def makeBackground(): |
|
|
|
return makeColor(bgHue, bgLum, bgSat) |
|
|
|
|
|
|
|
def foregroundContrast(): |
|
|
|
return getContrast(bgLum, 7) |
|
|
|
def foregroundLum(bg = bgLum): |
|
|
|
return lumFromContrast(bg, foreContrast) |
|
|
|
|
|
|
|
CONSTRAIN_LOWER = False |
|
|
|
CONSTRAIN_UPPER = True |
|
|
|
def constrain(orig, compare, limit, mode=CONSTRAIN_UPPER): |
|
|
|
comp = lambda a, b: a > b if mode else a < b |
|
|
|
return lumFromContrast(compare, limit) if comp(contrast(orig, compare), limit) else orig |
|
|
|
|
|
|
|
def genRainbow(hues, minCon, maxCon): |
|
|
|
backFull = colorsys.hls_to_rgb(bgHue, 0.5, bgSat) |
|
|
|
|
|
|
|
rainbow = [mixColors(colorsys.hls_to_rgb(hue/360.0, 0.5, 1.0), backFull, rainbowBlend) for hue in hues] |
|
|
|
rainbow = [mixColors(colorsys.hls_to_rgb(hue/360.0, 0.5, 1.0), backFull, hueBlend) for hue in hues] |
|
|
|
|
|
|
|
rainLums = [luminance(col) for col in rainbow] |
|
|
|
hiLum, loLum = max(rainLums), min(rainLums) |
|
|
|
minLum, maxLum = sorted((getContrast(bgLum, minCon), getContrast(bgLum, minCon if options.equiluminant else maxCon ))) |
|
|
|
minLum, maxLum = sorted((lumFromContrast(bgLum, minCon), lumFromContrast(bgLum, minCon if options.equiluminant else maxCon ))) |
|
|
|
maxLum = min(1.0, maxLum) |
|
|
|
|
|
|
|
darkenBrown = (options.equiluminant or options.lightBrown) |
|
|
@@ -162,7 +182,8 @@ def printBanner(commentChar): |
|
|
|
say("background {}: {} {} {}".format("HSL" if options.hsl else "HCL", bgHue, bgSat, origLum)) |
|
|
|
say("accent HC : {} {}".format(accentHue, accentSat)) |
|
|
|
say("foreground HC : {} {}".format(foreHue, foreSat)) |
|
|
|
say("hue blend : {}".format(rainbowBlend)) |
|
|
|
say("hue blend : {}".format(hueBlend)) |
|
|
|
say("fg contrast : {}".format(foreContrast)) |
|
|
|
sayIf(options.equiluminant, "equiluminant hues") |
|
|
|
sayIf(options.hsl, "using gamma-encoded HSL") |
|
|
|
|
|
|
@@ -174,16 +195,20 @@ def toHex(col): |
|
|
|
|
|
|
|
def base16Generate(): |
|
|
|
background = makeBackground() |
|
|
|
foreLum = foregroundContrast() |
|
|
|
foreLum = clamp(foregroundLum()) |
|
|
|
foreCon = contrast(foreLum, bgLum) |
|
|
|
foreground = makeColor(foreHue, foreLum, foreSat) |
|
|
|
commentLum = getContrast(bgLum, 3) |
|
|
|
commentLum = lumFromContrast(bgLum, max(4.5, 1.0 + foreCon / 2.0)) |
|
|
|
comment = makeColor(accentHue, commentLum, accentSat) |
|
|
|
accentLum = getContrast(foreLum, 4.5) |
|
|
|
accent = makeColor(accentHue, accentLum, accentSat) |
|
|
|
|
|
|
|
foreDark = makeColor(foreHue, (commentLum + foreLum) * 0.5, foreSat) |
|
|
|
backLighter = makeColor(bgHue, (bgLum + accentLum) * 0.5, bgSat) |
|
|
|
accentLum = constrain(lumFromContrast(foreLum, 4.5), bgLum, 2.0) |
|
|
|
accent = makeColor(accentHue, accentLum, accentSat) |
|
|
|
|
|
|
|
statusBgLum = lumFromContrast(bgLum, 1.25) |
|
|
|
backStatus = makeColor(bgHue, statusBgLum, bgSat) |
|
|
|
|
|
|
|
foreStatus = makeColor(foreHue, lumFromContrast(statusBgLum, 7.0), foreSat) |
|
|
|
|
|
|
|
# supposedly these two are rarely used so i don't care |
|
|
|
lastTwo = [lerp(foreLum, 1.0 if foreLum > bgLum else 0.0, (x + 1) / 3) for x in range(2)] |
|
|
|
|
|
|
@@ -191,7 +216,7 @@ def base16Generate(): |
|
|
|
backLight = makeColor(bgHue, lastTwo[1], bgSat) |
|
|
|
|
|
|
|
rainbow = genRainbow([RED, 23, YELLOW, GREEN, CYAN, BLUE, MAGENTA, 15], 4.5, 7.0) |
|
|
|
cols = [background, backLighter, accent, comment, foreDark, foreground, foreLight, backLight] + rainbow |
|
|
|
cols = [background, backStatus, accent, comment, foreStatus, foreground, foreLight, backLight] + rainbow |
|
|
|
|
|
|
|
printBanner("#") |
|
|
|
if options.lightBrown: |
|
|
@@ -205,7 +230,7 @@ def base16Generate(): |
|
|
|
return cols |
|
|
|
|
|
|
|
def base16Preview(im, cols): |
|
|
|
background, foreground, accent, comment, backLighter, foreDark, rainbow = cols[0], cols[5], cols[2], cols[3], cols[1], cols[6], cols[8:] |
|
|
|
background, foreground, accent, comment, backLighter, foreDark, rainbow = cols[0], cols[5], cols[2], cols[3], cols[1], cols[4], cols[8:] |
|
|
|
|
|
|
|
w, h = im.size() |
|
|
|
|
|
|
@@ -219,28 +244,27 @@ def base16Preview(im, cols): |
|
|
|
im.text(90, 123+i*35, "Colored text", rainbow[i], background) |
|
|
|
|
|
|
|
im.draw.rectangle((0, h-80, w, h-40), usable(backLighter)) |
|
|
|
im.text(5, h-75, "'Dark' foreground", foreDark, backLighter) |
|
|
|
im.text(5, h-75, "Status foreground", foreDark, backLighter) |
|
|
|
im.draw.line((0, h-42, w, h-42), usable(foreground), 2) |
|
|
|
|
|
|
|
im.drawPalette(cols) |
|
|
|
|
|
|
|
def xresourcesGenerate(): |
|
|
|
background = makeBackground() |
|
|
|
foreLum = foregroundContrast() |
|
|
|
foreLum = clamp(foregroundLum()) |
|
|
|
foreground = makeColor(foreHue, foreLum, foreSat) |
|
|
|
cursor = makeColor(accentHue, getContrast(foreLum, 3), accentSat) |
|
|
|
cursor = makeColor(accentHue, constrain(lumFromContrast(foreLum, 3), bgLum, 2.0), accentSat) |
|
|
|
|
|
|
|
rainHues = [RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN] |
|
|
|
|
|
|
|
hiCon, loCon = (4.5, 7.0), (3.0, 4.5) |
|
|
|
|
|
|
|
#hiRainbow = genRainbow(rainHues, *hiCon) |
|
|
|
loRainbow = genRainbow(rainHues, *loCon) |
|
|
|
hiRainbow = [makeColor(hue(c), getContrast(luminance(c), 3) if foreLum > bgLum else luminance(c) / 3, saturation(c)) for c in loRainbow] |
|
|
|
hiRainbow = [makeColor(hue(c), lumFromContrast(luminance(c), 3) if foreLum > bgLum else luminance(c) / 3, saturation(c)) for c in loRainbow] |
|
|
|
darkRainbow, lightRainbow = (loRainbow, hiRainbow) if foreLum > bgLum else (hiRainbow, loRainbow) |
|
|
|
firstGrey = min(getContrast(bgLum, 3), getContrast(bgLum, 4.5)) |
|
|
|
firstGrey = min(lumFromContrast(bgLum, 3), lumFromContrast(bgLum, 4.5)) |
|
|
|
|
|
|
|
greys = [makeColor(0, lum, 0) for lum in sorted((firstGrey, getContrast(firstGrey, 3)))] |
|
|
|
greys = [makeColor(0, lum, 0) for lum in sorted((firstGrey, lumFromContrast(firstGrey, 3)))] |
|
|
|
|
|
|
|
minLum, maxLum = sorted((bgLum, foreLum)) |
|
|
|
black = makeColor(0, minLum / 2.0, 0) |
|
|
|