diff options
Diffstat (limited to 'third_party/jpeg-xl/lib/extras/dec')
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/apng.cc | 119 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/color_description.cc | 99 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/color_hints.cc | 9 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/decode.cc | 6 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/decode.h | 2 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/exr.cc | 9 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/gif.cc | 28 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/jpegli.cc | 21 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/jpg.cc | 30 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/jxl.cc | 90 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/jxl.h | 4 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/pgx.cc | 11 | ||||
-rw-r--r-- | third_party/jpeg-xl/lib/extras/dec/pnm.cc | 31 |
13 files changed, 283 insertions, 176 deletions
diff --git a/third_party/jpeg-xl/lib/extras/dec/apng.cc b/third_party/jpeg-xl/lib/extras/dec/apng.cc index f77dab77d1..8b0da06eb1 100644 --- a/third_party/jpeg-xl/lib/extras/dec/apng.cc +++ b/third_party/jpeg-xl/lib/extras/dec/apng.cc @@ -71,9 +71,7 @@ const png_byte kIgnoredPngChunks[] = { }; // Returns floating-point value from the PNG encoding (times 10^5). -static double F64FromU32(const uint32_t x) { - return static_cast<int32_t>(x) * 1E-5; -} +double F64FromU32(const uint32_t x) { return static_cast<int32_t>(x) * 1E-5; } Status DecodeSRGB(const unsigned char* payload, const size_t payload_size, JxlColorEncoding* color_encoding) { @@ -402,7 +400,8 @@ class BlobsReaderPNG { } if (pos + 2 >= encoded_end) return false; // Truncated base16 2; - uint32_t nibble0, nibble1; + uint32_t nibble0; + uint32_t nibble1; JXL_RETURN_IF_ERROR(DecodeNibble(pos[0], &nibble0)); JXL_RETURN_IF_ERROR(DecodeNibble(pos[1], &nibble1)); bytes->push_back(static_cast<uint8_t>((nibble0 << 4) + nibble1)); @@ -432,9 +431,22 @@ constexpr uint32_t kId_cHRM = 0x4D524863; constexpr uint32_t kId_eXIf = 0x66495865; struct APNGFrame { - std::vector<uint8_t> pixels; + APNGFrame() : pixels(nullptr, free) {} + std::unique_ptr<void, decltype(free)*> pixels; + size_t pixels_size = 0; std::vector<uint8_t*> rows; unsigned int w, h, delay_num, delay_den; + Status Resize(size_t new_size) { + if (new_size > pixels_size) { + pixels.reset(malloc(new_size)); + if (!pixels.get()) { + // TODO(szabadka): use specialized OOM error code + return JXL_FAILURE("Failed to allocate memory for image buffer"); + } + pixels_size = new_size; + } + return true; + } }; struct Reader { @@ -447,7 +459,7 @@ struct Reader { next += to_copy; return (len == to_copy); } - bool Eof() { return next == last; } + bool Eof() const { return next == last; } }; const unsigned long cMaxPNGSize = 1000000UL; @@ -463,10 +475,11 @@ void info_fn(png_structp png_ptr, png_infop info_ptr) { void row_fn(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass) { - APNGFrame* frame = (APNGFrame*)png_get_progressive_ptr(png_ptr); + APNGFrame* frame = + reinterpret_cast<APNGFrame*>(png_get_progressive_ptr(png_ptr)); JXL_CHECK(frame); JXL_CHECK(row_num < frame->rows.size()); - JXL_CHECK(frame->rows[row_num] < frame->pixels.data() + frame->pixels.size()); + JXL_CHECK(frame->rows[row_num] < frame->rows[0] + frame->pixels_size); png_progressive_combine_row(png_ptr, frame->rows[row_num], new_row); } @@ -494,12 +507,13 @@ int processing_start(png_structp& png_ptr, png_infop& info_ptr, void* frame_ptr, unsigned char header[8] = {137, 80, 78, 71, 13, 10, 26, 10}; // Cleanup prior decoder, if any. - png_destroy_read_struct(&png_ptr, &info_ptr, 0); + png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); // Just in case. Not all versions on libpng wipe-out the pointers. png_ptr = nullptr; info_ptr = nullptr; - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); info_ptr = png_create_info_struct(png_ptr); if (!png_ptr || !info_ptr) return 1; @@ -508,18 +522,17 @@ int processing_start(png_structp& png_ptr, png_infop& info_ptr, void* frame_ptr, } png_set_keep_unknown_chunks(png_ptr, 1, kIgnoredPngChunks, - (int)sizeof(kIgnoredPngChunks) / 5); + static_cast<int>(sizeof(kIgnoredPngChunks) / 5)); png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE); - png_set_progressive_read_fn(png_ptr, frame_ptr, info_fn, row_fn, NULL); + png_set_progressive_read_fn(png_ptr, frame_ptr, info_fn, row_fn, nullptr); png_process_data(png_ptr, info_ptr, header, 8); png_process_data(png_ptr, info_ptr, chunkIHDR.data(), chunkIHDR.size()); if (hasInfo) { - for (unsigned int i = 0; i < chunksInfo.size(); i++) { - png_process_data(png_ptr, info_ptr, chunksInfo[i].data(), - chunksInfo[i].size()); + for (auto& chunk : chunksInfo) { + png_process_data(png_ptr, info_ptr, chunk.data(), chunk.size()); } } return 0; @@ -575,8 +588,6 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, const SizeConstraints* constraints) { #if JPEGXL_ENABLE_APNG Reader r; - unsigned int id, j, w, h, w0, h0, x0, y0; - unsigned int delay_num, delay_den, dop, bop, rowbytes, imagesize; unsigned char sig[8]; png_structp png_ptr = nullptr; png_infop info_ptr = nullptr; @@ -588,7 +599,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, bool seenFctl = false; APNGFrame frameRaw = {}; uint32_t num_channels; - JxlPixelFormat format; + JxlPixelFormat format = {}; unsigned int bytes_per_pixel = 0; struct FrameInfo { @@ -604,7 +615,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, // Make sure png memory is released in any case. auto scope_guard = MakeScopeGuard([&]() { - png_destroy_read_struct(&png_ptr, &info_ptr, 0); + png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); // Just in case. Not all versions on libpng wipe-out the pointers. png_ptr = nullptr; info_ptr = nullptr; @@ -616,7 +627,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, if (!r.Read(sig, 8) || memcmp(sig, png_signature, 8) != 0) { return false; } - id = read_chunk(&r, &chunkIHDR); + unsigned int id = read_chunk(&r, &chunkIHDR); ppf->info.exponent_bits_per_sample = 0; ppf->info.alpha_exponent_bits = 0; @@ -625,18 +636,22 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, ppf->frames.clear(); bool have_color = false; - bool have_cicp = false, have_iccp = false, have_srgb = false; + bool have_cicp = false; + bool have_iccp = false; + bool have_srgb = false; bool errorstate = true; if (id == kId_IHDR && chunkIHDR.size() == 25) { - x0 = 0; - y0 = 0; - delay_num = 1; - delay_den = 10; - dop = 0; - bop = 0; - - w0 = w = png_get_uint_32(chunkIHDR.data() + 8); - h0 = h = png_get_uint_32(chunkIHDR.data() + 12); + unsigned int x0 = 0; + unsigned int y0 = 0; + unsigned int delay_num = 1; + unsigned int delay_den = 10; + unsigned int dop = 0; + unsigned int bop = 0; + + unsigned int w = png_get_uint_32(chunkIHDR.data() + 8); + unsigned int h = png_get_uint_32(chunkIHDR.data() + 12); + unsigned int w0 = w; + unsigned int h0 = h; if (w > cMaxPNGSize || h > cMaxPNGSize) { return false; } @@ -648,8 +663,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, ppf->color_encoding.transfer_function = JXL_TRANSFER_FUNCTION_SRGB; ppf->color_encoding.rendering_intent = JXL_RENDERING_INTENT_RELATIVE; - if (!processing_start(png_ptr, info_ptr, (void*)&frameRaw, hasInfo, - chunkIHDR, chunksInfo)) { + if (!processing_start(png_ptr, info_ptr, static_cast<void*>(&frameRaw), + hasInfo, chunkIHDR, chunksInfo)) { while (!r.Eof()) { id = read_chunk(&r, &chunk); if (!id) break; @@ -657,7 +672,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, if (id == kId_acTL && !hasInfo && !isAnimated) { isAnimated = true; - ppf->info.have_animation = true; + ppf->info.have_animation = JXL_TRUE; ppf->info.animation.tps_numerator = 1000; ppf->info.animation.tps_denominator = 1; } else if (id == kId_IEND || @@ -666,8 +681,10 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, if (!processing_finish(png_ptr, info_ptr, &ppf->metadata)) { // Allocates the frame buffer. uint32_t duration = delay_num * 1000 / delay_den; - frames.push_back(FrameInfo{PackedImage(w0, h0, format), duration, - x0, w0, y0, h0, dop, bop}); + JXL_ASSIGN_OR_RETURN(PackedImage image, + PackedImage::Create(w0, h0, format)); + frames.push_back(FrameInfo{std::move(image), duration, x0, w0, y0, + h0, dop, bop}); auto& frame = frames.back().data; for (size_t y = 0; y < h0; ++y) { memcpy(static_cast<uint8_t*>(frame.pixels()) + frame.stride * y, @@ -707,7 +724,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, if (hasInfo) { memcpy(chunkIHDR.data() + 8, chunk.data() + 12, 8); - if (processing_start(png_ptr, info_ptr, (void*)&frameRaw, hasInfo, + if (processing_start(png_ptr, info_ptr, + static_cast<void*>(&frameRaw), hasInfo, chunkIHDR, chunksInfo)) { break; } @@ -724,7 +742,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, int colortype = png_get_color_type(png_ptr, info_ptr); int png_bit_depth = png_get_bit_depth(png_ptr, info_ptr); ppf->info.bits_per_sample = png_bit_depth; - png_color_8p sigbits = NULL; + png_color_8p sigbits = nullptr; png_get_sBIT(png_ptr, info_ptr, &sigbits); if (colortype & 1) { // palette will actually be 8-bit regardless of the index bitdepth @@ -784,12 +802,18 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, } bytes_per_pixel = num_channels * (format.data_type == JXL_TYPE_UINT16 ? 2 : 1); - rowbytes = w * bytes_per_pixel; - imagesize = h * rowbytes; - frameRaw.pixels.resize(imagesize); + size_t rowbytes = w * bytes_per_pixel; + if (h > std::numeric_limits<size_t>::max() / rowbytes) { + return JXL_FAILURE("Image too big."); + } + size_t imagesize = h * rowbytes; + JXL_RETURN_IF_ERROR(frameRaw.Resize(imagesize)); frameRaw.rows.resize(h); - for (j = 0; j < h; j++) - frameRaw.rows[j] = frameRaw.pixels.data() + j * rowbytes; + for (size_t j = 0; j < h; j++) { + frameRaw.rows[j] = + reinterpret_cast<uint8_t*>(frameRaw.pixels.get()) + + j * rowbytes; + } if (processing_data(png_ptr, info_ptr, chunk.data(), chunk.size())) { break; @@ -813,6 +837,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, have_cicp = true; have_color = true; ppf->icc.clear(); + ppf->primary_color_representation = + PackedPixelFile::kColorEncodingIsPrimary; } } else if (!have_cicp && id == kId_iCCP) { if (processing_data(png_ptr, info_ptr, chunk.data(), chunk.size())) { @@ -830,6 +856,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, &profile, &proflen); if (ok && proflen) { ppf->icc.assign(profile, profile + proflen); + ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary; have_color = true; have_iccp = true; } else { @@ -922,7 +949,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, py0 + pys >= y0 + ysize && use_for_next_frame) { // If the new frame is contained within the old frame, we can pad the // new frame with zeros and not blend. - PackedImage new_data(pxs, pys, frame.data.format); + JXL_ASSIGN_OR_RETURN(PackedImage new_data, + PackedImage::Create(pxs, pys, frame.data.format)); memset(new_data.pixels(), 0, new_data.pixels_size); for (size_t y = 0; y < ysize; y++) { size_t bytes_per_pixel = @@ -944,7 +972,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, ppf->frames.emplace_back(std::move(new_data)); } else { // If all else fails, insert a placeholder blank frame with kReplace. - PackedImage blank(pxs, pys, frame.data.format); + JXL_ASSIGN_OR_RETURN(PackedImage blank, + PackedImage::Create(pxs, pys, frame.data.format)); memset(blank.pixels(), 0, blank.pixels_size); ppf->frames.emplace_back(std::move(blank)); auto& pframe = ppf->frames.back(); @@ -984,7 +1013,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes, has_nontrivial_background && frame.dispose_op == DISPOSE_OP_BACKGROUND; } if (ppf->frames.empty()) return JXL_FAILURE("No frames decoded"); - ppf->frames.back().frame_info.is_last = true; + ppf->frames.back().frame_info.is_last = JXL_TRUE; return true; #else diff --git a/third_party/jpeg-xl/lib/extras/dec/color_description.cc b/third_party/jpeg-xl/lib/extras/dec/color_description.cc index 54f6aa4206..bf229632d0 100644 --- a/third_party/jpeg-xl/lib/extras/dec/color_description.cc +++ b/third_party/jpeg-xl/lib/extras/dec/color_description.cc @@ -9,6 +9,8 @@ #include <cmath> +#include "lib/jxl/base/common.h" + namespace jxl { namespace { @@ -19,49 +21,46 @@ struct EnumName { T value; }; -const EnumName<JxlColorSpace> kJxlColorSpaceNames[] = { - {"RGB", JXL_COLOR_SPACE_RGB}, - {"Gra", JXL_COLOR_SPACE_GRAY}, - {"XYB", JXL_COLOR_SPACE_XYB}, - {"CS?", JXL_COLOR_SPACE_UNKNOWN}, -}; - -const EnumName<JxlWhitePoint> kJxlWhitePointNames[] = { - {"D65", JXL_WHITE_POINT_D65}, - {"Cst", JXL_WHITE_POINT_CUSTOM}, - {"EER", JXL_WHITE_POINT_E}, - {"DCI", JXL_WHITE_POINT_DCI}, -}; - -const EnumName<JxlPrimaries> kJxlPrimariesNames[] = { - {"SRG", JXL_PRIMARIES_SRGB}, - {"Cst", JXL_PRIMARIES_CUSTOM}, - {"202", JXL_PRIMARIES_2100}, - {"DCI", JXL_PRIMARIES_P3}, -}; - -const EnumName<JxlTransferFunction> kJxlTransferFunctionNames[] = { - {"709", JXL_TRANSFER_FUNCTION_709}, - {"TF?", JXL_TRANSFER_FUNCTION_UNKNOWN}, - {"Lin", JXL_TRANSFER_FUNCTION_LINEAR}, - {"SRG", JXL_TRANSFER_FUNCTION_SRGB}, - {"PeQ", JXL_TRANSFER_FUNCTION_PQ}, - {"DCI", JXL_TRANSFER_FUNCTION_DCI}, - {"HLG", JXL_TRANSFER_FUNCTION_HLG}, - {"", JXL_TRANSFER_FUNCTION_GAMMA}, -}; - -const EnumName<JxlRenderingIntent> kJxlRenderingIntentNames[] = { - {"Per", JXL_RENDERING_INTENT_PERCEPTUAL}, - {"Rel", JXL_RENDERING_INTENT_RELATIVE}, - {"Sat", JXL_RENDERING_INTENT_SATURATION}, - {"Abs", JXL_RENDERING_INTENT_ABSOLUTE}, -}; - -template <typename T> -Status ParseEnum(const std::string& token, const EnumName<T>* enum_values, - size_t enum_len, T* value) { - for (size_t i = 0; i < enum_len; i++) { +constexpr auto kJxlColorSpaceNames = + to_array<EnumName<JxlColorSpace>>({{"RGB", JXL_COLOR_SPACE_RGB}, + {"Gra", JXL_COLOR_SPACE_GRAY}, + {"XYB", JXL_COLOR_SPACE_XYB}, + {"CS?", JXL_COLOR_SPACE_UNKNOWN}}); + +constexpr auto kJxlWhitePointNames = + to_array<EnumName<JxlWhitePoint>>({{"D65", JXL_WHITE_POINT_D65}, + {"Cst", JXL_WHITE_POINT_CUSTOM}, + {"EER", JXL_WHITE_POINT_E}, + {"DCI", JXL_WHITE_POINT_DCI}}); + +constexpr auto kJxlPrimariesNames = + to_array<EnumName<JxlPrimaries>>({{"SRG", JXL_PRIMARIES_SRGB}, + {"Cst", JXL_PRIMARIES_CUSTOM}, + {"202", JXL_PRIMARIES_2100}, + {"DCI", JXL_PRIMARIES_P3}}); + +constexpr auto kJxlTransferFunctionNames = + to_array<EnumName<JxlTransferFunction>>( + {{"709", JXL_TRANSFER_FUNCTION_709}, + {"TF?", JXL_TRANSFER_FUNCTION_UNKNOWN}, + {"Lin", JXL_TRANSFER_FUNCTION_LINEAR}, + {"SRG", JXL_TRANSFER_FUNCTION_SRGB}, + {"PeQ", JXL_TRANSFER_FUNCTION_PQ}, + {"DCI", JXL_TRANSFER_FUNCTION_DCI}, + {"HLG", JXL_TRANSFER_FUNCTION_HLG}, + {"", JXL_TRANSFER_FUNCTION_GAMMA}}); + +constexpr auto kJxlRenderingIntentNames = + to_array<EnumName<JxlRenderingIntent>>( + {{"Per", JXL_RENDERING_INTENT_PERCEPTUAL}, + {"Rel", JXL_RENDERING_INTENT_RELATIVE}, + {"Sat", JXL_RENDERING_INTENT_SATURATION}, + {"Abs", JXL_RENDERING_INTENT_ABSOLUTE}}); + +template <typename T, size_t N> +Status ParseEnum(const std::string& token, + const std::array<EnumName<T>, N>& enum_values, T* value) { + for (size_t i = 0; i < enum_values.size(); i++) { if (enum_values[i].name == token) { *value = enum_values[i].value; return true; @@ -69,9 +68,6 @@ Status ParseEnum(const std::string& token, const EnumName<T>* enum_values, } return false; } -#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0])) -#define PARSE_ENUM(type, token, value) \ - ParseEnum<type>(token, k##type##Names, ARRAY_SIZE(k##type##Names), value) class Tokenizer { public: @@ -122,7 +118,7 @@ Status ParseColorSpace(Tokenizer* tokenizer, JxlColorEncoding* c) { std::string str; JXL_RETURN_IF_ERROR(tokenizer->Next(&str)); JxlColorSpace cs; - if (PARSE_ENUM(JxlColorSpace, str, &cs)) { + if (ParseEnum(str, kJxlColorSpaceNames, &cs)) { c->color_space = cs; return true; } @@ -139,7 +135,7 @@ Status ParseWhitePoint(Tokenizer* tokenizer, JxlColorEncoding* c) { std::string str; JXL_RETURN_IF_ERROR(tokenizer->Next(&str)); - if (PARSE_ENUM(JxlWhitePoint, str, &c->white_point)) return true; + if (ParseEnum(str, kJxlWhitePointNames, &c->white_point)) return true; Tokenizer xy_tokenizer(&str, ';'); c->white_point = JXL_WHITE_POINT_CUSTOM; @@ -157,7 +153,7 @@ Status ParsePrimaries(Tokenizer* tokenizer, JxlColorEncoding* c) { std::string str; JXL_RETURN_IF_ERROR(tokenizer->Next(&str)); - if (PARSE_ENUM(JxlPrimaries, str, &c->primaries)) return true; + if (ParseEnum(str, kJxlPrimariesNames, &c->primaries)) return true; Tokenizer xy_tokenizer(&str, ';'); JXL_RETURN_IF_ERROR(ParseDouble(&xy_tokenizer, c->primaries_red_xy + 0)); @@ -174,7 +170,8 @@ Status ParsePrimaries(Tokenizer* tokenizer, JxlColorEncoding* c) { Status ParseRenderingIntent(Tokenizer* tokenizer, JxlColorEncoding* c) { std::string str; JXL_RETURN_IF_ERROR(tokenizer->Next(&str)); - if (PARSE_ENUM(JxlRenderingIntent, str, &c->rendering_intent)) return true; + if (ParseEnum(str, kJxlRenderingIntentNames, &c->rendering_intent)) + return true; return JXL_FAILURE("Invalid RenderingIntent %s\n", str.c_str()); } @@ -189,7 +186,7 @@ Status ParseTransferFunction(Tokenizer* tokenizer, JxlColorEncoding* c) { std::string str; JXL_RETURN_IF_ERROR(tokenizer->Next(&str)); - if (PARSE_ENUM(JxlTransferFunction, str, &c->transfer_function)) { + if (ParseEnum(str, kJxlTransferFunctionNames, &c->transfer_function)) { return true; } diff --git a/third_party/jpeg-xl/lib/extras/dec/color_hints.cc b/third_party/jpeg-xl/lib/extras/dec/color_hints.cc index 5c6d7b84a0..b1edd9f6ea 100644 --- a/third_party/jpeg-xl/lib/extras/dec/color_hints.cc +++ b/third_party/jpeg-xl/lib/extras/dec/color_hints.cc @@ -43,20 +43,21 @@ Status ApplyColorHints(const ColorHints& color_hints, } else if (key == "icc") { const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data()); std::vector<uint8_t> icc(data, data + value.size()); - ppf->icc.swap(icc); + ppf->icc = std::move(icc); + ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary; got_color_space = true; } else if (key == "exif") { const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data()); std::vector<uint8_t> blob(data, data + value.size()); - ppf->metadata.exif.swap(blob); + ppf->metadata.exif = std::move(blob); } else if (key == "xmp") { const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data()); std::vector<uint8_t> blob(data, data + value.size()); - ppf->metadata.xmp.swap(blob); + ppf->metadata.xmp = std::move(blob); } else if (key == "jumbf") { const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data()); std::vector<uint8_t> blob(data, data + value.size()); - ppf->metadata.jumbf.swap(blob); + ppf->metadata.jumbf = std::move(blob); } else { JXL_WARNING("Ignoring %s hint", key.c_str()); } diff --git a/third_party/jpeg-xl/lib/extras/dec/decode.cc b/third_party/jpeg-xl/lib/extras/dec/decode.cc index b3ca711bb2..3546cb65c0 100644 --- a/third_party/jpeg-xl/lib/extras/dec/decode.cc +++ b/third_party/jpeg-xl/lib/extras/dec/decode.cc @@ -35,7 +35,8 @@ std::string GetExtension(const std::string& path) { } // namespace -Codec CodecFromPath(std::string path, size_t* JXL_RESTRICT bits_per_sample, +Codec CodecFromPath(const std::string& path, + size_t* JXL_RESTRICT bits_per_sample, std::string* extension) { std::string ext = GetExtension(path); if (extension) { @@ -98,7 +99,7 @@ Status DecodeBytes(const Span<const uint8_t> bytes, *ppf = extras::PackedPixelFile(); // Default values when not set by decoders. - ppf->info.uses_original_profile = true; + ppf->info.uses_original_profile = JXL_TRUE; ppf->info.orientation = JXL_ORIENT_IDENTITY; const auto choose_codec = [&]() -> Codec { @@ -116,6 +117,7 @@ Status DecodeBytes(const Span<const uint8_t> bytes, dparams.accepted_formats.push_back( {num_channels, JXL_TYPE_FLOAT, JXL_LITTLE_ENDIAN, /*align=*/0}); } + dparams.output_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM; size_t decoded_bytes; if (DecodeImageJXL(bytes.data(), bytes.size(), dparams, &decoded_bytes, ppf) && diff --git a/third_party/jpeg-xl/lib/extras/dec/decode.h b/third_party/jpeg-xl/lib/extras/dec/decode.h index 0d7dfcbef2..1a90f4c6a3 100644 --- a/third_party/jpeg-xl/lib/extras/dec/decode.h +++ b/third_party/jpeg-xl/lib/extras/dec/decode.h @@ -40,7 +40,7 @@ bool CanDecode(Codec codec); // If and only if extension is ".pfm", *bits_per_sample is updated to 32 so // that Encode() would encode to PFM instead of PPM. -Codec CodecFromPath(std::string path, +Codec CodecFromPath(const std::string& path, size_t* JXL_RESTRICT bits_per_sample = nullptr, std::string* extension = nullptr); diff --git a/third_party/jpeg-xl/lib/extras/dec/exr.cc b/third_party/jpeg-xl/lib/extras/dec/exr.cc index 821e0f4b21..d5903155e9 100644 --- a/third_party/jpeg-xl/lib/extras/dec/exr.cc +++ b/third_party/jpeg-xl/lib/extras/dec/exr.cc @@ -121,7 +121,12 @@ Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints, }; ppf->frames.clear(); // Allocates the frame buffer. - ppf->frames.emplace_back(image_size.x, image_size.y, format); + { + JXL_ASSIGN_OR_RETURN( + PackedFrame frame, + PackedFrame::Create(image_size.x, image_size.y, format)); + ppf->frames.emplace_back(std::move(frame)); + } const auto& frame = ppf->frames.back(); const int row_size = input.dataWindow().size().x + 1; @@ -188,7 +193,7 @@ Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints, if (has_alpha) { ppf->info.alpha_bits = kExrAlphaBits; ppf->info.alpha_exponent_bits = ppf->info.exponent_bits_per_sample; - ppf->info.alpha_premultiplied = true; + ppf->info.alpha_premultiplied = JXL_TRUE; } ppf->info.intensity_target = intensity_target; return true; diff --git a/third_party/jpeg-xl/lib/extras/dec/gif.cc b/third_party/jpeg-xl/lib/extras/dec/gif.cc index 3d963941c0..3f89d460b8 100644 --- a/third_party/jpeg-xl/lib/extras/dec/gif.cc +++ b/third_party/jpeg-xl/lib/extras/dec/gif.cc @@ -50,8 +50,10 @@ void ensure_have_alpha(PackedFrame* frame) { /*endianness=*/JXL_NATIVE_ENDIAN, /*align=*/0, }; - frame->extra_channels.emplace_back(frame->color.xsize, frame->color.ysize, - alpha_format); + JXL_ASSIGN_OR_DIE(PackedImage image, + PackedImage::Create(frame->color.xsize, frame->color.ysize, + alpha_format)); + frame->extra_channels.emplace_back(std::move(image)); // We need to set opaque-by-default. std::fill_n(static_cast<uint8_t*>(frame->extra_channels[0].pixels()), frame->color.xsize * frame->color.ysize, 255u); @@ -136,7 +138,7 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints, } if (gif->ImageCount > 1) { - ppf->info.have_animation = true; + ppf->info.have_animation = JXL_TRUE; // Delays in GIF are specified in 100ths of a second. ppf->info.animation.tps_numerator = 100; ppf->info.animation.tps_denominator = 1; @@ -186,7 +188,9 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints, } const PackedRgba background_rgba{background_color.Red, background_color.Green, background_color.Blue, 0}; - PackedFrame canvas(gif->SWidth, gif->SHeight, canvas_format); + JXL_ASSIGN_OR_RETURN( + PackedFrame canvas, + PackedFrame::Create(gif->SWidth, gif->SHeight, canvas_format)); std::fill_n(static_cast<PackedRgba*>(canvas.color.pixels()), canvas.color.xsize * canvas.color.ysize, background_rgba); Rect canvas_rect{0, 0, canvas.color.xsize, canvas.color.ysize}; @@ -230,8 +234,14 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints, } // Allocates the frame buffer. - ppf->frames.emplace_back(total_rect.xsize(), total_rect.ysize(), - packed_frame_format); + { + JXL_ASSIGN_OR_RETURN( + PackedFrame frame, + PackedFrame::Create(total_rect.xsize(), total_rect.ysize(), + packed_frame_format)); + ppf->frames.emplace_back(std::move(frame)); + } + PackedFrame* frame = &ppf->frames.back(); // We cannot tell right from the start whether there will be a @@ -301,8 +311,10 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints, } // Update the canvas by creating a copy first. - PackedImage new_canvas_image(canvas.color.xsize, canvas.color.ysize, - canvas.color.format); + JXL_ASSIGN_OR_RETURN( + PackedImage new_canvas_image, + PackedImage::Create(canvas.color.xsize, canvas.color.ysize, + canvas.color.format)); memcpy(new_canvas_image.pixels(), canvas.color.pixels(), new_canvas_image.pixels_size); for (size_t y = 0, byte_index = 0; y < image_rect.ysize(); ++y) { diff --git a/third_party/jpeg-xl/lib/extras/dec/jpegli.cc b/third_party/jpeg-xl/lib/extras/dec/jpegli.cc index ffa1b79c25..443dfe86ba 100644 --- a/third_party/jpeg-xl/lib/extras/dec/jpegli.cc +++ b/third_party/jpeg-xl/lib/extras/dec/jpegli.cc @@ -27,7 +27,7 @@ constexpr unsigned char kExifSignature[6] = {0x45, 0x78, 0x69, constexpr int kExifMarker = JPEG_APP0 + 1; constexpr int kICCMarker = JPEG_APP0 + 2; -static inline bool IsJPG(const std::vector<uint8_t>& bytes) { +inline bool IsJPG(const std::vector<uint8_t>& bytes) { if (bytes.size() < 2) return false; if (bytes[0] != 0xFF || bytes[1] != 0xD8) return false; return true; @@ -188,7 +188,11 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed, } else if (dparams.force_grayscale) { cinfo.out_color_space = JCS_GRAYSCALE; } - if (!ReadICCProfile(&cinfo, &ppf->icc)) { + if (ReadICCProfile(&cinfo, &ppf->icc)) { + ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary; + } else { + ppf->primary_color_representation = + PackedPixelFile::kColorEncodingIsPrimary; ppf->icc.clear(); // Default to SRGB ppf->color_encoding.color_space = @@ -214,7 +218,7 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed, } else { return failure("unsupported data type"); } - ppf->info.uses_original_profile = true; + ppf->info.uses_original_profile = JXL_TRUE; // No alpha in JPG ppf->info.alpha_bits = 0; @@ -227,8 +231,8 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed, if (dparams.num_colors > 0) { cinfo.quantize_colors = TRUE; cinfo.desired_number_of_colors = dparams.num_colors; - cinfo.two_pass_quantize = dparams.two_pass_quant; - cinfo.dither_mode = (J_DITHER_MODE)dparams.dither_mode; + cinfo.two_pass_quantize = static_cast<boolean>(dparams.two_pass_quant); + cinfo.dither_mode = static_cast<J_DITHER_MODE>(dparams.dither_mode); } jpegli_start_decompress(&cinfo); @@ -242,7 +246,12 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed, }; ppf->frames.clear(); // Allocates the frame buffer. - ppf->frames.emplace_back(cinfo.image_width, cinfo.image_height, format); + { + JXL_ASSIGN_OR_RETURN( + PackedFrame frame, + PackedFrame::Create(cinfo.image_width, cinfo.image_height, format)); + ppf->frames.emplace_back(std::move(frame)); + } const auto& frame = ppf->frames.back(); JXL_ASSERT(sizeof(JSAMPLE) * cinfo.out_color_components * cinfo.image_width <= diff --git a/third_party/jpeg-xl/lib/extras/dec/jpg.cc b/third_party/jpeg-xl/lib/extras/dec/jpg.cc index 3c8a4bccfe..4a3e0d3b21 100644 --- a/third_party/jpeg-xl/lib/extras/dec/jpg.cc +++ b/third_party/jpeg-xl/lib/extras/dec/jpg.cc @@ -34,7 +34,7 @@ constexpr unsigned char kExifSignature[6] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; constexpr int kExifMarker = JPEG_APP0 + 1; -static inline bool IsJPG(const Span<const uint8_t> bytes) { +inline bool IsJPG(const Span<const uint8_t> bytes) { if (bytes.size() < 2) return false; if (bytes[0] != 0xFF || bytes[1] != 0xD8) return false; return true; @@ -242,7 +242,11 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes, if (nbcomp != 1 && nbcomp != 3) { return failure("unsupported number of components in JPEG"); } - if (!ReadICCProfile(&cinfo, &ppf->icc)) { + if (ReadICCProfile(&cinfo, &ppf->icc)) { + ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary; + } else { + ppf->primary_color_representation = + PackedPixelFile::kColorEncodingIsPrimary; ppf->icc.clear(); // Default to SRGB // Actually, (cinfo.output_components == nbcomp) will be checked after @@ -266,7 +270,7 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes, ppf->info.bits_per_sample = BITS_IN_JSAMPLE; JXL_ASSERT(BITS_IN_JSAMPLE == 8 || BITS_IN_JSAMPLE == 16); ppf->info.exponent_bits_per_sample = 0; - ppf->info.uses_original_profile = true; + ppf->info.uses_original_profile = JXL_TRUE; // No alpha in JPG ppf->info.alpha_bits = 0; @@ -278,8 +282,8 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes, if (dparams && dparams->num_colors > 0) { cinfo.quantize_colors = TRUE; cinfo.desired_number_of_colors = dparams->num_colors; - cinfo.two_pass_quantize = dparams->two_pass_quant; - cinfo.dither_mode = (J_DITHER_MODE)dparams->dither_mode; + cinfo.two_pass_quantize = static_cast<boolean>(dparams->two_pass_quant); + cinfo.dither_mode = static_cast<J_DITHER_MODE>(dparams->dither_mode); } jpeg_start_decompress(&cinfo); @@ -295,19 +299,25 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes, }; ppf->frames.clear(); // Allocates the frame buffer. - ppf->frames.emplace_back(cinfo.image_width, cinfo.image_height, format); + { + JXL_ASSIGN_OR_RETURN( + PackedFrame frame, + PackedFrame::Create(cinfo.image_width, cinfo.image_height, format)); + ppf->frames.emplace_back(std::move(frame)); + } const auto& frame = ppf->frames.back(); JXL_ASSERT(sizeof(JSAMPLE) * cinfo.out_color_components * cinfo.image_width <= frame.color.stride); if (cinfo.quantize_colors) { - jxl::msan::UnpoisonMemory(cinfo.colormap, cinfo.out_color_components * - sizeof(cinfo.colormap[0])); + JSAMPLE** colormap = cinfo.colormap; + jxl::msan::UnpoisonMemory(reinterpret_cast<void*>(colormap), + cinfo.out_color_components * sizeof(JSAMPLE*)); for (int c = 0; c < cinfo.out_color_components; ++c) { jxl::msan::UnpoisonMemory( - cinfo.colormap[c], - cinfo.actual_number_of_colors * sizeof(cinfo.colormap[c][0])); + reinterpret_cast<void*>(colormap[c]), + cinfo.actual_number_of_colors * sizeof(JSAMPLE)); } } for (size_t y = 0; y < cinfo.image_height; ++y) { diff --git a/third_party/jpeg-xl/lib/extras/dec/jxl.cc b/third_party/jpeg-xl/lib/extras/dec/jxl.cc index f3e62c970a..5b7fa03f02 100644 --- a/third_party/jpeg-xl/lib/extras/dec/jxl.cc +++ b/third_party/jpeg-xl/lib/extras/dec/jxl.cc @@ -16,20 +16,23 @@ #include "lib/extras/dec/color_description.h" #include "lib/jxl/base/exif.h" #include "lib/jxl/base/printf_macros.h" +#include "lib/jxl/base/status.h" namespace jxl { namespace extras { namespace { struct BoxProcessor { - BoxProcessor(JxlDecoder* dec) : dec_(dec) { Reset(); } + explicit BoxProcessor(JxlDecoder* dec) : dec_(dec) { Reset(); } void InitializeOutput(std::vector<uint8_t>* out) { + JXL_ASSERT(out != nullptr); box_data_ = out; AddMoreOutput(); } bool AddMoreOutput() { + JXL_ASSERT(box_data_ != nullptr); Flush(); static const size_t kBoxOutputChunkSize = 1 << 16; box_data_->resize(box_data_->size() + kBoxOutputChunkSize); @@ -126,7 +129,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size, return false; } - JxlPixelFormat format; + JxlPixelFormat format = {}; // Initialize to calm down clang-tidy. std::vector<JxlPixelFormat> accepted_formats = dparams.accepted_formats; JxlColorEncoding color_encoding; @@ -177,18 +180,18 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size, return false; } if (jpeg_bytes == nullptr) { - if (JXL_DEC_SUCCESS != - JxlDecoderSetRenderSpotcolors(dec, dparams.render_spotcolors)) { + if (JXL_DEC_SUCCESS != JxlDecoderSetRenderSpotcolors( + dec, TO_JXL_BOOL(dparams.render_spotcolors))) { fprintf(stderr, "JxlDecoderSetRenderSpotColors failed\n"); return false; } - if (JXL_DEC_SUCCESS != - JxlDecoderSetKeepOrientation(dec, dparams.keep_orientation)) { + if (JXL_DEC_SUCCESS != JxlDecoderSetKeepOrientation( + dec, TO_JXL_BOOL(dparams.keep_orientation))) { fprintf(stderr, "JxlDecoderSetKeepOrientation failed\n"); return false; } - if (JXL_DEC_SUCCESS != - JxlDecoderSetUnpremultiplyAlpha(dec, dparams.unpremultiply_alpha)) { + if (JXL_DEC_SUCCESS != JxlDecoderSetUnpremultiplyAlpha( + dec, TO_JXL_BOOL(dparams.unpremultiply_alpha))) { fprintf(stderr, "JxlDecoderSetUnpremultiplyAlpha failed\n"); return false; } @@ -267,6 +270,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size, return false; } } else if (status == JXL_DEC_JPEG_NEED_MORE_OUTPUT) { + JXL_ASSERT(jpeg_bytes != nullptr); // Help clang-tidy. // Decoded a chunk to JPEG. size_t used_jpeg_output = jpeg_data_chunk.size() - JxlDecoderReleaseJPEGBuffer(dec); @@ -309,7 +313,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size, } else { if (dparams.unpremultiply_alpha) { // Mark in the basic info that alpha was unpremultiplied. - ppf->info.alpha_premultiplied = false; + ppf->info.alpha_premultiplied = JXL_FALSE; } } bool alpha_found = false; @@ -327,7 +331,8 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size, } std::string name(eci.name_length + 1, 0); if (JXL_DEC_SUCCESS != - JxlDecoderGetExtraChannelName(dec, i, &name[0], name.size())) { + JxlDecoderGetExtraChannelName( + dec, i, const_cast<char*>(name.data()), name.size())) { fprintf(stderr, "JxlDecoderGetExtraChannelName failed\n"); return false; } @@ -351,24 +356,26 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size, } size_t icc_size = 0; JxlColorProfileTarget target = JXL_COLOR_PROFILE_TARGET_DATA; - ppf->color_encoding.color_space = JXL_COLOR_SPACE_UNKNOWN; - if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsEncodedProfile( - dec, target, &ppf->color_encoding) || - dparams.need_icc) { - // only get ICC if it is not an Enum color encoding - if (JXL_DEC_SUCCESS != - JxlDecoderGetICCProfileSize(dec, target, &icc_size)) { - fprintf(stderr, "JxlDecoderGetICCProfileSize failed\n"); - } - if (icc_size != 0) { - ppf->icc.resize(icc_size); - if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsICCProfile( - dec, target, ppf->icc.data(), icc_size)) { - fprintf(stderr, "JxlDecoderGetColorAsICCProfile failed\n"); - return false; - } + if (JXL_DEC_SUCCESS != + JxlDecoderGetICCProfileSize(dec, target, &icc_size)) { + fprintf(stderr, "JxlDecoderGetICCProfileSize failed\n"); + } + if (icc_size != 0) { + ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary; + ppf->icc.resize(icc_size); + if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsICCProfile( + dec, target, ppf->icc.data(), icc_size)) { + fprintf(stderr, "JxlDecoderGetColorAsICCProfile failed\n"); + return false; } } + if (JXL_DEC_SUCCESS == JxlDecoderGetColorAsEncodedProfile( + dec, target, &ppf->color_encoding)) { + ppf->primary_color_representation = + PackedPixelFile::kColorEncodingIsPrimary; + } else { + ppf->color_encoding.color_space = JXL_COLOR_SPACE_UNKNOWN; + } icc_size = 0; target = JXL_COLOR_PROFILE_TARGET_ORIGINAL; if (JXL_DEC_SUCCESS != @@ -385,14 +392,21 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size, } } } else if (status == JXL_DEC_FRAME) { - jxl::extras::PackedFrame frame(ppf->info.xsize, ppf->info.ysize, format); + auto frame_or = jxl::extras::PackedFrame::Create(ppf->info.xsize, + ppf->info.ysize, format); + if (!frame_or.status()) { + fprintf(stderr, "Failed to create image frame."); + return false; + } + jxl::extras::PackedFrame frame = std::move(frame_or).value(); if (JXL_DEC_SUCCESS != JxlDecoderGetFrameHeader(dec, &frame.frame_info)) { fprintf(stderr, "JxlDecoderGetFrameHeader failed\n"); return false; } frame.name.resize(frame.frame_info.name_length + 1, 0); if (JXL_DEC_SUCCESS != - JxlDecoderGetFrameName(dec, &frame.name[0], frame.name.size())) { + JxlDecoderGetFrameName(dec, const_cast<char*>(frame.name.data()), + frame.name.size())) { fprintf(stderr, "JxlDecoderGetFrameName failed\n"); return false; } @@ -423,9 +437,16 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size, fprintf(stderr, "JxlDecoderPreviewOutBufferSize failed\n"); return false; } + auto preview_image_or = jxl::extras::PackedImage::Create( + ppf->info.preview.xsize, ppf->info.preview.ysize, format); + if (!preview_image_or.status()) { + fprintf(stderr, "Failed to create preview image\n"); + return false; + } + jxl::extras::PackedImage preview_image = + std::move(preview_image_or).value(); ppf->preview_frame = std::unique_ptr<jxl::extras::PackedFrame>( - new jxl::extras::PackedFrame(ppf->info.preview.xsize, - ppf->info.preview.ysize, format)); + new jxl::extras::PackedFrame(std::move(preview_image))); if (buffer_size != ppf->preview_frame->color.pixels_size) { fprintf(stderr, "Invalid out buffer size %" PRIuS " %" PRIuS "\n", buffer_size, ppf->preview_frame->color.pixels_size); @@ -492,8 +513,13 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size, JxlPixelFormat ec_format = format; ec_format.num_channels = 1; for (auto& eci : ppf->extra_channels_info) { - frame.extra_channels.emplace_back(jxl::extras::PackedImage( - ppf->info.xsize, ppf->info.ysize, ec_format)); + auto image = jxl::extras::PackedImage::Create( + ppf->info.xsize, ppf->info.ysize, ec_format); + if (!image.status()) { + fprintf(stderr, "Failed to create extra channel image\n"); + return false; + } + frame.extra_channels.emplace_back(std::move(image).value()); auto& ec = frame.extra_channels.back(); size_t buffer_size; if (JXL_DEC_SUCCESS != JxlDecoderExtraChannelBufferSize( diff --git a/third_party/jpeg-xl/lib/extras/dec/jxl.h b/third_party/jpeg-xl/lib/extras/dec/jxl.h index cbada1f6dd..5f4ed7f683 100644 --- a/third_party/jpeg-xl/lib/extras/dec/jxl.h +++ b/third_party/jpeg-xl/lib/extras/dec/jxl.h @@ -41,10 +41,6 @@ struct JXLDecompressParams { // Whether truncated input should be treated as an error. bool allow_partial_input = false; - // Set to true if an ICC profile has to be synthesized for Enum color - // encodings - bool need_icc = false; - // How many passes to decode at most. By default, decode everything. uint32_t max_passes = std::numeric_limits<uint32_t>::max(); diff --git a/third_party/jpeg-xl/lib/extras/dec/pgx.cc b/third_party/jpeg-xl/lib/extras/dec/pgx.cc index a99eb0f4ee..4499069d77 100644 --- a/third_party/jpeg-xl/lib/extras/dec/pgx.cc +++ b/third_party/jpeg-xl/lib/extras/dec/pgx.cc @@ -150,7 +150,7 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes, const SizeConstraints* constraints) { Parser parser(bytes); HeaderPGX header = {}; - const uint8_t* pos; + const uint8_t* pos = nullptr; if (!parser.ParseHeader(&header, &pos)) return false; JXL_RETURN_IF_ERROR( VerifyDimensions(constraints, header.xsize, header.ysize)); @@ -165,7 +165,7 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes, // Original data is uint, so exponent_bits_per_sample = 0. ppf->info.bits_per_sample = header.bits_per_sample; ppf->info.exponent_bits_per_sample = 0; - ppf->info.uses_original_profile = true; + ppf->info.uses_original_profile = JXL_TRUE; // No alpha in PGX ppf->info.alpha_bits = 0; @@ -188,7 +188,12 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes, }; ppf->frames.clear(); // Allocates the frame buffer. - ppf->frames.emplace_back(header.xsize, header.ysize, format); + { + JXL_ASSIGN_OR_RETURN( + PackedFrame frame, + PackedFrame::Create(header.xsize, header.ysize, format)); + ppf->frames.emplace_back(std::move(frame)); + } const auto& frame = ppf->frames.back(); size_t pgx_remaining_size = bytes.data() + bytes.size() - pos; if (pgx_remaining_size < frame.color.pixels_size) { diff --git a/third_party/jpeg-xl/lib/extras/dec/pnm.cc b/third_party/jpeg-xl/lib/extras/dec/pnm.cc index 4c4618d41d..040c0bff81 100644 --- a/third_party/jpeg-xl/lib/extras/dec/pnm.cc +++ b/third_party/jpeg-xl/lib/extras/dec/pnm.cc @@ -9,6 +9,7 @@ #include <string.h> #include <cmath> +#include <cstdint> #include <mutex> #include "jxl/encode.h" @@ -55,8 +56,10 @@ class Parser { case 'f': header->is_gray = true; return ParseHeaderPFM(header, pos); + + default: + return false; } - return false; } // Exposed for testing @@ -160,11 +163,12 @@ class Parser { Status MatchString(const char* keyword, bool skipws = true) { const uint8_t* ppos = pos_; - while (*keyword) { + const uint8_t* kw = reinterpret_cast<const uint8_t*>(keyword); + while (*kw) { if (ppos >= end_) return JXL_FAILURE("PAM: unexpected end of input"); - if (*keyword != *ppos) return false; + if (*kw != *ppos) return false; ppos++; - keyword++; + kw++; } pos_ = ppos; if (skipws) { @@ -387,8 +391,8 @@ StatusOr<ChunkedPNMDecoder> ChunkedPNMDecoder::Init(const char* path) { const size_t num_channels = dec.header_.is_gray ? 1 : 3; const size_t bytes_per_pixel = num_channels * bytes_per_channel; size_t row_size = dec.header_.xsize * bytes_per_pixel; - if (header.ysize * row_size + dec.data_start_ < size) { - return JXL_FAILURE("Invalid ppm"); + if (size < header.ysize * row_size + dec.data_start_) { + return JXL_FAILURE("PNM file too small"); } return dec; } @@ -495,10 +499,18 @@ Status DecodeImagePNM(const Span<const uint8_t> bytes, }; const JxlPixelFormat ec_format{1, format.data_type, format.endianness, 0}; ppf->frames.clear(); - ppf->frames.emplace_back(header.xsize, header.ysize, format); + { + JXL_ASSIGN_OR_RETURN( + PackedFrame frame, + PackedFrame::Create(header.xsize, header.ysize, format)); + ppf->frames.emplace_back(std::move(frame)); + } auto* frame = &ppf->frames.back(); for (size_t i = 0; i < header.ec_types.size(); ++i) { - frame->extra_channels.emplace_back(header.xsize, header.ysize, ec_format); + JXL_ASSIGN_OR_RETURN( + PackedImage ec, + PackedImage::Create(header.xsize, header.ysize, ec_format)); + frame->extra_channels.emplace_back(std::move(ec)); } size_t pnm_remaining_size = bytes.data() + bytes.size() - pos; if (pnm_remaining_size < frame->color.pixels_size) { @@ -533,6 +545,9 @@ Status DecodeImagePNM(const Span<const uint8_t> bytes, } } } + if (ppf->info.exponent_bits_per_sample == 0) { + ppf->input_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM; + } return true; } |