diff --git a/colorhash/cli.py b/colorhash/cli.py
index 6c7efc6..398f16f 100644
--- a/colorhash/cli.py
+++ b/colorhash/cli.py
@@ -8,13 +8,13 @@ import textwrap
from .colorizer import PaletteColorizer
from .matricizer import Matricizer, NibbleMatricizer, RandomartMatricizer
from .palettes import Palette, DEFAULT_PALETTES, PALETTES
-from .svg import gensvg
+from .writer import ANSIWriter, SVGWriter
# TODO - WASM compile for embedding directly in HTML
# TODO - option to add a caption based on the filename
# TODO - load palettes from a file
-# TODO - ANSI 24-bit color output
+
def cli_main() -> None:
"Main function entrypoint."
@@ -49,7 +49,14 @@ def cli_main() -> None:
INPUT_TYPE_HELP = "INPUT TYPE (-x, --input-type)\n" + "\n".join(
[f" {choice} - {desc}" for choice, desc in INPUT_TYPE_CHOICES.items()]
)
- EPILOGUE = "\n\n".join([MATRIX_HELP, PALETTE_HELP, INPUT_TYPE_HELP])
+ OUTPUT_TYPE_CHOICES = {
+ "ansi": "the output should be colored for ANSI terminals using 24 bit true color",
+ "svg": "the output should be an SVG format",
+ }
+ OUTPUT_TYPE_HELP = "OUTPUT TYPE (-y, --output-type)\n" + "\n".join(
+ [f" {choice} - {desc}" for choice, desc in OUTPUT_TYPE_CHOICES.items()]
+ )
+ EPILOGUE = "\n\n".join([MATRIX_HELP, PALETTE_HELP, INPUT_TYPE_HELP, OUTPUT_TYPE_HELP])
progname: str = sys.argv[0]
if progname.endswith("__main__.py"):
@@ -102,12 +109,11 @@ def cli_main() -> None:
help="Choose the hash algorithm. default: sha512",
)
ap.add_argument(
- "-z",
- "--square-size",
+ "--svg-square-size",
metavar="PX",
type=int,
default=32,
- help="Decide how big the output squares are, in pixels. default: 32",
+ help="For SVG outputs, decide how big the output squares are, in pixels. default: 32",
)
ap.add_argument(
"-x",
@@ -116,6 +122,13 @@ def cli_main() -> None:
choices=INPUT_TYPE_CHOICES.keys(),
help="Determines how the input should be treated. default: path",
)
+ ap.add_argument(
+ "-y",
+ "--output-type",
+ default="ansi",
+ choices=OUTPUT_TYPE_CHOICES.keys(),
+ help="Determines how the output should be generated. default: ansi",
+ )
args = ap.parse_args()
############################################################################
@@ -182,9 +195,19 @@ def cli_main() -> None:
# Print SVG
matrix = matricizer.matricize(hashdata)
colors = colorizer.colorize(matrix)
- svg = gensvg(colors, args.square_size)
- if str(args.out) == "-":
- sys.stdout.write(svg)
- else:
- args.out.write_text(svg)
+
+ # Choose the output writer
+ writer: Writer
+ match args.output_type:
+ case "ansi":
+ writer = ANSIWriter()
+ case "svg":
+ writer = SVGWriter(args.svg_square_size)
+
+ output = writer.write(colors)
+
+ if str(args.out) == "-":
+ sys.stdout.write(output)
+ else:
+ args.out.write_text(output)
diff --git a/colorhash/svg.py b/colorhash/svg.py
deleted file mode 100644
index 1e168ae..0000000
--- a/colorhash/svg.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"SVG-related functions."
-from .colorizer import ColorMatrix
-
-
-def gensvg(matrix: ColorMatrix, square_size: int) -> str:
- """
- Generate an SVG based on a given matrix.
-
- :param matrix: the color matrix to generate the SVG for.
- :param square_size: the size of the squares generated, in pixels.
- :returns: the full generated SVG as a string.
- """
- h = len(matrix)
- w = len(matrix[0])
-
- # Start SVG string
- svg = f'"
- return svg
diff --git a/colorhash/writer.py b/colorhash/writer.py
new file mode 100644
index 0000000..a6f83eb
--- /dev/null
+++ b/colorhash/writer.py
@@ -0,0 +1,71 @@
+import abc
+
+from .color import Color
+from .colorizer import ColorMatrix
+
+
+class Writer(metaclass=abc.ABCMeta):
+ """
+ Base writer class.
+
+ This is used to write an input colorized matrix to a string, which is then forwarded to the
+ appropriate output.
+ """
+
+ @abc.abstractmethod
+ def write(self, matrix: ColorMatrix) -> str:
+ "Write the color matrix to a string."
+
+
+class ANSIWriter(Writer):
+ def write(self, matrix: ColorMatrix) -> str:
+ ESC = '\x1b'
+ RESET = f"{ESC}[0m"
+ C = "██"
+ def ansi_color(c: Color) -> str:
+ c = c.to_rgb()
+ return f"{ESC}[38;2;{round(c.r)};{round(c.g)};{round(c.b)}m"
+ out = ''
+ for row in matrix:
+ for col in row:
+ out += ansi_color(col)
+ out += C
+ out += "\n"
+ out += RESET
+ return out
+
+
+class SVGWriter(Writer):
+ def __init__(self, square_size: int) -> None:
+ """
+ Create a new SVG writer that uses the given square size.
+
+ :param square_size: the size of the squares generated, in pixels.
+ """
+ self.square_size = square_size
+
+ def write(self, matrix: ColorMatrix) -> str:
+ """
+ Generate an SVG based on a given matrix.
+
+ :param matrix: the color matrix to generate the SVG for.
+ :returns: the full generated SVG as a string.
+ """
+ h = len(matrix)
+ w = len(matrix[0])
+
+ # Start SVG string
+ svg = f'"
+ return svg
+
diff --git a/tools/genexamples.sh b/tools/genexamples.sh
index 1d611fb..9e51436 100755
--- a/tools/genexamples.sh
+++ b/tools/genexamples.sh
@@ -11,9 +11,12 @@ find "examples" -type f -name '*.in' | \
while read infile; do
for hash in "${hashes[@]}"; do
for matrix in "${matrices[@]}"; do
- outfile="examples/$(basename -s .in "$infile")-$hash-$matrix.svg"
- echo "Generating $outfile"
- python3 -m colorhash "$infile" --out "$outfile" --hash "$hash" --matrix "$matrix"
+ svgfile="examples/$(basename -s .in "$infile")-$hash-$matrix.svg"
+ pngfile="examples/$(basename -s .in "$infile")-$hash-$matrix.png"
+ echo "Generating $svgfile"
+ python3 -m colorhash "$infile" --output-type svg --out "$svgfile" --hash "$hash" --matrix "$matrix"
+ echo "Generating $pngfile"
+ convert "$svgfile" "$pngfile"
done
done
done