Settings window #21
@@ -169,6 +169,7 @@ Singleton {
|
|||||||
color: {
|
color: {
|
||||||
wallust: general.color.wallust,
|
wallust: general.color.wallust,
|
||||||
mode: general.color.mode,
|
mode: general.color.mode,
|
||||||
|
smart: general.color.smart,
|
||||||
schemeGeneration: general.color.schemeGeneration,
|
schemeGeneration: general.color.schemeGeneration,
|
||||||
scheduleDarkStart: general.color.scheduleDarkStart,
|
scheduleDarkStart: general.color.scheduleDarkStart,
|
||||||
scheduleDarkEnd: general.color.scheduleDarkEnd,
|
scheduleDarkEnd: general.color.scheduleDarkEnd,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ JsonObject {
|
|||||||
property int scheduleDarkEnd: 0
|
property int scheduleDarkEnd: 0
|
||||||
property int scheduleDarkStart: 0
|
property int scheduleDarkStart: 0
|
||||||
property bool schemeGeneration: true
|
property bool schemeGeneration: true
|
||||||
|
property bool smart: false
|
||||||
property bool wallust: false
|
property bool wallust: false
|
||||||
}
|
}
|
||||||
component Idle: JsonObject {
|
component Idle: JsonObject {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from materialyoucolor.quantize import QuantizeCelebi
|
|||||||
from materialyoucolor.score.score import Score
|
from materialyoucolor.score.score import Score
|
||||||
from materialyoucolor.dynamiccolor.material_dynamic_colors import MaterialDynamicColors
|
from materialyoucolor.dynamiccolor.material_dynamic_colors import MaterialDynamicColors
|
||||||
from materialyoucolor.hct.hct import Hct
|
from materialyoucolor.hct.hct import Hct
|
||||||
|
from materialyoucolor.utils.color_utils import argb_from_rgb
|
||||||
from materialyoucolor.utils.math_utils import difference_degrees, rotation_direction, sanitize_degrees_double
|
from materialyoucolor.utils.math_utils import difference_degrees, rotation_direction, sanitize_degrees_double
|
||||||
|
|
||||||
app = typer.Typer()
|
app = typer.Typer()
|
||||||
@@ -47,35 +48,40 @@ def generate(
|
|||||||
raise typer.BadParameter(
|
raise typer.BadParameter(
|
||||||
"Use either --image-path or --preset, not both.")
|
"Use either --image-path or --preset, not both.")
|
||||||
|
|
||||||
if scheme is None:
|
cli_mode = mode is not None
|
||||||
with CONFIG.open() as f:
|
|
||||||
scheme = json.load(f)["colors"]["schemeType"]
|
|
||||||
|
|
||||||
match scheme:
|
def get_scheme_class(scheme_name: str):
|
||||||
|
match scheme_name:
|
||||||
case "fruit-salad":
|
case "fruit-salad":
|
||||||
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad as Scheme
|
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad
|
||||||
case 'expressive':
|
return SchemeFruitSalad
|
||||||
from materialyoucolor.scheme.scheme_expressive import SchemeExpressive as Scheme
|
case "expressive":
|
||||||
case 'monochrome':
|
from materialyoucolor.scheme.scheme_expressive import SchemeExpressive
|
||||||
from materialyoucolor.scheme.scheme_monochrome import SchemeMonochrome as Scheme
|
return SchemeExpressive
|
||||||
case 'rainbow':
|
case "monochrome":
|
||||||
from materialyoucolor.scheme.scheme_rainbow import SchemeRainbow as Scheme
|
from materialyoucolor.scheme.scheme_monochrome import SchemeMonochrome
|
||||||
case 'tonal-spot':
|
return SchemeMonochrome
|
||||||
from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot as Scheme
|
case "rainbow":
|
||||||
case 'neutral':
|
from materialyoucolor.scheme.scheme_rainbow import SchemeRainbow
|
||||||
from materialyoucolor.scheme.scheme_neutral import SchemeNeutral as Scheme
|
return SchemeRainbow
|
||||||
case 'fidelity':
|
case "tonal-spot":
|
||||||
from materialyoucolor.scheme.scheme_fidelity import SchemeFidelity as Scheme
|
from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot
|
||||||
case 'content':
|
return SchemeTonalSpot
|
||||||
from materialyoucolor.scheme.scheme_content import SchemeContent as Scheme
|
case "neutral":
|
||||||
case 'vibrant':
|
from materialyoucolor.scheme.scheme_neutral import SchemeNeutral
|
||||||
from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant as Scheme
|
return SchemeNeutral
|
||||||
|
case "fidelity":
|
||||||
|
from materialyoucolor.scheme.scheme_fidelity import SchemeFidelity
|
||||||
|
return SchemeFidelity
|
||||||
|
case "content":
|
||||||
|
from materialyoucolor.scheme.scheme_content import SchemeContent
|
||||||
|
return SchemeContent
|
||||||
|
case "vibrant":
|
||||||
|
from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant
|
||||||
|
return SchemeVibrant
|
||||||
case _:
|
case _:
|
||||||
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad as Scheme
|
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad
|
||||||
|
return SchemeFruitSalad
|
||||||
if mode is None:
|
|
||||||
with CONFIG.open() as f:
|
|
||||||
mode = json.load(f)["general"]["color"]["mode"]
|
|
||||||
|
|
||||||
def hex_to_hct(hex_color: str) -> Hct:
|
def hex_to_hct(hex_color: str) -> Hct:
|
||||||
s = hex_color.strip()
|
s = hex_color.strip()
|
||||||
@@ -226,6 +232,16 @@ def generate(
|
|||||||
except (PermissionError, OSError, BlockingIOError):
|
except (PermissionError, OSError, BlockingIOError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def smart_mode(image_path: Path) -> str:
|
||||||
|
is_dark = ""
|
||||||
|
|
||||||
|
with Image.open(image_path) as img:
|
||||||
|
img.thumbnail((1, 1), Image.LANCZOS)
|
||||||
|
hct = Hct.from_int(argb_from_rgb(*img.getpixel((0, 0))))
|
||||||
|
is_dark = "light" if hct.tone > 60 else "dark"
|
||||||
|
|
||||||
|
return is_dark
|
||||||
|
|
||||||
def build_template_context(
|
def build_template_context(
|
||||||
*,
|
*,
|
||||||
colors: dict[str, str],
|
colors: dict[str, str],
|
||||||
@@ -375,11 +391,11 @@ def generate(
|
|||||||
raise typer.BadParameter(
|
raise typer.BadParameter(
|
||||||
f"Preset '{name}' not found. Available presets: {', '.join(PRESETS.keys())}")
|
f"Preset '{name}' not found. Available presets: {', '.join(PRESETS.keys())}")
|
||||||
|
|
||||||
def generate_color_scheme(seed: Hct, mode: str) -> dict[str, str]:
|
def generate_color_scheme(seed: Hct, mode: str, scheme_class) -> dict[str, str]:
|
||||||
|
|
||||||
is_dark = mode.lower() == "dark"
|
is_dark = mode.lower() == "dark"
|
||||||
|
|
||||||
scheme = Scheme(
|
scheme = scheme_class(
|
||||||
seed,
|
seed,
|
||||||
is_dark,
|
is_dark,
|
||||||
0.0
|
0.0
|
||||||
@@ -398,36 +414,38 @@ def generate(
|
|||||||
return "#{:06X}".format(argb_int & 0xFFFFFF)
|
return "#{:06X}".format(argb_int & 0xFFFFFF)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
with CONFIG.open() as f:
|
||||||
|
config = json.load(f)
|
||||||
|
|
||||||
|
scheme = scheme or config["colors"]["schemeType"]
|
||||||
|
config_mode = config["general"]["color"]["mode"]
|
||||||
|
smart = bool(config["general"]["color"].get("smart", False))
|
||||||
|
scheme_class = get_scheme_class(scheme)
|
||||||
|
|
||||||
if preset:
|
if preset:
|
||||||
seed = seed_from_preset(preset)
|
seed = seed_from_preset(preset)
|
||||||
colors = generate_color_scheme(seed, mode)
|
effective_mode = mode or config_mode
|
||||||
name, flavor = preset.split(":")
|
name, flavor = preset.split(":")
|
||||||
elif image_path:
|
else:
|
||||||
|
image_path = image_path or Path(WALL_PATH)
|
||||||
generate_thumbnail(image_path, str(THUMB_PATH))
|
generate_thumbnail(image_path, str(THUMB_PATH))
|
||||||
seed = seed_from_image(THUMB_PATH)
|
seed = seed_from_image(THUMB_PATH)
|
||||||
colors = generate_color_scheme(seed, mode)
|
|
||||||
name = "dynamic"
|
name = "dynamic"
|
||||||
flavor = "default"
|
flavor = "default"
|
||||||
elif mode:
|
|
||||||
generate_thumbnail(WALL_PATH, str(THUMB_PATH))
|
|
||||||
seed = seed_from_image(THUMB_PATH)
|
|
||||||
colors = generate_color_scheme(seed, mode)
|
|
||||||
name = "dynamic"
|
|
||||||
flavor = "default"
|
|
||||||
elif scheme:
|
|
||||||
with OUTPUT.open() as f:
|
|
||||||
js = json.load(f)
|
|
||||||
seed = Hct.from_int(js["seed"])
|
|
||||||
mode = str(js["mode"])
|
|
||||||
|
|
||||||
colors = generate_color_scheme(seed, mode)
|
if smart:
|
||||||
name = "dynamic"
|
effective_mode = smart_mode(THUMB_PATH)
|
||||||
flavor = "default"
|
elif mode is not None:
|
||||||
|
effective_mode = mode
|
||||||
|
else:
|
||||||
|
effective_mode = config_mode
|
||||||
|
|
||||||
|
colors = generate_color_scheme(seed, effective_mode, scheme_class)
|
||||||
|
|
||||||
output_dict = {
|
output_dict = {
|
||||||
"name": name,
|
"name": name,
|
||||||
"flavor": flavor,
|
"flavor": flavor,
|
||||||
"mode": mode,
|
"mode": effective_mode,
|
||||||
"variant": scheme,
|
"variant": scheme,
|
||||||
"colors": colors,
|
"colors": colors,
|
||||||
"seed": seed.to_int()
|
"seed": seed.to_int()
|
||||||
@@ -438,7 +456,7 @@ def generate(
|
|||||||
ctx = build_template_context(
|
ctx = build_template_context(
|
||||||
colors=colors,
|
colors=colors,
|
||||||
seed=seed,
|
seed=seed,
|
||||||
mode=mode,
|
mode=effective_mode,
|
||||||
wallpaper_path=wp,
|
wallpaper_path=wp,
|
||||||
name=name,
|
name=name,
|
||||||
flavor=flavor,
|
flavor=flavor,
|
||||||
|
|||||||
Reference in New Issue
Block a user