maoschanz / maoschanz/drawing

perf: utilities_get_rgba_for_xy() allocates a GdkPixbuf per pixel read

Open
#689 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
869
Forks
106
PR merge metrics
No merged PRs in 30d

Description

## Problem

`utilities_get_rgba_for_xy()` in `src/utilities/utilities_paths.py` calls `Gdk.pixbuf_get_from_surface(surface, x, y, 1, 1)` to read a single pixel. This allocates a full GdkPixbuf GObject on the heap for every call.

`utilities_get_magic_path()` (used by the paint bucket / magic wand) calls this function up to **50,000 times** per operation, making GObject allocation the dominant cost.

## Proposed Fix

Replace the GdkPixbuf allocation with a direct read from the Cairo surface pixel buffer via `surface.get_data()`, handling the BGRA→RGBA conversion and alpha un-premultiplication in Python.

Cache the buffer once in `utilities_get_magic_path()` instead of re-acquiring it per pixel.

## Measured Impact

Benchmarked on Python 3.12.3 / Cairo 1.18.0 / GTK 3 / Linux:

| Scenario | Before | After | Speedup |
|---|---|---|---|
| Single pixel read (median) | 3.5 μs | 0.78 μs | **4.5×** |
| 10,000 consecutive reads | 36.4 ms | 7.1 ms | **5.1×** |
| Paint bucket worst case (50K reads, projected) | ~180 ms | ~36 ms | **~5×** |

Also fixes an off-by-one in the bounds check (`x > width` → `x >= width`).

## Affected Tools

- Paint bucket / magic wand (heaviest user — 50K calls per fill)
- Color picker (per mouse-move)
- Eraser color comparison

Contributor guide

Open the contributing guide

Research direction

Start in src/utilities/utilities_paths.py with utilities_get_rgba_for_xy() and utilities_get_magic_path(), then inspect how the Cairo surface exposes its pixel buffer. Replace the per-read GdkPixbuf allocation, reuse the buffer during magic-path processing, preserve BGRA/RGBA and alpha handling, and correct the bounds check; verify the measured pixel-read and fill performance.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
performance
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.