gfx

package module
v0.36.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 18, 2026 License: BSD-3-Clause Imports: 0 Imported by: 0

README

gfx — pure-Go 2D graphics foundation

github.com/go-gfx/gfx is a pure-Go, CGO=0 2D graphics foundation: the shared substrate that sits below the fleet's image-processing and rendering libraries.

It is not an image-processing library (that is go-images, the scikit-image analogue) and not a widget toolkit (that is go-widgets). It is the common layer both stand on: pixel buffers, colour science, high-quality resampling, image codecs, and vector rasterization — each usable on its own, with no third-party dependencies.

Packages

Package Purpose
geometry points, rectangles, affine transforms
color full colour science: HSV/HSL/HWB, XYZ/Lab/LCh/Luv/OKLab/OKLCH, Y′CbCr, CMYK, D65↔D50 Bradford, ΔE (76/94/2000/OK), separable + non-separable blends, premultiplied alpha
raster shared pixel-buffer / pixel-format substrate
resample high-quality resizing: box/area, bicubic (Catmull-Rom), Lanczos
codec image decoders/encoders: png, jpeg, webp, ico, icns, gif, tiff
vector paths, anti-aliased fill/stroke rasterizer (round joins & caps, non-zero / even-odd), linear/radial gradients, source-over compositing
iso isometric projection (project / unproject / depth-sort) and shaded pixel primitives — cube, brick, pyramid, slope, line, side — composited into a depth-ordered scene (the pure-Go obelisk.js)

Consumers

  • go-images — image processing/analysis, built on raster/color/resample.
  • go-widgets/painter — tri-backend renderer, built on vector/raster/color.
  • go-webengine — HTML/CSS → image, built on resample/codec/vector.
  • go-widgets/desktop — icon & thumbnail rendering.

What an SVG may ask for

An SVG is text, and two of the numbers in it decide allocations: the document's own width/height, and the dimensions an embedded <image href="data:…"> declares in its header. A surface is four bytes a pixel.

⛔ Measured before svg.Options.MaxPixels existed:

input before after
~110 bytes of text declaring width="40000" height="40000" 6103.5 MiB allocated, rasterised without complaint 0.0 MiB, "a surface of 40000x40000 is 1600000000 pixels, past the 40000000 allowed"
a 246-byte SVG whose <image> claims 20000×20000 1526.1 MiB held, then drawn into a 100×100 surface 0.0 MiB, skipped

Both are bounded by Options.MaxPixels, whose zero value is svg.DefaultMaxPixels — forty million pixels, a hundred and sixty million bytes, the same ceiling go-pdfkit/render uses. A service rendering documents from strangers should set it to what its own pages need rather than inherit that.

The embedded picture is refused from its header, through image.DecodeConfig, before anything is decoded: ⛔ a ceiling enforced after the allocation it bounds is not a ceiling, it is a comment. Scale counts towards it, because the surface is the product and only one of the two numbers is ours.

Status

Landed: geometry (float64 point / axis-aligned rect / 2-D affine matrix — translate, scale, rotate, shear, compose, invert, transform point & rect), raster (pixel substrate), color (a complete colour-science layer: premultiplied alpha; the sRGB and generic-gamma transfer functions; the cylindrical sRGB models HSV/HSL/HWB; the CIE hub XYZ with D65 and D50 white points and Bradford D65↔D50 adaptation; CIE L*a*b*/LCh, L*u*v*/LCh(uv), Ottosson OKLab/OKLCH; Y′CbCr BT.601/709 and naive CMYK; the ΔE colour-difference metrics ΔE76, ΔE94, CIEDE2000 and ΔE-OK; the W3C separable and non-separable blend modes; and a second, scikit-image-byte-compatible sRGB↔XYZ↔Lab regime so go-images can share one colour library — all numerically checked against the colour-science oracle and the published CIE / W3C / Sharma reference values), resample (nearest, bilinear, box/area, bicubic, Lanczos — each with a premultiplied-alpha variant), and vector (2-D path builder + anti-aliased scanline fill/stroke rasterizer, extracted verbatim from go-widgets/painter and proven pixel-identical to it, now with linear/radial gradients and source-over compositing of any paint through a coverage grid). Colour-science and blend results match the published CIE / W3C reference values. Pure-Go, CGO=0, 100% covered, six-arch CI, numeric parity with Pillow. See docs/perf.md.

Known issue: loong64 with Go 1.27.0 or 1.27.1

