bytecanvas
A pure Python image library made by Antonio to make image generation way easier. (zlib for DEFLATE compression, struct for binary packing).
Built for situations where installing Pillow isn't practical (constrained/sandboxed hosts, environments where compiling C extensions fails, or you just want to know exactly what's touching your image bytes) and for PNG-focused workflows that don't need the full weight of a general-purpose imaging library.
Features
- PNG decoding — 8-bit, non-interlaced PNGs across all standard color types:
- RGB
- RGBA
- Grayscale
- Grayscale + alpha
- Indexed/palette (with
tRNStransparency support) - All 5 PNG filter types (None, Sub, Up, Average, Paeth) implemented for scanline unfiltering
- PNG encoding — RGBA output, DEFLATE-compressed via stdlib
zlib - Pixel-level access —
get_pixel/set_pixelwith bounds checking - Alpha blending —
set_pixel_blendcomposites a color onto the existing pixel instead of overwriting it - Drawing primitives:
- Filled and outlined rectangles
- Lines (Bresenham's algorithm)
- Image-onto-image pasting, with optional blending
- Zero runtime dependencies — the entire library is
zlib+struct, both standard library
What's out of scope
This is a focused PNG tool, not a full replacement for every image format:
- No JPEG, GIF, BMP, or WEBP — each requires its own from-scratch codec (JPEG alone involves DCT, Huffman coding, and chroma subsampling; these are substantial standalone projects)
- No interlaced (Adam7) PNGs
- No 16-bit-per-channel PNGs
- No TrueType/OpenType font rendering (would require a font parser + bezier rasterizer)
If you need those, Pillow remains the right tool — pixelforge trades breadth for having no dependency footprint at all.
Install
pip install bytecanvas
Quick start
from bytecanvas import Image
# Create a blank canvas
img = Image(200, 100, fill=(255, 255, 255, 255))
# Draw
img.rect(10, 10, 90, 60, (255, 0, 0, 255))
img.rect(100, 20, 150, 50, (0, 200, 0, 255), filled=False) # outline only
img.line(0, 0, 199, 99, (0, 0, 255, 255))
img.set_pixel(50, 50, (0, 255, 0, 255))
img.set_pixel_blend(60, 60, (255, 0, 0, 128)) # 50% blend over whatever's there
# Save
img.save_png("output.png")
# Load an existing PNG
loaded = Image.open_png("output.png")
print(loaded.get_pixel(50, 50))
print(loaded.width, loaded.height)
API reference
Image(width, height, fill=(0, 0, 0, 0))
Creates a new RGBA image. fill is a 4-tuple, defaults to fully transparent black.
Image.open_png(path) / Image.from_png_bytes(raw_bytes)
Class methods that decode a PNG from disk or from raw bytes, returning an Image.
.save_png(path, compress_level=6) / .to_png_bytes(compress_level=6)
Encodes the image as PNG, to disk or as bytes. compress_level is passed straight to zlib (0–9).
.get_pixel(x, y) → (r, g, b, a)
Raises PFError if out of bounds.
.set_pixel(x, y, color)
Overwrites a pixel. color can be a 3-tuple (alpha assumed 255) or 4-tuple.
.set_pixel_blend(x, y, color)
Alpha-composites color onto the existing pixel. Silently no-ops if out of bounds (safe for drawing near edges).
.fill(color)
Fills the entire image with one color.
.rect(x0, y0, x1, y1, color, filled=True)
Draws a rectangle. Coordinates are clamped to image bounds and auto-sorted (so x0 > x1 is fine).
.line(x0, y0, x1, y1, color)
Bresenham line, blended.
.paste(other_image, x, y, blend=True)
Pastes another Image onto this one at (x, y). Clips automatically at edges.
.copy()
Returns a deep copy.
Correctness
The PNG decoder and encoder have been cross-validated against Pillow-generated reference files (not just tested against pixelforge's own output) across RGBA, RGB, grayscale, and palette color modes, with zero pixel-level discrepancies. Round-trip encode→decode is pixel-exact.
License
MIT
Release files for bytecanvas 1.6.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bytecanvas-1.6.3.tar.gz | 6.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bytecanvas-1.6.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 13.4 kB
Release files / bytecanvas-1.6.3.tar.gz
| Download URL | bytecanvas-1.6.3.tar.gz |
|---|---|
| Size | 6.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7b6c68c79d3c4c19bda5b4cd7220adad677e34081f5e93232e9316083c6b323e
|
|
BLAKE2b-256 checksum How to use checksums |
3b59868bc4fedacb837e43e73ea9479abb0e60e8eff8ed7512bb59816426495f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|
Release files / bytecanvas-1.6.3-py3-none-any.whl
| Download URL | bytecanvas-1.6.3-py3-none-any.whl |
|---|---|
| Size | 7.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2bbe548bb99241eff0df91c41403a9f863c70eb3627e8db290396f8fb954be65
|
|
BLAKE2b-256 checksum How to use checksums |
9503da860468afd9e7c901ccfc0870b680ab8c76b71808a471c5393d8944e0d7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|