diff --git a/src/document/html/parser/link.c b/src/document/html/parser/link.c index 41b98b4f3..73520a475 100644 --- a/src/document/html/parser/link.c +++ b/src/document/html/parser/link.c @@ -40,6 +40,7 @@ #include "globhist/globhist.h" #include "mime/mime.h" #include "protocol/uri.h" +#include "terminal/image.h" #ifdef CONFIG_KITTY #include "terminal/kitty.h" #endif diff --git a/src/terminal/Makefile b/src/terminal/Makefile index 317c32172..2b57c99f6 100644 --- a/src/terminal/Makefile +++ b/src/terminal/Makefile @@ -11,6 +11,7 @@ OBJS = \ draw.o \ event.o \ hardio.o \ + image.o \ kbd.o \ screen.o \ tab.o \ diff --git a/src/terminal/image.c b/src/terminal/image.c new file mode 100644 index 000000000..bfc39f740 --- /dev/null +++ b/src/terminal/image.c @@ -0,0 +1,123 @@ +/* Terminal kitty and sixel routines. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#ifdef CONFIG_GZIP +#include +#endif + +#ifdef CONFIG_LIBSIXEL +#include +#endif + +#include "elinks.h" + +#include "terminal/image.h" +#include "util/base64.h" +#include "util/memory.h" +#include "util/string.h" + +#if defined(CONFIG_KITTY) || defined(CONFIG_SIXEL) +#define STB_IMAGE_IMPLEMENTATION +#include "terminal/stb_image.h" +#endif + +#ifdef CONFIG_KITTY +unsigned char * +el_kitty_get_image(char *data, int length, int *outlen, int *width, int *height, int *compressed) +{ + ELOG + int comp; + unsigned char *pixels = stbi_load_from_memory((unsigned char *)data, length, width, height, &comp, KITTY_BYTES_PER_PIXEL); + unsigned char *b64; + + if (!pixels) { + return NULL; + } + int size = *width * *height * KITTY_BYTES_PER_PIXEL; + *compressed = 0; + +#ifdef CONFIG_GZIP + unsigned char *complace = (unsigned char *)mem_alloc(size); + + if (complace) { + unsigned long compsize = size; + int res = compress(complace, &compsize, pixels, size); + + if (res == Z_OK) { + *compressed = 1; + b64 = base64_encode_bin(complace, compsize, outlen); + stbi_image_free(pixels); + mem_free(complace); + return b64; + } + mem_free(complace); + } +#endif + b64 = base64_encode_bin(pixels, size, outlen); + stbi_image_free(pixels); + + return b64; +} +#endif + +#ifdef CONFIG_LIBSIXEL +static int +sixel_write_callback(char *data, int size, void *priv) +{ + ELOG + struct string *text = priv; + + add_bytes_to_string(text, data, size); + return size; +} + +unsigned char * +el_sixel_get_image(char *data, int length, int *outlen) +{ + ELOG + int comp; + int width; + int height; + unsigned char *outdata = NULL; + unsigned char *pixels = stbi_load_from_memory((unsigned char *)data, length, &width, &height, &comp, 3); + + if (!pixels) { + return NULL; + } + sixel_output_t *output = NULL; + sixel_dither_t *dither = NULL; + + struct string ret; + + if (!init_string(&ret)) { + goto end; + } + SIXELSTATUS status = sixel_output_new(&output, sixel_write_callback, &ret, NULL); + + if (SIXEL_FAILED(status)) { + goto end; + } + dither = sixel_dither_get(SIXEL_BUILTIN_XTERM256); + sixel_dither_set_pixelformat(dither, SIXEL_PIXELFORMAT_RGB888); + status = sixel_encode(pixels, width, height, 3, dither, output); + outdata = (unsigned char *)memacpy(ret.source, ret.length); + + if (outdata) { + *outlen = ret.length; + } + done_string(&ret); +end: + stbi_image_free(pixels); + + return outdata; +} +#endif diff --git a/src/terminal/image.h b/src/terminal/image.h new file mode 100644 index 000000000..192060b54 --- /dev/null +++ b/src/terminal/image.h @@ -0,0 +1,20 @@ +#ifndef EL__TERMINAL_IMAGE_H +#define EL__TERMINAL_IMAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_KITTY +unsigned char *el_kitty_get_image(char *data, int len, int *outlen, int *width, int *height, int *compressed); +#endif + +#ifdef CONFIG_LIBSIXEL +unsigned char *el_sixel_get_image(char *data, int len, int *outlen); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EL__TERMINAL_IMAGE_H */ diff --git a/src/terminal/kitty.c b/src/terminal/kitty.c index a57b69976..58c379426 100644 --- a/src/terminal/kitty.c +++ b/src/terminal/kitty.c @@ -10,10 +10,6 @@ #include #include -#ifdef CONFIG_GZIP -#include -#endif - #include "elinks.h" #include "document/document.h" @@ -26,46 +22,6 @@ #include "util/base64.h" #include "util/memory.h" -#define STB_IMAGE_IMPLEMENTATION -#include "terminal/stb_image.h" - -unsigned char * -el_kitty_get_image(char *data, int length, int *outlen, int *width, int *height, int *compressed) -{ - ELOG - int comp; - unsigned char *pixels = stbi_load_from_memory((unsigned char *)data, length, width, height, &comp, KITTY_BYTES_PER_PIXEL); - unsigned char *b64; - - if (!pixels) { - return NULL; - } - int size = *width * *height * KITTY_BYTES_PER_PIXEL; - *compressed = 0; - -#ifdef CONFIG_GZIP - unsigned char *complace = (unsigned char *)mem_alloc(size); - - if (complace) { - unsigned long compsize = size; - int res = compress(complace, &compsize, pixels, size); - - if (res == Z_OK) { - *compressed = 1; - b64 = base64_encode_bin(complace, compsize, outlen); - stbi_image_free(pixels); - mem_free(complace); - return b64; - } - mem_free(complace); - } -#endif - b64 = base64_encode_bin(pixels, size, outlen); - stbi_image_free(pixels); - - return b64; -} - int add_kitty_image_to_document(struct document *doc, char *data, int datalen, int lineno, struct k_image **imagine, int width, int height) { diff --git a/src/terminal/meson.build b/src/terminal/meson.build index 08c5a075c..586ef9962 100644 --- a/src/terminal/meson.build +++ b/src/terminal/meson.build @@ -10,4 +10,4 @@ endif if conf_data.get('CONFIG_TERMINFO') srcs += files('terminfo.c') endif -srcs += files('color.c', 'draw.c', 'event.c', 'hardio.c', 'kbd.c', 'screen.c', 'tab.c', 'terminal.c', 'window.c') +srcs += files('color.c', 'draw.c', 'event.c', 'hardio.c', 'image.c', 'kbd.c', 'screen.c', 'tab.c', 'terminal.c', 'window.c') diff --git a/src/terminal/sixel.c b/src/terminal/sixel.c index 4fc15c95b..b5b566d3d 100644 --- a/src/terminal/sixel.c +++ b/src/terminal/sixel.c @@ -27,11 +27,6 @@ #include "config.h" #endif -#ifdef HAVE_MEMFD_CREATE -#define _GNU_SOURCE /* See feature_test_macros(7) */ -#include -#endif - #include #include #include @@ -1055,76 +1050,3 @@ end: return dest; } - -unsigned char * -el_sixel_get_image(char *data, int length, int *outlen) -{ - ELOG - SIXELSTATUS status = SIXEL_FALSE; - sixel_encoder_t *encoder = NULL; - unsigned char *ret = NULL; - *outlen = 0; - -#ifdef HAVE_MEMFD_CREATE -#ifdef CONFIG_MEMCOUNT - init_allocator(); - status = sixel_encoder_new(&encoder, el_sixel_allocator); -#else - status = sixel_encoder_new(&encoder, NULL); -#endif - - if (SIXEL_FAILED(status)) { - goto error; - } - int fdout = -1; - - encoder->outfd = memfd_create("out.sixel", 0); - fdout = dup(encoder->outfd); - encoder->fstatic = 1; - - int fdin = memfd_create("input.sixel", 0); - FILE *f = fdopen(fdin, "wb"); - - if (!f) { - goto error; - } - fwrite(data, 1, length, f); - rewind(f); - - struct string name; - if (!init_string(&name)) { - goto error; - } - add_format_to_string(&name, "/proc/self/fd/%d", fdin); - status = sixel_encoder_encode(encoder, name.source); - done_string(&name); - - if (SIXEL_FAILED(status)) { - goto error; - } - - struct stat sb; - fstat(fdout, &sb); - - if (sb.st_size > 0) { - ret = (unsigned char *)mem_alloc(sb.st_size); - - if (ret) { - FILE *f2 = fdopen(fdout, "rb"); - if (f2) { - rewind(f2); - *outlen = (int)fread(ret, 1, (size_t)sb.st_size, f2); - fclose(f2); - } - } - } - close(fdout); - -error: - if (f) { - fclose(f); - } - sixel_encoder_unref(encoder); -#endif - return ret; -} diff --git a/src/terminal/sixel.h b/src/terminal/sixel.h index 74e03f7c3..6099f5ef6 100644 --- a/src/terminal/sixel.h +++ b/src/terminal/sixel.h @@ -34,8 +34,6 @@ int add_image_to_document(struct document *doc, struct string *pixels, int linen struct image *copy_frame(struct image *src, struct el_box *box, int cell_width, int cell_height, int dx, int dy); -unsigned char *el_sixel_get_image(char *data, int len, int *outlen); - #endif #ifdef __cplusplus