golang/go#81000 is a loong64 code-generation fault that this package's own test suite found, and the upstream report is this repository's color test run on real LoongArch silicon (cfarm401), not under emulation. On loong64 the rule (Cvt64Fto32 x) => (TRUNCDW x) leaves an integer result in a floating-point register, so spilling it emits an 8-byte store; when the destination slot is narrower, that store reaches the live stack slots beside it.

affected GOARCH=loong64 built with go1.27.0 or go1.27.1
not affected go1.26.x, and every other architecture
fixed in Go 1.28 (CL 820040)
backport golang/go#81147, still open for 1.27.2 — and no go1.27.2 is released

go.mod declares a floor, so nothing stops you building this library with an affected toolchain. If you target loong64, build with go1.26.x until the backport lands.

What we have measured, and what we have not. Scanning the emitted loong64 code of every package here under go1.27.1 finds 64 of these conversions in shipped code, one of them spilled, and that one into an 8-aligned 8-byte int slot — a store that fills its own slot and reaches no neighbour. The corrupting shape appears only in two of our test frames, where a test's register pressure spills a uint8 onto consecutive bytes. So we know of no library path that is wrong today.

That is a bound, not a guarantee: inlining and register allocation are decided per build, so a program that compiles this library into a larger binary can create pressure these frames do not have. The scan and its controls are cmd/truncspill and the figures are in issue #13.

Our own loong64 CI lane is pinned to go1.26.4 for this reason, which is written out at the pin in .github/workflows/ci.yml with the condition for removing it.

License

BSD-3-Clause — see LICENSE. Copyright the go-gfx authors.

Documentation

Overview

Package gfx is the module root for the go-gfx pure-Go 2D graphics foundation.

The functionality lives in subpackages (geometry, color, raster, resample, codec, vector). This file exists only to document the module and give it a root package; import the subpackage you need.

Directories

Path Synopsis
Package codec is go-gfx's unified image-decoding registry: one Decode entry point that sniffs a byte slice's container format and dispatches to the appropriate REFERENCE decoder, returning the shared raster.Image substrate the rest of go-gfx consumes.
Package codec is go-gfx's unified image-decoding registry: one Decode entry point that sniffs a byte slice's container format and dispatches to the appropriate REFERENCE decoder, returning the shared raster.Image substrate the rest of go-gfx consumes.
Package color holds go-gfx's colour helpers.
Package color holds go-gfx's colour helpers.
Package geometry is go-gfx's floating-point 2-D geometry substrate: a Point, an axis-aligned Rect, and a 2-D affine Matrix (translate / scale / rotate / shear, composed, inverted, and applied to points and rectangles).
Package geometry is go-gfx's floating-point 2-D geometry substrate: a Point, an axis-aligned Rect, and a 2-D affine Matrix (translate / scale / rotate / shear, composed, inverted, and applied to points and rectangles).
Package iso is go-gfx's isometric projection and primitive-drawing layer: the pure-Go equivalent of obelisk.js.
Package iso is go-gfx's isometric projection and primitive-drawing layer: the pure-Go equivalent of obelisk.js.
Package raster is the shared pixel-buffer substrate of go-gfx: a densely packed 8-bit RGBA image the higher layers (resample, color, and the fleet's image-processing and rendering libraries) read and write.
Package raster is the shared pixel-buffer substrate of go-gfx: a densely packed 8-bit RGBA image the higher layers (resample, color, and the fleet's image-processing and rendering libraries) read and write.
Package resample resizes RGBA images with a choice of separable filters: nearest-neighbour, bilinear, box/area, bicubic (Catmull-Rom) and Lanczos (a=3).
Package resample resizes RGBA images with a choice of separable filters: nearest-neighbour, bilinear, box/area, bicubic (Catmull-Rom) and Lanczos (a=3).
Package svg parses a document from an SVG subset and rasterises it to a straight-alpha RGBA bitmap, built on the sibling github.com/go-gfx/gfx/vector and github.com/go-gfx/gfx/raster packages.
Package svg parses a document from an SVG subset and rasterises it to a straight-alpha RGBA bitmap, built on the sibling github.com/go-gfx/gfx/vector and github.com/go-gfx/gfx/raster packages.
Package vector is go-gfx's pure-Go 2-D vector rasterizer: it turns arbitrary outlines (move / line / quadratic / cubic / close) into per-pixel coverage, with an anti-aliased scanline accumulator and a round-join / round-cap stroker.
Package vector is go-gfx's pure-Go 2-D vector rasterizer: it turns arbitrary outlines (move / line / quadratic / cubic / close) into per-pixel coverage, with an anti-aliased scanline accumulator and a round-join / round-cap stroker.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL