summaryrefslogtreecommitdiffstats
path: root/lib/gui/qoi.c
diff options
context:
space:
mode:
authorJules Maselbas <jmaselbas@kalray.eu>2022-01-18 00:02:32 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2022-01-20 09:14:22 +0100
commitd50ba51c753740787b1730f64af244b9903f26f0 (patch)
treeb091c7bdff1f43327de3c23717c88bac1ec56800 /lib/gui/qoi.c
parenteacac60aeb46a0d35c92c673fcaa118befd54bfe (diff)
downloadbarebox-d50ba51c753740787b1730f64af244b9903f26f0.tar.gz
barebox-d50ba51c753740787b1730f64af244b9903f26f0.tar.xz
gui: Add qoi image format
The "Quite OK Image Format", aka QOI, aims to be a fast, lossless image compression format, with comparable compression factor against png, and beeing faster to encode and decode. In barebox only care about decoding, the qoi image format might be an intresting alternative to both bmp and png, some kind of midle ground. The project home page can be found at https://qoiformat.org, there is a reference implementation, for both encoder and decoder, in a single header file (qoi.h) hosted at https://github.com/phoboslab/qoi. There is no plan for future version, this is a frozen format. In case the reference implementation should be updated, the qoi.h file must be copied to the lib/gui/qoi.h without requiring modifications. Signed-off-by: Jules Maselbas <jmaselbas@kalray.eu> Link: https://lore.barebox.org/20220117230235.13549-3-jmaselbas@kalray.eu Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'lib/gui/qoi.c')
-rw-r--r--lib/gui/qoi.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/lib/gui/qoi.c b/lib/gui/qoi.c
new file mode 100644
index 0000000000..b931868f16
--- /dev/null
+++ b/lib/gui/qoi.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+
+#define pr_fmt(fmt) "qoi: " fmt
+
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <fb.h>
+#include <asm/byteorder.h>
+#include <gui/graphic_utils.h>
+#include <init.h>
+#include <gui/image_renderer.h>
+#include <asm/unaligned.h>
+
+#define QOI_NO_STDIO
+#define QOI_IMPLEMENTATION
+#include "qoi.h"
+
+static struct image *qoi_open(char *inbuf, int insize)
+{
+ struct image *img;
+ void *data;
+ qoi_desc qoi;
+
+ img = calloc(1, sizeof(*img));
+ if (!img)
+ return ERR_PTR(-ENOMEM);
+
+ data = qoi_decode(inbuf, insize, &qoi, 0);
+ if (!data) {
+ free(img);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ img->data = data;
+ img->height = qoi.height;
+ img->width = qoi.width;
+ img->bits_per_pixel = qoi.channels * 8;
+
+ pr_debug("%d x %d x %d data@0x%p\n", img->width, img->height,
+ img->bits_per_pixel, img->data);
+ return img;
+}
+
+static void qoi_close(struct image *img)
+{
+ free(img->data);
+}
+
+static int qoi_renderer(struct screen *sc, struct surface *s, struct image *img)
+{
+ int alpha = img->bits_per_pixel == (4 * 8);
+ int width = s->width;
+ int height = s->height;
+ int startx = s->x;
+ int starty = s->y;
+ void *buf;
+
+ if (s->width < 0)
+ width = img->width;
+ if (s->height < 0)
+ height = img->height;
+
+ if (startx < 0) {
+ startx = (sc->s.width - width) / 2;
+ if (startx < 0)
+ startx = 0;
+ }
+
+ if (starty < 0) {
+ starty = (sc->s.height - height) / 2;
+ if (starty < 0)
+ starty = 0;
+ }
+
+ width = min(width, sc->s.width - startx);
+ height = min(height, sc->s.height - starty);
+
+ buf = gui_screen_render_buffer(sc);
+
+ gu_rgba_blend(sc->info, img, buf, height, width, startx, starty, alpha);
+
+ return img->height;
+}
+
+static struct image_renderer qoi = {
+ .type = filetype_qoi,
+ .open = qoi_open,
+ .close = qoi_close,
+ .renderer = qoi_renderer,
+};
+
+static int qoi_init(void)
+{
+ return image_renderer_register(&qoi);
+}
+fs_initcall(qoi_init);