|
|
@@ -7,7 +7,7 @@ parser.add_option("-p", "--preview", |
|
|
|
action="store_true", |
|
|
|
dest="showPreview", |
|
|
|
default=False, |
|
|
|
help="show preview") |
|
|
|
help="generate a preview image") |
|
|
|
parser.add_option("-n", "--name", |
|
|
|
action="store", |
|
|
|
dest="name", |
|
|
@@ -23,6 +23,16 @@ parser.add_option("-r", "--rainbow-blend", |
|
|
|
dest="rainbowBlend", |
|
|
|
default=0.0, |
|
|
|
help="mix ratio between last 8 colors' hues and background") |
|
|
|
parser.add_option("-e", "--equiluminant", |
|
|
|
action="store_true", |
|
|
|
dest="equiluminant", |
|
|
|
default=0.0, |
|
|
|
help="use the same luminance for last 8 colors") |
|
|
|
parser.add_option("-b", "--light-brown", |
|
|
|
action="store_true", |
|
|
|
dest="lightBrown", |
|
|
|
default=0.0, |
|
|
|
help="don't darken last color") |
|
|
|
|
|
|
|
(options, args) = parser.parse_args() |
|
|
|
if len(args) < 2: |
|
|
@@ -31,16 +41,19 @@ if len(args) < 2: |
|
|
|
def parseTuple(st): |
|
|
|
return tuple(float(x) for x in st.split(",")) |
|
|
|
|
|
|
|
def floatOrDie(fl, errSt): |
|
|
|
try: |
|
|
|
return float(fl) |
|
|
|
except: |
|
|
|
parser.error(errSt) |
|
|
|
|
|
|
|
bgHue, bgSat, bgLum = parseTuple(args[0]) |
|
|
|
|
|
|
|
accentHue, accentSat = parseTuple(args[1]) |
|
|
|
|
|
|
|
foreHue, foreSat = parseTuple(args[2]) if len(args) > 2 else (0.0, 0.0) |
|
|
|
|
|
|
|
try: |
|
|
|
rainbowBlend = float(options.rainbowBlend) |
|
|
|
except: |
|
|
|
parser.error("rainbow blend must be a number") |
|
|
|
rainbowBlend = floatOrDie(options.rainbowBlend, "rainbow blend must be a number") |
|
|
|
|
|
|
|
def lerp(a, b, t): |
|
|
|
return a + (b - a) * t |
|
|
@@ -61,7 +74,7 @@ def contrast(a, b): |
|
|
|
def getContrast(lum, ratio): |
|
|
|
hi = ratio*lum + (ratio - 1)*0.05 |
|
|
|
lo = (lum + 0.05 - ratio * 0.05) / ratio |
|
|
|
return hi if hi < 1.0 or lo < 0.0 else lo |
|
|
|
return hi if hi < 0.99 or lo < 0.0 else lo |
|
|
|
|
|
|
|
def makeColor(hue, lum, sat = 1.0): |
|
|
|
orig = luminance(colorsys.hls_to_rgb(hue, 0.5, sat)) |
|
|
@@ -74,7 +87,7 @@ def toSRGB(col): |
|
|
|
return tuple(x*12.92 if x < 0.0031308 else 1.055*x**(1/2.4) - 0.055 for x in col) |
|
|
|
|
|
|
|
def usable(col): |
|
|
|
return tuple(int(x*255) for x in toSRGB(col)) |
|
|
|
return tuple(int(x*255+0.5) for x in toSRGB(col)) |
|
|
|
|
|
|
|
def toHex(col): |
|
|
|
return "".join(["{:02x}".format(x) for x in usable(col)]) |
|
|
@@ -96,21 +109,35 @@ lastTwo = [lerp(foreLum, 1.0 if foreLum > bgLum else 0.0, (x + 1) / 3) for x in |
|
|
|
foreLight = makeColor(foreHue, lastTwo[0], foreSat) |
|
|
|
backLight = makeColor(bgHue, lastTwo[1], bgSat) |
|
|
|
|
|
|
|
rainHues = [0, 20, 60, 120, 180, 240, 300, 20] |
|
|
|
rainHues = [0, 23, 60, 120, 200, 240, 300, 15] |
|
|
|
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 rainHues] |
|
|
|
|
|
|
|
rainLums = [luminance(col) for col in rainbow] |
|
|
|
hiLum, loLum = max(rainLums), min(rainLums) |
|
|
|
minLum, maxLum = sorted((getContrast(bgLum, 4), getContrast(bgLum, 6))) |
|
|
|
minLum, maxLum = sorted((getContrast(bgLum, 3.5), getContrast(bgLum, 3.5 if options.equiluminant else 6 ))) |
|
|
|
maxLum = min(1.0, maxLum) |
|
|
|
|
|
|
|
darkenBrown = (options.equiluminant or options.lightBrown) |
|
|
|
|
|
|
|
rainHLS = [colorsys.rgb_to_hls(*col) for col in rainbow] |
|
|
|
rainbow = [makeColor(rainHLS[c][0], reposition(loLum, hiLum+0.00001, rainLums[c], minLum, maxLum) if c < 7 else minLum, rainHLS[c][2]) for c in range(len(rainbow))] |
|
|
|
rainbow = [makeColor(rainHLS[c][0], reposition(loLum, hiLum+0.00001, rainLums[c], minLum, maxLum) if c < 7 or darkenBrown else minLum, rainHLS[c][2] / (1 if c < 7 else 1.5)) for c in range(len(rainbow))] |
|
|
|
|
|
|
|
cols = [background, backLighter, accent, comment, foreDark, foreground, foreLight, backLight] + rainbow |
|
|
|
|
|
|
|
print("scheme: \"{}\"".format(options.name)) |
|
|
|
print("# generated by acid16 - https://git.lain.church/whut/acid16") |
|
|
|
print("# --- settings ---") |
|
|
|
print("# background HCL: {} {} {}".format(bgHue, bgSat, bgLum)) |
|
|
|
print("# accent HC : {} {}".format(accentHue, accentSat)) |
|
|
|
print("# foreground HC : {} {}".format(foreHue, foreSat)) |
|
|
|
print("# rainbow blend : {}".format(rainbowBlend)) |
|
|
|
if options.equiluminant: |
|
|
|
print("# equiluminant \"rainbow\" hues") |
|
|
|
if options.lightBrown: |
|
|
|
print("# not darkening last color (brown)") |
|
|
|
|
|
|
|
print("\nscheme: \"{}\"".format(options.name)) |
|
|
|
print("author: \"{}\"".format(options.author)) |
|
|
|
|
|
|
|
for i in range(len(cols)): |
|
|
@@ -118,27 +145,27 @@ for i in range(len(cols)): |
|
|
|
|
|
|
|
if options.showPreview: |
|
|
|
font = ImageFont.truetype("LiberationMono-Regular.ttf", 20) |
|
|
|
h, w = imSize = (640, 640) |
|
|
|
w, h = imSize = (640, 480) |
|
|
|
|
|
|
|
im = Image.new("RGB", (640, 640), usable(background)) |
|
|
|
im = Image.new("RGB", imSize, usable(background)) |
|
|
|
draw = ImageDraw.Draw(im) |
|
|
|
desc = lambda t, a, b: "{} (contrast {:.1f}:1)".format(t, contrast(luminance(a), luminance(b))) |
|
|
|
text = lambda x, y, t, col, other: draw.text((x, y), desc(t, col, other), usable(col), font) |
|
|
|
|
|
|
|
draw.rectangle((2, 2, 638, 32), usable(accent)) |
|
|
|
draw.rectangle((2, 2, w-2, 32), usable(accent)) |
|
|
|
text(5, 5, "Foreground on highlight", foreground, accent) |
|
|
|
text(5, 45, "Foreground on background", foreground, background) |
|
|
|
text(5, 85, "# Comment color", comment, background) |
|
|
|
|
|
|
|
for i in range(len(rainbow)): |
|
|
|
draw.rectangle((4, 120+i*40, 84, 150+i*40), usable(rainbow[i])) |
|
|
|
text(90, 125+i*40, "Colored text", rainbow[i], background) |
|
|
|
draw.rectangle((4, 120+i*35, 84, 145+i*35), usable(rainbow[i])) |
|
|
|
text(90, 123+i*35, "Colored text", rainbow[i], background) |
|
|
|
|
|
|
|
draw.rectangle((0, 560, 640, 600), usable(backLighter)) |
|
|
|
text(5, 565, "'Dark' foreground", foreDark, backLighter) |
|
|
|
draw.line((0, 598, 640, 598), usable(foreground), 2) |
|
|
|
draw.rectangle((0, h-80, w, h-40), usable(backLighter)) |
|
|
|
text(5, h-75, "'Dark' foreground", foreDark, backLighter) |
|
|
|
draw.line((0, h-42, w, h-42), usable(foreground), 2) |
|
|
|
|
|
|
|
for i in range(len(cols)): |
|
|
|
draw.rectangle((i*40,600,i*40+39,639), usable(cols[i])) |
|
|
|
draw.rectangle((i*40,h-40,i*40+39,h), usable(cols[i])) |
|
|
|
|
|
|
|
im.show() |