forked from old/legacy-imlib2
parent
9468f7132c
commit
a55f36133d
|
@ -65,6 +65,18 @@ typedef struct _ImlibImage ImlibImage;
|
|||
#define PIXEL_G(argb) (((argb) >> 8) & 0xff)
|
||||
#define PIXEL_B(argb) (((argb) ) & 0xff)
|
||||
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
#define A_VAL(p) ((uint8_t *)(p))[3]
|
||||
#define R_VAL(p) ((uint8_t *)(p))[2]
|
||||
#define G_VAL(p) ((uint8_t *)(p))[1]
|
||||
#define B_VAL(p) ((uint8_t *)(p))[0]
|
||||
#else
|
||||
#define A_VAL(p) ((uint8_t *)(p))[0]
|
||||
#define R_VAL(p) ((uint8_t *)(p))[1]
|
||||
#define G_VAL(p) ((uint8_t *)(p))[2]
|
||||
#define B_VAL(p) ((uint8_t *)(p))[3]
|
||||
#endif
|
||||
|
||||
/* debug.h */
|
||||
|
||||
#if IMLIB2_DEBUG
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#define MAX_RUNNERS 4 /* Maybe set to Ncpu/2? */
|
||||
|
||||
#include <jxl/decode.h>
|
||||
#include <jxl/encode.h>
|
||||
#if MAX_RUNNERS > 0
|
||||
#include <jxl/thread_parallel_runner.h>
|
||||
#endif
|
||||
|
@ -215,4 +216,181 @@ _load(ImlibImage * im, int load_data)
|
|||
return rc;
|
||||
}
|
||||
|
||||
IMLIB_LOADER(_formats, _load, NULL);
|
||||
static int
|
||||
_save(ImlibImage * im)
|
||||
{
|
||||
int rc;
|
||||
JxlEncoderStatus jst;
|
||||
JxlEncoder *enc;
|
||||
JxlBasicInfo info;
|
||||
JxlEncoderFrameSettings *opts;
|
||||
|
||||
JxlPixelFormat pbuf_fmt = {
|
||||
.data_type = JXL_TYPE_UINT8,
|
||||
.endianness = JXL_NATIVE_ENDIAN,
|
||||
};
|
||||
ImlibImageTag *tag;
|
||||
const uint32_t *ptr;
|
||||
uint8_t *buffer = NULL, *buf_ptr;
|
||||
size_t buf_len, i, npix;
|
||||
|
||||
#if MAX_RUNNERS > 0
|
||||
size_t n_runners;
|
||||
JxlParallelRunner *runner = NULL;
|
||||
#endif
|
||||
|
||||
rc = LOAD_FAIL;
|
||||
|
||||
enc = JxlEncoderCreate(NULL);
|
||||
if (!enc)
|
||||
goto quit;
|
||||
|
||||
#if MAX_RUNNERS > 0
|
||||
n_runners = JxlThreadParallelRunnerDefaultNumWorkerThreads();
|
||||
if (n_runners > MAX_RUNNERS)
|
||||
n_runners = MAX_RUNNERS;
|
||||
D("n_runners = %ld\n", n_runners);
|
||||
runner = JxlThreadParallelRunnerCreate(NULL, n_runners);
|
||||
if (!runner)
|
||||
goto quit;
|
||||
|
||||
jst = JxlEncoderSetParallelRunner(enc, JxlThreadParallelRunner, runner);
|
||||
if (jst != JXL_ENC_SUCCESS)
|
||||
goto quit;
|
||||
#endif /* MAX_RUNNERS */
|
||||
|
||||
JxlEncoderInitBasicInfo(&info);
|
||||
info.xsize = im->w;
|
||||
info.ysize = im->h;
|
||||
if (im->has_alpha)
|
||||
{
|
||||
info.alpha_bits = 8;
|
||||
info.num_extra_channels = 1;
|
||||
}
|
||||
|
||||
jst = JxlEncoderSetBasicInfo(enc, &info);
|
||||
if (jst != JXL_ENC_SUCCESS)
|
||||
goto quit;
|
||||
|
||||
opts = JxlEncoderFrameSettingsCreate(enc, NULL);
|
||||
if (!opts)
|
||||
goto quit;
|
||||
|
||||
tag = __imlib_GetTag(im, "quality");
|
||||
if (tag)
|
||||
{
|
||||
int quality;
|
||||
float distance;
|
||||
|
||||
quality = (tag->val) >= 0 ? tag->val : 0;
|
||||
if (quality >= 100)
|
||||
{
|
||||
D("Quality=%d: Lossless\n", quality);
|
||||
JxlEncoderSetFrameDistance(opts, 0.f);
|
||||
JxlEncoderSetFrameLossless(opts, JXL_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = 15.f * (1.f - .01 * quality); // 0 - 100 -> 15 - 0
|
||||
D("Quality=%d: Distance=%.1f\n", quality, distance);
|
||||
JxlEncoderSetFrameLossless(opts, JXL_FALSE);
|
||||
JxlEncoderSetFrameDistance(opts, distance);
|
||||
}
|
||||
}
|
||||
|
||||
tag = __imlib_GetTag(im, "compression");
|
||||
if (tag)
|
||||
{
|
||||
int compression;
|
||||
|
||||
compression = (tag->val < 1) ? 1 : (tag->val > 9) ? 9 : tag->val;
|
||||
D("Compression=%d\n", compression);
|
||||
JxlEncoderFrameSettingsSetOption(opts, JXL_ENC_FRAME_SETTING_EFFORT,
|
||||
compression);
|
||||
}
|
||||
|
||||
// Create buffer for format conversion and output
|
||||
pbuf_fmt.num_channels = (im->has_alpha) ? 4 : 3;
|
||||
npix = im->w * im->h;
|
||||
buf_len = pbuf_fmt.num_channels * npix;
|
||||
if (buf_len < 4096)
|
||||
buf_len = 4096; // Not too small for output
|
||||
|
||||
buffer = malloc(buf_len);
|
||||
if (!buffer)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
||||
// Convert format for libjxl
|
||||
ptr = im->data;
|
||||
buf_ptr = buffer;
|
||||
if (pbuf_fmt.num_channels == 3)
|
||||
{
|
||||
for (i = 0; i < npix; i++, ptr++, buf_ptr += 3)
|
||||
{
|
||||
buf_ptr[0] = R_VAL(ptr);
|
||||
buf_ptr[1] = G_VAL(ptr);
|
||||
buf_ptr[2] = B_VAL(ptr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < npix; i++, ptr++, buf_ptr += 4)
|
||||
{
|
||||
buf_ptr[0] = R_VAL(ptr);
|
||||
buf_ptr[1] = G_VAL(ptr);
|
||||
buf_ptr[2] = B_VAL(ptr);
|
||||
buf_ptr[3] = A_VAL(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
jst = JxlEncoderAddImageFrame(opts, &pbuf_fmt, buffer, buf_len);
|
||||
if (jst != JXL_ENC_SUCCESS)
|
||||
goto quit;
|
||||
|
||||
JxlEncoderCloseInput(enc);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t *next_out;
|
||||
size_t avail_out;
|
||||
|
||||
next_out = buffer;
|
||||
avail_out = buf_len;
|
||||
jst = JxlEncoderProcessOutput(enc, &next_out, &avail_out);
|
||||
switch (jst)
|
||||
{
|
||||
default:
|
||||
goto quit;
|
||||
case JXL_ENC_SUCCESS:
|
||||
case JXL_ENC_NEED_MORE_OUTPUT:
|
||||
D("Write: jst=%d %d\n", jst, (int)(buf_len - avail_out));
|
||||
if (next_out == buffer)
|
||||
goto quit;
|
||||
|
||||
if (fwrite(buffer, 1, buf_len - avail_out, im->fi->fp) !=
|
||||
buf_len - avail_out)
|
||||
goto quit;
|
||||
|
||||
if (jst == JXL_ENC_SUCCESS)
|
||||
goto done;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
rc = LOAD_SUCCESS;
|
||||
|
||||
quit:
|
||||
free(buffer);
|
||||
#if MAX_RUNNERS > 0
|
||||
if (runner)
|
||||
JxlThreadParallelRunnerDestroy(runner);
|
||||
#endif
|
||||
if (enc)
|
||||
JxlEncoderDestroy(enc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
IMLIB_LOADER(_formats, _load, _save);
|
||||
|
|
|
@ -27,7 +27,7 @@ static const test_rec_t exts[] = {
|
|||
// { "id3", { 0, 0 } },
|
||||
// { "j2k", { 0, 0 } },
|
||||
{ "jpeg", { 2458451111, 3483232328 } },
|
||||
// { "jxl", { 0, 0 } },
|
||||
{ "jxl", { 2681286418, 774897965 } },
|
||||
// { "lbm", { 0, 0 } },
|
||||
// { "lzma", { 0, 0 } },
|
||||
{ "png", { 1153555547, 2937827957 } },
|
||||
|
|
Loading…
Reference in New Issue