250 if (!io->isReadable()) {
251 errFile <<
"Cannot read image contents";
256 const auto data = io->readAll();
258 const auto validation =
259 JxlSignatureCheck(
reinterpret_cast<const uint8_t *
>(data.constData()),
static_cast<size_t>(data.size()));
261 switch (validation) {
262 case JXL_SIG_NOT_ENOUGH_BYTES:
263 errFile <<
"Failed magic byte validation, not enough data";
265 case JXL_SIG_INVALID:
266 errFile <<
"Failed magic byte validation, incorrect format";
273 auto runner = JxlResizableParallelRunnerMake(
nullptr);
274 auto dec = JxlDecoderMake(
nullptr);
279 static constexpr std::array<JxlBlendMode, 3> supportedBlendMode = {JXL_BLEND_REPLACE, JXL_BLEND_BLEND, JXL_BLEND_MULADD};
282 bool isAnimated =
false;
283 bool isMultilayer =
false;
284 bool isMultipage =
false;
285 bool forceCoalesce =
false;
288 != JxlDecoderSubscribeEvents(dec.get(), JXL_DEC_BASIC_INFO | JXL_DEC_FRAME)) {
289 errFile <<
"JxlDecoderSubscribeEvents failed";
293 if (JXL_DEC_SUCCESS != JxlDecoderSetParallelRunner(dec.get(), JxlResizableParallelRunner, runner.get())) {
294 errFile <<
"JxlDecoderSetParallelRunner failed";
299 != JxlDecoderSetInput(dec.get(),
300 reinterpret_cast<const uint8_t *
>(data.constData()),
301 static_cast<size_t>(data.size()))) {
302 errFile <<
"JxlDecoderSetInput failed";
305 JxlDecoderCloseInput(dec.get());
307 if (JXL_DEC_SUCCESS != JxlDecoderSetDecompressBoxes(dec.get(), JXL_TRUE)) {
308 errFile <<
"JxlDecoderSetDecompressBoxes failed";
312 if (JXL_DEC_SUCCESS != JxlDecoderSetCoalescing(dec.get(), JXL_FALSE)) {
313 errFile <<
"JxlDecoderSetCoalescing failed";
318 JxlDecoderStatus status = JxlDecoderProcessInput(dec.get());
320 if (status == JXL_DEC_ERROR) {
323 }
else if (status == JXL_DEC_NEED_MORE_INPUT) {
324 errFile <<
"Error, already provided all input";
326 }
else if (status == JXL_DEC_BASIC_INFO) {
327 if (JXL_DEC_SUCCESS != JxlDecoderGetBasicInfo(dec.get(), &
d.m_info)) {
328 errFile <<
"JxlDecoderGetBasicInfo failed";
332 if (
d.m_info.have_animation) {
333 isMultilayer =
false;
336 forceCoalesce =
true;
339 dbgFile <<
"Extra Channel[s] info:";
340 for (uint32_t i = 0; i <
d.m_info.num_extra_channels; i++) {
341 if (JXL_DEC_SUCCESS != JxlDecoderGetExtraChannelInfo(dec.get(), i, &
d.m_extra)) {
342 errFile <<
"JxlDecoderGetExtraChannelInfo failed";
348 const QString channelTypeString = [&]() {
349 switch (
d.m_extra.type) {
350 case JXL_CHANNEL_ALPHA:
351 return QString(
"JXL-Alpha");
352 case JXL_CHANNEL_DEPTH:
353 return QString(
"JXL-Depth");
354 case JXL_CHANNEL_SPOT_COLOR:
355 return QString(
"JXL-SpotColor");
356 case JXL_CHANNEL_SELECTION_MASK:
357 return QString(
"JXL-SelectionMask");
358 case JXL_CHANNEL_BLACK:
359 return QString(
"JXL-Black");
360 case JXL_CHANNEL_CFA:
361 return QString(
"JXL-CFA");
362 case JXL_CHANNEL_THERMAL:
363 return QString(
"JXL-Thermal");
365 return QString(
"JXL-UNKNOWN");
370 dbgFile <<
"index:" << i <<
" | type:" << channelTypeString;
371 if (
d.m_extra.type == JXL_CHANNEL_BLACK) {
375 if (
d.m_extra.type == JXL_CHANNEL_SPOT_COLOR) {
376 warnFile <<
"Spot color channels unsupported! Rewinding decoder with coalescing enabled";
377 document->setWarningMessage(i18nc(
"JPEG-XL errors",
378 "Detected JPEG-XL image with spot color channels, "
379 "importing flattened image."));
380 forceCoalesce =
true;
385 dbgFile <<
"Size:" <<
d.m_info.xsize <<
"x" <<
d.m_info.ysize;
386 dbgFile <<
"Depth:" <<
d.m_info.bits_per_sample <<
d.m_info.exponent_bits_per_sample;
387 dbgFile <<
"Number of color channels:" <<
d.m_info.num_color_channels;
388 dbgFile <<
"Number of extra channels:" <<
d.m_info.num_extra_channels;
389 dbgFile <<
"Extra channels depth:" <<
d.m_info.alpha_bits <<
d.m_info.alpha_exponent_bits;
390 dbgFile <<
"Has animation:" <<
d.m_info.have_animation <<
"loops:" <<
d.m_info.animation.num_loops
391 <<
"tick:" <<
d.m_info.animation.tps_numerator <<
d.m_info.animation.tps_denominator;
392 dbgFile <<
"Internal pixel format:" << (
d.m_info.uses_original_profile ?
"Original" :
"XYB");
393 JxlResizableParallelRunnerSetThreads(
395 JxlResizableParallelRunnerSuggestThreads(
d.m_info.xsize,
d.m_info.ysize));
397 if (
d.m_info.exponent_bits_per_sample != 0) {
398 if (
d.m_info.bits_per_sample <= 16) {
399 d.m_pixelFormat.data_type = JXL_TYPE_FLOAT16;
401 }
else if (
d.m_info.bits_per_sample <= 32) {
402 d.m_pixelFormat.data_type = JXL_TYPE_FLOAT;
405 errFile <<
"Unsupported JPEG-XL input depth" <<
d.m_info.bits_per_sample
406 <<
d.m_info.exponent_bits_per_sample;
409 }
else if (
d.m_info.bits_per_sample <= 8) {
410 d.m_pixelFormat.data_type = JXL_TYPE_UINT8;
412 }
else if (
d.m_info.bits_per_sample <= 16) {
413 d.m_pixelFormat.data_type = JXL_TYPE_UINT16;
416 errFile <<
"Unsupported JPEG-XL input depth" <<
d.m_info.bits_per_sample
417 <<
d.m_info.exponent_bits_per_sample;
421 if (
d.m_info.num_color_channels == 1) {
423 d.m_pixelFormat.num_channels = 2;
425 }
else if (
d.m_info.num_color_channels == 3 && !
d.isCMYK) {
427 d.m_pixelFormat.num_channels = 4;
429 }
else if (
d.m_info.num_color_channels == 3 &&
d.isCMYK) {
431 d.m_pixelFormat.num_channels = 4;
434 warnFile <<
"Forcing a RGBA conversion, unknown color space";
435 d.m_pixelFormat.num_channels = 4;
439 if (!
d.m_info.uses_original_profile) {
440 d.m_pixelFormat_target.data_type =
d.m_pixelFormat.data_type;
441 d.m_pixelFormat.data_type = JXL_TYPE_FLOAT;
442 d.m_depthID_target =
d.m_depthID;
443 d.m_colorID_target =
d.m_colorID;
450 }
else if (status == JXL_DEC_FRAME) {
451 if (JXL_DEC_SUCCESS != JxlDecoderGetFrameHeader(dec.get(), &
d.m_header)) {
452 errFile <<
"JxlDecoderGetFrameHeader failed";
456 const JxlBlendMode blendMode =
d.m_header.layer_info.blend_info.blendmode;
457 const bool isBlendSupported =
458 std::find(supportedBlendMode.begin(), supportedBlendMode.end(), blendMode) != supportedBlendMode.end();
460 if (!isBlendSupported) {
461 forceCoalesce =
true;
464 if (
d.m_header.duration == 0) {
466 }
else if (
d.m_header.duration == 0xFFFFFFFF) {
469 forceCoalesce =
true;
473 isMultilayer =
false;
474 forceCoalesce =
true;
476 }
else if (status == JXL_DEC_SUCCESS) {
481 JxlDecoderReset(dec.get());
484 if (JXL_DEC_SUCCESS != JxlDecoderSetCoalescing(dec.get(), forceCoalesce ? JXL_TRUE : JXL_FALSE)) {
485 errFile <<
"JxlDecoderSetCoalescing failed";
490 != JxlDecoderSubscribeEvents(dec.get(),
491 JXL_DEC_COLOR_ENCODING | JXL_DEC_FULL_IMAGE | JXL_DEC_BOX | JXL_DEC_FRAME)) {
492 errFile <<
"JxlDecoderSubscribeEvents failed";
496 if (JXL_DEC_SUCCESS != JxlDecoderSetParallelRunner(dec.get(), JxlResizableParallelRunner, runner.get())) {
497 errFile <<
"JxlDecoderSetParallelRunner failed";
502 != JxlDecoderSetInput(dec.get(),
503 reinterpret_cast<const uint8_t *
>(data.constData()),
504 static_cast<size_t>(data.size()))) {
505 errFile <<
"JxlDecoderSetInput failed";
508 JxlDecoderCloseInput(dec.get());
510 if (JXL_DEC_SUCCESS != JxlDecoderSetDecompressBoxes(dec.get(), JXL_TRUE)) {
511 errFile <<
"JxlDecoderSetDecompressBoxes failed";
517 std::multimap<QByteArray, QByteArray> metadataBoxes;
518 std::vector<KisLayerSP> additionalLayers;
519 bool bgLayerSet =
false;
520 bool needColorTransform =
false;
521 bool needIntermediateTransform =
false;
522 QByteArray boxType(5, 0x0);
523 QByteArray box(16384, 0x0);
524 auto boxSize = box.size();
528 JxlDecoderStatus status = JxlDecoderProcessInput(dec.get());
530 if (status == JXL_DEC_ERROR) {
533 }
else if (status == JXL_DEC_NEED_MORE_INPUT) {
534 errFile <<
"Error, already provided all input";
536 }
else if (status == JXL_DEC_COLOR_ENCODING) {
545 JxlColorEncoding colorEncoding{};
547 == JxlDecoderGetColorAsEncodedProfile(dec.get(),
548#
if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0)
551 JXL_COLOR_PROFILE_TARGET_DATA,
554 switch (colorEncoding.transfer_function) {
555 case JXL_TRANSFER_FUNCTION_PQ: {
556 dbgFile <<
"linearizing from PQ";
560 case JXL_TRANSFER_FUNCTION_HLG: {
561 dbgFile <<
"linearizing from HLG";
562 if (!document->fileBatchMode()) {
566 d.displayGamma = dlg.
gamma();
572 case JXL_TRANSFER_FUNCTION_DCI: {
573 dbgFile <<
"linearizing from SMPTE 428";
577 case JXL_TRANSFER_FUNCTION_709:
579 case JXL_TRANSFER_FUNCTION_SRGB:
581 case JXL_TRANSFER_FUNCTION_GAMMA: {
583 const double estGamma = 1.0 / colorEncoding.gamma;
584 const double error = 0.0001;
587 if ((std::fabs(estGamma - 1.8) < error) || (std::fabs(estGamma - (461.0 / 256.0)) < error)) {
589 }
else if (std::fabs(estGamma - 2.2) < error) {
591 }
else if (std::fabs(estGamma - (563.0 / 256.0)) < error) {
593 }
else if (std::fabs(estGamma - 2.4) < error) {
595 }
else if (std::fabs(estGamma - 2.8) < error) {
598 warnFile <<
"Found custom estimated gamma value for JXL color space" << estGamma;
602 case JXL_TRANSFER_FUNCTION_LINEAR:
604 case JXL_TRANSFER_FUNCTION_UNKNOWN:
612 switch (colorEncoding.primaries) {
613 case JXL_PRIMARIES_SRGB:
615 case JXL_PRIMARIES_2100:
617 case JXL_PRIMARIES_P3:
625 if (colorEncoding.primaries != JXL_PRIMARIES_CUSTOM) {
628 return {colorEncoding.white_point_xy[0],
629 colorEncoding.white_point_xy[1],
630 colorEncoding.primaries_red_xy[0],
631 colorEncoding.primaries_red_xy[1],
632 colorEncoding.primaries_green_xy[0],
633 colorEncoding.primaries_green_xy[1],
634 colorEncoding.primaries_blue_xy[0],
635 colorEncoding.primaries_blue_xy[1]};
639 if (colorEncoding.rendering_intent == JXL_RENDERING_INTENT_PERCEPTUAL) {
641 }
else if (colorEncoding.rendering_intent == JXL_RENDERING_INTENT_RELATIVE) {
643 }
else if (colorEncoding.rendering_intent == JXL_RENDERING_INTENT_ABSOLUTE) {
645 }
else if (colorEncoding.rendering_intent == JXL_RENDERING_INTENT_SATURATION) {
648 warnFile <<
"Cannot determine color rendering intent, set to Perceptual instead";
655 dbgFile <<
"CICP profile data:" << colorants << colorPrimaries << transferFunction;
658 dbgFile <<
"JXL CICP profile found" << profile->
name();
663 d.m_pixelFormat.data_type =
d.m_pixelFormat_target.data_type;
673 QByteArray iccProfile;
675 != JxlDecoderGetICCProfileSize(dec.get(),
676#
if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0,9,0)
679 JXL_COLOR_PROFILE_TARGET_DATA,
681 errFile <<
"ICC profile size retrieval failed";
682 document->setErrorMessage(i18nc(
"JPEG-XL errors",
"Unable to read the image profile."));
685 iccProfile.resize(
static_cast<int>(iccSize));
687 != JxlDecoderGetColorAsICCProfile(dec.get(),
688#
if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0,9,0)
691 JXL_COLOR_PROFILE_TARGET_DATA,
692 reinterpret_cast<uint8_t *
>(iccProfile.data()),
693 static_cast<size_t>(iccProfile.size()))) {
694 document->setErrorMessage(i18nc(
"JPEG-XL errors",
"Unable to read the image profile."));
699 size_t iccTargetSize = 0;
700 QByteArray iccTargetProfile;
701 if (!
d.m_info.uses_original_profile) {
703 != JxlDecoderGetICCProfileSize(dec.get(),
704#
if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0,9,0)
707 JXL_COLOR_PROFILE_TARGET_ORIGINAL,
709 errFile <<
"ICC profile size retrieval failed";
710 document->setErrorMessage(i18nc(
"JPEG-XL errors",
"Unable to read the image profile."));
713 iccTargetProfile.resize(
static_cast<int>(iccTargetSize));
715 != JxlDecoderGetColorAsICCProfile(dec.get(),
716#
if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0,9,0)
719 JXL_COLOR_PROFILE_TARGET_ORIGINAL,
720 reinterpret_cast<uint8_t *
>(iccTargetProfile.data()),
721 static_cast<size_t>(iccTargetProfile.size()))) {
722 document->setErrorMessage(i18nc(
"JPEG-XL errors",
"Unable to read the image profile."));
727 if (iccTargetSize && (iccProfile != iccTargetProfile)) {
734 dbgFile <<
"XYB with color transform needed";
735 needColorTransform =
true;
745 profileIntermediate);
747 d.m_depthID_target.id(),
750 d.m_depthID_target.id(),
756 needIntermediateTransform =
true;
758 }
else if (!
d.m_info.uses_original_profile) {
763 dbgFile <<
"XYB without color transform needed";
764 needColorTransform =
false;
765 d.m_depthID =
d.m_depthID_target;
766 d.m_colorID =
d.m_colorID_target;
767 d.m_pixelFormat.data_type =
d.m_pixelFormat_target.data_type;
772 dbgFile <<
"JXL CICP data couldn't be handled, falling back to ICC profile retrieval";
774 d.m_depthID_target.id(),
777 d.m_depthID_target.id(),
782 dbgFile <<
"Original without color transform needed";
783 needColorTransform =
false;
792 dbgFile <<
"Source profile:" <<
d.cs->profile()->name();
793 dbgFile <<
"Source space:" <<
d.cs->name() <<
d.cs->colorModelId() <<
d.cs->colorDepthId();
794 dbgFile <<
"Target profile:" <<
d.cs_target->profile()->name();
795 dbgFile <<
"Color space:" <<
d.cs_target->name() <<
d.cs_target->colorModelId()
796 <<
d.cs_target->colorDepthId();
798 dbgFile <<
"Color space:" <<
d.cs->name() <<
d.cs->colorModelId() <<
d.cs->colorDepthId();
800 dbgFile <<
"JXL depth" <<
d.m_pixelFormat.data_type;
802 d.lCoef =
d.cs->lumaCoefficients();
804 image =
new KisImage(document->createUndoStore(),
805 static_cast<int>(
d.m_info.xsize),
806 static_cast<int>(
d.m_info.ysize),
810 layer =
new KisPaintLayer(image, image->nextLayerName(), UCHAR_MAX);
811 }
else if (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER) {
816 if (JXL_DEC_SUCCESS != JxlDecoderImageOutBufferSize(dec.get(), &
d.m_pixelFormat, &rawSize)) {
817 qWarning() <<
"JxlDecoderImageOutBufferSize failed";
820 d.m_rawData.resize(rawSize);
822 != JxlDecoderSetImageOutBuffer(dec.get(),
824 reinterpret_cast<uint8_t *
>(
d.m_rawData.data()),
825 static_cast<size_t>(
d.m_rawData.size()))) {
826 qWarning() <<
"JxlDecoderSetImageOutBuffer failed";
832 size_t bufferSize = 0;
834 != JxlDecoderExtraChannelBufferSize(dec.get(), &
d.m_pixelFormat, &bufferSize,
d.cmykChannelID)) {
835 errFile <<
"JxlDecoderExtraChannelBufferSize failed";
839 d.kPlane.resize(bufferSize);
841 != JxlDecoderSetExtraChannelBuffer(dec.get(),
846 errFile <<
"JxlDecoderSetExtraChannelBuffer failed";
851 }
else if (status == JXL_DEC_FRAME) {
852 if (JXL_DEC_SUCCESS != JxlDecoderGetFrameHeader(dec.get(), &
d.m_header)) {
853 errFile <<
"JxlDecoderGetFrameHeader failed";
857 const JxlBlendMode blendMode =
d.m_header.layer_info.blend_info.blendmode;
859 if (isMultilayer || isMultipage) {
861 QByteArray layerNameRaw;
862 if (
d.m_header.name_length) {
865 document->setErrorMessage(i18nc(
"JPEG-XL",
"Invalid JPEG-XL layer name length"));
868 layerNameRaw.resize(
static_cast<int>(
d.m_header.name_length + 1));
870 != JxlDecoderGetFrameName(dec.get(),
872 static_cast<size_t>(layerNameRaw.size()))) {
873 errFile <<
"JxlDecoderGetFrameName failed";
876 dbgFile <<
"\tlayer name:" << QString(layerNameRaw);
879 layerName = QString::fromUtf8(layerNameRaw.data(),
d.m_header.name_length);
881 layerName = QString(
"Layer");
885 if (!layerNameRaw.isEmpty()) {
886 layer->setName(layerName);
889 additionalLayers.emplace_back(
new KisPaintLayer(image, layerName, UCHAR_MAX));
890 if (blendMode == JXL_BLEND_MULADD) {
891 additionalLayers.back()->setCompositeOpId(QString(
"add"));
895 }
else if (status == JXL_DEC_FULL_IMAGE) {
898 const JxlLayerInfo layerInfo =
d.m_header.layer_info;
899 const QRect layerBounds = QRect(
static_cast<int>(layerInfo.crop_x0),
900 static_cast<int>(layerInfo.crop_y0),
901 static_cast<int>(layerInfo.xsize),
902 static_cast<int>(layerInfo.ysize));
904 dbgFile <<
"Importing frame @" <<
d.m_nextFrameTime
905 <<
d.m_header.duration;
911 const uint32_t frameDurationNorm =
d.m_header.duration == 0xFFFFFFFF ? 1 :
d.m_header.duration;
912 if (
d.m_nextFrameTime == 0) {
913 dbgFile <<
"Animation detected, ticks per second:"
914 <<
d.m_info.animation.tps_numerator
915 <<
d.m_info.animation.tps_denominator;
922 std::lround(
d.m_info.animation.tps_numerator
923 /
static_cast<double>(
924 d.m_info.animation.tps_denominator));
925 if (framerate > 240) {
926 warnFile <<
"JXL ticks per second value exceeds 240, "
927 "approximating FPS from the duration of "
929 document->setWarningMessage(
930 i18nc(
"JPEG-XL errors",
931 "The animation declares a frame rate of more "
933 const int approximatedFramerate = std::lround(
934 1000.0 /
static_cast<double>(
d.m_header.duration));
935 d.m_durationFrameInTicks =
936 static_cast<int>(frameDurationNorm);
937 framerate = std::max(approximatedFramerate, 1);
939 d.m_durationFrameInTicks = 1;
941 dbgFile <<
"Framerate:" << framerate;
942 layer->enableAnimation();
943 image->animationInterface()->setDocumentRangeStartFrame(0);
944 image->animationInterface()->setFramerate(framerate);
947 const int currentFrameTime = std::lround(
948 static_cast<double>(
d.m_nextFrameTime)
949 /
static_cast<double>(
d.m_durationFrameInTicks));
953 image->animationInterface()->setDocumentRangeEndFrame(
954 std::lround(
static_cast<double>(
d.m_nextFrameTime
956 /
static_cast<double>(
d.m_durationFrameInTicks))
958 frame->
importFrame(currentFrameTime,
d.m_currentFrame,
nullptr);
959 d.m_nextFrameTime +=
static_cast<int>(frameDurationNorm);
961 if (
d.isCMYK &&
d.m_info.uses_original_profile) {
965 layerBounds.height());
968 planes[3] =
reinterpret_cast<quint8 *
>(
d.kPlane.data());
969 d.m_currentFrame->writePlanarBytes(planes,
973 layerBounds.height());
982 f->process(
d.m_currentFrame, layerBounds, kfc->cloneWithResourcesSnapshot());
985 layer->paintDevice()->makeCloneFrom(
d.m_currentFrame, layerBounds);
988 additionalLayers.back()->paintDevice()->makeCloneFrom(
d.m_currentFrame, layerBounds);
991 }
else if (status == JXL_DEC_SUCCESS || status == JXL_DEC_BOX) {
992 if (std::strlen(boxType.data()) != 0) {
994 const auto availOut = JxlDecoderReleaseBoxBuffer(dec.get());
995 const int finalSize = box.size() -
static_cast<int>(availOut);
998 QByteArray type = boxType.toLower();
999 if ((std::equal(
exifTag.begin(),
exifTag.end(), type.constBegin())
1000 || std::equal(
xmpTag.begin(),
xmpTag.end(), type.constBegin()))
1001 && finalSize != 0) {
1002 metadataBoxes.emplace(type, QByteArray(box.data(), finalSize));
1008 if (status == JXL_DEC_SUCCESS) {
1013 for (
auto &metaBox : metadataBoxes) {
1014 const QByteArray &type = metaBox.first;
1015 QByteArray &
value = metaBox.second;
1016 QBuffer buf(&
value);
1017 if (std::equal(
exifTag.begin(),
exifTag.end(), type.constBegin())) {
1018 dbgFile <<
"Loading EXIF data. Size: " <<
value.size();
1020 const auto *backend =
1024 backend->
loadFrom(layer->metaData(), &buf);
1025 }
else if (std::equal(
xmpTag.begin(),
xmpTag.end(), type.constBegin())) {
1026 dbgFile <<
"Loading XMP or IPTC data. Size: " <<
value.size();
1028 const auto *xmpBackend =
1032 if (!xmpBackend->loadFrom(layer->metaData(), &buf)) {
1036 iptcBackend->
loadFrom(layer->metaData(), &buf);
1043 image->addNode(layer, image->rootLayer().data());
1045 for (
const KisLayerSP &addLayer : additionalLayers) {
1046 image->addNode(addLayer, image->rootLayer().data());
1048 if (needColorTransform) {
1049 if (needIntermediateTransform) {
1050 dbgFile <<
"Transforming to intermediate color space";
1051 image->convertImageColorSpace(
d.cs_intermediate,
1054 image->waitForDone();
1056 dbgFile <<
"Transforming to target color space";
1057 image->convertImageColorSpace(
d.cs_target,
1060 image->waitForDone();
1062 document->setCurrentImage(image);
1065 if (JxlDecoderGetBoxType(dec.get(), boxType.data(), JXL_TRUE) != JXL_DEC_SUCCESS) {
1066 errFile <<
"JxlDecoderGetBoxType failed";
1069 const QByteArray type = boxType.toLower();
1070 if (std::equal(
exifTag.begin(),
exifTag.end(), type.constBegin())
1071 || std::equal(
xmpTag.begin(),
xmpTag.end(), type.constBegin())) {
1072 if (JxlDecoderSetBoxBuffer(
1074 reinterpret_cast<uint8_t *
>(box.data()),
1075 static_cast<size_t>(box.size()))
1076 != JXL_DEC_SUCCESS) {
1077 errFile <<
"JxlDecoderSetBoxBuffer failed";
1081 dbgFile <<
"Skipping box" << boxType.data();
1084 }
else if (status == JXL_DEC_BOX_NEED_MORE_OUTPUT) {
1086 boxSize = box.size();
1087 box.resize(boxSize * 2);
1089 JxlDecoderReleaseBoxBuffer(dec.get());
1090 if (JxlDecoderSetBoxBuffer(
1092 reinterpret_cast<uint8_t *
>(box.data() + boxSize),
1093 static_cast<size_t>(box.size() - boxSize))
1094 != JXL_DEC_SUCCESS) {
1095 errFile <<
"JxlDecoderGetBoxType failed";
1099 errFile <<
"Unknown decoder status" << status;