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

Overview

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:

  • Typesetting and rasterizing text, including styled rich text via spans.
  • Drawing paths, shapes and curves with even-odd and non-zero windings.
  • Pixel-perfect AA quality.
  • Supported file formats are PNG, BMP, JPG, SVG + more in development.
  • Strokes with joins and caps.
  • Shadows, glows and blurs.
  • Complex masking: Subtract, Intersect, Exclude.
  • Complex blends: Darken, Multiply, Color Dodge, Hue, Luminosity... etc.
  • Many operations are SIMD accelerated.

Image file formats

Format Read Write
PNG
JPEG
BMP
GIF
SVG

Font file formats

Format Read
TTF
OTF
SVG

Joins and caps

Supported Caps:

  • Butt
  • Round
  • Square

Supported Joins:

  • Miter (with miter angle limit)
  • Bevel
  • Round

Blending & masking

Supported Blend Modes:

  • Normal
  • Darken
  • Multiply
  • ColorBurn
  • Lighten
  • Screen
  • Color Dodge
  • Overlay
  • Soft Light
  • Hard Light
  • Difference
  • Exclusion
  • Hue
  • Saturation
  • Color
  • Luminosity

Supported Mask Modes:

  • Mask
  • Overwrite
  • Subtract Mask
  • Intersect Mask
  • Exclude Mask

SVG style paths:

Format Supported Description
M m move to
L l line to
h h horizontal line to
V v vertical line to
C c S s cublic to
Q q T t quadratic to
A a arc to
z close 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.paints[0].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.PK_SOLID)
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.PK_SOLID)
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.PK_SOLID)
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.PK_SOLID)
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.PK_SOLID)
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.PK_GRADIENT_RADIAL)

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.PK_IMAGE_TILED)
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.PK_SOLID)
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

