image: Use stb_image for image loading
diff --git a/CONFIG.md b/CONFIG.md
index e3fd2a4f..caf49277 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -84,7 +84,7 @@ Limine graphical terminal control options. They are ignored if using text mode.
* `TERM_FOREGROUND_BRIGHT` - Terminal text foreground bright colour (RRGGBB).
* `TERM_MARGIN` - Set the amount of margin around the terminal.
* `TERM_MARGIN_GRADIENT` - Set the thickness in pixel for the gradient around the terminal.
-* `TERM_WALLPAPER` - URI where to find the .BMP file to use as wallpaper.
+* `TERM_WALLPAPER` - URI where to find the file to use as wallpaper. BMP, PNG, and JPEG formats are supported.
* `TERM_WALLPAPER_STYLE` - The style which will be used to display the wallpaper image: `tiled`, `centered`, or `stretched`. Default is `stretched`.
* `TERM_BACKDROP` - When the background style is `centered`, this specifies the colour of the backdrop for parts of the screen not covered by the background image, in RRGGBB format.
diff --git a/README.md b/README.md
index fbc27c37..9bd75d20 100644
--- a/README.md
+++ b/README.md
@@ -231,7 +231,8 @@ An example `limine.cfg` file can be found in [`test/limine.cfg`](https://github.
More info on the format of `limine.cfg` can be found in [`CONFIG.md`](https://github.com/limine-bootloader/limine/blob/trunk/CONFIG.md).
## Acknowledgments
-Limine uses a stripped-down version of [tinf](https://github.com/jibsen/tinf).
+Limine uses a stripped-down version of [tinf](https://github.com/jibsen/tinf) for early GZIP decompression.
+Limine relies on [stb_image](https://github.com/nothings/stb/blob/master/stb_image.h) for runtime GZIP decompression and image loading.
## Discord server
We have a [Discord server](https://discord.gg/QEeZMz4) if you need support,
diff --git a/common/lib/bmp.c b/common/lib/bmp.c
deleted file mode 100644
index 0a8cb37f..00000000
--- a/common/lib/bmp.c
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <stdint.h>
-#include <fs/file.h>
-#include <lib/image.h>
-#include <lib/bmp.h>
-#include <lib/libc.h>
-#include <lib/misc.h>
-#include <mm/pmm.h>
-
-struct bmp_header {
- uint16_t bf_signature;
- uint32_t bf_size;
- uint32_t reserved;
- uint32_t bf_offset;
-
- uint32_t bi_size;
- uint32_t bi_width;
- uint32_t bi_height;
- uint16_t bi_planes;
- uint16_t bi_bpp;
- uint32_t bi_compression;
- uint32_t bi_image_size;
- uint32_t bi_xcount;
- uint32_t bi_ycount;
- uint32_t bi_clr_used;
- uint32_t bi_clr_important;
- uint32_t red_mask;
- uint32_t green_mask;
- uint32_t blue_mask;
-} __attribute__((packed));
-
-bool bmp_open_image(struct image *image, struct file_handle *file) {
- struct bmp_header header;
- fread(file, &header, 0, sizeof(struct bmp_header));
-
- if (memcmp(&header.bf_signature, "BM", 2) != 0)
- return false;
-
- // We don't support bpp lower than 8
- if (header.bi_bpp % 8 != 0)
- return false;
-
- image->img = ext_mem_alloc(header.bf_size);
-
- uint32_t bf_size;
- if (header.bf_offset + header.bf_size > file->size) {
- bf_size = file->size - header.bf_offset;
- } else {
- bf_size = header.bf_size;
- }
-
- fread(file, image->img, header.bf_offset, bf_size);
-
- image->allocated_size = header.bf_size;
-
- image->x_size = header.bi_width;
- image->y_size = header.bi_height;
- image->pitch = ALIGN_UP(header.bi_width * header.bi_bpp, 32) / 8;
- image->bpp = header.bi_bpp;
- image->img_width = header.bi_width;
- image->img_height = header.bi_height;
-
- return true;
-}
diff --git a/common/lib/bmp.h b/common/lib/bmp.h
deleted file mode 100644
index 8763d6b4..00000000
--- a/common/lib/bmp.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __LIB__BMP_H__
-#define __LIB__BMP_H__
-
-#include <stdint.h>
-#include <fs/file.h>
-#include <lib/image.h>
-
-bool bmp_open_image(struct image *image, struct file_handle *file);
-
-#endif
diff --git a/common/lib/gterm.c b/common/lib/gterm.c
index ec3b7e7f..b01dcd20 100644
--- a/common/lib/gterm.c
+++ b/common/lib/gterm.c
@@ -434,7 +434,7 @@ __attribute__((always_inline)) static inline void genloop(struct fb_info *fb, si
case IMAGE_TILED:
for (size_t y = ystart; y < yend; y++) {
size_t image_y = y % img_height, image_x = xstart % img_width;
- const size_t off = img_pitch * (img_height - 1 - image_y);
+ const size_t off = img_pitch * image_y;
size_t canvas_off = fb->framebuffer_width * y;
for (size_t x = xstart; x < xend; x++) {
uint32_t img_pixel = *(uint32_t*)(img + image_x * colsize + off);
@@ -448,7 +448,7 @@ __attribute__((always_inline)) static inline void genloop(struct fb_info *fb, si
case IMAGE_CENTERED:
for (size_t y = ystart; y < yend; y++) {
size_t image_y = y - background->y_displacement;
- const size_t off = img_pitch * (img_height - 1 - image_y);
+ const size_t off = img_pitch * image_y;
size_t canvas_off = fb->framebuffer_width * y;
if (image_y >= background->y_size) { /* external part */
for (size_t x = xstart; x < xend; x++) {
@@ -473,7 +473,7 @@ __attribute__((always_inline)) static inline void genloop(struct fb_info *fb, si
case IMAGE_STRETCHED:
for (size_t y = ystart; y < yend; y++) {
size_t img_y = (y * img_height) / fb->framebuffer_height; // calculate Y with full precision
- size_t off = img_pitch * (img_height - 1 - img_y);
+ size_t off = img_pitch * img_y;
size_t canvas_off = fb->framebuffer_width * y;
size_t ratio = int_to_fixedp6(img_width) / fb->framebuffer_width;
diff --git a/common/lib/image.c b/common/lib/image.c
index bc2d0319..758ee312 100644
--- a/common/lib/image.c
+++ b/common/lib/image.c
@@ -1,9 +1,10 @@
#include <stdint.h>
#include <stddef.h>
+#include <lib/image.h>
#include <lib/config.h>
#include <lib/misc.h>
#include <mm/pmm.h>
-#include <lib/bmp.h>
+#include <stb/stb_image.h>
void image_make_centered(struct image *image, int frame_x_size, int frame_y_size, uint32_t back_colour) {
image->type = IMAGE_CENTERED;
@@ -26,11 +27,36 @@ struct image *image_open(struct file_handle *file) {
image->type = IMAGE_TILED;
- if (bmp_open_image(image, file))
- return image;
+ void *src = ext_mem_alloc(file->size);
- pmm_free(image, sizeof(struct image));
- return NULL;
+ fread(file, src, 0, file->size);
+
+ int x, y, bpp;
+
+ image->img = stbi_load_from_memory(src, file->size, &x, &y, &bpp, 4);
+
+ pmm_free(src, file->size);
+
+ if (image->img == NULL) {
+ pmm_free(image, sizeof(struct image));
+ return NULL;
+ }
+
+ // Convert ABGR to XRGB
+ uint32_t *pptr = (void *)image->img;
+ for (int i = 0; i < x * y; i++) {
+ pptr[i] = (pptr[i] & 0x0000ff00) | ((pptr[i] & 0x00ff0000) >> 16) | ((pptr[i] & 0x000000ff) << 16);
+ }
+
+ image->allocated_size = x * y * 4;
+ image->x_size = x;
+ image->y_size = y;
+ image->pitch = x * 4;
+ image->bpp = 32;
+ image->img_width = x;
+ image->img_height = y;
+
+ return image;
}
void image_close(struct image *image) {
diff --git a/common/lib/libc.h b/common/lib/libc.h
index 7e8add9d..19b50fc9 100644
--- a/common/lib/libc.h
+++ b/common/lib/libc.h
@@ -10,6 +10,8 @@ bool isspace(int c);
int toupper(int c);
int tolower(int c);
+int abs(int i);
+
void *memset(void *, int, size_t);
void *memcpy(void *, const void *, size_t);
int memcmp(const void *, const void *, size_t);
diff --git a/common/lib/libc.s2.c b/common/lib/libc.s2.c
index 34f93a1f..c3eda16d 100644
--- a/common/lib/libc.s2.c
+++ b/common/lib/libc.s2.c
@@ -26,6 +26,10 @@ int tolower(int c) {
return c;
}
+int abs(int i) {
+ return i < 0 ? -i : i;
+}
+
char *strcpy(char *dest, const char *src) {
size_t i;
diff --git a/common/stb_image.patch b/common/stb_image.patch
index ebeb5312..56d4c47c 100644
--- a/common/stb_image.patch
+++ b/common/stb_image.patch
@@ -1,6 +1,6 @@
---- common/stb/stb_image.h 2023-02-18 09:34:39.771655260 +0100
-+++ common/stb/stb_image.h 2023-02-18 09:35:26.014990183 +0100
-@@ -127,6 +127,28 @@
+--- common/stb/stb_image.h 2023-03-05 06:32:45.628671768 +0100
++++ common/stb/stb_image.h 2023-03-05 07:47:29.931051098 +0100
+@@ -127,6 +127,31 @@
#ifndef STBI_INCLUDE_STB_IMAGE_H
#define STBI_INCLUDE_STB_IMAGE_H
@@ -25,11 +25,14 @@
+
+#define STBI_ONLY_ZLIB
+#define STBI_SUPPORT_ZLIB
++#define STBI_ONLY_JPEG
++#define STBI_ONLY_PNG
++#define STBI_ONLY_BMP
+
// DOCUMENTATION
//
// Limitations:
-@@ -381,7 +403,7 @@
+@@ -381,7 +406,7 @@
STBI_rgb_alpha = 4
};
@@ -38,7 +41,7 @@
typedef unsigned char stbi_uc;
typedef unsigned short stbi_us;
-@@ -584,8 +606,8 @@
+@@ -584,8 +609,8 @@
#include <stdarg.h>
#include <stddef.h> // ptrdiff_t on osx
@@ -49,7 +52,7 @@
#include <limits.h>
#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR)
-@@ -1574,10 +1596,12 @@
+@@ -1574,10 +1599,12 @@
STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }
#endif
