Skip to main content

PyBlend (Blend2D for Python) 🎨🚀

Python Version License JIT Accelerated

PyBlend is a Python binding and wrapper for Blend2D — the ultra-fast 2D vector graphics engine powered by an embedded JIT compiler (AsmJit) and SIMD hardware acceleration (AVX2, AVX-512, SSE).


🌟 Key Features

  • ⚡ Maximum Performance: Native 2D vector rasterization with runtime JIT compilation for composite operations, gradients, and path clipping.
  • 🐍 Idiomatic Python OOP: Clean, intuitive API featuring Context, Image, Path, Font, LinearGradient, RadialGradient, ConicGradient, Pattern, and Matrix2D.
  • 🔄 Zero-Copy NumPy Interoperability: Direct access to image memory buffers via img.to_numpy() without redundant data copying.
  • 🖼️ Pillow (PIL) Integration: Seamless conversion to and from PIL images (img.to_pil() and Image.from_pil()).
  • ✍️ Advanced Typography: OpenType / TrueType text layout, font metrics, text advance measurement, and glyph stroking/filling.
  • 🛡️ Memory Safety: Automatic reference counting and lifecycle management for all native Blend2D resources.

📦 Exclusive Installation (via Hugging Face)

PyBlend releases and pre-compiled high-performance binary wheels are hosted exclusively on Hugging Face:

# Direct pip install from Hugging Face repository
pip install "https://huggingface.co/ArifiIslam/PyBlend/resolve/main/dist/pyblend2d-0.21.2-py3-none-any.whl"

Or clone directly from Hugging Face:

git clone https://huggingface.co/ArifiIslam/PyBlend
cd PyBlend
pip install -e .

🚀 Quickstart

1. Basic Drawing & Context Manager

from blend2d import Image, Context, Format

# Create 800x600 surface in PRGB32 format
img = Image(800, 600, Format.PRGB32)

with Context(img) as ctx:
    # Fill background
    ctx.fill_all("#0F172A")

    # Draw smooth anti-aliased circles
    ctx.fill_circle(200, 300, 100, "#3B82F6")
    ctx.stroke_width = 4.0
    ctx.stroke_circle(200, 300, 100, "#93C5FD")

    # Draw rounded rectangle
    ctx.fill_round_rect(400, 200, 300, 200, 24, "#10B981")
    ctx.stroke_width = 3.0
    ctx.stroke_round_rect(400, 200, 300, 200, 24, "#A7F3D0")

# Save directly to PNG
img.write_to_file("output.png")

2. Linear, Radial & Conic Gradients

from blend2d import Image, Context, LinearGradient, RadialGradient, ConicGradient

img = Image(600, 400)
with Context(img) as ctx:
    # Linear Gradient
    grad = LinearGradient(50, 50, 550, 350)
    grad.add_stop(0.0, "#EC4899")
    grad.add_stop(0.5, "#8B5CF6")
    grad.add_stop(1.0, "#06B6D4")

    ctx.fill_round_rect(50, 50, 500, 300, 30, grad)

img.write_to_file("gradient.png")

3. Vector Paths & Bezier Curves

from blend2d import Image, Context, Path

img = Image(400, 400)
with Context(img) as ctx:
    ctx.fill_all("#18181B")

    # Build vector path
    p = Path()
    p.move_to(50, 200)
    p.cubic_to(150, 50, 250, 350, 350, 200)
    p.close()

    ctx.fill_path(p, "#38BDF833")
    ctx.stroke_width = 3.0
    ctx.stroke_path(p, "#38BDF8")

img.write_to_file("curve.png")

4. Typography & Font Metrics

from blend2d import Image, Context, Font

img = Image(600, 200)
with Context(img) as ctx:
    ctx.fill_all("#0B0F19")

    font = Font.from_file("C:/Windows/Fonts/segoeui.ttf", 36.0)
    
    # Measure text bounding box & advance
    metrics = font.get_text_metrics("Hello Blend2D!")
    print(f"Advance width: {metrics.advance.x}px")

    ctx.fill_text(40, 110, font, "Hello Blend2D!", "#38BDF8")

img.write_to_file("text.png")

5. Zero-Copy NumPy Interoperability

import numpy as np
from blend2d import Image, Context

img = Image(500, 500)

# Get direct pointer buffer view as NumPy array (no memory copy)
buf = img.to_numpy(copy=False)

