Home

Awesome

Pixie - A full-featured 2D graphics library for Python

Pixie is a 2D graphics library similar to Cairo and Skia.

Github Actions

pip install pixie-python

Features:

Image file formats

FormatReadWrite
PNG
JPEG
BMP
QOI
GIF
SVG
PPM

Font file formats

FormatRead
TTF
OTF
SVG

Joins and caps

Supported Caps:

Supported Joins:

Blending & masking

Supported Blend Modes:

Supported Mask Modes:

SVG style paths:

FormatSupportedDescription
M mmove to
L lline to
h hhorizontal line to
V vvertical line to
C c S scublic to
Q q T tquadratic to
A aarc to
zclose path

Testing

pytest

Examples

git clone https://github.com/treeform/pixie-python to run examples.

Text

python examples/text.py

font = pixie.read_font("examples/data/Roboto-Regular_1.ttf")
font.size = 20

text = "Typesetting is the arrangement and composition of text in graphic design and publishing in both digital and traditional medias."

image.fill_text(
    font,
    text,
    bounds = pixie.Vector2(180, 180),
    transform = pixie.translate(10, 10)
)

example output

Text spans

python examples/text_spans.py

typeface = pixie.read_typeface("examples/data/Ubuntu-Regular_1.ttf")

def make_font(typeface, size, color):
    font = typeface.new_font()
    font.size = size
    font.paint.color = color
    return font

spans = pixie.SeqSpan()
spans.append(pixie.Span(
    "verb [with object] ",
    make_font(typeface, 12, pixie.Color(0.78125, 0.78125, 0.78125, 1))
))
spans.append(pixie.Span(
    "strallow\n",
    make_font(typeface, 36, pixie.Color(0, 0, 0, 1))
))
spans.append(pixie.Span(
    "\nstral·low\n",
    make_font(typeface, 13, pixie.Color(0, 0.5, 0.953125, 1))
))
spans.append(pixie.Span(
    "\n1. free (something) from restrictive restrictions \"the regulations are intended to strallow changes in public policy\" ",
    make_font(typeface, 14, pixie.Color(0.3125, 0.3125, 0.3125, 1))
))

image.arrangement_fill_text(
    spans.typeset(bounds = pixie.Vector2(180, 180)),
    transform = pixie.translate(10, 10)
)

example output

Square

python examples/square.py

paint = pixie.Paint(pixie.SOLID_PAINT)
paint.color = pixie.Color(1, 0, 0, 1)

ctx = image.new_context()
ctx.fill_style = paint

ctx.fill_rect(50, 50, 100, 100)

example output

Line

python examples/line.py

paint = pixie.Paint(pixie.SOLID_PAINT)
paint.color = pixie.parse_color("#FF5C00")

ctx = image.new_context()
ctx.stroke_style = paint
ctx.line_width = 10

ctx.stroke_segment(25, 25, 175, 175)

example output

Rounded rectangle

python examples/rounded_rectangle.py

paint = pixie.Paint(pixie.SOLID_PAINT)
paint.color = pixie.Color(0, 1, 0, 1)

ctx = image.new_context()
ctx.fill_style = paint
ctx.rounded_rect(50, 50, 100, 100, 25, 25, 25, 25)
ctx.fill()

example output

Heart

python examples/heart.py

path = pixie.parse_path(
    """
    M 20 60
    A 40 40 90 0 1 100 60
    A 40 40 90 0 1 180 60
    Q 180 120 100 180
    Q 20 120 20 60
    z
    """
)

paint = pixie.Paint(pixie.SOLID_PAINT)
paint.color = pixie.parse_color("#FC427B")

image.fill_path(path, paint)

example output

Masking

python examples/masking.py

lines = pixie.Image(200, 200)
lines.fill(pixie.parse_color("#FC427B"))

paint = pixie.Paint(pixie.SOLID_PAINT)
paint.color = pixie.parse_color("#F8D1DD")

ctx = lines.new_context()
ctx.stroke_style = paint
ctx.line_width = 30

ctx.stroke_segment(25, 25, 175, 175)
ctx.stroke_segment(25, 175, 175, 25)

path = pixie.parse_path(
    """
    M 20 60
    A 40 40 90 0 1 100 60
    A 40 40 90 0 1 180 60
    Q 180 120 100 180
    Q 20 120 20 60
    z
    """
)

mask = pixie.Mask(200, 200)
mask.fill_path(path)

lines.mask_draw(mask)
image.draw(lines)

example output

Gradient

python examples/gradient.py

paint = pixie.Paint(pixie.RADIAL_GRADIENT_PAINT)

paint.gradient_handle_positions.append(pixie.Vector2(100, 100))
paint.gradient_handle_positions.append(pixie.Vector2(200, 100))
paint.gradient_handle_positions.append(pixie.Vector2(100, 200))

paint.gradient_stops.append(pixie.ColorStop(pixie.Color(1, 0, 0, 1), 0))
paint.gradient_stops.append(pixie.ColorStop(pixie.Color(1, 0, 0, 0.15625), 1))

path = pixie.parse_path(
    """
    M 20 60
    A 40 40 90 0 1 100 60
    A 40 40 90 0 1 180 60
    Q 180 120 100 180
    Q 20 120 20 60
    z
    """
)

image.fill_path(path, paint)

example output

Image tiled

python examples/image_tiled.py

path = pixie.Path()
path.polygon(100, 100, 70, 8)

paint = pixie.Paint(pixie.TILED_IMAGE_PAINT)
paint.image = pixie.read_image("examples/data/baboon.png")
paint.image_mat = pixie.scale(0.08, 0.08)

image.fill_path(path, paint)

example output

Shadow

python examples/shadow.py

path = pixie.Path()
path.polygon(100, 100, 70, sides = 8)

paint = pixie.Paint(pixie.SOLID_PAINT)
paint.color = pixie.Color(1, 1, 1, 1)

polygon_image = pixie.Image(200, 200)
polygon_image.fill_path(path, paint)

shadow = polygon_image.shadow(
    offset = pixie.Vector2(2, 2),
    spread = 2,
    blur = 10,
    color = pixie.Color(0, 0, 0, 0.78125)
)

image.draw(shadow)
image.draw(polygon_image)

example output

Blur

python examples/blur.py

trees = pixie.read_image("examples/data/trees.png")

path = pixie.Path()
path.polygon(100, 100, 70, 6)

mask = pixie.Mask(200, 200)
mask.fill_path(path)

blur = trees.copy()
blur.blur(20)
blur.mask_draw(mask)

image.draw(trees)
image.draw(blur)

example output

Tiger

python examples/tiger.py

tiger = pixie.read_image("examples/data/tiger.svg")

image.draw(
    tiger,
    pixie.translate(100, 100) *
    pixie.scale(0.2, 0.2) *
    pixie.translate(-450, -450)
)

example output