From bd3504c58025499b5fd0f845d7af19bbcca315b9 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Thu, 31 Jan 2019 21:40:28 +0000 Subject: Add libjpeg-turbo backend --- .travis.yml | 1 + Makefile | 5 ++ config.mk | 6 ++ src/backend_libjpeg.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/backend_libjpeg.h | 9 +++ src/main.c | 5 ++ 6 files changed, 207 insertions(+) create mode 100644 src/backend_libjpeg.c create mode 100644 src/backend_libjpeg.h diff --git a/.travis.yml b/.travis.yml index 219e882..ffbf7e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,7 @@ addons: apt: packages: - libfreeimage-dev + - libjpeg-turbo8-dev - libpng-dev - librsvg2-dev - libsdl2-ttf-dev diff --git a/Makefile b/Makefile index fa4dcbc..18d07dd 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,11 @@ ifeq ($(BACKEND_LIBPNG),yes) override LIBS += -lpng endif +ifeq ($(BACKEND_LIBJPEG),yes) + override CPPFLAGS += -DIMV_BACKEND_LIBJPEG + override LIBS += -lturbojpeg +endif + ifeq ($(BACKEND_LIBRSVG),yes) override CPPFLAGS += -DIMV_BACKEND_LIBRSVG $(shell pkg-config --cflags librsvg-2.0) override LIBS += $(shell pkg-config --libs librsvg-2.0) diff --git a/config.mk b/config.mk index e2fa1bf..1dc4065 100644 --- a/config.mk +++ b/config.mk @@ -12,6 +12,12 @@ BACKEND_FREEIMAGE=yes # license: libpng license BACKEND_LIBPNG=no +# libjpeg-turbo https://libjpeg-turbo.org/ +# provides: jpeg +# depends: none +# license: modified bsd +BACKEND_LIBJPEG=no + # librsvg https://wiki.gnome.org/Projects/LibRsvg # provides: svg # depends: gdk-pixbuf2 pango libcroco diff --git a/src/backend_libjpeg.c b/src/backend_libjpeg.c new file mode 100644 index 0000000..acbd6b3 --- /dev/null +++ b/src/backend_libjpeg.c @@ -0,0 +1,181 @@ +#include "backend_libjpeg.h" +#include "backend.h" +#include "source.h" +#include +#include +#include +#include +#include +#include + +#ifdef IMV_BACKEND_LIBJPEG + +#include + +struct private { + int fd; + void *data; + size_t len; + tjhandle jpeg; +}; + +static void source_free(struct imv_source *src) +{ + free(src->name); + src->name = NULL; + + struct private *private = src->private; + tjDestroy(private->jpeg); + munmap(private->data, private->len); + private->data = NULL; + close(private->fd); + + free(src->private); + src->private = NULL; + + free(src); +} + +static struct imv_bitmap *to_imv_bitmap(int width, int height, void *bitmap) +{ + struct imv_bitmap *bmp = malloc(sizeof(struct imv_bitmap)); + bmp->width = width; + bmp->height = height; + bmp->format = IMV_ABGR; + bmp->data = bitmap; + return bmp; +} + +static void report_error(struct imv_source *src) +{ + if (!src->callback) { + fprintf(stderr, "imv_source(%s) has no callback configured. " + "Discarding error.\n", src->name); + return; + } + + struct imv_source_message msg; + msg.source = src; + msg.user_data = src->user_data; + msg.bitmap = NULL; + msg.error = "Internal error"; + + src->callback(&msg); +} + +static void send_bitmap(struct imv_source *src, void *bitmap) +{ + if (!src->callback) { + fprintf(stderr, "imv_source(%s) has no callback configured. " + "Discarding result.\n", src->name); + return; + } + + struct imv_source_message msg; + msg.source = src; + msg.user_data = src->user_data; + msg.bitmap = to_imv_bitmap(src->width, src->height, bitmap); + msg.frametime = 0; + msg.error = NULL; + + src->callback(&msg); +} + +static void load_image(struct imv_source *src) +{ + struct private *private = src->private; + + void *bitmap = malloc(src->height * src->width * 4); + int rcode = tjDecompress2(private->jpeg, private->data, private->len, + bitmap, src->width, 0, src->height, TJPF_RGBA, TJFLAG_FASTDCT); + + if (!rcode) { + send_bitmap(src, bitmap); + } else { + free(bitmap); + report_error(src); + return; + } +} + +static enum backend_result open_path(const char *path, struct imv_source **src) +{ + struct private private; + + private.fd = open(path, O_RDONLY); + if (private.fd < 0) { + return BACKEND_BAD_PATH; + } + + off_t len = lseek(private.fd, 0, SEEK_END); + if (len < 0) { + close(private.fd); + return BACKEND_BAD_PATH; + } + + private.len = len; + + private.data = mmap(NULL, private.len, PROT_READ, MAP_PRIVATE, private.fd, 0); + if (!private.data) { + close(private.fd); + return BACKEND_BAD_PATH; + } + + private.jpeg = tjInitDecompress(); + if (!private.jpeg) { + munmap(private.data, private.len); + close(private.fd); + return BACKEND_UNSUPPORTED; + } + + int width, height; + int rcode = tjDecompressHeader(private.jpeg, private.data, private.len, + &width, &height); + if (rcode) { + tjDestroy(private.jpeg); + munmap(private.data, private.len); + close(private.fd); + return BACKEND_UNSUPPORTED; + } + + struct imv_source *source = calloc(1, sizeof(struct imv_source)); + source->name = strdup(path); + source->width = width; + source->height = height; + source->num_frames = 1; + source->next_frame = 1; + source->load_first_frame = &load_image; + source->load_next_frame = NULL; + source->free = &source_free; + source->callback = NULL; + source->user_data = NULL; + source->private = malloc(sizeof private); + memcpy(source->private, &private, sizeof private); + + *src = source; + return BACKEND_SUCCESS; +} + +const struct imv_backend libjpeg_backend = { + .name = "libjpeg-turbo", + .description = "Fast JPEG codec based on libjpeg. " + "This software is based in part on the work " + "of the Independent JPEG Group.", + .website = "https://libjpeg-turbo.org/", + .license = "The Modified BSD License", + .open_path = &open_path, +}; + +const struct imv_backend *imv_backend_libjpeg(void) +{ + return &libjpeg_backend; +} + +#else + +const struct imv_backend *imv_backend_libjpeg(void) +{ + return NULL; +} + +#endif diff --git a/src/backend_libjpeg.h b/src/backend_libjpeg.h new file mode 100644 index 0000000..cc9664a --- /dev/null +++ b/src/backend_libjpeg.h @@ -0,0 +1,9 @@ +#ifndef IMV_BACKEND_LIBJPEG_H +#define IMV_BACKEND_LIBJPEG_H + +struct imv_backend; + +/* Get an instance of the libjpeg backend */ +const struct imv_backend *imv_backend_libjpeg(void); + +#endif diff --git a/src/main.c b/src/main.c index 06baced..7f5b7c0 100644 --- a/src/main.c +++ b/src/main.c @@ -4,6 +4,7 @@ #include "backend_freeimage.h" #include "backend_libpng.h" +#include "backend_libjpeg.h" #include "backend_librsvg.h" int main(int argc, char** argv) @@ -22,6 +23,10 @@ int main(int argc, char** argv) imv_install_backend(imv, imv_backend_libpng()); #endif +#ifdef IMV_BACKEND_LIBJPEG + imv_install_backend(imv, imv_backend_libjpeg()); +#endif + #ifdef IMV_BACKEND_LIBRSVG imv_install_backend(imv, imv_backend_librsvg()); #endif -- cgit v1.2.3