# Modify pixels directly using vector math
y, x = np.mgrid[0:500, 0:500]
buf[:, :, 0] = (x % 256).astype(np.uint8)  # Blue
buf[:, :, 1] = (y % 256).astype(np.uint8)  # Green
buf[:, :, 2] = 128                         # Red
buf[:, :, 3] = 255                         # Alpha

# Render vector overlays on top of the NumPy buffer
with Context(img) as ctx:
    ctx.stroke_width = 5.0
    ctx.stroke_circle(250, 250, 150, "white")

img.write_to_file("numpy_blend.png")

6. Mass Bulk Array Operations (100,000+ Shapes in 1 Call)

Render massive GIS maps, scatter plots, and point clouds in a single C call with zero Python loop overhead:

import numpy as np
from blend2d import Image, Context

img = Image(1000, 1000)
with Context(img) as ctx:
    ctx.fill_all("#090D16")

    # Generate 100,000 rectangles [x, y, w, h] as a float64 NumPy array
    rects = np.random.uniform(0, 950, (100000, 4)).astype(np.float64)

    # ⚡ Single C call — renders in ~30ms!
    ctx.fill_rect_array(rects, "#38BDF822")

img.write_to_file("bulk_rectangles.png")

7. Typography to Vector Path Outlines

Convert shaped text (including multi-lingual and Arabic) directly into editable vector Path contours:

from blend2d import Image, Context, Font, LinearGradient

img = Image(800, 200)
font = Font.from_file("C:/Windows/Fonts/segoeui.ttf", 48.0)

# Convert text string to vector bezier contours
text_path = font.get_text_outlines("PyBlend 2D Vector Outlines", origin=(40, 120))

with Context(img) as ctx:
    ctx.fill_all("#0B0F19")
    
    # Fill text with dynamic linear gradient
    grad = LinearGradient(40, 0, 700, 0)
    grad.add_stop(0.0, "#38BDF8")
    grad.add_stop(1.0, "#F43F5E")
    
    ctx.fill_path(text_path, grad)
    ctx.stroke_width = 1.5
    ctx.stroke_path(text_path, "#FFFFFF66")

img.write_to_file("vector_text.png")

8. Zero-Copy FFmpeg Streaming & Native Buffer Protocol

Stream raw frames directly to FFmpeg stdin or sockets with zero memory copies:

import subprocess
from blend2d import Image, Context

img = Image(1920, 1080)

# Direct zero-copy memoryview
frame_buffer = img.buffer

# Example: Write directly to FFmpeg subprocess
# proc = subprocess.Popen(['ffmpeg', '-f', 'rawvideo', '-pix_fmt', 'bgra', ...], stdin=subprocess.PIPE)
# proc.stdin.write(frame_buffer)

☁️ Google Colab & Kaggle Support

PyBlend ships with pre-compiled Linux x86_64 JIT binaries (libblend2d.so), allowing instant execution on Colab and Kaggle without building from source:

!pip install pyblend2d
import blend2d
print("Blend2D running with JIT & SIMD on Linux Cloud!")

🧪 Running the Test Suite

Run the full pytest suite:

python -m pytest tests -v

🎨 Running Examples

python examples/01_basic_shapes.py
python examples/02_gradients_and_patterns.py
python examples/03_vector_paths_and_bezier.py
python examples/04_typography_and_text.py
python examples/05_numpy_vector_overlay.py
python examples/06_composite_ops.py
python examples/07_bulk_gis_and_vector_text.py

Generated outputs will be placed in the output/ directory.


📄 License

This library is licensed under the Zlib License. Blend2D is licensed under the Zlib License.

Metadata

Release files for pyblend2d 0.21.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for pyblend2d 0.21.2
File Interpreter ABI Platform
pyblend2d-0.21.2-py3-none-any.whl Python 3 none any Details

Release files / pyblend2d-0.21.2-py3-none-any.whl

Download URL pyblend2d-0.21.2-py3-none-any.whl
Size 9.9 MB
Tags Python 3
SHA-256 checksum
How to use checksums
066d714b09df405de239b95e6e4b39a2622b302eeb5bc216af74606346ceefb7
BLAKE2b-256 checksum
How to use checksums
16d2a41b85614c3175a2f658da3b40c091c3a6ac7b2aa6c39f0d3f27c4b63b0a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.0

Release history Release notifications | RSS feed

0.22.0

2 release files

This release

0.21.2 This release

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page