diff options
author | Jules Maselbas <jmaselbas@kalray.eu> | 2022-01-18 00:02:32 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2022-01-20 09:14:22 +0100 |
commit | d50ba51c753740787b1730f64af244b9903f26f0 (patch) | |
tree | b091c7bdff1f43327de3c23717c88bac1ec56800 /lib/gui/qoi.c | |
parent | eacac60aeb46a0d35c92c673fcaa118befd54bfe (diff) | |
download | barebox-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.c | 97 |
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); |