summaryrefslogtreecommitdiff
path: root/lib/jxl/dec_cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/jxl/dec_cache.cc')
-rw-r--r--lib/jxl/dec_cache.cc85
1 files changed, 57 insertions, 28 deletions
diff --git a/lib/jxl/dec_cache.cc b/lib/jxl/dec_cache.cc
index b819b51..d5e15bc 100644
--- a/lib/jxl/dec_cache.cc
+++ b/lib/jxl/dec_cache.cc
@@ -6,8 +6,10 @@
#include "lib/jxl/dec_cache.h"
#include "lib/jxl/blending.h"
+#include "lib/jxl/common.h" // JXL_HIGH_PRECISION
#include "lib/jxl/render_pipeline/stage_blending.h"
#include "lib/jxl/render_pipeline/stage_chroma_upsampling.h"
+#include "lib/jxl/render_pipeline/stage_cms.h"
#include "lib/jxl/render_pipeline/stage_epf.h"
#include "lib/jxl/render_pipeline/stage_from_linear.h"
#include "lib/jxl/render_pipeline/stage_gaborish.h"
@@ -28,7 +30,7 @@ Status PassesDecoderState::PreparePipeline(ImageBundle* decoded,
PipelineOptions options) {
const FrameHeader& frame_header = shared->frame_header;
size_t num_c = 3 + frame_header.nonserialized_metadata->m.num_extra_channels;
- if ((frame_header.flags & FrameHeader::kNoise) != 0) {
+ if (options.render_noise && (frame_header.flags & FrameHeader::kNoise) != 0) {
num_c += 3;
}
@@ -110,8 +112,7 @@ Status PassesDecoderState::PreparePipeline(ImageBundle* decoded,
CeilLog2Nonzero(frame_header.upsampling)));
}
}
-
- if ((frame_header.flags & FrameHeader::kNoise) != 0) {
+ if (options.render_noise && (frame_header.flags & FrameHeader::kNoise) != 0) {
builder.AddStage(GetConvolveNoiseStage(num_c - 3));
builder.AddStage(GetAddNoiseStage(shared->image_features.noise_params,
shared->cmap, num_c - 3));
@@ -138,29 +139,29 @@ Status PassesDecoderState::PreparePipeline(ImageBundle* decoded,
}
}
- size_t width = options.coalescing
- ? frame_header.nonserialized_metadata->xsize()
- : shared->frame_dim.xsize_upsampled;
- size_t height = options.coalescing
- ? frame_header.nonserialized_metadata->ysize()
- : shared->frame_dim.ysize_upsampled;
-
if (fast_xyb_srgb8_conversion) {
+#if !JXL_HIGH_PRECISION
JXL_ASSERT(!NeedsBlending(this));
JXL_ASSERT(!frame_header.CanBeReferenced() ||
frame_header.save_before_color_transform);
JXL_ASSERT(!options.render_spotcolors ||
!decoded->metadata()->Find(ExtraChannel::kSpotColor));
- builder.AddStage(GetFastXYBTosRGB8Stage(rgb_output, rgb_stride, width,
- height, rgb_output_is_rgba,
- has_alpha, alpha_c));
+ bool is_rgba = (main_output.format.num_channels == 4);
+ uint8_t* rgb_output = reinterpret_cast<uint8_t*>(main_output.buffer);
+ builder.AddStage(GetFastXYBTosRGB8Stage(rgb_output, main_output.stride,
+ width, height, is_rgba, has_alpha,
+ alpha_c));
+#endif
} else {
bool linear = false;
if (frame_header.color_transform == ColorTransform::kYCbCr) {
builder.AddStage(GetYCbCrStage());
} else if (frame_header.color_transform == ColorTransform::kXYB) {
- builder.AddStage(GetXYBStage(output_encoding_info.opsin_params));
- linear = true;
+ builder.AddStage(GetXYBStage(output_encoding_info));
+ if (output_encoding_info.color_encoding.GetColorSpace() !=
+ ColorSpace::kXYB) {
+ linear = true;
+ }
} // Nothing to do for kNone.
if (options.coalescing && NeedsBlending(this)) {
@@ -200,29 +201,57 @@ Status PassesDecoderState::PreparePipeline(ImageBundle* decoded,
if (!linear) {
auto to_linear_stage = GetToLinearStage(output_encoding_info);
if (!to_linear_stage) {
- return JXL_FAILURE(
- "attempting to perform tone mapping on colorspace not "
- "convertible to linear");
+ if (!output_encoding_info.cms_set) {
+ return JXL_FAILURE("Cannot tonemap this colorspace without a CMS");
+ }
+ auto cms_stage = GetCmsStage(output_encoding_info);
+ if (cms_stage) {
+ builder.AddStage(std::move(cms_stage));
+ }
+ } else {
+ builder.AddStage(std::move(to_linear_stage));
}
- builder.AddStage(std::move(to_linear_stage));
linear = true;
}
builder.AddStage(std::move(tone_mapping_stage));
}
if (linear) {
- builder.AddStage(GetFromLinearStage(output_encoding_info));
+ const size_t channels_src =
+ (output_encoding_info.orig_color_encoding.IsCMYK()
+ ? 4
+ : output_encoding_info.orig_color_encoding.Channels());
+ const size_t channels_dst =
+ output_encoding_info.color_encoding.Channels();
+ bool mixing_color_and_grey = (channels_dst != channels_src);
+ if ((output_encoding_info.color_encoding_is_original) ||
+ (!output_encoding_info.cms_set) || mixing_color_and_grey) {
+ // in those cases we only need a linear stage in other cases we attempt
+ // to obtain an cms stage: the cases are
+ // - output_encoding_info.color_encoding_is_original: no cms stage
+ // needed because it would be a no-op
+ // - !output_encoding_info.cms_set: can't use the cms, so no point in
+ // trying to add a cms stage
+ // - mixing_color_and_grey: cms stage can't handle that
+ // TODO(firsching): remove "mixing_color_and_grey" condition after
+ // adding support for greyscale to cms stage.
+ builder.AddStage(GetFromLinearStage(output_encoding_info));
+ } else {
+ if (!output_encoding_info.linear_color_encoding.CreateICC()) {
+ return JXL_FAILURE("Failed to create ICC");
+ }
+ auto cms_stage = GetCmsStage(output_encoding_info);
+ if (cms_stage) {
+ builder.AddStage(std::move(cms_stage));
+ }
+ }
linear = false;
}
- if (pixel_callback.IsPresent()) {
- builder.AddStage(GetWriteToPixelCallbackStage(
- pixel_callback, width, height, rgb_output_is_rgba, has_alpha,
- unpremul_alpha, alpha_c));
- } else if (rgb_output) {
- builder.AddStage(GetWriteToU8Stage(rgb_output, rgb_stride, height,
- rgb_output_is_rgba, has_alpha,
- alpha_c));
+ if (main_output.callback.IsPresent() || main_output.buffer) {
+ builder.AddStage(GetWriteToOutputStage(main_output, width, height,
+ has_alpha, unpremul_alpha, alpha_c,
+ undo_orientation, extra_output));
} else {
builder.AddStage(GetWriteToImageBundleStage(
decoded, output_encoding_info.color_encoding));