mirror of
https://github.com/rkd77/elinks.git
synced 2025-06-30 22:19:29 -04:00
[image] Added more portable code for encoding sixel image
This commit is contained in:
parent
70189a892a
commit
9de22e9085
@ -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
|
||||
|
@ -11,6 +11,7 @@ OBJS = \
|
||||
draw.o \
|
||||
event.o \
|
||||
hardio.o \
|
||||
image.o \
|
||||
kbd.o \
|
||||
screen.o \
|
||||
tab.o \
|
||||
|
123
src/terminal/image.c
Normal file
123
src/terminal/image.c
Normal file
@ -0,0 +1,123 @@
|
||||
/* Terminal kitty and sixel routines. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef CONFIG_GZIP
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIBSIXEL
|
||||
#include <sixel.h>
|
||||
#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
|
20
src/terminal/image.h
Normal file
20
src/terminal/image.h
Normal file
@ -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 */
|
@ -10,10 +10,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef CONFIG_GZIP
|
||||
#include <zlib.h>
|
||||
#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)
|
||||
{
|
||||
|
@ -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')
|
||||
|
@ -27,11 +27,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MEMFD_CREATE
|
||||
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user