- C 93.4%
- Makefile 6.6%
| examples | ADD: Vector math + point-list shapes functions implemented | |
| src | ADD: Vector math + point-list shapes functions implemented | |
| .gitignore | New example file (hue.c) + better Makefile for running examples and building | |
| LICENSE | Initial commit | |
| Makefile | add 2d vector and vector wrappers for existing forms + new example :) | |
| README.md | ADD: Vector math + point-list shapes functions implemented | |
libzard is a lightweight C graphics library that implements a simple software renderer for generating images in the PPM format.
Features
- Minimal, ergonomic API with a
begin/endsession model - Pure software rendering — no GPU, no external dependencies
- Primitive drawing support:
- Lines
- Rectangles (outline and filled)
- Circles (outline and filled)
- Triangles (outline and filled)
- Direct pixel manipulation
- PPM image output (P3 ASCII and P6 binary)
- 2D vector support (
zvec2_t) with float precision - Vector math helpers for composing point-list shapes
- Frame-by-frame animation helpers for generating PPM sequences
About the PPM Format
PPM (Portable Pixmap) is a straightforward image format designed for simplicity and portability. libzard supports both variants:
P3 (ASCII)
P3
<width> <height>
255
R G B R G B R G B ...
P6 (Binary)
P6
<width> <height>
255
<raw binary RGB data>
Each pixel is represented by three 8-bit channel values:
- Red (0–255)
- Green (0–255)
- Blue (0–255)
Example
P3
2 1
255
255 0 0 0 255 0
This produces a 2-pixel wide image consisting of one red pixel followed by one green pixel.
P3 vs P6
| P3 (ASCII) | P6 (Binary) | |
|---|---|---|
| Readability | Human-readable | Binary |
| File size | Large | Compact |
| Performance | Slower to write | Faster to write |
| Best for | Debugging, learning | Production use |
Installation
Build
make
Install system-wide
sudo make install
This installs:
libzard.a→/usr/local/libzard.h→/usr/local/include
Uninstall
sudo make uninstall
Clean
make clean
Usage
Example
Example 1:
#include <zard.h>
int main() {
zard_begin("output_1.ppm", 400, 300, ZARD_P6);
zard_clear(ZARD_BLACK);
zard_line(0, 0, 399, 299, ZARD_WHITE);
zard_rect(50, 50, 100, 80, ZARD_RED);
zard_fill_circle(200, 150, 40, ZARD_BLUE);
zard_end();
return 0;
}
Example 2:
#include <zard.h>
int main() {
zard_begin("output_2.ppm", 400, 300, ZARD_P6);
zard_clear(ZARD_BLACK);
zvec2_t a = {50.0f, 50.0f};
zvec2_t b = {350.0f, 250.0f};
zvec2_t center = {200.0f, 150.0f};
zard_line_v(a, b, ZARD_WHITE);
zard_circle_v(center, 40, ZARD_BLUE);
zard_end();
return 0;
}
Example 3:
#include <zard.h>
int main() {
int frames = 60;
zard_anim_init("output-%02d.ppm", 960, 540, ZARD_P6);
for (int i = 0; i < frames; i++) {
zard_frame_begin(i);
zard_clear(ZARD_BLACK);
zard_fill_circle(i * 8, 270, 40, ZARD_RED);
zard_frame_end();
}
zard_anim_done(frames);
return 0;
}
Vector shape example:
#include <math.h>#include <zard.h>
int main() {
zard_begin("shape.ppm", 400, 400, ZARD_P6);
zard_clear(ZARD_BLACK);
float pi = acosf(-1.0f);
zvec2_t center = zard_vec2(200.0f, 200.0f);
zvec2_t star[10];
zard_make_star(star, 5, center, 50.0f, 140.0f, -pi * 0.5f);
zard_fill_polygon_v(star, 10, ZARD_BLUE);
zard_polygon_v(star, 10, ZARD_WHITE);
zard_end();
return 0;
}
Compile
gcc main.c -lzard -lm -o app
When using the local build without installing system-wide:
gcc main.c -I./src -L./build -lzard -lm -o app
Run examples
make run
Run a single example by name:
make run-one NAME=basic
API Reference
Session
| Function | Description |
|---|---|
zard_begin(filename, w, h, fmt) |
Initializes a rendering session |
zard_end() |
Finalizes and writes the output file |
zard_clear(color) |
Fills the canvas with a solid color |
zard_create(w, h) |
Allocates an image buffer |
zard_destroy(img) |
Frees an image buffer |
zard_write_ppm(img, filename, fmt) |
Writes an image as PPM |
Primitives
| Function | Description |
|---|---|
zard_pixel(x, y, color) |
Sets a single pixel |
zard_line(x0, y0, x1, y1, color) |
Draws a line |
zard_rect(x, y, w, h, color) |
Draws a rectangle outline |
zard_fill_rect(x, y, w, h, color) |
Draws a filled rectangle |
zard_circle(cx, cy, r, color) |
Draws a circle outline |
zard_fill_circle(cx, cy, r, color) |
Draws a filled circle |
zard_triangle(x1,y1,x2,y2,x3,y3,color) |
Draws a triangle outline |
zard_fill_triangle(x1,y1,x2,y2,x3,y3,color) |
Draws a filled triangle |
Vectorized
| Function | Description |
|---|---|
zard_pixel_v(vec, color) |
Sets a pixel using a vector |
zard_line_v(a, b, color) |
Draws a line between vectors |
zard_rect_v(pos, w, h, color) |
Rectangle from position vector |
zard_fill_rect_v(pos, w, h, color) |
Filled rectangle |
zard_circle_v(center, r, color) |
Circle from center vector |
zard_fill_circle_v(center, r, color) |
Filled circle |
zard_triangle_v(a, b, c, color) |
Triangle using vectors |
zard_fill_triangle_v(a, b, c, color) |
Filled triangle |
Vector Math And Shapes
| Function | Description |
|---|---|
zard_vec2(x, y) / ZARD_VEC2(x, y) |
Creates a 2D vector |
zard_vadd(a, b) / zard_vsub(a, b) |
Adds or subtracts vectors |
zard_vmul(v, s) / zard_vdiv(v, s) |
Scales a vector |
zard_vdot(a, b) / zard_vlen(v) |
Dot product and length |
zard_vnorm(v) |
Normalizes a vector |
zard_vlerp(a, b, t) |
Interpolates between two points |
zard_vperp(v) |
Gets the perpendicular vector |
zard_vfrom_angle(angle, radius) |
Creates a polar vector |
zard_vrotate(v, angle) |
Rotates a vector around origin |
zard_vrotate_around(p, center, angle) |
Rotates a point around another |
zard_polyline_v(points, count, closed, color) |
Draws connected points |
zard_polygon_v(points, count, color) |
Draws a closed point-list outline |
zard_fill_polygon_v(points, count, color) |
Fills a simple polygon |
zard_make_ngon(out, count, center, radius, rotation) |
Generates a regular polygon |
zard_make_star(out, points, center, inner, outer, rotation) |
Generates a star |
zard_make_bezier(out, count, p0, p1, p2, p3) |
Samples a cubic Bezier curve |
Animation
| Function | Description |
|---|---|
zard_anim_init(pattern, w, h, fmt) |
Initializes an animation sequence |
zard_frame_begin(frame_index) |
Starts rendering a frame |
zard_frame_end() |
Writes the current frame |
zard_anim_done(total_frames) |
Finalizes the animation sequence |
Generated frames can be converted with tools such as ffmpeg:
ffmpeg -framerate 60 -i output-%02d.ppm output.mp4
Built-in Colors
ZARD_BLACK, ZARD_WHITE, ZARD_RED, ZARD_GREEN, ZARD_BLUE, ZARD_CYAN, ZARD_MAGENTA, ZARD_YELLOW, ZARD_GRAY, ZARD_ORANGE
Custom colors can be defined with ZARD_RGB(r, g, b).
License
MIT License — Copyright (c) 2026 grassleaff. All Rights Reserved.