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

Sort image pixels by colour

//
// coloursort.c - written by Ted Burke - 4-Aug-2022
//

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

int main(int argc, char **argv)
{
    uint8_t *p;
    FILE *pipein, *fout;
    char buf[1024];
    int w=800, h=600;

    // Get image dimensions
    sprintf(buf, "ffmpeg -i %s 2>&1 | grep '^\\s*Stream' | grep -o '[0-9]\\+x[0-9]\\+'", argv[1]);
    pipein = popen(buf, "r");
    fscanf(pipein, "%dx%d", &w, &h);
    pclose(pipein);

    printf("Width: %d, Height: %d\n", w, h);

    // Allocate pixel buffer
    p = malloc(3*w*h);

    // Load image file specified on commmand line
    sprintf(buf, "ffmpeg -i %s -f image2pipe -vcodec rawvideo -pix_fmt rgb24 -", argv[1]);
    pipein = popen(buf, "r");
    fread(p, 3, w*h, pipein);
    pclose(pipein);

    // Sort pixels in order of increasing average RGB channel value
    uint8_t red, green, blue;
    int n, N = w*h;
    int sorted = 0;
    for (int v=0 ; v<3*255+1 ; ++v) // check all possible R+G+B values
    {
        for (n=sorted ; n<N ; ++n) // scan unsorted pixels for this R+G+B value
        {
            if (p[n*3]+p[n*3+1]+p[n*3+2] == v) // check R+G+B value
            {
                // swap this pixel back to the current sorting index
                red = p[3*sorted];
                green = p[3*sorted+1];
                blue = p[3*sorted+2];
                p[3*sorted] = p[3*n];
                p[3*sorted+1] = p[3*n+1];
                p[3*sorted+2] = p[3*n+2];
                p[3*n] = red;
                p[3*n+1] = green;
                p[3*n+2] = blue;
                sorted++;
            }
        }
    }

    // Write image to output file
    fout = fopen("output.ppm", "w");
    fprintf(fout, "P6\n#coloursorted by Ted Burke\n%d %d\n255\n", w, h);
    fwrite(p, 3, w*h, fout);
    fclose(fout);

    free(p);
    return 0;
}