diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aaab7a3..93330c8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,6 +8,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - id: check-added-large-files + args: ['--maxkb=950'] - repo: https://github.com/psf/black rev: 24.2.0 hooks: diff --git a/README.md b/README.md index 9fb49e3..cfbdb5b 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,12 @@ Takes an image file and generates a cross stitch pattern using a user specified ## Results -Photo by [Kiki Siepel](https://unsplash.com/@studiokiek?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/images/nature/flower?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) -Alt text +Palestinian Flag -Colored with Symbols -Black White with Symbols -Colored -Keys +Colored with Symbols +Black White with Symbols +Colored +Keys ## Usage @@ -31,7 +30,7 @@ pip install tarraz ### CLI Example ```shell -tarraz .tmp/palestinian_flag.jpg --colors 6 --stitches-count 100 +tarraz images/palestine.png --colors 4 --stitches-count 200 ``` ### Python Example @@ -45,7 +44,7 @@ from tarraz.models import RGB # Choose a color provider -image_path = ".tmp/flower.jpg" +image_path = "images/palestine.png" provider = DMCProvider() tarraz = Tarraz( @@ -76,7 +75,7 @@ SVGStitcher.stitch( ### Options ```shell $ tarraz --help -usage: tarraz [-h] [-v] [-c COLORS] [-n STITCHES_COUNT] [-w WIDTH] [-m DMC] [-t TRANSPARENT [TRANSPARENT ...]] [-s DIST] [-z CELL_SIZE] [--no-cleanup] [--svg] image +usage: tarraz [-h] [--version] [-c COLORS] [-n STITCHES_COUNT] [-w WIDTH] [-m DMC] [-t TRANSPARENT [TRANSPARENT ...]] [-o DIST] [-z CELL_SIZE] [--no-cleanup] [--svg] image Generate a DMC-colored cross-stitch pattern from a given image. @@ -95,7 +94,7 @@ optional arguments: -m DMC, --dmc DMC DMC json color path. -t TRANSPARENT [TRANSPARENT ...], --transparent TRANSPARENT [TRANSPARENT ...] A Color to ignore from the end result. - -s DIST, --dist DIST DMC json color path. + -o DIST, --dist DIST DMC json color path. -z CELL_SIZE, --cell-size CELL_SIZE The size of the generated Aida fabric cell. --no-cleanup Don't run cleanup job on generated image. diff --git a/images/black_white_symbols.jpg b/images/black_white_symbols.jpg deleted file mode 100644 index d9399bb..0000000 Binary files a/images/black_white_symbols.jpg and /dev/null differ diff --git a/images/colored.jpg b/images/colored.jpg deleted file mode 100644 index 3369245..0000000 Binary files a/images/colored.jpg and /dev/null differ diff --git a/images/colored_symbols.jpg b/images/colored_symbols.jpg deleted file mode 100644 index 7bc82b8..0000000 Binary files a/images/colored_symbols.jpg and /dev/null differ diff --git a/images/flower.jpg b/images/flower.jpg deleted file mode 100644 index bc99b93..0000000 Binary files a/images/flower.jpg and /dev/null differ diff --git a/images/key.jpg b/images/key.jpg deleted file mode 100644 index 3cc821c..0000000 Binary files a/images/key.jpg and /dev/null differ diff --git a/images/palestine.png b/images/palestine.png new file mode 100644 index 0000000..567e326 Binary files /dev/null and b/images/palestine.png differ diff --git a/images/results/black_white_symbols.jpg b/images/results/black_white_symbols.jpg new file mode 100644 index 0000000..43ec466 Binary files /dev/null and b/images/results/black_white_symbols.jpg differ diff --git a/images/results/colored.jpg b/images/results/colored.jpg new file mode 100644 index 0000000..397d644 Binary files /dev/null and b/images/results/colored.jpg differ diff --git a/images/results/colored_symbols.jpg b/images/results/colored_symbols.jpg new file mode 100644 index 0000000..2f81ddd Binary files /dev/null and b/images/results/colored_symbols.jpg differ diff --git a/images/results/key.jpg b/images/results/key.jpg new file mode 100644 index 0000000..205e983 Binary files /dev/null and b/images/results/key.jpg differ diff --git a/poetry.lock b/poetry.lock index d4aa756..21a50f4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -283,4 +283,4 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [metadata] lock-version = "2.0" python-versions = ">=3.8" -content-hash = "37d4f9bacb4d3c587d57e39c38450d50a7418ae4197c4fd62ac3a33f2d68aa55" +content-hash = "546bc79e6fb6361e242d9d393a3e67dd9a92409efd0eda6ac5233055923cb0a5" diff --git a/pyproject.toml b/pyproject.toml index 87d7c4c..717efed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,14 +15,14 @@ known_first_party = "tarraz" [tool.poetry] name = "tarraz" -version = "1.1.2" +version = "1.2.0" description = "A cross-stitch image generator. Generates a cross stitch pattern given by a user and generates a DMC colored pattern." authors = ["Ahmed Jazzar "] maintainers = [] license = "GNU Affero General Public License v3" readme = "README.md" -packages = [{ include = "tarraz"}] +packages = [{ include = "tarraz" }] homepage = "https://www.nitfe.com/" repository = "https://github.com/nitfe/tarraz.git" documentation = "https://github.com/nitfe/tarraz/blob/main/README.md" @@ -47,11 +47,11 @@ Changelog = "https://github.com/nitfe/tarraz/releases" # Requirements [tool.poetry.dependencies] python = ">=3.8" -pillow = "*" +pillow = ">=9.5.0" [tool.poetry.dev-dependencies] pre-commit = { version = "*" } # Entry point -[tool.poetry.scripts] -tarraz = "tarraz.main:main" +[tool.poetry.plugins.console_scripts] +"tarraz" = "tarraz.main:main" diff --git a/tarraz/main.py b/tarraz/main.py index 4a72c61..040a423 100644 --- a/tarraz/main.py +++ b/tarraz/main.py @@ -1,5 +1,6 @@ import argparse import importlib.metadata +import logging import os from tarraz import constants @@ -14,7 +15,6 @@ def init_argparse() -> argparse.ArgumentParser: parser.add_argument( - "-v", "--version", action="version", version=f"{parser.prog} version {VERSION}", @@ -59,7 +59,7 @@ def init_argparse() -> argparse.ArgumentParser: help="A Color to ignore from the end result.", ) parser.add_argument( - "-s", + "-o", "--dist", type=str, default=constants.BASE_DIR / ".tmp/", @@ -82,6 +82,12 @@ def init_argparse() -> argparse.ArgumentParser: action="store_true", help="Export result to svg files.", ) + parser.add_argument( + "-v", + "--verbose", + action="store_true", + help="Show debug messages.", + ) return parser @@ -89,6 +95,9 @@ def main() -> None: p = init_argparse() args = p.parse_args() + if args.verbose: + logger.setLevel(logging.DEBUG) + base_file_name = os.path.basename(args.image).split(".")[0] logger.info("Generating pattern for %s...", base_file_name) diff --git a/tarraz/processor.py b/tarraz/processor.py index 1d56c21..c6097a8 100644 --- a/tarraz/processor.py +++ b/tarraz/processor.py @@ -1,8 +1,9 @@ +from typing import TYPE_CHECKING, List, Union + from PIL import Image -from typing import List, TYPE_CHECKING, Union from tarraz.logger import logger -from tarraz.models import Color, Coordinate, ImageSize, RGB +from tarraz.models import RGB, Color, Coordinate, ImageSize from tarraz.providers import DMCProvider from tarraz.utils import generate_image, get_neighbours, index_of @@ -31,7 +32,7 @@ def __init__( self._cleanup = cleanup self._colors_num = colors_num - self._image = Image.open(image_path) + self._image = Image.open(image_path).convert("RGB") self._provider = provider self._x_count = x_count diff --git a/tarraz/stitcher/display.py b/tarraz/stitcher/display.py index d8ba0d8..dbfb50e 100644 --- a/tarraz/stitcher/display.py +++ b/tarraz/stitcher/display.py @@ -1,6 +1,7 @@ from typing import TYPE_CHECKING, Optional from PIL import Image + from tarraz.stitcher import Stitcher if TYPE_CHECKING: @@ -12,16 +13,16 @@ def init(self, width: int, height: int) -> None: self.result = Image.new("RGB", (width, height)) def draw_cell( - self, color: "Optional[Color]", coordinate: "Coordinate", size: int + self, coordinate: "Coordinate", size: int, color: "Optional[Color]" = None ) -> None: pixels = self.result.load() for i in range(coordinate.x, coordinate.x + size): for j in range(coordinate.y, coordinate.y + size): - pixels[i - size, j - size] = color.rgb + pixels[i - size, j - size] = color.rgb if color else (255, 255, 255, 0) def finish(self) -> None: self.result.show() - def save(self, dist_dir: str, ext: str) -> None: + def save(self, ext: str) -> None: return diff --git a/tarraz/stitcher/stitcher.py b/tarraz/stitcher/stitcher.py index 82e6dd1..d38dcf9 100644 --- a/tarraz/stitcher/stitcher.py +++ b/tarraz/stitcher/stitcher.py @@ -1,13 +1,13 @@ import os from abc import ABC -from typing import TYPE_CHECKING, Optional, List +from typing import TYPE_CHECKING, List, Optional from tarraz import constants from tarraz.logger import logger from tarraz.models import Coordinate if TYPE_CHECKING: - from tarraz.models import Color, ImageSize, Palette, PaletteImage, RGB + from tarraz.models import RGB, Color, ImageSize, Palette, PaletteImage class Stitcher(ABC): @@ -56,7 +56,7 @@ def generate_key( return NotImplemented def draw_cell( - self, color: "Optional[Color]", coordinate: "Coordinate", size: int + self, coordinate: "Coordinate", size: int, color: "Optional[Color]" = None ) -> NotImplemented: return NotImplemented @@ -69,6 +69,9 @@ def draw_cells( config: "Optional[dict]" = None, transparent: "Optional[List[RGB]]" = None, ): + if not transparent: + transparent = [] + x = y = cell_size for row in pattern: for color_i in row: @@ -76,7 +79,7 @@ def draw_cells( color = ( colors[color_i] if colors[color_i].rgb not in transparent else None ) - self.draw_cell(color, coordinate, cell_size) + self.draw_cell(coordinate, cell_size, color=color) x += cell_size y += cell_size x = cell_size @@ -104,6 +107,9 @@ def stitch( width = size.width * cell_size height = size.height * cell_size + if not transparent: + transparent = [] + if not configs: configs = [{"name": "NO_CONFIG"}] diff --git a/tarraz/stitcher/svg.py b/tarraz/stitcher/svg.py index ab03e97..d85c8a1 100644 --- a/tarraz/stitcher/svg.py +++ b/tarraz/stitcher/svg.py @@ -1,5 +1,5 @@ import os -from typing import TYPE_CHECKING, Optional, List +from typing import TYPE_CHECKING, List, Optional from tarraz.logger import logger from tarraz.models import Color, Coordinate @@ -7,10 +7,10 @@ if TYPE_CHECKING: from tarraz.models import ( + RGB, ImageSize, Palette, PaletteImage, - RGB, StrokeType, SVGAttributes, ) @@ -77,9 +77,9 @@ def generate_key( keyed.add(color.code) def draw_cell( - self, color: "Optional[Color]", coordinate: "Coordinate", size: int + self, coordinate: "Coordinate", size: int, color: "Optional[Color]" = None ) -> None: - fill, symbols, stroke = self._get_svg_attributes(color, coordinate, size) + fill, symbols, stroke = self._get_svg_attributes(coordinate, size, color=color) self._append_to_file( f""" @@ -244,7 +244,7 @@ def _gen_glyph(color: "Color", coordinate: "Coordinate", scale: float = 1.0) -> def _add_key_to_svg( self, coordinate: "Coordinate", size: int, color: "Color" ) -> None: - fill, symbols, stroke = self._get_svg_attributes(color, coordinate, size) + fill, symbols, stroke = self._get_svg_attributes(coordinate, size, color) self._append_to_file( f""" @@ -308,7 +308,7 @@ def _add_key_to_svg( ) def _get_svg_attributes( - self, color: "Optional[Color]", coordinate: "Coordinate", size: int + self, coordinate: "Coordinate", size: int, color: "Optional[Color]" = None ) -> "SVGAttributes": fill = "fill:rgb(255,255,255);" stroke: "StrokeType" = "stroke:none;"