Comments
  • Having some trouble with vertical alignment

    Having some trouble with vertical alignment

    I'm trying to have some text with two lines, aligned to the bottom of some bounds, and with a small line-height so that the two lines are closer together. However the text is not going where I would expect. It looks like it's going too downwards. When aligned to bottom it even goes outside the bounds. If I leave the line-height to default it also doesn't look right. Am I missing something?

    Here's an example and it's output:

    import pixie
    
    image = pixie.Image(800, 800)
    image.fill(pixie.Color(1, 1, 1, 1))
    
    paint = pixie.Paint(pixie.PK_SOLID)
    paint.color = pixie.Color(1, 0, 0, 1)
    ctx = image.new_context()
    ctx.line_width = 1
    ctx.stroke_style = paint
    ctx.stroke_rect(0, 266, 800, 318)
    
    text = "AbCd\naBcD"
    
    font = pixie.read_font("./Inter-Bold.otf")
    font.size = 182
    font.line_height = 140
    
    font.paint.color = pixie.Color(1, 0, 0, 1)
    image.fill_text(
        font,
        text,
        bounds = pixie.Vector2(800, 318),
        h_align = pixie.HA_CENTER,
        v_align = pixie.VA_TOP,
        transform = pixie.translate(0, 266)
    )
    
    font.paint.color = pixie.Color(0, 1, 0, 1)
    image.fill_text(
        font,
        text,
        bounds = pixie.Vector2(800, 318),
        h_align = pixie.HA_CENTER,
        v_align = pixie.VA_MIDDLE,
        transform = pixie.translate(0, 266)
    )
    
    font.paint.color = pixie.Color(0, 0, 1, 1)
    image.fill_text(
        font,
        text,
        bounds = pixie.Vector2(800, 318),
        h_align = pixie.HA_CENTER,
        v_align = pixie.VA_BOTTOM,
        transform = pixie.translate(0, 266)
    )
    
    image.write_file("out.png")
    

    result

    opened by EnricoMonese 4
  • Unable to load jpg on Linux

    Unable to load jpg on Linux

    Installed pixie-python via pip, however when I try to load a JPG I get the following exception.

    Exception has occurred: PixieError
    Decoding JPG requires -d:pixieUseStb
    

    I guess pixie is using std image library under the hood and the package did not get compiled with the correct options to support this?

    opened by EdMUK 3
  • genny supporting dart ffi

    genny supporting dart ffi

    Hi treeform, very nice lib (looking at the python output), I have recently discovered Flutter over dart language, they create a nice vibrant UI experience. BUT:

    its ffi lib is just so ugly, shudders! it's ffi interop is very verbose and looks annoying to get done, at the same time, devs seem to flock to this (relatively) new platform but not many want to get hands dirty in C code, so Nim to the rescue right?

    Can genny also support the dart programming language? it's just generating a lot of ugly boilerplate code.

    I think it's a chance to get more people to use Nim, and thereby building more libs and contributing to it, which was one of your purposes with genny.

    Aside from that, I personally want to leverage Nim libraries that i and others have written, and use dart and flutter mainly for the GUI story (though in terms of features, dart looks to be a decent language. unfortunately for dart, in terms of syntax - verbose like java and I think no templates, but this is just first impressions.)

    opened by kobi2187 2
  • support encodeImage method

    support encodeImage method

    I see there is an encodeImage proc in the nim library, would it be possible to support that as well as the already existing write_file() in the python layer?

    https://nimdocs.com/treeform/pixie/pixie.html#encodeImage%2CImage%2CFileFormat

    opened by RobBrazier 2
  • OSError: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found on Google Colab

    OSError: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found on Google Colab

    import pixie gives error:

    ---------------------------------------------------------------------------
    
    OSError                                   Traceback (most recent call last)
    
    <ipython-input-14-4833f4429f21> in <module>()
    ----> 1 import pixie
          2 
          3 
    
    3 frames
    
    /usr/lib/python3.7/ctypes/__init__.py in __init__(self, name, mode, handle, use_errno, use_last_error)
        362 
        363         if handle is None:
    --> 364             self._handle = _dlopen(self._name, mode)
        365         else:
        366             self._handle = handle
    
    OSError: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /usr/local/lib/python3.7/dist-packages/pixie/libpixie.so)
    

    https://i.imgur.com/N1ue3Ce.png

    opened by arye321 2
  • module 'pixie' has no attribute 'PK_SOLID'

    module 'pixie' has no attribute 'PK_SOLID'

    This is the source code:

    import pixie
    
    image = pixie.Image(200, 200)
    image.fill(pixie.Color(1, 1, 1, 1))
    
    paint = pixie.Paint(pixie.PK_SOLID)
    paint.color = pixie.Color(1, 0, 0, 1)
    
    ctx = image.new_context()
    ctx.fill_style = paint
    
    ctx.fill_rect(50, 50, 100, 100)
    
    image.write_file("examples/square.png")
    

    I got the following results: Traceback (most recent call last): File "F:\Python\Python Project\Test\test.py", line 6, in paint = pixie.Paint(pixie.PK_SOLID) AttributeError: module 'pixie' has no attribute 'PK_SOLID'

    opened by ZaneHuangPro 1
  • Request: Text h_align = pixie.JUSTIFY_ALIGN

    Request: Text h_align = pixie.JUSTIFY_ALIGN

    Would be nice if add this alignment style, also give access to Arrangement attributes(selectionRects, lines, positions).

    I've made this little library for making this feature for me, it behaves like the Microsoft Word Office.

    import
        nimpy,
        pixie,
        unicode
    
    pyExportModule("pixie_utils")
    
    const
        LF = Rune(10)
        NR = Rune(0)
    
    proc justifyArrangement*(arrangement: Arrangement, maxWidth: float32) {.raises: [].} =
        proc right(rect: Rect): float32 =
            rect.x + rect.w
    
        let
            runes: ptr = arrangement.runes.addr
            positions: ptr = arrangement.positions.addr
            rects: ptr = arrangement.selectionRects.addr
            last_lineId: int = arrangement.lines.len-1
        var
            rune, last_rune: Rune
            last_wordRuneId: int
            spaces_idx: seq[int]
            inc_width, space_width, line_width, x_offset: float32
        
        for lineId, (start, stop) in arrangement.lines:
            last_rune = runes[stop]
    
            # This line must not be justified, if it is the last or if the last rune is a breakline char.
            if lineId == last_lineId or last_rune.uint32 == LF.uint32:
                continue
    
            echo runes[start..stop]
            # Get the spaces indexes of this line to increase their width, and get the line width.
            spaces_idx = @[]
            last_rune = NR
            for r_id in start..stop:
                rune = runes[r_id]
                if not rune.isWhiteSpace():
                    if last_rune.isWhiteSpace():
                        spaces_idx.add(r_id-1)
                    last_wordRuneId = r_id
                last_rune = runes[r_id]
    
            line_width = rects[last_wordRuneId].right
    
            echo "Line spaces: ", spaces_idx.len
            if spaces_idx.len > 0:
                # Get the amount of pixels/units to increase each space width in the middle of the line.
                inc_width = (maxWidth - line_width) / spaces_idx.len.float32
    
                if inc_width > 0:
                    space_width = rects[spaces_idx[0]].w + inc_width
    
                    # Adjust the runes X position
                    x_offset = 0
                    for r_id in spaces_idx[0]..stop:
                        positions[r_id].x += x_offset
    
                        if r_id in spaces_idx:
                            rects[r_id].x += x_offset
                            rects[r_id].w = space_width
                            x_offset += inc_width
                        else:
                            rects[r_id].x += x_offset
    
    proc justifyArrangement(arrangement_ref: int, maxWidth: float32) {.exportpy: "justifyArrangement".} =
        justifyArrangement(cast[Arrangement](arrangement_ref), maxWidth)
    
    opened by IagoBeuller 0
  • Request: image.to_bytes() function

    Request: image.to_bytes() function

    I need the bytes of the images, for example, use them in pillow or pygame.

    I've made this little library for making this feature for me, it gets the image data bytes as well the png file bytes.

    import
        nimpy,
        pixie
    
    pyExportModule("pixie_utils")
    
    proc getImageBytes*(image: Image, format: string = "png"): string {.raises: [PixieError].} =
      # Gets the bytes from image.
      let encodeFormat = case format:
        of "png": PngFormat
        of "bmp": BmpFormat
        of "jpg", "jpeg": JpegFormat
        of "qoi": QoiFormat
        of "ppm": PpmFormat
        else:
          raise newException(PixieError, "Unsupported image format")
    
      result = image.encodeImage(encodeFormat)
    
    proc getImageData*(image: Image): string {.raises: [].} =
      # Gets the image data as bytes.
      result = newString(image.width * image.height * 4)
      var
        i = 0
        rgba: ColorRGBA
      
      for color in image.data:
        rgba = color.rgba()
        result[i] = rgba.r.char
        result[i+1] = rgba.g.char
        result[i+2] = rgba.b.char
        result[i+3] = rgba.a.char
        i += 4
    
    proc getImageBytes(image_ref: int, format: string = "png"): string {.exportpy: "getImageBytes".} =
        result = getImageBytes(cast[Image](image_ref), format)
    
    proc getImageData(image_ref: int): string {.exportpy: "getImageData".} =
        result = getImageData(cast[Image](image_ref))
    
    opened by IagoBeuller 0
  • Can I do Image Mosaic Using this library?

    Can I do Image Mosaic Using this library?

    Hi,

    If I have known the related offset of translation and angle in pixels between centers of 2 images, can I use this library to generate a mosaic without explicitly considering allocating a big matrix matching to final image size, compensating for non-integer offset values, and converting the offset between image centers to left-up image origin?

    Now, I'm doing these trivial things. It's fragile and troublesome.

    opened by HikariS97 0
