:: limine / common / lib / image.c 2.7 KB raw

1
#include <stdint.h>
2
#include <stddef.h>
3
#include <lib/image.h>
4
#include <lib/config.h>
5
#include <lib/misc.h>
6
#include <mm/pmm.h>
7
#include <lib/qoi.h>
8
#include <lib/stb_image.h>
9
10
void image_make_centered(struct image *image, int frame_x_size, int frame_y_size, uint32_t back_colour) {
11
    image->type = IMAGE_CENTERED;
12
13
    image->x_displacement = (int64_t)frame_x_size / 2 - (int64_t)image->x_size / 2;
14
    image->y_displacement = (int64_t)frame_y_size / 2 - (int64_t)image->y_size / 2;
15
    image->back_colour = back_colour;
16
}
17
18
19
void image_make_stretched(struct image *image, int new_x_size, int new_y_size) {
20
    image->type = IMAGE_STRETCHED;
21
22
    image->x_size = new_x_size;
23
    image->y_size = new_y_size;
24
}
25
26
static void free_image_data(struct image *image) {
27
    if (image->isQoi) {
28
        qoi_free(image->img);
29
    } else {
30
        stbi_image_free(image->img);
31
    }
32
}
33
34
struct image *image_open(struct file_handle *file) {
35
    struct image *image = ext_mem_alloc(sizeof(struct image));
36
37
    image->type = IMAGE_TILED;
38
39
    void *src = ext_mem_alloc(file->size);
40
41
    fread(file, src, 0, file->size);
42
43
    int x = 0, y = 0;
44
    image->isQoi = file->size >= 4
45
                  && ((const uint8_t *)src)[0] == 'q'
46
                  && ((const uint8_t *)src)[1] == 'o'
47
                  && ((const uint8_t *)src)[2] == 'i'
48
                  && ((const uint8_t *)src)[3] == 'f';
49
50
    if (image->isQoi) {
51
        image->img = qoi_decode(src, file->size, &x, &y);
52
    } else {
53
        int bpp;
54
        image->img = stbi_load_from_memory(src, file->size, &x, &y, &bpp, 4);
55
    }
56
57
    pmm_free(src, file->size);
58
59
    if (image->img == NULL || x == 0 || y == 0) {
60
        free_image_data(image);
61
        pmm_free(image, sizeof(struct image));
62
        return NULL;
63
    }
64
65
    // stb_image returns RGBA bytes (little-endian uint32 ABGR); convert to
66
    // the framebuffer-native XRGB layout. The QOI decoder already produces
67
    // XRGB, so this step is skipped on that path.
68
    if (!image->isQoi) {
69
        uint32_t *pptr = (void *)image->img;
70
        size_t pixel_count = CHECKED_MUL((size_t)x, (size_t)y,
71
            ({ free_image_data(image); pmm_free(image, sizeof(struct image)); return NULL; }));
72
        for (size_t i = 0; i < pixel_count; i++) {
73
            pptr[i] = (pptr[i] & 0x0000ff00) | ((pptr[i] & 0x00ff0000) >> 16) | ((pptr[i] & 0x000000ff) << 16);
74
        }
75
    }
76
77
    image->x_size = x;
78
    image->y_size = y;
79
    image->pitch = (int)CHECKED_MUL((size_t)x, 4,
80
        ({ free_image_data(image); pmm_free(image, sizeof(struct image)); return NULL; }));
81
    image->bpp = 32;
82
    image->img_width = x;
83
    image->img_height = y;
84
85
    return image;
86
}
87
88
void image_close(struct image *image) {
89
    free_image_data(image);
90
    pmm_free(image, sizeof(struct image));
91
}
tab: 248 wrap: offon