From fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:14:29 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- .../lib/jxl/modular/encoding/context_predict.h | 12 ++-- .../jpeg-xl/lib/jxl/modular/encoding/dec_ma.cc | 2 + .../lib/jxl/modular/encoding/enc_debug_tree.cc | 2 +- .../lib/jxl/modular/encoding/enc_encoding.cc | 82 +++++++++++++--------- .../jpeg-xl/lib/jxl/modular/encoding/enc_ma.cc | 15 ++-- .../jpeg-xl/lib/jxl/modular/encoding/encoding.cc | 12 +++- .../jpeg-xl/lib/jxl/modular/modular_image.cc | 35 +++++---- .../jpeg-xl/lib/jxl/modular/modular_image.h | 36 ++++++---- third_party/jpeg-xl/lib/jxl/modular/options.h | 8 ++- .../lib/jxl/modular/transform/enc_palette.cc | 38 ++++++---- .../lib/jxl/modular/transform/enc_squeeze.cc | 49 ++++++++----- .../jpeg-xl/lib/jxl/modular/transform/palette.cc | 19 +++-- .../jpeg-xl/lib/jxl/modular/transform/palette.h | 1 + .../jpeg-xl/lib/jxl/modular/transform/squeeze.cc | 19 +++-- .../jpeg-xl/lib/jxl/modular/transform/squeeze.h | 2 +- .../jpeg-xl/lib/jxl/modular/transform/transform.h | 14 ++-- 16 files changed, 217 insertions(+), 129 deletions(-) (limited to 'third_party/jpeg-xl/lib/jxl/modular') diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h b/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h index 4c3a33a52a..7bec5128fc 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h +++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/context_predict.h @@ -10,6 +10,7 @@ #include #include "lib/jxl/fields.h" +#include "lib/jxl/image_ops.h" #include "lib/jxl/modular/modular_image.h" #include "lib/jxl/modular/options.h" @@ -78,14 +79,14 @@ struct State { 294337, 289262, 284359, 279620, 275036, 270600, 266305, 262144}; constexpr static pixel_type_w AddBits(pixel_type_w x) { - return uint64_t(x) << kPredExtraBits; + return static_cast(x) << kPredExtraBits; } State(Header header, size_t xsize, size_t ysize) : header(header) { // Extra margin to avoid out-of-bounds writes. // All have space for two rows of data. - for (size_t i = 0; i < 4; i++) { - pred_errors[i].resize((xsize + 2) * 2); + for (auto &pred_error : pred_errors) { + pred_error.resize((xsize + 2) * 2); } error.resize((xsize + 2) * 2); } @@ -538,8 +539,9 @@ JXL_INLINE PredictionResult Predict( } if (mode & kAllPredictions) { for (size_t i = 0; i < kNumModularPredictors; i++) { - predictions[i] = PredictOne((Predictor)i, left, top, toptop, topleft, - topright, leftleft, toprightright, wp_pred); + predictions[i] = + PredictOne(static_cast(i), left, top, toptop, topleft, + topright, leftleft, toprightright, wp_pred); } } result.guess += PredictOne(predictor, left, top, toptop, topleft, topright, diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/dec_ma.cc b/third_party/jpeg-xl/lib/jxl/modular/encoding/dec_ma.cc index ee7177bcd6..b53b9a9103 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/encoding/dec_ma.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/dec_ma.cc @@ -5,6 +5,8 @@ #include "lib/jxl/modular/encoding/dec_ma.h" +#include + #include "lib/jxl/base/printf_macros.h" #include "lib/jxl/dec_ans.h" #include "lib/jxl/modular/encoding/ma_common.h" diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc index bd27f28458..f863823629 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_debug_tree.cc @@ -95,7 +95,7 @@ std::string PropertyName(size_t i) { case 15: return "WGH"; default: - return "ch[" + ToString(15 - (int)i) + "]"; + return "ch[" + ToString(15 - static_cast(i)) + "]"; } } diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_encoding.cc b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_encoding.cc index fc2e69e4a6..84d8137d21 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_encoding.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_encoding.cc @@ -6,35 +6,24 @@ #include #include -#include #include -#include #include -#include -#include -#include #include "lib/jxl/base/common.h" #include "lib/jxl/base/printf_macros.h" #include "lib/jxl/base/status.h" -#include "lib/jxl/dec_ans.h" -#include "lib/jxl/dec_bit_reader.h" #include "lib/jxl/enc_ans.h" #include "lib/jxl/enc_aux_out.h" #include "lib/jxl/enc_bit_writer.h" #include "lib/jxl/enc_fields.h" -#include "lib/jxl/entropy_coder.h" #include "lib/jxl/fields.h" #include "lib/jxl/image_ops.h" #include "lib/jxl/modular/encoding/context_predict.h" -#include "lib/jxl/modular/encoding/enc_debug_tree.h" #include "lib/jxl/modular/encoding/enc_ma.h" #include "lib/jxl/modular/encoding/encoding.h" #include "lib/jxl/modular/encoding/ma_common.h" #include "lib/jxl/modular/options.h" -#include "lib/jxl/modular/transform/transform.h" #include "lib/jxl/pack_signed.h" -#include "lib/jxl/toc.h" namespace jxl { @@ -61,7 +50,7 @@ inline std::array PredictorColor(Predictor p) { return {{255, 0, 255}}; case Predictor::Weighted: return {{0, 255, 255}}; - // TODO + // TODO(jon) default: return {{255, 255, 255}}; }; @@ -101,17 +90,17 @@ Tree MakeFixedTree(int property, const std::vector &cutoffs, } // namespace -void GatherTreeData(const Image &image, pixel_type chan, size_t group_id, - const weighted::Header &wp_header, - const ModularOptions &options, TreeSamples &tree_samples, - size_t *total_pixels) { +Status GatherTreeData(const Image &image, pixel_type chan, size_t group_id, + const weighted::Header &wp_header, + const ModularOptions &options, TreeSamples &tree_samples, + size_t *total_pixels) { const Channel &channel = image.channel[chan]; JXL_DEBUG_V(7, "Learning %" PRIuS "x%" PRIuS " channel %d", channel.w, channel.h, chan); std::array static_props = { - {chan, (int)group_id}}; + {chan, static_cast(group_id)}}; Properties properties(kNumNonrefProperties + kExtraPropsPerChannel * options.max_properties); double pixel_fraction = std::min(1.0f, options.nb_repeats); @@ -137,7 +126,9 @@ void GatherTreeData(const Image &image, pixel_type chan, size_t group_id, }; const intptr_t onerow = channel.plane.PixelsPerRow(); - Channel references(properties.size() - kNumNonrefProperties, channel.w); + JXL_ASSIGN_OR_RETURN( + Channel references, + Channel::Create(properties.size() - kNumNonrefProperties, channel.w)); weighted::State wp_state(wp_header, channel.w, channel.h); tree_samples.PrepareForSamples(pixel_fraction * channel.h * channel.w + 64); const bool multiple_predictors = tree_samples.NumPredictors() != 1; @@ -198,6 +189,7 @@ void GatherTreeData(const Image &image, pixel_type chan, size_t group_id, } } } + return true; } Tree PredefinedTree(ModularOptions::TreeKind tree_kind, size_t total_pixels) { @@ -316,7 +308,9 @@ Status EncodeModularChannelMAANS(const Image &image, pixel_type chan, JXL_ASSERT(channel.w != 0 && channel.h != 0); Image3F predictor_img; - if (kWantDebug) predictor_img = Image3F(channel.w, channel.h); + if (kWantDebug) { + JXL_ASSIGN_OR_RETURN(predictor_img, Image3F::Create(channel.w, channel.h)); + } JXL_DEBUG_V(6, "Encoding %" PRIuS "x%" PRIuS @@ -325,8 +319,9 @@ Status EncodeModularChannelMAANS(const Image &image, pixel_type chan, channel.w, channel.h, chan, channel.hshift, channel.vshift); std::array static_props = { - {chan, (int)group_id}}; - bool use_wp, is_wp_only; + {chan, static_cast(group_id)}}; + bool use_wp; + bool is_wp_only; bool is_gradient_only; size_t num_props; FlatTree tree = FilterTree(global_tree, static_props, &num_props, &use_wp, @@ -439,7 +434,8 @@ Status EncodeModularChannelMAANS(const Image &image, pixel_type chan, FillImage(static_cast(PredictorColor(tree[0].predictor)[c]), &predictor_img.Plane(c)); } - uint32_t mul_shift = FloorLog2Nonzero((uint32_t)tree[0].multiplier); + uint32_t mul_shift = + FloorLog2Nonzero(static_cast(tree[0].multiplier)); const intptr_t onerow = channel.plane.PixelsPerRow(); for (size_t y = 0; y < channel.h; y++) { const pixel_type *JXL_RESTRICT r = channel.Row(y); @@ -454,7 +450,9 @@ Status EncodeModularChannelMAANS(const Image &image, pixel_type chan, } else if (!use_wp && !skip_encoder_fast_path) { const intptr_t onerow = channel.plane.PixelsPerRow(); - Channel references(properties.size() - kNumNonrefProperties, channel.w); + JXL_ASSIGN_OR_RETURN( + Channel references, + Channel::Create(properties.size() - kNumNonrefProperties, channel.w)); for (size_t y = 0; y < channel.h; y++) { const pixel_type *JXL_RESTRICT p = channel.Row(y); PrecomputeReferences(channel, y, image, chan, &references); @@ -481,7 +479,9 @@ Status EncodeModularChannelMAANS(const Image &image, pixel_type chan, } } else { const intptr_t onerow = channel.plane.PixelsPerRow(); - Channel references(properties.size() - kNumNonrefProperties, channel.w); + JXL_ASSIGN_OR_RETURN( + Channel references, + Channel::Create(properties.size() - kNumNonrefProperties, channel.w)); weighted::State wp_state(wp_header, channel.w, channel.h); for (size_t y = 0; y < channel.h; y++) { const pixel_type *JXL_RESTRICT p = channel.Row(y); @@ -556,8 +556,20 @@ Status ModularEncode(const Image &image, const ModularOptions &options, TreeSamples tree_samples_storage; size_t total_pixels_storage = 0; if (!total_pixels) total_pixels = &total_pixels_storage; + if (*total_pixels == 0) { + for (size_t i = 0; i < nb_channels; i++) { + if (i >= image.nb_meta_channels && + (image.channel[i].w > options.max_chan_size || + image.channel[i].h > options.max_chan_size)) { + break; + } + *total_pixels += image.channel[i].w * image.channel[i].h; + } + *total_pixels = std::max(*total_pixels, 1); + } // If there's no tree, compute one (or gather data to). - if (tree == nullptr) { + if (tree == nullptr && + options.tree_kind == ModularOptions::TreeKind::kLearn) { bool gather_data = tree_samples != nullptr; if (tree_samples == nullptr) { JXL_RETURN_IF_ERROR(tree_samples_storage.SetPredictor( @@ -586,9 +598,9 @@ Status ModularEncode(const Image &image, const ModularOptions &options, image.channel[i].h > options.max_chan_size)) { break; } - GatherTreeData(image, i, group_id, header->wp_header, options, - gather_data ? *tree_samples : tree_samples_storage, - total_pixels); + JXL_RETURN_IF_ERROR(GatherTreeData( + image, i, group_id, header->wp_header, options, + gather_data ? *tree_samples : tree_samples_storage, total_pixels)); } if (gather_data) return true; } @@ -609,10 +621,10 @@ Status ModularEncode(const Image &image, const ModularOptions &options, ? LearnTree(std::move(tree_samples_storage), *total_pixels, options) : PredefinedTree(options.tree_kind, *total_pixels); tree = &tree_storage; - tokens = &tokens_storage[0]; + tokens = tokens_storage.data(); Tree decoded_tree; - TokenizeTree(*tree, &tree_tokens[0], &decoded_tree); + TokenizeTree(*tree, tree_tokens.data(), &decoded_tree); JXL_ASSERT(tree->size() == decoded_tree.size()); tree_storage = std::move(decoded_tree); @@ -622,9 +634,9 @@ Status ModularEncode(const Image &image, const ModularOptions &options, } */ // Write tree - BuildAndEncodeHistograms(HistogramParams(), kNumTreeContexts, tree_tokens, - &code, &context_map, writer, kLayerModularTree, - aux_out); + BuildAndEncodeHistograms(options.histogram_params, kNumTreeContexts, + tree_tokens, &code, &context_map, writer, + kLayerModularTree, aux_out); WriteTokens(tree_tokens[0], code, context_map, 0, writer, kLayerModularTree, aux_out); } @@ -669,7 +681,7 @@ Status ModularEncode(const Image &image, const ModularOptions &options, if (!header->use_global_tree) { EntropyEncodingData code; std::vector context_map; - HistogramParams histo_params; + HistogramParams histo_params = options.histogram_params; histo_params.image_widths.push_back(image_width); BuildAndEncodeHistograms(histo_params, (tree->size() + 1) / 2, tokens_storage, &code, &context_map, writer, layer, @@ -691,7 +703,7 @@ Status ModularGenericCompress(Image &image, const ModularOptions &opts, if (image.w == 0 || image.h == 0) return true; ModularOptions options = opts; // Make a copy to modify it. - if (options.predictor == static_cast(-1)) { + if (options.predictor == kUndefinedPredictor) { options.predictor = Predictor::Gradient; } diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_ma.cc b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_ma.cc index ef72b2477b..de629ad038 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_ma.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/enc_ma.cc @@ -109,8 +109,8 @@ IntersectionType BoxIntersects(StaticPropRange needle, StaticPropRange haystack, void SplitTreeSamples(TreeSamples &tree_samples, size_t begin, size_t pos, size_t end, size_t prop) { auto cmp = [&](size_t a, size_t b) { - return int32_t(tree_samples.Property(prop, a)) - - int32_t(tree_samples.Property(prop, b)); + return static_cast(tree_samples.Property(prop, a)) - + static_cast(tree_samples.Property(prop, b)); }; Rng rng(0); while (end > begin + 1) { @@ -243,7 +243,8 @@ void FindBestSplit(TreeSamples &tree_samples, float threshold, // properties. We do this even if the current node is not a leaf, to // minimize the number of nodes in the resulting tree. for (size_t i = 0; i < mul_info.size(); i++) { - uint32_t axis, val; + uint32_t axis; + uint32_t val; IntersectionType t = BoxIntersects(static_prop_range, mul_info[i].range, axis, val); if (t == IntersectionType::kNone) continue; @@ -696,7 +697,11 @@ void TreeSamples::Swap(size_t a, size_t b) { } void TreeSamples::ThreeShuffle(size_t a, size_t b, size_t c) { - if (b == c) return Swap(a, b); + if (b == c) { + Swap(a, b); + return; + } + for (auto &r : residuals) { auto tmp = r[a]; r[a] = r[c]; @@ -966,7 +971,7 @@ void CollectPixelSamples(const Image &image, const ModularOptions &options, const pixel_type *row = image.channel[channel_ids[i]].Row(y); pixel_samples.push_back(row[x]); size_t xp = x == 0 ? 1 : x - 1; - diff_samples.push_back((int64_t)row[x] - row[xp]); + diff_samples.push_back(static_cast(row[x]) - row[xp]); } } diff --git a/third_party/jpeg-xl/lib/jxl/modular/encoding/encoding.cc b/third_party/jpeg-xl/lib/jxl/modular/encoding/encoding.cc index a6abdcfc91..bb690b74ba 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/encoding/encoding.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/encoding/encoding.cc @@ -14,6 +14,8 @@ #include "lib/jxl/base/scope_guard.h" #include "lib/jxl/dec_ans.h" #include "lib/jxl/dec_bit_reader.h" +#include "lib/jxl/frame_dimensions.h" +#include "lib/jxl/image_ops.h" #include "lib/jxl/modular/encoding/context_predict.h" #include "lib/jxl/modular/options.h" #include "lib/jxl/pack_signed.h" @@ -141,7 +143,7 @@ Status DecodeModularChannelMAANS(BitReader *br, ANSSymbolReader *reader, Channel &channel = image->channel[chan]; std::array static_props = { - {chan, (int)group_id}}; + {chan, static_cast(group_id)}}; // TODO(veluca): filter the tree according to static_props. // zero pixel channel? could happen @@ -376,7 +378,9 @@ Status DecodeModularChannelMAANS(BitReader *br, ANSSymbolReader *reader, MATreeLookup tree_lookup(tree); Properties properties = Properties(num_props); const intptr_t onerow = channel.plane.PixelsPerRow(); - Channel references(properties.size() - kNumNonrefProperties, channel.w); + JXL_ASSIGN_OR_RETURN( + Channel references, + Channel::Create(properties.size() - kNumNonrefProperties, channel.w)); for (size_t y = 0; y < channel.h; y++) { pixel_type *JXL_RESTRICT p = channel.Row(y); PrecomputeReferences(channel, y, *image, chan, &references); @@ -422,7 +426,9 @@ Status DecodeModularChannelMAANS(BitReader *br, ANSSymbolReader *reader, MATreeLookup tree_lookup(tree); Properties properties = Properties(num_props); const intptr_t onerow = channel.plane.PixelsPerRow(); - Channel references(properties.size() - kNumNonrefProperties, channel.w); + JXL_ASSIGN_OR_RETURN( + Channel references, + Channel::Create(properties.size() - kNumNonrefProperties, channel.w)); weighted::State wp_state(wp_header, channel.w, channel.h); for (size_t y = 0; y < channel.h; y++) { pixel_type *JXL_RESTRICT p = channel.Row(y); diff --git a/third_party/jpeg-xl/lib/jxl/modular/modular_image.cc b/third_party/jpeg-xl/lib/jxl/modular/modular_image.cc index 746d7c87fd..32a5531080 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/modular_image.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/modular_image.cc @@ -8,6 +8,7 @@ #include #include "lib/jxl/base/status.h" +#include "lib/jxl/image_ops.h" #include "lib/jxl/modular/transform/transform.h" namespace jxl { @@ -28,9 +29,18 @@ void Image::undo_transforms(const weighted::Header &wp_header, } } -Image::Image(size_t iw, size_t ih, int bitdepth, int nb_chans) - : w(iw), h(ih), bitdepth(bitdepth), nb_meta_channels(0), error(false) { - for (int i = 0; i < nb_chans; i++) channel.emplace_back(Channel(iw, ih)); +Image::Image(size_t iw, size_t ih, int bitdepth) + : w(iw), h(ih), bitdepth(bitdepth), nb_meta_channels(0), error(false) {} + +StatusOr Image::Create(size_t iw, size_t ih, int bitdepth, + int nb_chans) { + Image result(iw, ih, bitdepth); + for (int i = 0; i < nb_chans; i++) { + StatusOr channel_or = Channel::Create(iw, ih); + JXL_RETURN_IF_ERROR(channel_or.status()); + result.channel.emplace_back(std::move(channel_or).value()); + } + return result; } Image::Image() : w(0), h(0), bitdepth(8), nb_meta_channels(0), error(true) {} @@ -46,17 +56,18 @@ Image &Image::operator=(Image &&other) noexcept { return *this; } -Image Image::clone() { - Image c(w, h, bitdepth, 0); - c.nb_meta_channels = nb_meta_channels; - c.error = error; - c.transform = transform; - for (Channel &ch : channel) { - Channel a(ch.w, ch.h, ch.hshift, ch.vshift); +StatusOr Image::Clone(const Image &that) { + Image clone(that.w, that.h, that.bitdepth); + clone.nb_meta_channels = that.nb_meta_channels; + clone.error = that.error; + clone.transform = that.transform; + for (const Channel &ch : that.channel) { + JXL_ASSIGN_OR_RETURN(Channel a, + Channel::Create(ch.w, ch.h, ch.hshift, ch.vshift)); CopyImageTo(ch.plane, &a.plane); - c.channel.push_back(std::move(a)); + clone.channel.push_back(std::move(a)); } - return c; + return clone; } #if JXL_DEBUG_V_LEVEL >= 1 diff --git a/third_party/jpeg-xl/lib/jxl/modular/modular_image.h b/third_party/jpeg-xl/lib/jxl/modular/modular_image.h index 56e80d823a..eb95b1cb6c 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/modular_image.h +++ b/third_party/jpeg-xl/lib/jxl/modular/modular_image.h @@ -18,7 +18,6 @@ #include "lib/jxl/base/data_parallel.h" #include "lib/jxl/base/status.h" #include "lib/jxl/image.h" -#include "lib/jxl/image_ops.h" namespace jxl { @@ -36,12 +35,16 @@ class Channel { jxl::Plane plane; size_t w, h; int hshift, vshift; // w ~= image.w >> hshift; h ~= image.h >> vshift - Channel(size_t iw, size_t ih, int hsh = 0, int vsh = 0) - : plane(iw, ih), w(iw), h(ih), hshift(hsh), vshift(vsh) {} - Channel(const Channel& other) = delete; Channel& operator=(const Channel& other) = delete; + static StatusOr Create(size_t iw, size_t ih, int hsh = 0, + int vsh = 0) { + JXL_ASSIGN_OR_RETURN(Plane plane, + Plane::Create(iw, ih)); + return Channel(std::move(plane), iw, ih, hsh, vsh); + } + // Move assignment Channel& operator=(Channel&& other) noexcept { w = other.w; @@ -55,21 +58,25 @@ class Channel { // Move constructor Channel(Channel&& other) noexcept = default; - void shrink() { - if (plane.xsize() == w && plane.ysize() == h) return; - jxl::Plane resizedplane(w, h); - plane = std::move(resizedplane); + Status shrink() { + if (plane.xsize() == w && plane.ysize() == h) return true; + JXL_ASSIGN_OR_RETURN(plane, Plane::Create(w, h)); + return true; } - void shrink(int nw, int nh) { + Status shrink(int nw, int nh) { w = nw; h = nh; - shrink(); + return shrink(); } JXL_INLINE pixel_type* Row(const size_t y) { return plane.Row(y); } JXL_INLINE const pixel_type* Row(const size_t y) const { return plane.Row(y); } + + private: + Channel(jxl::Plane&& p, size_t iw, size_t ih, int hsh, int vsh) + : plane(std::move(p)), w(iw), h(ih), hshift(hsh), vshift(vsh) {} }; class Transform; @@ -88,7 +95,6 @@ class Image { size_t nb_meta_channels; // first few channels might contain palette(s) bool error; // true if a fatal error occurred, false otherwise - Image(size_t iw, size_t ih, int bitdepth, int nb_chans); Image(); Image(const Image& other) = delete; @@ -97,6 +103,9 @@ class Image { Image& operator=(Image&& other) noexcept; Image(Image&& other) noexcept = default; + static StatusOr Create(size_t iw, size_t ih, int bitdepth, + int nb_chans); + bool empty() const { for (const auto& ch : channel) { if (ch.w && ch.h) return false; @@ -104,12 +113,15 @@ class Image { return true; } - Image clone(); + static StatusOr Clone(const Image& that); void undo_transforms(const weighted::Header& wp_header, jxl::ThreadPool* pool = nullptr); std::string DebugString() const; + + private: + Image(size_t iw, size_t ih, int bitdepth); }; } // namespace jxl diff --git a/third_party/jpeg-xl/lib/jxl/modular/options.h b/third_party/jpeg-xl/lib/jxl/modular/options.h index ce6596b912..6613b513de 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/options.h +++ b/third_party/jpeg-xl/lib/jxl/modular/options.h @@ -11,6 +11,8 @@ #include #include +#include "lib/jxl/enc_ans_params.h" + namespace jxl { using PropertyVal = int32_t; @@ -37,6 +39,8 @@ enum class Predictor : uint32_t { 15, // Find the best decision tree for predictors/predictor per row }; +constexpr Predictor kUndefinedPredictor = static_cast(~0u); + constexpr size_t kNumModularPredictors = static_cast(Predictor::Average4) + 1; constexpr size_t kNumModularEncoderPredictors = @@ -80,7 +84,7 @@ struct ModularOptions { size_t max_property_values = 32; // Predictor to use for each channel. - Predictor predictor = static_cast(-1); + Predictor predictor = kUndefinedPredictor; int wp_mode = 0; @@ -108,6 +112,8 @@ struct ModularOptions { }; TreeKind tree_kind = TreeKind::kLearn; + HistogramParams histogram_params; + // Ignore the image and just pretend all tokens are zeroes bool zero_tokens = false; }; diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc index f5172aa126..24c64f5aad 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/enc_palette.cc @@ -10,8 +10,8 @@ #include #include "lib/jxl/base/common.h" -#include "lib/jxl/base/data_parallel.h" #include "lib/jxl/base/status.h" +#include "lib/jxl/image_ops.h" #include "lib/jxl/modular/encoding/context_predict.h" #include "lib/jxl/modular/modular_image.h" #include "lib/jxl/modular/transform/enc_transform.h" @@ -34,7 +34,8 @@ float ColorDistance(const std::vector &JXL_RESTRICT a, if (a.size() >= 3) { ave3 = (a[0] + b[0] + a[1] + b[1] + a[2] + b[2]) * (1.21f / 3.0f); } - float sum_a = 0, sum_b = 0; + float sum_a = 0; + float sum_b = 0; for (size_t c = 0; c < a.size(); ++c) { const float difference = static_cast(a[c]) - static_cast(b[c]); @@ -132,7 +133,8 @@ struct PaletteIterationData { delta_frequency.first[1], delta_frequency.first[2]}; float delta_distance = - sqrt(palette_internal::ColorDistance({0, 0, 0}, current_delta)) + 1; + std::sqrt(palette_internal::ColorDistance({0, 0, 0}, current_delta)) + + 1; delta_frequency.second *= delta_distance * delta_distance_multiplier; } @@ -174,7 +176,8 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, // Channel palette special case if (nb_colors == 0) return false; std::vector lookup; - pixel_type minval, maxval; + pixel_type minval; + pixel_type maxval; compute_minmax(input.channel[begin_c], &minval, &maxval); size_t lookup_table_size = static_cast(maxval) - static_cast(minval) + 1; @@ -189,12 +192,12 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, const bool new_color = chpalette.insert(p[x]).second; if (new_color) { idx++; - if (idx > (int)nb_colors) return false; + if (idx > static_cast(nb_colors)) return false; } } } JXL_DEBUG_V(6, "Channel %i uses only %i colors.", begin_c, idx); - Channel pch(idx, 1); + JXL_ASSIGN_OR_RETURN(Channel pch, Channel::Create(idx, 1)); pch.hshift = -1; pch.vshift = -1; nb_colors = idx; @@ -206,9 +209,12 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, for (size_t y = 0; y < h; y++) { pixel_type *p = input.channel[begin_c].Row(y); for (size_t x = 0; x < w; x++) { - for (idx = 0; p[x] != p_palette[idx] && idx < (int)nb_colors; idx++) { + for (idx = 0; + p[x] != p_palette[idx] && idx < static_cast(nb_colors); + idx++) { + // no-op } - JXL_DASSERT(idx < (int)nb_colors); + JXL_DASSERT(idx < static_cast(nb_colors)); p[x] = idx; } } @@ -226,12 +232,12 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, if (lookup[p[x] - minval] == 0) { lookup[p[x] - minval] = 1; idx++; - if (idx > (int)nb_colors) return false; + if (idx > static_cast(nb_colors)) return false; } } } JXL_DEBUG_V(6, "Channel %i uses only %i colors.", begin_c, idx); - Channel pch(idx, 1); + JXL_ASSIGN_OR_RETURN(Channel pch, Channel::Create(idx, 1)); pch.hshift = -1; pch.vshift = -1; nb_colors = idx; @@ -256,7 +262,8 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, Image quantized_input; if (lossy) { - quantized_input = Image(w, h, input.bitdepth, nb); + JXL_ASSIGN_OR_RETURN(quantized_input, + Image::Create(w, h, input.bitdepth, nb)); for (size_t c = 0; c < nb; c++) { CopyImageTo(input.channel[begin_c + c].plane, &quantized_input.channel[c].plane); @@ -337,7 +344,7 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, JXL_DEBUG_V(6, "Channels %i-%i can be represented using a %i-color palette.", begin_c, end_c, nb_colors); - Channel pch(nb_colors, nb); + JXL_ASSIGN_OR_RETURN(Channel pch, Channel::Create(nb_colors, nb)); pch.hshift = -1; pch.vshift = -1; pixel_type *JXL_RESTRICT p_palette = pch.Row(0); @@ -361,7 +368,8 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, std::sort(candidate_palette_imageorder.begin(), candidate_palette_imageorder.end(), [](std::vector ap, std::vector bp) { - float ay, by; + float ay; + float by; ay = (0.299f * ap[0] + 0.587f * ap[1] + 0.114f * ap[2] + 0.1f); if (ap.size() > 3) ay *= 1.f + ap[3]; by = (0.299f * bp[0] + 0.587f * bp[1] + 0.114f * bp[2] + 0.1f); @@ -420,7 +428,7 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, for (int diffusion_index = 0; diffusion_index < 2; ++diffusion_index) { for (size_t c = 0; c < nb; c++) { color_with_error[c] = - p_in[c][x] + palette_iteration_data.final_run * + p_in[c][x] + (palette_iteration_data.final_run ? 1 : 0) * kDiffusionMultiplier[diffusion_index] * error_row[0][c][x + 2]; color[c] = Clamp1(lroundf(color_with_error[c]), 0l, @@ -503,7 +511,7 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c, float local_error = color_with_error[c] - best_val[c]; len_error += local_error * local_error; } - len_error = sqrt(len_error); + len_error = std::sqrt(len_error); float modulate = 1.0; int len_limit = 38 << std::max(0, bit_depth - 8); if (len_error > len_limit) { diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/enc_squeeze.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/enc_squeeze.cc index 489f72a90d..0d924c0ace 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/enc_squeeze.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/enc_squeeze.cc @@ -14,15 +14,20 @@ namespace jxl { -void FwdHSqueeze(Image &input, int c, int rc) { +#define AVERAGE(X, Y) (((X) + (Y) + (((X) > (Y)) ? 1 : 0)) >> 1) + +Status FwdHSqueeze(Image &input, int c, int rc) { const Channel &chin = input.channel[c]; JXL_DEBUG_V(4, "Doing horizontal squeeze of channel %i to new channel %i", c, rc); - Channel chout((chin.w + 1) / 2, chin.h, chin.hshift + 1, chin.vshift); - Channel chout_residual(chin.w - chout.w, chout.h, chin.hshift + 1, - chin.vshift); + JXL_ASSIGN_OR_RETURN( + Channel chout, + Channel::Create((chin.w + 1) / 2, chin.h, chin.hshift + 1, chin.vshift)); + JXL_ASSIGN_OR_RETURN( + Channel chout_residual, + Channel::Create(chin.w - chout.w, chout.h, chin.hshift + 1, chin.vshift)); for (size_t y = 0; y < chout.h; y++) { const pixel_type *JXL_RESTRICT p_in = chin.Row(y); @@ -31,18 +36,19 @@ void FwdHSqueeze(Image &input, int c, int rc) { for (size_t x = 0; x < chout_residual.w; x++) { pixel_type A = p_in[x * 2]; pixel_type B = p_in[x * 2 + 1]; - pixel_type avg = (A + B + (A > B)) >> 1; + pixel_type avg = AVERAGE(A, B); p_out[x] = avg; pixel_type diff = A - B; pixel_type next_avg = avg; if (x + 1 < chout_residual.w) { - next_avg = (p_in[x * 2 + 2] + p_in[x * 2 + 3] + - (p_in[x * 2 + 2] > p_in[x * 2 + 3])) >> - 1; // which will be chout.value(y,x+1) - } else if (chin.w & 1) + pixel_type C = p_in[x * 2 + 2]; + pixel_type D = p_in[x * 2 + 3]; + next_avg = AVERAGE(C, D); // which will be chout.value(y,x+1) + } else if (chin.w & 1) { next_avg = p_in[x * 2 + 2]; + } pixel_type left = (x > 0 ? p_in[x * 2 - 1] : avg); pixel_type tendency = SmoothTendency(left, avg, next_avg); @@ -55,17 +61,21 @@ void FwdHSqueeze(Image &input, int c, int rc) { } input.channel[c] = std::move(chout); input.channel.insert(input.channel.begin() + rc, std::move(chout_residual)); + return true; } -void FwdVSqueeze(Image &input, int c, int rc) { +Status FwdVSqueeze(Image &input, int c, int rc) { const Channel &chin = input.channel[c]; JXL_DEBUG_V(4, "Doing vertical squeeze of channel %i to new channel %i", c, rc); - Channel chout(chin.w, (chin.h + 1) / 2, chin.hshift, chin.vshift + 1); - Channel chout_residual(chin.w, chin.h - chout.h, chin.hshift, - chin.vshift + 1); + JXL_ASSIGN_OR_RETURN( + Channel chout, + Channel::Create(chin.w, (chin.h + 1) / 2, chin.hshift, chin.vshift + 1)); + JXL_ASSIGN_OR_RETURN( + Channel chout_residual, + Channel::Create(chin.w, chin.h - chout.h, chin.hshift, chin.vshift + 1)); intptr_t onerow_in = chin.plane.PixelsPerRow(); for (size_t y = 0; y < chout_residual.h; y++) { const pixel_type *JXL_RESTRICT p_in = chin.Row(y * 2); @@ -74,16 +84,16 @@ void FwdVSqueeze(Image &input, int c, int rc) { for (size_t x = 0; x < chout.w; x++) { pixel_type A = p_in[x]; pixel_type B = p_in[x + onerow_in]; - pixel_type avg = (A + B + (A > B)) >> 1; + pixel_type avg = AVERAGE(A, B); p_out[x] = avg; pixel_type diff = A - B; pixel_type next_avg = avg; if (y + 1 < chout_residual.h) { - next_avg = (p_in[x + 2 * onerow_in] + p_in[x + 3 * onerow_in] + - (p_in[x + 2 * onerow_in] > p_in[x + 3 * onerow_in])) >> - 1; // which will be chout.value(y+1,x) + pixel_type C = p_in[x + 2 * onerow_in]; + pixel_type D = p_in[x + 3 * onerow_in]; + next_avg = AVERAGE(C, D); // which will be chout.value(y+1,x) } else if (chin.h & 1) { next_avg = p_in[x + 2 * onerow_in]; } @@ -104,6 +114,7 @@ void FwdVSqueeze(Image &input, int c, int rc) { } input.channel[c] = std::move(chout); input.channel.insert(input.channel.begin() + rc, std::move(chout_residual)); + return true; } Status FwdSqueeze(Image &input, std::vector parameters, @@ -128,9 +139,9 @@ Status FwdSqueeze(Image &input, std::vector parameters, } for (uint32_t c = beginc; c <= endc; c++) { if (horizontal) { - FwdHSqueeze(input, c, offset + c - beginc); + JXL_RETURN_IF_ERROR(FwdHSqueeze(input, c, offset + c - beginc)); } else { - FwdVSqueeze(input, c, offset + c - beginc); + JXL_RETURN_IF_ERROR(FwdVSqueeze(input, c, offset + c - beginc)); } } } diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc index bffbacf160..1ab499ccf6 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.cc @@ -23,9 +23,11 @@ Status InvPalette(Image &input, uint32_t begin_c, uint32_t nb_colors, size_t h = input.channel[c0].h; if (nb < 1) return JXL_FAILURE("Corrupted transforms"); for (int i = 1; i < nb; i++) { - input.channel.insert( - input.channel.begin() + c0 + 1, - Channel(w, h, input.channel[c0].hshift, input.channel[c0].vshift)); + StatusOr channel_or = Channel::Create( + w, h, input.channel[c0].hshift, input.channel[c0].vshift); + JXL_RETURN_IF_ERROR(channel_or.status()); + input.channel.insert(input.channel.begin() + c0 + 1, + std::move(channel_or).value()); } const Channel &palette = input.channel[0]; const pixel_type *JXL_RESTRICT p_palette = input.channel[0].Row(0); @@ -44,7 +46,8 @@ Status InvPalette(Image &input, uint32_t begin_c, uint32_t nb_colors, const size_t y = task; pixel_type *p = input.channel[c0].Row(y); for (size_t x = 0; x < w; x++) { - const int index = Clamp1(p[x], 0, (pixel_type)palette.w - 1); + const int index = + Clamp1(p[x], 0, static_cast(palette.w) - 1); p[x] = palette_internal::GetPaletteValue( p_palette, index, /*c=*/0, /*palette_size=*/palette.w, @@ -75,8 +78,10 @@ Status InvPalette(Image &input, uint32_t begin_c, uint32_t nb_colors, } } else { // Parallelized per channel. - ImageI indices = std::move(input.channel[c0].plane); - input.channel[c0].plane = ImageI(indices.xsize(), indices.ysize()); + ImageI indices; + ImageI &plane = input.channel[c0].plane; + JXL_ASSIGN_OR_RETURN(indices, ImageI::Create(plane.xsize(), plane.ysize())); + plane.Swap(indices); if (predictor == Predictor::Weighted) { JXL_RETURN_IF_ERROR(RunOnPool( pool, 0, nb, ThreadPool::NoInit, @@ -167,7 +172,7 @@ Status MetaPalette(Image &input, uint32_t begin_c, uint32_t end_c, } input.channel.erase(input.channel.begin() + begin_c + 1, input.channel.begin() + end_c + 1); - Channel pch(nb_colors + nb_deltas, nb); + JXL_ASSIGN_OR_RETURN(Channel pch, Channel::Create(nb_colors + nb_deltas, nb)); pch.hshift = -1; pch.vshift = -1; input.channel.insert(input.channel.begin(), std::move(pch)); diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h index 279ef04568..e0405a2162 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/palette.h @@ -101,6 +101,7 @@ GetPaletteValue(const pixel_type *const palette, int index, const size_t c, // index >= kLargeCube ** 3 ? switch (c) { case 0: + default: break; case 1: index /= kLargeCube; diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.cc b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.cc index e9892ea48f..580829741a 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.cc +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.cc @@ -113,7 +113,9 @@ Status InvHSqueeze(Image &input, uint32_t c, uint32_t rc, ThreadPool *pool) { } // Note: chin.w >= chin_residual.w and at most 1 different. - Channel chout(chin.w + chin_residual.w, chin.h, chin.hshift - 1, chin.vshift); + JXL_ASSIGN_OR_RETURN(Channel chout, + Channel::Create(chin.w + chin_residual.w, chin.h, + chin.hshift - 1, chin.vshift)); JXL_DEBUG_V(4, "Undoing horizontal squeeze of channel %i using residuals in " "channel %i (going from width %" PRIuS " to %" PRIuS ")", @@ -222,7 +224,9 @@ Status InvVSqueeze(Image &input, uint32_t c, uint32_t rc, ThreadPool *pool) { } // Note: chin.h >= chin_residual.h and at most 1 different. - Channel chout(chin.w, chin.h + chin_residual.h, chin.hshift, chin.vshift - 1); + JXL_ASSIGN_OR_RETURN(Channel chout, + Channel::Create(chin.w, chin.h + chin_residual.h, + chin.hshift, chin.vshift - 1)); JXL_DEBUG_V( 4, "Undoing vertical squeeze of channel %i using residuals in channel " @@ -238,7 +242,8 @@ Status InvVSqueeze(Image &input, uint32_t c, uint32_t rc, ThreadPool *pool) { static constexpr const int kColsPerThread = 64; const auto unsqueeze_slice = [&](const uint32_t task, size_t /* thread */) { const size_t x0 = task * kColsPerThread; - const size_t x1 = std::min((size_t)(task + 1) * kColsPerThread, chin.w); + const size_t x1 = + std::min(static_cast(task + 1) * kColsPerThread, chin.w); const size_t w = x1 - x0; // We only iterate up to std::min(chin_residual.h, chin.h) which is // always chin_residual.h. @@ -289,7 +294,7 @@ Status InvVSqueeze(Image &input, uint32_t c, uint32_t rc, ThreadPool *pool) { return true; } -Status InvSqueeze(Image &input, std::vector parameters, +Status InvSqueeze(Image &input, const std::vector ¶meters, ThreadPool *pool) { for (int i = parameters.size() - 1; i >= 0; i--) { JXL_RETURN_IF_ERROR( @@ -340,7 +345,7 @@ HWY_AFTER_NAMESPACE(); namespace jxl { HWY_EXPORT(InvSqueeze); -Status InvSqueeze(Image &input, std::vector parameters, +Status InvSqueeze(Image &input, const std::vector ¶meters, ThreadPool *pool) { return HWY_DYNAMIC_DISPATCH(InvSqueeze)(input, parameters, pool); } @@ -459,8 +464,8 @@ Status MetaSqueeze(Image &image, std::vector *parameters) { if (image.channel[c].vshift >= 0) image.channel[c].vshift++; h = h - (h + 1) / 2; } - image.channel[c].shrink(); - Channel placeholder(w, h); + JXL_RETURN_IF_ERROR(image.channel[c].shrink()); + JXL_ASSIGN_OR_RETURN(Channel placeholder, Channel::Create(w, h)); placeholder.hshift = image.channel[c].hshift; placeholder.vshift = image.channel[c].vshift; diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h index 305a0ca3ec..bbd16c59c0 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/squeeze.h @@ -81,7 +81,7 @@ Status CheckMetaSqueezeParams(const SqueezeParams ¶meter, int num_channels); Status MetaSqueeze(Image &image, std::vector *parameters); -Status InvSqueeze(Image &input, std::vector parameters, +Status InvSqueeze(Image &input, const std::vector ¶meters, ThreadPool *pool); } // namespace jxl diff --git a/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h b/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h index d5d3259f7a..b68861706f 100644 --- a/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h +++ b/third_party/jpeg-xl/lib/jxl/modular/transform/transform.h @@ -77,11 +77,13 @@ class Transform : public Fields { Transform() : Transform(TransformId::kInvalid) {} Status VisitFields(Visitor *JXL_RESTRICT visitor) override { - JXL_QUIET_RETURN_IF_ERROR(visitor->U32( - Val((uint32_t)TransformId::kRCT), Val((uint32_t)TransformId::kPalette), - Val((uint32_t)TransformId::kSqueeze), - Val((uint32_t)TransformId::kInvalid), (uint32_t)TransformId::kRCT, - reinterpret_cast(&id))); + JXL_QUIET_RETURN_IF_ERROR( + visitor->U32(Val(static_cast(TransformId::kRCT)), + Val(static_cast(TransformId::kPalette)), + Val(static_cast(TransformId::kSqueeze)), + Val(static_cast(TransformId::kInvalid)), + static_cast(TransformId::kRCT), + reinterpret_cast(&id))); if (id == TransformId::kInvalid) { return JXL_FAILURE("Invalid transform ID"); } @@ -109,7 +111,7 @@ class Transform : public Fields { visitor->U32(Val(0), BitsOffset(8, 1), BitsOffset(10, 257), BitsOffset(16, 1281), 0, &nb_deltas)); JXL_QUIET_RETURN_IF_ERROR( - visitor->Bits(4, (uint32_t)Predictor::Zero, + visitor->Bits(4, static_cast(Predictor::Zero), reinterpret_cast(&predictor))); if (predictor >= Predictor::Best) { return JXL_FAILURE("Invalid predictor"); -- cgit v1.2.3