Releases(4.3.0)
  • 4.3.0(May 24, 2022)

    What's Changed

    • 4.3.0 by @guzba in https://github.com/treeform/pixie-python/pull/21

    Full Changelog: https://github.com/treeform/pixie-python/compare/4.0.1...4.3.0

    Source code(tar.gz)
    Source code(zip)
  • 4.0.1(Feb 23, 2022)

    What's Changed

    • 4.0.1 by @guzba in https://github.com/treeform/pixie-python/pull/18

    Full Changelog: https://github.com/treeform/pixie-python/compare/3.1.4...4.0.1

    Source code(tar.gz)
    Source code(zip)
  • 3.1.4(Feb 6, 2022)

    What's Changed

    • pixie 3.1.4 by @guzba in https://github.com/treeform/pixie-python/pull/16

    Full Changelog: https://github.com/treeform/pixie-python/compare/3.0.2...3.1.4

    Source code(tar.gz)
    Source code(zip)
  • 3.0.2(Oct 28, 2021)

    What's Changed

    • font.paint by @guzba in https://github.com/treeform/pixie-python/pull/14

    Full Changelog: https://github.com/treeform/pixie-python/compare/0.1.4...3.0.2

    Source code(tar.gz)
    Source code(zip)
Owner
treeform
I like the Nim programming language.
treeform
chineseocr/table_line 表格线检测模型pytorch版

table_line_pytorch chineseocr/table_detct 表格线检测模型table_line pytorch版 原项目github: https://github.com/chineseocr/table-detect 1、模型转换 下载原项目table_detect模型文

1 Oct 21, 2021
一款基于Qt与OpenCV的仿真数字示波器

一款基于Qt与OpenCV的仿真数字示波器

郭赟 4 Nov 02, 2022
Generic framework for historical document processing

dhSegment dhSegment is a tool for Historical Document Processing. Its generic approach allows to segment regions and extract content from different ty

