Canvas Solution

canvas.c:

#include "canvas.h"
#include <stdio.h>
#include <stdlib.h>
 
static Canvas make_empty_canvas(void)
{
    Canvas c;
    c.width = 0;
    c.height = 0;
    c.pixels = NULL;
    return c;
}
 
Canvas init_canvas(int width, int height)
{
    Canvas c;
    int y;
 
    c.width = 0;
    c.height = 0;
    c.pixels = NULL;
 
    if (width <= 0 || height <= 0)
    {
        return c;
    }
 
    c.pixels = malloc(height * sizeof(Pixel *));
    for (y = 0; y < height; ++y)
    {
        c.pixels[y] = malloc(width * sizeof(Pixel));
        if (!c.pixels[y])
        {
            int i;
            for (i = 0; i < y; ++i)
            {
                free(c.pixels[i]);
            }
            free(c.pixels);
            c.pixels = NULL;
            return make_empty_canvas();
        }
    }
 
    c.width = width;
    c.height = height;
    return c;
}
 
Canvas load_asset(const char *filename)
{
    Canvas c = make_empty_canvas();
    FILE *f = fopen(filename, "r");
    int w, h;
    int x, y;
 
    if (!f)
    {
        return c;
    }
 
    if (fscanf(f, "%d %d", &w, &h) != 2)
    {
        fclose(f);
        return c;
    }
 
    c = init_canvas(w, h);
    if (!c.pixels)
    {
        fclose(f);
        return c;
    }
 
    for (y = 0; y < c.height; ++y)
    {
        for (x = 0; x < c.width; ++x)
        {
            int r, g, b;
            if (fscanf(f, "%d %d %d", &r, &g, &b) != 3)
            {
                /* on bad input just free and return empty */
                free_canvas(c);
                fclose(f);
                return make_empty_canvas();
            }
            c.pixels[y][x].r = (unsigned char)r;
            c.pixels[y][x].g = (unsigned char)g;
            c.pixels[y][x].b = (unsigned char)b;
        }
    }
 
    fclose(f);
    return c;
}
 
void free_canvas(Canvas c)
{
    int y;
 
    if (!c.pixels)
    {
        return;
    }
 
    for (y = 0; y < c.height; ++y)
    {
        free(c.pixels[y]);
    }
    free(c.pixels);
}
 
void invert_colors(Canvas *c)
{
    int x, y;
 
    if (!c || !c->pixels)
    {
        return;
    }
 
    for (y = 0; y < c->height; ++y)
    {
        for (x = 0; x < c->width; ++x)
        {
            Pixel *p = &c->pixels[y][x];
            p->r = 255 - p->r;
            p->g = 255 - p->g;
            p->b = 255 - p->b;
        }
    }
}
 
Canvas get_brightest_canvas(Canvas canvases[], int size)
{
    int i, x, y;
    double best_brightness = -1.0;
    Canvas best = make_empty_canvas();
 
    if (!canvases || size <= 0)
    {
        return best;
    }
 
    for (i = 0; i < size; ++i)
    {
        Canvas c = canvases[i];
        long sum = 0;
        long count;
 
        if (!c.pixels || c.width <= 0 || c.height <= 0)
        {
            continue;
        }
 
        for (y = 0; y < c.height; ++y)
        {
            for (x = 0; x < c.width; ++x)
            {
                Pixel p = c.pixels[y][x];
                sum += p.r + p.g + p.b;
            }
        }
 
        count = (long)c.width * (long)c.height * 3L;
        if (count == 0)
        {
            continue;
        }
 
        double avg = (double)sum / (double)count;
        if (avg > best_brightness)
        {
            best_brightness = avg;
            best = c;
        }
    }
 
    return best;
}

canvas.h:

#ifndef CANVAS_H
#define CANVAS_H
 
typedef struct
{
    unsigned char r;
    unsigned char g;
    unsigned char b;
} Pixel;
 
typedef struct
{
    int width;
    int height;
    Pixel **pixels; /* pixels[y][x] */
} Canvas;
 
Canvas init_canvas(int width, int height);
Canvas load_asset(const char *filename);
void free_canvas(Canvas c);
void invert_colors(Canvas *c);
Canvas get_brightest_canvas(Canvas canvases[], int size);
 
#endif

main.c:

#include <stdio.h>
#include <stdlib.h>
#include "canvas.h"
 
void print_canvas(Canvas c){
    printf("\n--- Canvas (%dx%d) ---\n", c.width, c.height);
 
    for (int y = 0; y < c.height; y++){
        for (int x = 0; x < c.width; x++){
            Pixel p = c.pixels[y][x];
            printf("\033[38;2;%d;%d;%dm", p.r, p.g, p.b);
            printf("@@");
            printf("\033[0m");
        }
        printf("\n");
    }
    printf("---------------------\n");
}
 
Canvas* load_all_canvases(){
    int capacity = 4;
    Canvas *canvas_array = malloc(capacity * sizeof(Canvas));
    Canvas c = load_asset("assets/cat.txt");
    canvas_array[0] = c;
    c = load_asset("assets/dog.txt");
    canvas_array[1] = c;
    c = load_asset("assets/fish.txt");
    canvas_array[2] = c;
    c = load_asset("assets/star.txt");
    canvas_array[3] = c;
    return canvas_array;
}
 
int main()
{
    int choice = 0;
    Canvas *canvases = load_all_canvases();
    for (;;) {
        printf("\n=== Menu ===\n");
        printf("1) Print an image\n");
        printf("2) Invert an image\n");
        printf("3) Get the brightest image\n");
        printf("4) Exit\n");
        printf("Your choice: ");
        scanf("%d", &choice);
 
        if (choice == 4) {
            for (int i = 0; i < 4; i++) {
                free_canvas(canvases[i]);
            }
            free(canvases);
            break;
        }
 
        if (!canvases) {
            printf("No images are loaded. Put images in ./assets and restart.\n");
            continue;
        }
 
        switch (choice) {
            case 1: {
                printf("Which image do you want to print?\n");
                printf("0 : Cat\n");
                printf("1 : Dog\n");
                printf("2 : Fish\n");
                printf("3 : Star\n");
                printf("Your choice: ");
                scanf("%d", &choice);
                if (choice < 0 || choice > 3) {
                    printf("Invalid choice, please try again!\n");
                    break;
                }
                print_canvas(canvases[choice]);
                break;
            }
            case 2: {
                printf("Which image do you want to invert?\n");
                printf("0 : Cat\n");
                printf("1 : Dog\n");
                printf("2 : Fish\n");
                printf("3 : Star\n");
                printf("Your choice: ");
                scanf("%d", &choice);
                if (choice < 0 || choice > 3) {
                    printf("Invalid choice, please try again!\n");
                    break;
                }
                invert_colors(&canvases[choice]);
                print_canvas(canvases[choice]);
                break;
            }
            case 3: {
                Canvas brightest = get_brightest_canvas(canvases, 4);
                print_canvas(brightest);
                break;
            }
            default:
                printf("Wrong choice, please try again!\n");
                break;
        }
    }
 
    return 0;
}