_           _                 
 | |_ ___  __| |____  ___ _   _ 
 | __/ _ \/ _` |_  / / _ \ | | |
 | ||  __/ (_| |/ / |  __/ |_| |
  \__\___|\__,_/___(_)___|\__,_|

shapemaker.c work in progress

Example images

Example output images

Code

to compile:

gcc shapemaker.c -o shapemaker

Full C code:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>

int clamp(int val, int min, int max) {return val < min ? min : val > max ? max : val;}
int min(int a, int b) {return a > b ? b : a;}
int max(int a, int b) {return a > b ? a : b;}

int main(int argc, char **argv)
{
    // Seed random number generation to obtain a different
    // shape (or shapes) each time the program runs
    srand(time(0));

    // Default options
    int number_of_images = 16, image_number;
    int w = 640, h = 480;
    //int n = 1;
    char filename[256];
    char filestem[256] = "output";

    // Pixel buffer
    uint8_t *p = NULL;
    int x, y;
    int colour;

    p = malloc(w*h*sizeof(*p));

    // Shape parameters
    int bg_topleft, bg_topright, bg_bottomleft, bg_bottomright;
    double u, v;
    int cx, cy;
    int rmax, rmin, r, rr;
    int x1, x2, y1, y2;

    // Print greeting
    printf("shapemaker 0.1\nwritten by Ted Burke 18-Dec-2025\n");
    printf("Generates a set of PGM images with random shapes\n\n");

    for (image_number = 1 ; image_number <= number_of_images ; ++image_number)
    {
        // Generate background
        bg_topleft = rand()%256;
        bg_topright = rand()%256;
        bg_bottomleft = rand()%256;
        bg_bottomright = rand()%256;
        for (y = 0 ; y < h ; ++y) for (x = 0 ; x < w ; ++x)
        {
            u = (1.0*x)/w;
            v = (1.0*y)/h;
            colour = (1-v)*((1-u)*bg_topleft + u*bg_topright) + v*((1-u)*bg_bottomleft + u*bg_bottomright);
            p[y*w+x] = clamp(colour+(rand()%64), 0, 255);
        }

        // Add shape to image
        cx = rand()%w; cy = rand()%h;
        rmax = min(w, h) / 4; rmin = rmax / 2;
        r = rmin + rand()%(rmax-rmin); rr = r * r;
        y1 = max(0, cy-r); y2 = min(h, cy+r);
        x1 = max(0, cx-r); x2 = min(w, cx+r);
        for (y = y1 ; y < y2 ; ++y) for (x = x1 ; x < x2 ; ++x)
        {
            if ((x-cx)*(x-cx) + (y-cy)*(y-cy) > rr) continue;
            colour = p[y*w+x];
            colour = (colour + 128) % 256;
            p[y*w+x] = colour;;
        }

        // Write PGM file
        snprintf(filename, sizeof filename, "%s_%003d.pgm", filestem, image_number);
        fprintf(stderr, "Writing image %s...", filename);
        FILE *fpgm = fopen(filename, "w");
        fprintf(fpgm, "P2\n%d %d\n255\n", w, h);
        for (y = 0 ; y < h ; ++y) for (x = 0 ; x < w ; ++x)
        {
            fprintf(fpgm, "%d%c", p[y*w+x], x == w-1 ? '\n' : ' ');
        }
        fclose(fpgm);
        fprintf(stderr, "Done\n", filename);
    }

    return 0;
}