Pixel storage in C: FbFormat describes a byte layout, FbBuffer holds one surface in it and reads, writes, converts and copies it
Package info
github.com/php-io-extensions/fb
Language:C
Type:php-ext
Ext name:ext-fb
pkg:composer/php-io-extensions/fb
Requires
- php: >=8.4
Requires (Dev)
- pestphp/pest: ^4.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-09 04:44:18 UTC
README
Pixel storage in C. FbFormat says how pixels are stored; FbBuffer holds one
surface in that format and reads, writes, converts and copies it. Written
directly in C against the Zend API, with no dependency: it knows nothing of any
framework. PHP 8.4+, NTS and ZTS, Linux and macOS.
Formats
| Layout | Bytes | Pixel word |
|---|---|---|
FB_LAYOUT_MONO_ROWS |
1 bit per pixel, rows padded to a byte | 0 / 1 (1 is lit, white) |
FB_LAYOUT_MONO_PAGES |
one byte per column per 8-row page (SSD1306) | 0 / 1 |
FB_LAYOUT_INDEX2, _INDEX4, _INDEX8 |
2, 4 or 8 bits per pixel, rows padded | a grey level, or a palette code |
FB_LAYOUT_RGB444 |
two pixels in three bytes | 0xRGB |
FB_LAYOUT_RGB565 |
two bytes | RGB565 |
FB_LAYOUT_RGB666 |
three bytes, six bits left-aligned in each | 0xRRGGBB, low two bits of each channel zero |
FB_LAYOUT_RGB888 |
three bytes | 0xRRGGBB |
FB_LAYOUT_RGBA8888 |
four bytes | 0xRRGGBBAA |
FB_LAYOUT_PLANAR |
one 1-bit plane per ink | a mask of inks; 0 is paper |
Orders: FB_BIT_ORDER_MSB / _LSB (mono, index, planar), FB_BYTE_ORDER_MSB /
_LSB (RGB565), FB_CHANNELS_RGB / _BGR (12 to 24 bits) and _RGBA /
_BGRA / _ARGB / _ABGR (32 bits), FB_SCAN_TOP_DOWN / _BOTTOM_UP (the
row order a region is emitted in). The word never changes with an order.
A palette is a list of [int $rgb, bool $inverted, int $code], at most 16: the
colour as 0xRRGGBB, whether a planar plane stores the ink as 0, and the word
an index layout stores for it. Planar needs one; an index layout without one
holds grey levels.
Colours map with integer arithmetic on 0..255 channels: Rec. 709 luma for mono (lit at half) and grey, the nearest palette entry for index and planar (the earlier entry wins a tie), bit packing for RGB.
Example
$format = new FbFormat(FB_LAYOUT_RGB565); $buffer = new FbBuffer($format, 240, 135); $buffer->fill(0x0000); $buffer->rect(20, 20, 100, 50, 0xF800); $buffer->set(0, 0, $format->mapRgba8(255, 128, 0)); $wire = $buffer->bytes(); // as stored, top row first $part = $buffer->region(20, 20, 100, 50); // a rect, as stored $bgra = $buffer->region(0, 0, 240, 135, new FbFormat(FB_LAYOUT_RGBA8888, channelOrder: FB_CHANNELS_BGRA)); $address = $buffer->pointer(); // valid while $buffer lives
paintSpans($spans, 0xRRGGBBAA) paints coverage spans, 7 bytes each
(y, x, length as uint16, coverage as uint8, little-endian), the format a
rasteriser such as ext-rasterize answers: RGB and grey layouts blend
source-over by alpha × coverage, mono, palette and planar layouts write the
colour where that reaches half.
paintRgba8($rgba8, $w, $h, $inverse, $x, $y, $tw, $th, $opacity, $smooth, $row)
places an RGBA8 image scaled, turned or moved: $inverse is the six numbers
[a, b, c, d, e, f] that map a target pixel's centre back to a point of the
image, the target rect says which pixels to visit, and each one is blended by
source alpha × opacity, from the nearest source pixel or smoothly from the
four around it. $row is for a buffer that is a window onto a taller surface:
the surface row its own row 0 stands for.
Coordinates outside a buffer are a ValueError. A pixel list with any entry
outside is refused whole, with nothing written. The stubs in stubs/ are the
full declaration.
Install
./install-macos.sh # Homebrew php@8.4 and php@8.4-zts, or pass PHP binaries ./install-debian-trixie.sh # Debian trixie, Raspberry Pi OS
Test
composer install && php vendor/bin/pest