Skip to content
Snippets Groups Projects
Commit b540cd3e authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

Add support for runtime-linking libjxl

This also supports static linking for OSs that don't have sane ways
of sharing libraries system-wide.
parent af5ec10b
No related branches found
No related tags found
No related merge requests found
Pipeline #7450 passed
......@@ -59,6 +59,12 @@ if(NOT WITHOUT_OOII)
list(APPEND SOURCE ooii.c ooii_bmenus.c ooii_cmenus.c ooii_logons.c ooii_sounds.c)
endif()
if(NOT WITHOUT_JPEG_XL)
if (JPEG_XL_FOUND)
list(APPEND SOURCE libjxl.c)
endif()
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
list(APPEND SOURCE DarwinWrappers.m)
find_library(FOUNDATION_LIBRARY Foundation)
......
#include "libjxl.h"
#include "xp_dl.h"
#ifdef WITH_JPEG_XL
struct jxlfuncs Jxl;
#ifdef WITH_STATIC_JXL
bool load_jxl_funcs(void)
{
Jxl.ColorEncodingSetToSRGB = JxlColorEncodingSetToSRGB;
Jxl.DecoderCloseInput = JxlDecoderCloseInput;
Jxl.DecoderCreate = JxlDecoderCreate;
Jxl.DecoderDestroy = JxlDecoderDestroy;
Jxl.DecoderGetBasicInfo = JxlDecoderGetBasicInfo;
Jxl.DecoderImageOutBufferSize = JxlDecoderImageOutBufferSize;
Jxl.DecoderProcessInput = JxlDecoderProcessInput;
Jxl.DecoderReleaseInput = JxlDecoderReleaseInput;
Jxl.DecoderSetImageOutBuffer = JxlDecoderSetImageOutBuffer;
Jxl.DecoderSetInput = JxlDecoderSetInput;
#ifdef WITH_JPEG_XL_THREADS
Jxl.DecoderSetParallelRunner = JxlDecoderSetParallelRunner;
#endif
Jxl.DecoderSetPreferredColorProfile = JxlDecoderSetPreferredColorProfile;
Jxl.DecoderSubscribeEvents = JxlDecoderSubscribeEvents;
#ifdef WITH_JPEG_XL_THREADS
Jxl.ResizableParallelRunner = JxlResizableParallelRunner;
Jxl.ResizableParallelRunnerCreate = JxlResizableParallelRunnerCreate;
Jxl.ResizableParallelRunnerDestroy = JxlResizableParallelRunnerDestroy;
Jxl.ResizableParallelRunnerSetThreads = JxlResizableParallelRunnerSetThreads;
Jxl.ResizableParallelRunnerSuggestThreads = JxlResizableParallelRunnerSuggestThreads;
#endif
if (Jxl.DecoderSetParallelRunner == NULL ||
Jxl.ResizableParallelRunner == NULL ||
Jxl.ResizableParallelRunnerCreate == NULL ||
Jxl.ResizableParallelRunnerDestroy == NULL ||
Jxl.ResizableParallelRunnerSetThreads == NULL ||
Jxl.ResizableParallelRunnerSuggestThreads == NULL)
Jxl.status = JXL_STATUS_NOTHREADS;
else
Jxl.status = JXL_STATUS_OK;
return true;
}
#else
bool load_jxl_funcs(void)
{
dll_handle jxl_dll;
const char *libnames[] = {"jxl", NULL};
if (Jxl.status == JXL_STATUS_OK)
return true;
if (Jxl.status == JXL_STATUS_NOTHREADS)
return true;
if (Jxl.status == JXL_STATUS_FAILED)
return false;
Jxl.status = JXL_STATUS_FAILED;
if ((jxl_dll = xp_dlopen(libnames, RTLD_LAZY | RTLD_GLOBAL, JPEGXL_MAJOR_VERSION)) == NULL)
return false;
if ((Jxl.ColorEncodingSetToSRGB = xp_dlsym(jxl_dll, JxlColorEncodingSetToSRGB)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
if ((Jxl.DecoderCloseInput = xp_dlsym(jxl_dll, JxlDecoderCloseInput)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
if ((Jxl.DecoderCreate = xp_dlsym(jxl_dll, JxlDecoderCreate)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
if ((Jxl.DecoderDestroy = xp_dlsym(jxl_dll, JxlDecoderDestroy)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
if ((Jxl.DecoderGetBasicInfo = xp_dlsym(jxl_dll, JxlDecoderGetBasicInfo)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
if ((Jxl.DecoderImageOutBufferSize = xp_dlsym(jxl_dll, JxlDecoderImageOutBufferSize)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
if ((Jxl.DecoderProcessInput = xp_dlsym(jxl_dll, JxlDecoderProcessInput)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
if ((Jxl.DecoderReleaseInput = xp_dlsym(jxl_dll, JxlDecoderReleaseInput)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
if ((Jxl.DecoderSetImageOutBuffer = xp_dlsym(jxl_dll, JxlDecoderSetImageOutBuffer)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
if ((Jxl.DecoderSetInput = xp_dlsym(jxl_dll, JxlDecoderSetInput)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
#ifdef WITH_JPEG_XL_THREADS
if ((Jxl.DecoderSetParallelRunner = xp_dlsym(jxl_dll, JxlDecoderSetParallelRunner)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
#endif
if ((Jxl.DecoderSetPreferredColorProfile = xp_dlsym(jxl_dll, JxlDecoderSetPreferredColorProfile)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
if ((Jxl.DecoderSubscribeEvents = xp_dlsym(jxl_dll, JxlDecoderSubscribeEvents)) == NULL) {
xp_dlclose(jxl_dll);
return false;
}
Jxl.status = JXL_STATUS_NOTHREADS;
#ifdef WITH_JPEG_XL_THREADS
dll_handle jxlt_dll;
const char *tlibnames[] = {"jxl_threads", NULL};
Jxl.status = JXL_STATUS_FAILED;
if ((jxlt_dll = xp_dlopen(tlibnames, RTLD_LAZY | RTLD_GLOBAL, JPEGXL_MAJOR_VERSION)) == NULL)
return true;
if ((Jxl.ResizableParallelRunner = xp_dlsym(jxlt_dll, JxlResizableParallelRunner)) == NULL) {
xp_dlclose(jxl_dll);
return true;
}
if ((Jxl.ResizableParallelRunnerCreate = xp_dlsym(jxlt_dll, JxlResizableParallelRunnerCreate)) == NULL) {
xp_dlclose(jxl_dll);
return true;
}
if ((Jxl.ResizableParallelRunnerDestroy = xp_dlsym(jxlt_dll, JxlResizableParallelRunnerDestroy)) == NULL) {
xp_dlclose(jxl_dll);
return true;
}
if ((Jxl.ResizableParallelRunnerSetThreads = xp_dlsym(jxlt_dll, JxlResizableParallelRunnerSetThreads)) == NULL) {
xp_dlclose(jxl_dll);
return true;
}
if ((Jxl.ResizableParallelRunnerSuggestThreads = xp_dlsym(jxlt_dll, JxlResizableParallelRunnerSuggestThreads)) == NULL) {
xp_dlclose(jxl_dll);
return true;
}
Jxl.status = JXL_STATUS_OK;
#endif
return true;
}
#endif
#endif
#ifndef JXLFUNCS_H
#define JXLFUNCS_H
#ifdef WITH_JPEG_XL
#include <stdbool.h>
#include <jxl/decode.h>
#include <jxl/encode.h>
#ifdef WITH_JPEG_XL_THREADS
#include <jxl/resizable_parallel_runner.h>
#endif
enum JxlStatus {
JXL_STATUS_UNINITIALIZED,
JXL_STATUS_FAILED,
JXL_STATUS_NOTHREADS,
JXL_STATUS_OK
};
struct jxlfuncs {
void (*ColorEncodingSetToSRGB)(JxlColorEncoding*, JXL_BOOL);
void (*DecoderCloseInput)(JxlDecoder*);
JxlDecoder *(*DecoderCreate)(const JxlMemoryManager*);
void (*DecoderDestroy)(JxlDecoder*);
JxlDecoderStatus (*DecoderGetBasicInfo)(const JxlDecoder*, JxlBasicInfo* info);
JxlDecoderStatus (*DecoderImageOutBufferSize)(const JxlDecoder*, const JxlPixelFormat*, size_t*);
JxlDecoderStatus (*DecoderProcessInput)(JxlDecoder*);
size_t (*DecoderReleaseInput)(JxlDecoder*);
JxlDecoderStatus (*DecoderSetImageOutBuffer)(JxlDecoder*, const JxlPixelFormat*, void*, size_t);
JxlDecoderStatus (*DecoderSetInput)(JxlDecoder*, const uint8_t*, size_t);
JxlDecoderStatus (*DecoderSetParallelRunner)(JxlDecoder*, JxlParallelRunner, void*);
JxlDecoderStatus (*DecoderSetPreferredColorProfile)(JxlDecoder*, const JxlColorEncoding*);
JxlDecoderStatus (*DecoderSubscribeEvents)(JxlDecoder*, int);
JxlParallelRetCode (*ResizableParallelRunner)(void*, void*, JxlParallelRunInit, JxlParallelRunFunction, uint32_t, uint32_t);
void *(*ResizableParallelRunnerCreate)(const JxlMemoryManager*);
void (*ResizableParallelRunnerDestroy)(void*);
void (*ResizableParallelRunnerSetThreads)(void*, size_t);
uint32_t (*ResizableParallelRunnerSuggestThreads)(uint64_t, uint64_t);
int status;
};
extern struct jxlfuncs Jxl;
bool load_jxl_funcs(void);
#endif
#endif
......@@ -44,11 +44,7 @@
#include "ripper.h"
#ifdef WITH_JPEG_XL
#include <jxl/decode.h>
#include <jxl/encode.h>
#ifdef WITH_JPEG_XL_THREADS
#include <jxl/resizable_parallel_runner.h>
#endif
#include "libjxl.h"
#include "xpmap.h"
#endif
......@@ -95,7 +91,8 @@ static uint8_t pnm_gamma[256] = {
248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254,
254, 255, 255
};
uint8_t pnm_gamma_max = 255;
static uint8_t pnm_gamma_max = 255;
static bool jxl_support = false;
void
get_cterm_size(int *cols, int *rows, int ns)
......@@ -3109,58 +3106,62 @@ read_jxl(const char *fn)
.endianness = JXL_NATIVE_ENDIAN,
.align = 1
};
JxlColorEncodingSetToSRGB(&ce, JXL_FALSE);
JxlDecoder *dec = JxlDecoderCreate(NULL);
Jxl.ColorEncodingSetToSRGB(&ce, JXL_FALSE);
JxlDecoder *dec = Jxl.DecoderCreate(NULL);
if (dec == NULL) {
xpunmap(map);
return NULL;
}
#ifdef WITH_JPEG_XL_THREADS
void *rpr = JxlResizableParallelRunnerCreate(NULL);
void *rpr = NULL;
if (Jxl.status == JXL_STATUS_OK) {
rpr = Jxl.ResizableParallelRunnerCreate(NULL);
if (rpr) {
if (JxlDecoderSetParallelRunner(dec, JxlResizableParallelRunner, rpr) != JXL_DEC_SUCCESS) {
JxlResizableParallelRunnerDestroy(rpr);
if (Jxl.DecoderSetParallelRunner(dec, Jxl.ResizableParallelRunner, rpr) != JXL_DEC_SUCCESS) {
Jxl.ResizableParallelRunnerDestroy(rpr);
rpr = NULL;
}
}
}
#endif
if (JxlDecoderSetInput(dec, map->addr, map->size) != JXL_DEC_SUCCESS) {
if (Jxl.DecoderSetInput(dec, map->addr, map->size) != JXL_DEC_SUCCESS) {
xpunmap(map);
JxlDecoderDestroy(dec);
Jxl.DecoderDestroy(dec);
return NULL;
}
JxlDecoderCloseInput(dec);
if (JxlDecoderSubscribeEvents(dec, JXL_DEC_BASIC_INFO | JXL_DEC_COLOR_ENCODING | JXL_DEC_FULL_IMAGE) != JXL_DEC_SUCCESS) {
Jxl.DecoderCloseInput(dec);
if (Jxl.DecoderSubscribeEvents(dec, JXL_DEC_BASIC_INFO | JXL_DEC_COLOR_ENCODING | JXL_DEC_FULL_IMAGE) != JXL_DEC_SUCCESS) {
xpunmap(map);
JxlDecoderDestroy(dec);
Jxl.DecoderDestroy(dec);
return NULL;
}
for (bool done = false; !done;) {
st = JxlDecoderProcessInput(dec);
st = Jxl.DecoderProcessInput(dec);
switch(st) {
case JXL_DEC_ERROR:
done = true;
break;
case JXL_DEC_BASIC_INFO:
if (JxlDecoderGetBasicInfo(dec, &info) != JXL_DEC_SUCCESS) {
if (Jxl.DecoderGetBasicInfo(dec, &info) != JXL_DEC_SUCCESS) {
done = true;
break;
}
width = info.xsize;
height = info.ysize;
#ifdef WITH_JPEG_XL_THREADS
JxlResizableParallelRunnerSetThreads(rpr, JxlResizableParallelRunnerSuggestThreads(info.xsize, info.ysize));
if (Jxl.status == JXL_STATUS_OK)
Jxl.ResizableParallelRunnerSetThreads(rpr, Jxl.ResizableParallelRunnerSuggestThreads(info.xsize, info.ysize));
#endif
break;
case JXL_DEC_COLOR_ENCODING:
// TODO...
if (JxlDecoderSetPreferredColorProfile(dec, &ce) != JXL_DEC_SUCCESS) {
if (Jxl.DecoderSetPreferredColorProfile(dec, &ce) != JXL_DEC_SUCCESS) {
done = true;
break;
}
break;
case JXL_DEC_NEED_IMAGE_OUT_BUFFER:
if (JxlDecoderImageOutBufferSize(dec, &format, &sz) != JXL_DEC_SUCCESS) {
if (Jxl.DecoderImageOutBufferSize(dec, &format, &sz) != JXL_DEC_SUCCESS) {
done = true;
break;
}
......@@ -3174,7 +3175,7 @@ read_jxl(const char *fn)
done = true;
break;
}
JxlDecoderSetImageOutBuffer(dec, &format, pbuf, sz);
Jxl.DecoderSetImageOutBuffer(dec, &format, pbuf, sz);
break;
case JXL_DEC_FULL_IMAGE:
// Got a single frame... this is not necessarily the whole image though.
......@@ -3204,11 +3205,11 @@ read_jxl(const char *fn)
free(pbuf);
#ifdef WITH_JPEG_XL_THREADS
if (rpr)
JxlResizableParallelRunnerDestroy(rpr);
Jxl.ResizableParallelRunnerDestroy(rpr);
#endif
JxlDecoderReleaseInput(dec);
Jxl.DecoderReleaseInput(dec);
xpunmap(map);
JxlDecoderDestroy(dec);
Jxl.DecoderDestroy(dec);
return pret;
}
......@@ -4150,6 +4151,9 @@ doterm(struct bbslist *bbs)
#ifndef WITHOUT_OOII
ooii_buf[0] = 0;
#endif
#ifdef WITH_JPEG_XL
jxl_support = load_jxl_funcs();
#endif
/* Main input loop */
oldmc = hold_update;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment