Skip to content

Add jxl cmyk support #3883

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 37 additions & 28 deletions libvips/foreign/jxlsave.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
*/

/*
#define DEBUG
*/
#define DEBUG

#ifdef HAVE_CONFIG_H
#include <config.h>
Expand Down Expand Up @@ -251,12 +251,8 @@ vips_foreign_save_jxl_print_status(JxlEncoderStatus status)
printf("JXL_ENC_NEED_MORE_OUTPUT\n");
break;

case JXL_ENC_NOT_SUPPORTED:
printf("JXL_ENC_NOT_SUPPORTED\n");
break;

default:
printf("JXL_ENC_<unknown>\n");
printf("JXL_ENC_<unknown %d>\n", status);
break;
}
}
Expand Down Expand Up @@ -285,8 +281,7 @@ vips_foreign_save_jxl_process_output(VipsForeignSaveJxl *jxl)
break;

default:
vips_foreign_save_jxl_error(jxl,
"JxlEncoderProcessOutput");
vips_foreign_save_jxl_error(jxl, "JxlEncoderProcessOutput");
#ifdef DEBUG
vips_foreign_save_jxl_print_status(status);
#endif /*DEBUG*/
Expand Down Expand Up @@ -497,14 +492,12 @@ vips_foreign_save_jxl_build(VipsObject *object)
if (jxl->distance == 0)
jxl->lossless = TRUE;

jxl->runner = JxlThreadParallelRunnerCreate(NULL,
vips_concurrency_get());
jxl->runner = JxlThreadParallelRunnerCreate(NULL, vips_concurrency_get());
jxl->encoder = JxlEncoderCreate(NULL);

if (JxlEncoderSetParallelRunner(jxl->encoder,
JxlThreadParallelRunner, jxl->runner)) {
vips_foreign_save_jxl_error(jxl,
"JxlDecoderSetParallelRunner");
vips_foreign_save_jxl_error(jxl, "JxlDecoderSetParallelRunner");
return -1;
}

Expand All @@ -526,12 +519,11 @@ vips_foreign_save_jxl_build(VipsObject *object)
in = t[0];

/* Mimics VIPS_SAVEABLE_RGBA.
*
* FIXME: add support encoding images with > 4 bands.
*/
if (in->Bands > 4) {
if (vips_extract_band(in, &t[1], 0,
"n", 4,
NULL))
if (vips_extract_band(in, &t[1], 0, "n", 4, NULL))
return -1;
in = t[1];
}
Expand Down Expand Up @@ -574,6 +566,12 @@ vips_foreign_save_jxl_build(VipsObject *object)
jxl->info.num_color_channels = VIPS_MIN(3, in->Bands);
break;

case VIPS_INTERPRETATION_CMYK:
// CMYK is respresented as CMY plus a kBlack extra channel ... this is
// set just after SetBasicInfo
jxl->info.num_color_channels = VIPS_MIN(3, in->Bands);
break;

default:
jxl->info.num_color_channels = in->Bands;
}
Expand Down Expand Up @@ -603,8 +601,7 @@ vips_foreign_save_jxl_build(VipsObject *object)

if (vips_image_hasalpha(in)) {
jxl->info.alpha_bits = jxl->info.bits_per_sample;
jxl->info.alpha_exponent_bits =
jxl->info.exponent_bits_per_sample;
jxl->info.alpha_exponent_bits = jxl->info.exponent_bits_per_sample;
}
else {
jxl->info.alpha_exponent_bits = 0;
Expand All @@ -629,23 +626,36 @@ vips_foreign_save_jxl_build(VipsObject *object)
return -1;
}

/* For CMYK, we need to tag the first extra channel as kBlack. Other extra
* channels default to alpha.
*/
if (in->Type == VIPS_INTERPRETATION_CMYK &&
jxl->info.num_extra_channels > 0) {
JxlExtraChannelInfo info;

JxlEncoderInitExtraChannelInfo(JXL_CHANNEL_BLACK, &info);
info.bits_per_sample = jxl->info.bits_per_sample;
info.dim_shift = 1;
if (JxlEncoderSetExtraChannelInfo(jxl->encoder, 0, &info)) {
vips_foreign_save_jxl_error(jxl, "JxlEncoderSetExtraChannelInfo");
return -1;
}
}

/* Set any ICC profile.
*/
if (vips_image_get_typeof(in, VIPS_META_ICC_NAME)) {
const void *data;
size_t length;

if (vips_image_get_blob(in,
VIPS_META_ICC_NAME, &data, &length))
if (vips_image_get_blob(in, VIPS_META_ICC_NAME, &data, &length))
return -1;

#ifdef DEBUG
printf("attaching %zd bytes of ICC\n", length);
#endif /*DEBUG*/
if (JxlEncoderSetICCProfile(jxl->encoder,
(guint8 *) data, length)) {
vips_foreign_save_jxl_error(jxl,
"JxlEncoderSetColorEncoding");
if (JxlEncoderSetICCProfile(jxl->encoder, (guint8 *) data, length)) {
vips_foreign_save_jxl_error(jxl, "JxlEncoderSetColorEncoding");
return -1;
}
}
Expand All @@ -670,10 +680,8 @@ vips_foreign_save_jxl_build(VipsObject *object)
jxl->format.num_channels < 3);
}

if (JxlEncoderSetColorEncoding(jxl->encoder,
&jxl->color_encoding)) {
vips_foreign_save_jxl_error(jxl,
"JxlEncoderSetColorEncoding");
if (JxlEncoderSetColorEncoding(jxl->encoder, &jxl->color_encoding)) {
vips_foreign_save_jxl_error(jxl, "JxlEncoderSetColorEncoding");
return -1;
}
}
Expand Down Expand Up @@ -861,7 +869,8 @@ vips_foreign_save_jxl_file_build(VipsObject *object)
if (!(jxl->target = vips_target_new_to_file(file->filename)))
return -1;

if (VIPS_OBJECT_CLASS(vips_foreign_save_jxl_file_parent_class)->build(object))
if (VIPS_OBJECT_CLASS(vips_foreign_save_jxl_file_parent_class)->
build(object))
return -1;

return 0;
Expand Down