Zigimg
Zig library for reading and writing different image formats
Install / Use
/learn @zigimg/ZigimgREADME
Zig Image library
This is a work in progress library to create, process, read and write different image formats with Zig programming language.
Install & Build
This library currently uses zig 0.15.2, we do plan to go back to using mach nominated zig until a newer version than 0.15.2 will be nominated.
Use zigimg in your project
How to add to your project:
As a submodule
- Clone this repository or add as a submodule
- Add to your
build.zig
pub fn build(b: *std.Build) void {
exe.root_module.addAnonymousModule("zigimg", .{ .root_source_file = b.path("zigimg.zig") });
}
Through the package manager
- Run this command in your project folder to add
zigimgto yourbuild.zig.zon
zig fetch --save git+https://github.com/zigimg/zigimg.git
- Get the module in your
build.zigfile
const zigimg_dependency = b.dependency("zigimg", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("zigimg", zigimg_dependency.module("zigimg"));
After you are done setting up, you can look at the user guide below.
Test suite
To run the test suite, checkout the test suite and run
- Checkout zigimg
- Go back one folder and checkout the test suite
- Run the tests with
zig build
zig build test
Supported image formats
| Image Format | Read | Write | | ------------- |:-------------:|:--------------:| | ANIM | ❌ | ❌ | | BMP | ✔️ (Partial) | ✔️ (Partial) | | Farbfeld | ✔️ | ✔️ | | GIF | ✔️ | ✔️ | | ICO | ❌ | ❌ | | IFF | ✔️ | ❌ | | JPEG | ✔️ (Partial) | ✔️ | | PAM | ✔️ | ✔️ | | PBM | ✔️ | ✔️ | | PCX | ✔️ | ✔️ | | PGM | ✔️ (Partial) | ✔️ (Partial) | | PNG | ✔️ | ✔️ (Partial) | | PPM | ✔️ (Partial) | ✔️ (Partial) | | QOI | ✔️ | ✔️ | | SGI | ✔️ | ❌ | | SUN | ✔️ | ❌ | | TGA | ✔️ | ✔️ | | TIFF | ✔️ (Partial) | ❌ | | XBM | ✔️ | ❌ | | XPM | ❌ | ❌ |
BMP - Bitmap
- version 4 BMP
- version 5 BMP
- 24-bit RGB read & write
- 32-bit RGBA read & write
- Doesn't support any compression
GIF - Graphics Interchange Format
- Support GIF87a and GIF89a
- Support animated GIF with Netscape application extension for looping information
- Supports interlaced
- Supports tiled and layered images used to achieve pseudo true color and more.
- The plain text extension is not supported
IFF - InterchangeFileFormat
- Supports 1-8 bit, 24 bit, HAM6/8, EHB ILBM files
- Supports uncompressed, byterun 1 & 2 (Atari) compressed ILBM files
- Supports PBM (Deluxe Paint DOS) encoded files
- Supports ACBM (Amiga Basic) files
- Color cycle chunks are ignored
- Mask is not supported (skipped)
JPEG - Joint Photographic Experts Group
- 8-bit baseline and progressive
PAM - Portable Arbitrary Map
Currently, this only supports a subset of PAMs where:
- The tuple type is official (see
man 5 pam) or easily inferred (and by extension, depth is 4 or less) - All the images in a sequence have the same dimensions and maxval (it is technically possible to support animations with different maxvals and tuple types as each
AnimationFramehas its ownPixelStorage, however, this is likely not expected by users of the library) - Grayscale,
- Grayscale with alpha
- Rgb555
- Rgb24 and Rgba32
- Bgr24 and Bgra32
- Rgb48 and Rgba64
PBM - Portable Bitmap format
- Everything is supported
PCX - ZSoft Picture Exchange format
- Support monochrome, 4 color, 16 color and 256 color indexed images
- Support 24-bit RGB images
PGM - Portable Graymap format
- Support 8-bit and 16-bit grayscale images
- 16-bit ascii grayscale loading not tested
PNG - Portable Network Graphics
- Support all pixel formats supported by PNG (grayscale, grayscale+alpha, indexed, truecolor, truecolor with alpha) in 8-bit or 16-bit.
- Support the mininal chunks in order to decode the image.
- Can write all supported pixel formats but writing interlaced images is not supported yet.
PPM - Portable Pixmap format
- Support 24-bit RGB (8-bit per channel)
- Missing 48-bit RGB (16-bit per channel)
QOI - Quite OK Image format
- Imported from https://github.com/MasterQ32/zig-qoi with blessing of the author
SGI - Silicon Graphics Image
- Supports 8-bit, RGB (24/48-bit), RGBA(32/64-bit) files
- Supports RLE and uncompressed files
SUN - Sun Raster format
- Supports 1/8/24/32-bit files
- Supports uncompressed & RLE files
- Supports BGR/RGB encoding
- TIFF/IFF/Experimental encoding is not supported
TGA - Truevision TGA format
- Supports uncompressed and compressed 8-bit grayscale, indexed with 16-bit and 24-bit colormap, truecolor with 16-bit(RGB555), 24-bit or 32-bit bit depth.
- Supports reading version 1 and version 2
- Supports writing version 2
TIFF - Tagged Image File Format
What's supported:
- bilevel, grayscale, palette and RGB(A) files
- most baseline tags
- Raw, LZW, Deflate, PackBits, CCITT 1D files
- big-endian (MM) and little-endian (II) files should both be decoded fine
What's missing:
- Tile-based files are not supported
- YCbCr, CMJN and CIE Lab files are not supported
- JPEG, CCITT Fax 3 / 4 are not supported yet
Notes
- Only the first IFD is decoded
- Orientation tag is not supported yet
XBM - X BitMap format
- Everything is supported
Supported Pixel formats
- Indexed: 1bpp (bit per pixel), 2bpp, 4bpp, 8bpp, 16bpp
- Grayscale: 1bpp, 2bpp, 4bpp, 8bpp, 16bpp, 8bpp with alpha, 16bpp with alpha
- Truecolor: RGB332, RGB555, RGB565, RGB24 (8-bit per channel), RGBA32 (8-bit per channel), BGR555, BGR24 (8-bit per channel), BGRA32 (8-bit per channel), RGB48 (16-bit per channel), RGBA64 (16-bit per channel)
- float: 32-bit float RGBA, this is the neutral format.
User Guide
Design philosophy
zigimg offers color and image functionality. The library is designed around either using the convenient Image (or Image.Managed) struct that can read and write image formats no matter the format.
Or you can also use the image format directly in case you want to extract more data from the image format. So if you find that Image does not give you the information that you need from a PNG or other format, you can use the PNG format albeit with a more manual API that Image hide from you.
Image vs Image.Managed
Image does not bundle a memory allocator and Image.Managed does, similar to std.ArrayList() and std.array_list.Managed in Zig standard library. For all the examples we are going to use Image but the API is similar when using Image.Managed.
Buffer requirements
Starting with Zig 0.15, all the I/O operations on file can accept a buffer for buffering. zigimg requires valid buffering buffers for reading from files and writing images to file. You can use zigimg.io.DEFAULT_BUFFER_SIZE as a size for the buffer you pass to the various file functions.
Read an image
It is pretty straightforward to read an image using the Image struct.
From a file
You can use either a file path
const std = @import("std");
const zigimg = @import("zigimg");
pub fn main() !void {
const allocator = std.heap.smp_allocator;
var read_buffer: [zigimg.io.DEFAULT_BUFFER_SIZE]u8 = undefined;
var image = try zigimg.Image.fromFilePath(allocator, "my_image.png", read_buffer[0..]);
defer image.deinit(allocator);
// Do something with your image
}
or a std.fs.File directly
const std = @import("std");
const zigimg = @import("zigimg");
pub fn main() !void {
const allocator = std.heap.smp_allocator;
var file = try std.fs.cwd().openFile(file_path, .{});
defer file.close();
var read_buffer: [zigimg.io.DEFAULT_BUFFER_SIZE]u8 = undefined;
var image = try zigimg.Image.fromFile(allocator, &file, read_buffer[0..]);
defer image.deinit(allocator);
// Do something with your image
}
From memory
const std = @import("std");
const zigimg = @import("zigimg");
const image_data = @embedFile("test.bmp");
pub fn main() !void {
const allocator = std.heap.smp_allocator;
const image = try zigimg.Image.fromMemory(allocator, image_data[0..]);
defer image.deinit(allocator);
// Do something with your image
}
Accessing pixel data
For a single image, they are two ways to get access to the pixel data.
Accessing a specific format directly
You can access the pixel data directly using Image.pixels. pixels is an union of all supported pixel formats.
For RGB pixel formats, just use the pixel format enum value and addresss the data directly.
pub fn example() void {
// [...]
// Assuming you already have an image loa

