Files
sspai-100-hours-series-python/projects/click-cli/watermark/main.py

212 lines
4.8 KiB
Python

import logging
import pathlib
import click
from watermark.markers import make
ImagePath = click.Path(exists=True, allow_dash=True, dir_okay=False)
def ensure_logger(level):
logging.basicConfig(
level=level,
format="[{asctime}] [{levelname}] [{name}] - {message}",
style="{",
)
logger = logging.getLogger("watermark.cli")
COMMON_OPTIONS = [
click.option(
"--alpha",
type=click.FloatRange(0.0, 1.0),
help="the alpha value",
show_default=True,
),
click.option(
"--rotation",
type=int,
default=0,
help="the rotation value",
show_default=True,
),
click.option(
"--offset",
type=int,
default=30,
help="the offset value",
show_default=True,
),
click.option(
"--location",
"loc",
type=click.Choice(
[
"top-left",
"top",
"top-right",
"center-left",
"center",
"center-right",
"bottom-left",
"bottom",
"bottom-right",
"all",
]
),
default="bottom-right",
help="""\
the location value,
text watermark will be placed at the all locations if set "all" option.
""",
show_default=True,
),
click.option(
"-v",
"--verbose",
is_flag=True,
default=False,
help="show debug info",
show_default=True,
),
]
def shared_options(func):
for option in COMMON_OPTIONS[::-1]:
func = option(func)
return func
@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx: click.Context, **kwargs):
r"""the watermark cli tools implemented by 100gle."""
if not ctx.invoked_subcommand:
banner()
def banner():
msg = r"""
_ __ __ __
| | / /____ _ / /_ ___ _____ ____ ___ ____ _ _____ / /__
| | /| / // __ `// __// _ \ / ___// __ `__ \ / __ `// ___// //_/
| |/ |/ // /_/ // /_ / __// / / / / / / // /_/ // / / ,<
|__/|__/ \__,_/ \__/ \___//_/ /_/ /_/ /_/ \__,_//_/ /_/|_|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Hope you enjoy it.
You can use this command to get help:
$ watermark -h
"""
click.echo(msg)
@cli.command()
@click.argument("content")
@click.argument("path", type=ImagePath)
@click.option(
"-f",
"--font-name",
"font",
type=str,
help="the font name value",
)
@click.option(
"-F",
"--font-path",
type=ImagePath,
help="the font path if font name isn't passed.",
)
@click.option(
"-s",
"--font-size",
"size",
type=int,
default=20,
help="the font size value",
show_default=True,
)
@click.option(
"--color",
type=str,
default="black",
help="""\
the color value,
you can use hex color code like "#000000" or color name "black".
""",
show_default=True,
)
@shared_options
def text(path, font, font_path, **kwargs):
"""the sub-command for text watermark."""
verbose = kwargs.get("verbose")
if verbose:
ensure_logger(level=logging.DEBUG)
logger.debug("enable verbose mode.")
font_or_path = font or font_path
logger.debug(f"image watermark options are: {kwargs}")
fpath = pathlib.Path(path)
name = fpath.stem
ext = fpath.suffix
image_suffixes = {".jpg", ".jpeg", ".png"}
if ext not in image_suffixes:
click.echo(f"[WARNING] can't handle {ext} image type.")
exit(1)
marked = make(path=path, text=font_or_path, **kwargs)
file = fpath.parent.joinpath(f"{name}_marked{ext}")
marked.save(file, quality=95)
logger.debug(f"add watermark to {path} success. see {file}")
@cli.command()
@click.argument("path", type=ImagePath)
@click.option(
"--image-watermark-path",
"image_path",
type=ImagePath,
help="the path of image watermark",
)
@click.option(
"--zoom",
type=float,
default=0.5,
help="the zoom value",
show_default=True,
)
@shared_options
def image(path, image_path, **kwargs):
"""the sub-command for image watermark."""
verbose = kwargs.pop("verbose")
if verbose:
ensure_logger(level=logging.DEBUG)
logger.debug("enable verbose mode.")
logger.debug(f"image watermark options are: {kwargs}")
fpath = pathlib.Path(path)
name = fpath.stem
ext = fpath.suffix
image_suffixes = {".jpg", ".jpeg", ".png"}
if ext not in image_suffixes:
click.echo(f"[WARNING] can't handle {ext} image type.")
exit(1)
marked = make(path=path, image=image_path, **kwargs)
file = fpath.parent.joinpath(f"{name}_marked{ext}")
marked.save(file, quality=95)
logger.debug(f"add watermark to {path} success. see {file}")
if __name__ == "__main__":
cli()