Digital Humanities Laboratory 343 Dec 24, 2022
Hand gesture detection project with aweome UI implementation.

an awesome hand gesture detection project for you to be creative! Imagination is the limit to do with this project.

AR Ashraf 39 Sep 26, 2022
Camera Intrinsic Calibration and Hand-Eye Calibration in Pybullet

This repository is mainly for camera intrinsic calibration and hand-eye calibration. Synthetic experiments are conducted in PyBullet simulator. 1. Tes

CAI Junhao 7 Oct 03, 2022
Repository relating to the CVPR21 paper TimeLens: Event-based Video Frame Interpolation

TimeLens: Event-based Video Frame Interpolation This repository is about the High Speed Event and RGB (HS-ERGB) dataset, used in the 2021 CVPR paper T

Robotics and Perception Group 544 Dec 19, 2022
Document manipulation detection with python

image manipulation detection task: -- tianchi function image segmentation salie

JiaKui Hu 3 Aug 22, 2022
Awesome anomaly detection in medical images

A curated list of awesome anomaly detection works in medical imaging, inspired by the other awesome-* initiatives.

Kang Zhou 57 Dec 19, 2022
2 telegram-bots: for image recognition and for text generation

💻 📱 Telegram_Bots 🔎 & 📖 2 telegram-bots: for image recognition and for text generation. About Image recognition bot: User sends a photo and bot de

Marina Polukoshko 1 Jan 27, 2022
OCR-D-compliant page segmentation

ocrd_segment This repository aims to provide a number of OCR-D-compliant processors for layout analysis and evaluation. Installation In your virtual e

OCR-D 59 Sep 10, 2022
The world's simplest facial recognition api for Python and the command line

Face Recognition You can also read a translated version of this file in Chinese 简体中文版 or in Korean 한국어 or in Japanese 日本語. Recognize and manipulate fa

Adam Geitgey 47k Jan 07, 2023
Fatigue Driving Detection Based on Dlib

Fatigue Driving Detection Based on Dlib

5 Dec 14, 2022
A document scanner application for laptops/desktops developed using python, Tkinter and OpenCV.

DcoumentScanner A document scanner application for laptops/desktops developed using python, Tkinter and OpenCV. Directly install the .exe file to inst

Harsh Vardhan Singh 1 Oct 29, 2021
OpenCVを用いたカメラキャリブレーションのサンプルです。2021/06/21時点でPython実装のある3種類(通常カメラ向け、魚眼レンズ向け(fisheyeモジュール)、全方位カメラ向け(omnidirモジュール))について用意しています。

OpenCV-CameraCalibration-Example FishEyeCameraCalibration.mp4 OpenCVを用いたカメラキャリブレーションのサンプルです 2021/06/21時点でPython実装のある以下3種類について用意しています。 通常カメラ向け 魚眼レンズ向け(

KazuhitoTakahashi 34 Nov 17, 2022
Text recognition (optical character recognition) with deep learning methods.

What Is Wrong With Scene Text Recognition Model Comparisons? Dataset and Model Analysis | paper | training and evaluation data | failure cases and cle

Clova AI Research 3.2k Jan 04, 2023
Zoom , GoogleMeets에서 Vtuber 데뷔하기

EasyVtuber Facial landmark와 GAN을 이용한 Character Face Generation Google Meets, Zoom 등에서 자신만의 웹툰, 만화 캐릭터로 대화해보세요! 악세사리는 어느정도 추가해도 잘 작동해요! 안타깝게도 RTX 2070

Gunwoo Han 140 Dec 23, 2022
This repository provides train&test code, dataset, det.&rec. annotation, evaluation script, annotation tool, and ranking.

SCUT-CTW1500 Datasets We have updated annotations for both train and test set. Train: 1000 images [images][annos] Additional point annotation for each

Yuliang Liu 600 Dec 18, 2022
Sort By Face

Sort-By-Face This is an application with which you can either sort all the pictures by faces from a corpus of photos or retrieve all your photos from

0 Nov 29, 2021
CUTIE (TensorFlow implementation of Convolutional Universal Text Information Extractor)

CUTIE TensorFlow implementation of the paper "CUTIE: Learning to Understand Documents with Convolutional Universal Text Information Extractor." Xiaohu

Zhao,Xiaohui 147 Dec 20, 2022
Turn images of tables into CSV data. Detect tables from images and run OCR on the cells.

Table of Contents Overview Requirements Demo Modules Overview This python package contains modules to help with finding and extracting tabular data fr

Eric Ihli 311 Dec 24, 2022