Metadata-Version: 2.4
Name: img2sktch
Version: 0.1.0
Summary: Convert images to pencil sketches and extract contour paths for pen plotters and generative art.
Author: NacreousDawn596
License: MIT
Project-URL: Repository, https://github.com/NacreousDawn596/img2sktch
Project-URL: Issues, https://github.com/NacreousDawn596/img2sktch/issues
Keywords: sketch,pencil,image processing,contour,pen plotter,opencv,numpy
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Scientific/Engineering :: Image Processing
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24
Requires-Dist: opencv-python>=4.8
Requires-Dist: Pillow>=10.0
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# img2sktch

**img2sktch** is a Python library for converting images to pencil sketches and extracting contour paths.
It grew out of a hardware pen plotter project and works equally well for generative art, image preprocessing,
and anywhere you want a clean line representation of a photo.

> _"if a non-stochastic data-less approach can be taken to solving a problem, then machine learning should never be applied."_

---

## Installation

```bash
pip install img2sktch
```

For development:

```bash
git clone https://github.com/NacreousDawn596/img2sktch
cd img2sktch
pip install -e ".[dev]"
```

---

## Quick start

```python
import img2sktch as i2s

# Load from file, bytes, PIL, or numpy — all work the same way
frame = i2s.from_file("photo.jpg")

# Apply a pencil sketch
sketch = i2s.PencilSketch(blur_sigma=21)(frame)

# Save
i2s.to_file(sketch, "sketch.png")
```

---

## Examples

| Original | Pencil | Edge | Hatch |
| :---: | :---: | :---: | :---: |
| ![Original](assets/monalisa.jpg) | ![Pencil](assets/pencilsketch.png) | ![Edge](assets/edgesketch.png) | ![Hatch](assets/hatchsketch.png) |

---

## Sketch modes

### PencilSketch

Classic dodge-blend effect. Works by blurring the inverted grayscale image and blending it back
with the original using a color-dodge formula.

```python
from img2sktch import PencilSketch

sketch = PencilSketch(
    blur_sigma=21,       # gaussian blur strength on the inverted image
    sharpen_value=None,  # optional int to apply an unsharp kernel after dodge
)(frame)
```

### EdgeSketch

Canny edge detection, inverted so you get black lines on white.

```python
from img2sktch import EdgeSketch

sketch = EdgeSketch(
    threshold1=1,
    threshold2=81,
    blur_ksize=9,
    invert=True,
)(frame)
```

### HatchSketch

Hatching lines overlaid on shadow regions, inspired by pen-and-ink illustration.

```python
from img2sktch import HatchSketch

sketch = HatchSketch(
    num_directions=4,   # number of hatch angles
    spacing=6,          # pixels between lines
    angle_offset=0.0,
    blur_sigma=3,
)(frame)
```

---

## I/O helpers

The library accepts and returns images in whatever format you have them in.

```python
import img2sktch as i2s
from PIL import Image
import io

# From file path
frame = i2s.from_file("photo.jpg")

# From raw bytes (e.g. received over a network or from an upload)
with open("photo.jpg", "rb") as f:
    frame = i2s.from_bytes(f.read())

# From a file-like object (BytesIO, requests.Response.raw, etc.)
buf = io.BytesIO(open("photo.jpg", "rb").read())
frame = i2s.from_bytes(buf)

# From a PIL Image
pil_img = Image.open("photo.jpg")
frame = i2s.from_pil(pil_img)

# From a numpy array (grayscale or BGRA are handled automatically)
frame = i2s.from_numpy(some_array)
```

Saving is symmetric:

```python
# To file
i2s.to_file(sketch, "out.png")
i2s.to_file(sketch, "out.jpg", quality=90)

# To raw bytes (for serving over HTTP, saving to a database, etc.)
raw = i2s.to_bytes(sketch, fmt=".png")
raw = i2s.to_bytes(sketch, fmt=".jpg", quality=85)

# To a BytesIO buffer
buf = i2s.to_bytesio(sketch, fmt=".png")  # returns io.BytesIO, cursor at 0

# To a PIL Image
pil = i2s.to_pil(sketch)
```

---

## Contour extraction

Extract simplified polylines from a sketch image. Useful for pen plotters, laser cutters,
or anywhere that needs vector paths rather than raster output.

```python
from img2sktch import PencilSketch, image_to_contours

sketch = PencilSketch()(frame)
contours = image_to_contours(
    sketch,
    simplification=1.0,    # epsilon as % of arc length; 0 = no simplification
    canny_threshold1=50,
    canny_threshold2=150,
    pen_diameter=2.0,
    max_width=2000,
    multiplier=4.5,
    min_area=10.0,
)
# contours is a list of [(x, y), ...] polylines, centered on the origin
```

### Export to SVG

```python
from img2sktch import contours_to_svg

svg = contours_to_svg(contours, width=800, height=800, stroke="black", stroke_width=1.0)
with open("sketch.svg", "w") as f:
    f.write(svg)
```

### Export to Arduino (.ino)

Generate ready-to-flash Arduino code for a 3-motor pen plotter:

```python
from img2sktch.contours import contours_to_arduino

code = contours_to_arduino(contours, scale=1.0, offset_x=0, offset_y=0)
with open("drawing.ino", "w") as f:
    f.write(code)
```

---

## Image transforms

```python
from img2sktch.transform import resize, crop_center, pad_to_square, rotate, auto_contrast

# Resize — aspect-ratio preserved if only one dimension given
small = resize(frame, width=800)
small = resize(frame, scale=0.5)

# Crop the center 512x512 pixels
cropped = crop_center(frame, 512, 512)

# Pad to square with white fill
square = pad_to_square(frame, fill=255)

# Rotate 30 degrees, canvas expands to fit
rotated = rotate(frame, angle=30, expand=True, fill=255)

# Stretch contrast to full range
enhanced = auto_contrast(frame)
```

---

## Command-line interface

A `img2sktch` command is installed alongside the package.

```bash
# Apply a pencil sketch
img2sktch sketch photo.jpg out.png --mode pencil --blur-sigma 21

# Apply edge sketch, resize first
img2sktch sketch photo.jpg out.png --mode edge --width 1024

# Hatch sketch
img2sktch sketch photo.jpg out.png --mode hatch --hatch-directions 4 --hatch-spacing 8

# Extract contours and export as SVG
img2sktch contours photo.jpg sketch.svg --simplification 1.0

# Extract contours and generate Arduino code
img2sktch contours photo.jpg drawing.ino --max-width 2200 --multiplier 6

# Pipe image bytes from stdin
cat photo.jpg | img2sktch sketch - out.png
```

---

## Project structure

```
img2sktch/
    img2sktch/
        __init__.py     # public API
        sketch.py       # PencilSketch, EdgeSketch, HatchSketch
        contours.py     # image_to_contours, contours_to_svg, contours_to_arduino
        transform.py    # resize, crop_center, pad_to_square, rotate, auto_contrast
        io.py           # from_file, from_bytes, from_pil, to_file, to_bytes, to_pil, ...
        cli.py          # CLI entry point
    pyproject.toml
    LICENSE
    README.md
```

---

## Dependencies

- [opencv-python](https://pypi.org/project/opencv-python/) >= 4.8
- [numpy](https://numpy.org/) >= 1.24
- [Pillow](https://python-pillow.org/) >= 10.0

---

## License

MIT. See [LICENSE](LICENSE) for details.
