зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1889046 - Update libjxl to a5e4aa1fc1fe5bee252225a2616dccde7fd35da0 r=saschanaz
Differential Revision: https://phabricator.services.mozilla.com/D206312
This commit is contained in:
Родитель
0b5fb7f1ea
Коммит
d58dd3a136
|
@ -10,9 +10,9 @@ origin:
|
|||
|
||||
url: https://github.com/libjxl/libjxl
|
||||
|
||||
release: f06a34c77b1bd11bafbe82989241e68c756ccca2 (2024-03-11T15:14:53Z).
|
||||
release: a5e4aa1fc1fe5bee252225a2616dccde7fd35da0 (2024-04-01T20:09:39Z).
|
||||
|
||||
revision: f06a34c77b1bd11bafbe82989241e68c756ccca2
|
||||
revision: a5e4aa1fc1fe5bee252225a2616dccde7fd35da0
|
||||
|
||||
license: Apache-2.0
|
||||
|
||||
|
|
|
@ -16,6 +16,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Fixed
|
||||
|
||||
|
||||
## [0.10.2] - 2024-03-08
|
||||
|
||||
### Fixed
|
||||
- bugs in (lossless) encoding (#3367, #3359 and #3386)
|
||||
- re-enable installation of MIME file (#3375)
|
||||
- bugs in streaming mode (#3379 and #3380)
|
||||
|
||||
## [0.10.1] - 2024-02-28
|
||||
|
||||
### Fixed
|
||||
- reduce allocations (#3336 and #3339),
|
||||
fixing a significant speed regression present since 0.9.0
|
||||
- bug in streaming encoding (#3331)
|
||||
|
||||
## [0.10.0] - 2024-02-21
|
||||
|
||||
### Added
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository", "new_git_repository")
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
workspace(name = "libjxl")
|
||||
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
jpeg-xl (0.10.0) UNRELEASED; urgency=medium
|
||||
jpeg-xl (0.10.2) unstable; urgency=medium
|
||||
|
||||
* Bump JPEG XL version to 0.10.2.
|
||||
|
||||
-- JPEG XL Maintainers <jpegxl@google.com> Thu, 07 Mar 2024 13:50:05 +0100
|
||||
|
||||
jpeg-xl (0.10.1) unstable; urgency=medium
|
||||
|
||||
* Bump JPEG XL version to 0.10.1.
|
||||
|
||||
-- JPEG XL Maintainers <jpegxl@google.com> Wed, 28 Feb 2024 12:52:20 +0100
|
||||
|
||||
jpeg-xl (0.10.0) unstable; urgency=medium
|
||||
|
||||
* Bump JPEG XL version to 0.10.0.
|
||||
|
||||
-- JPEG XL Maintainers <jpegxl@google.com> Tue, 21 Nov 2023 10:32:59 +0100
|
||||
-- JPEG XL Maintainers <jpegxl@google.com> Wed, 21 Feb 2024 08:37:00 +0100
|
||||
|
||||
jpeg-xl (0.9.0) unstable; urgency=medium
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
|
|||
return false;
|
||||
}
|
||||
|
||||
long size = ftell(file);
|
||||
long size = ftell(file); // NOLINT
|
||||
// Avoid invalid file or directory.
|
||||
if (size >= LONG_MAX || size < 0) {
|
||||
fclose(file);
|
||||
|
|
|
@ -169,7 +169,7 @@ bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
|
|||
return false;
|
||||
}
|
||||
|
||||
long size = ftell(file);
|
||||
long size = ftell(file); // NOLINT
|
||||
// Avoid invalid file or directory.
|
||||
if (size >= LONG_MAX || size < 0) {
|
||||
fclose(file);
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
// This C++ example decodes a JPEG XL image progressively (input bytes are
|
||||
// passed in chunks). The example outputs the intermediate steps to PAM files.
|
||||
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <jxl/decode.h>
|
||||
#include <jxl/decode_cxx.h>
|
||||
|
@ -174,7 +178,7 @@ bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
|
|||
return false;
|
||||
}
|
||||
|
||||
long size = ftell(file);
|
||||
long size = ftell(file); // NOLINT
|
||||
// Avoid invalid file or directory.
|
||||
if (size >= LONG_MAX || size < 0) {
|
||||
fclose(file);
|
||||
|
@ -220,7 +224,7 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
size_t chunksize = jxl.size();
|
||||
if (argc > 3) {
|
||||
long cs = atol(argv[3]);
|
||||
long cs = atol(argv[3]); // NOLINT
|
||||
if (cs < 100) {
|
||||
fprintf(stderr, "Chunk size is too low, try at least 100 bytes\n");
|
||||
return 1;
|
||||
|
|
|
@ -48,7 +48,7 @@ bool ReadPFM(const char* filename, std::vector<float>* pixels, uint32_t* xsize,
|
|||
return false;
|
||||
}
|
||||
|
||||
long size = ftell(file);
|
||||
long size = ftell(file); // NOLINT
|
||||
// Avoid invalid file or directory.
|
||||
if (size >= LONG_MAX || size < 0) {
|
||||
fclose(file);
|
||||
|
@ -64,7 +64,7 @@ bool ReadPFM(const char* filename, std::vector<float>* pixels, uint32_t* xsize,
|
|||
data.resize(size);
|
||||
|
||||
size_t readsize = fread(data.data(), 1, size, file);
|
||||
if (static_cast<long>(readsize) != size) {
|
||||
if (static_cast<long>(readsize) != size) { // NOLINT
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
|
||||
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
|
||||
|
||||
# Load sources/headers/tests lists.
|
||||
load(
|
||||
"jxl_lists.bzl",
|
||||
|
@ -57,8 +60,6 @@ load(
|
|||
"libjxl_test_shards",
|
||||
"libjxl_test_timeouts",
|
||||
)
|
||||
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
|
||||
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
|
||||
|
||||
DEFAULT_VISIBILITY = ["//:__subpackages__"]
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
set(JPEGXL_MAJOR_VERSION 0)
|
||||
set(JPEGXL_MINOR_VERSION 10)
|
||||
set(JPEGXL_PATCH_VERSION 0)
|
||||
set(JPEGXL_PATCH_VERSION 2)
|
||||
set(JPEGXL_LIBRARY_VERSION
|
||||
"${JPEGXL_MAJOR_VERSION}.${JPEGXL_MINOR_VERSION}.${JPEGXL_PATCH_VERSION}")
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "lib/extras/enc/encode.h"
|
||||
#include "lib/extras/packed_image.h"
|
||||
#include "lib/jxl/base/byte_order.h"
|
||||
#include "lib/jxl/base/data_parallel.h"
|
||||
#include "lib/jxl/base/random.h"
|
||||
#include "lib/jxl/base/span.h"
|
||||
#include "lib/jxl/base/status.h"
|
||||
|
@ -333,10 +334,10 @@ TEST(CodecTest, TestRoundTrip) {
|
|||
params.add_alpha = add_alpha;
|
||||
params.big_endian = big_endian;
|
||||
params.add_extra_channels = false;
|
||||
TestRoundTrip(params, &pool);
|
||||
TestRoundTrip(params, pool.get());
|
||||
if (codec == Codec::kPNM && add_alpha) {
|
||||
params.add_extra_channels = true;
|
||||
TestRoundTrip(params, &pool);
|
||||
TestRoundTrip(params, pool.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -369,7 +370,7 @@ TEST(CodecTest, LosslessPNMRoundtrip) {
|
|||
EncodedImage encoded;
|
||||
auto encoder = Encoder::FromExtension(extension);
|
||||
ASSERT_TRUE(encoder.get());
|
||||
ASSERT_TRUE(encoder->Encode(ppf, &encoded, &pool));
|
||||
ASSERT_TRUE(encoder->Encode(ppf, &encoded, pool.get()));
|
||||
ASSERT_EQ(encoded.bitstreams.size(), 1);
|
||||
ASSERT_EQ(orig.size(), encoded.bitstreams[0].size());
|
||||
EXPECT_EQ(0,
|
||||
|
|
|
@ -381,9 +381,11 @@ class BlobsReaderPNG {
|
|||
|
||||
// We need 2*bytes for the hex values plus 1 byte every 36 values,
|
||||
// plus terminal \n for length.
|
||||
const unsigned long needed_bytes =
|
||||
bytes_to_decode * 2 + 1 + DivCeil(bytes_to_decode, 36);
|
||||
if (needed_bytes != static_cast<size_t>(encoded_end - pos)) {
|
||||
size_t tail = static_cast<size_t>(encoded_end - pos);
|
||||
bool ok = ((tail / 2) >= bytes_to_decode);
|
||||
if (ok) tail -= 2 * static_cast<size_t>(bytes_to_decode);
|
||||
ok = ok && (tail == 1 + DivCeil(bytes_to_decode, 36));
|
||||
if (!ok) {
|
||||
return JXL_FAILURE("Not enough bytes to parse %d bytes in hex",
|
||||
bytes_to_decode);
|
||||
}
|
||||
|
@ -439,7 +441,7 @@ struct APNGFrame {
|
|||
Status Resize(size_t new_size) {
|
||||
if (new_size > pixels_size) {
|
||||
pixels.reset(malloc(new_size));
|
||||
if (!pixels.get()) {
|
||||
if (!pixels) {
|
||||
// TODO(szabadka): use specialized OOM error code
|
||||
return JXL_FAILURE("Failed to allocate memory for image buffer");
|
||||
}
|
||||
|
@ -462,7 +464,7 @@ struct Reader {
|
|||
bool Eof() const { return next == last; }
|
||||
};
|
||||
|
||||
const unsigned long cMaxPNGSize = 1000000UL;
|
||||
const uint32_t cMaxPNGSize = 1000000UL;
|
||||
const size_t kMaxPNGChunkSize = 1lu << 30; // 1 GB
|
||||
|
||||
void info_fn(png_structp png_ptr, png_infop info_ptr) {
|
||||
|
@ -641,17 +643,17 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
|
|||
bool have_srgb = false;
|
||||
bool errorstate = true;
|
||||
if (id == kId_IHDR && chunkIHDR.size() == 25) {
|
||||
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;
|
||||
uint32_t x0 = 0;
|
||||
uint32_t y0 = 0;
|
||||
uint32_t delay_num = 1;
|
||||
uint32_t delay_den = 10;
|
||||
uint32_t dop = 0;
|
||||
uint32_t 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;
|
||||
uint32_t w = png_get_uint_32(chunkIHDR.data() + 8);
|
||||
uint32_t h = png_get_uint_32(chunkIHDR.data() + 12);
|
||||
uint32_t w0 = w;
|
||||
uint32_t h0 = h;
|
||||
if (w > cMaxPNGSize || h > cMaxPNGSize) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -332,7 +332,7 @@ struct PNMChunkedInputFrame {
|
|||
METHOD_TO_C_CALLBACK(&PNMChunkedInputFrame::ReleaseCurrentData)};
|
||||
}
|
||||
|
||||
void GetColorChannelsPixelFormat(JxlPixelFormat* pixel_format) {
|
||||
void /* NOLINT */ GetColorChannelsPixelFormat(JxlPixelFormat* pixel_format) {
|
||||
*pixel_format = format;
|
||||
}
|
||||
|
||||
|
@ -349,12 +349,14 @@ struct PNMChunkedInputFrame {
|
|||
|
||||
void GetExtraChannelPixelFormat(size_t ec_index,
|
||||
JxlPixelFormat* pixel_format) {
|
||||
(void)this;
|
||||
JXL_ABORT("Not implemented");
|
||||
}
|
||||
|
||||
const void* GetExtraChannelDataAt(size_t ec_index, size_t xpos, size_t ypos,
|
||||
size_t xsize, size_t ysize,
|
||||
size_t* row_offset) {
|
||||
(void)this;
|
||||
JXL_ABORT("Not implemented");
|
||||
}
|
||||
|
||||
|
|
|
@ -73,17 +73,30 @@ class APNGEncoder : public Encoder {
|
|||
}
|
||||
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
|
||||
ThreadPool* pool) const override {
|
||||
// Encode main image frames
|
||||
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
|
||||
encoded_image->icc.clear();
|
||||
encoded_image->bitstreams.resize(1);
|
||||
return EncodePackedPixelFileToAPNG(ppf, pool,
|
||||
&encoded_image->bitstreams.front());
|
||||
JXL_RETURN_IF_ERROR(EncodePackedPixelFileToAPNG(
|
||||
ppf, pool, &encoded_image->bitstreams.front()));
|
||||
|
||||
// Encode extra channels
|
||||
for (size_t i = 0; i < ppf.extra_channels_info.size(); ++i) {
|
||||
encoded_image->extra_channel_bitstreams.emplace_back();
|
||||
auto& ec_bitstreams = encoded_image->extra_channel_bitstreams.back();
|
||||
ec_bitstreams.emplace_back();
|
||||
JXL_RETURN_IF_ERROR(EncodePackedPixelFileToAPNG(
|
||||
ppf, pool, &ec_bitstreams.back(), true, i));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Status EncodePackedPixelFileToAPNG(const PackedPixelFile& ppf,
|
||||
ThreadPool* pool,
|
||||
std::vector<uint8_t>* bytes) const;
|
||||
std::vector<uint8_t>* bytes,
|
||||
bool encode_extra_channels = false,
|
||||
size_t extra_channel_index = 0) const;
|
||||
};
|
||||
|
||||
void PngWrite(png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||
|
@ -266,15 +279,21 @@ void MaybeAddCLLi(const JxlColorEncoding& c_enc, const float intensity_target,
|
|||
}
|
||||
|
||||
Status APNGEncoder::EncodePackedPixelFileToAPNG(
|
||||
const PackedPixelFile& ppf, ThreadPool* pool,
|
||||
std::vector<uint8_t>* bytes) const {
|
||||
size_t xsize = ppf.info.xsize;
|
||||
size_t ysize = ppf.info.ysize;
|
||||
bool has_alpha = ppf.info.alpha_bits != 0;
|
||||
bool is_gray = ppf.info.num_color_channels == 1;
|
||||
size_t color_channels = ppf.info.num_color_channels;
|
||||
const PackedPixelFile& ppf, ThreadPool* pool, std::vector<uint8_t>* bytes,
|
||||
bool encode_extra_channels, size_t extra_channel_index) const {
|
||||
JxlExtraChannelInfo ec_info{};
|
||||
if (encode_extra_channels) {
|
||||
if (ppf.extra_channels_info.size() <= extra_channel_index) {
|
||||
return JXL_FAILURE("Invalid index for extra channel");
|
||||
}
|
||||
ec_info = ppf.extra_channels_info[extra_channel_index].ec_info;
|
||||
}
|
||||
|
||||
bool has_alpha = !encode_extra_channels && (ppf.info.alpha_bits != 0);
|
||||
bool is_gray = encode_extra_channels || (ppf.info.num_color_channels == 1);
|
||||
size_t color_channels =
|
||||
encode_extra_channels ? 1 : ppf.info.num_color_channels;
|
||||
size_t num_channels = color_channels + (has_alpha ? 1 : 0);
|
||||
size_t num_samples = num_channels * xsize * ysize;
|
||||
|
||||
if (!ppf.info.have_animation && ppf.frames.size() != 1) {
|
||||
return JXL_FAILURE("Invalid number of frames");
|
||||
|
@ -284,9 +303,24 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
|
|||
size_t anim_chunks = 0;
|
||||
|
||||
for (const auto& frame : ppf.frames) {
|
||||
JXL_RETURN_IF_ERROR(VerifyPackedImage(frame.color, ppf.info));
|
||||
const PackedImage& color = encode_extra_channels
|
||||
? frame.extra_channels[extra_channel_index]
|
||||
: frame.color;
|
||||
|
||||
const PackedImage& color = frame.color;
|
||||
size_t xsize = color.xsize;
|
||||
size_t ysize = color.ysize;
|
||||
size_t num_samples = num_channels * xsize * ysize;
|
||||
|
||||
uint32_t bits_per_sample = encode_extra_channels ? ec_info.bits_per_sample
|
||||
: ppf.info.bits_per_sample;
|
||||
if (!encode_extra_channels) {
|
||||
JXL_RETURN_IF_ERROR(VerifyPackedImage(color, ppf.info));
|
||||
} else {
|
||||
JXL_RETURN_IF_ERROR(VerifyFormat(color.format));
|
||||
JXL_RETURN_IF_ERROR(VerifyBitDepth(color.format.data_type,
|
||||
bits_per_sample,
|
||||
ec_info.exponent_bits_per_sample));
|
||||
}
|
||||
const JxlPixelFormat format = color.format;
|
||||
const uint8_t* in = reinterpret_cast<const uint8_t*>(color.pixels());
|
||||
size_t data_bits_per_sample = PackedImage::BitsPerChannel(format.data_type);
|
||||
|
@ -297,24 +331,23 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
|
|||
std::vector<uint8_t> out(out_size);
|
||||
|
||||
if (format.data_type == JXL_TYPE_UINT8) {
|
||||
if (ppf.info.bits_per_sample < 8) {
|
||||
float mul = 255.0 / ((1u << ppf.info.bits_per_sample) - 1);
|
||||
if (bits_per_sample < 8) {
|
||||
float mul = 255.0 / ((1u << bits_per_sample) - 1);
|
||||
for (size_t i = 0; i < num_samples; ++i) {
|
||||
out[i] = static_cast<uint8_t>(in[i] * mul + 0.5);
|
||||
out[i] = static_cast<uint8_t>(std::lroundf(in[i] * mul));
|
||||
}
|
||||
} else {
|
||||
memcpy(out.data(), in, out_size);
|
||||
}
|
||||
} else if (format.data_type == JXL_TYPE_UINT16) {
|
||||
if (ppf.info.bits_per_sample < 16 ||
|
||||
format.endianness != JXL_BIG_ENDIAN) {
|
||||
float mul = 65535.0 / ((1u << ppf.info.bits_per_sample) - 1);
|
||||
if (bits_per_sample < 16 || format.endianness != JXL_BIG_ENDIAN) {
|
||||
float mul = 65535.0 / ((1u << bits_per_sample) - 1);
|
||||
const uint8_t* p_in = in;
|
||||
uint8_t* p_out = out.data();
|
||||
for (size_t i = 0; i < num_samples; ++i, p_in += 2, p_out += 2) {
|
||||
uint32_t val = (format.endianness == JXL_BIG_ENDIAN ? LoadBE16(p_in)
|
||||
: LoadLE16(p_in));
|
||||
StoreBE16(static_cast<uint32_t>(val * mul + 0.5), p_out);
|
||||
StoreBE16(static_cast<uint32_t>(std::lroundf(val * mul)), p_out);
|
||||
}
|
||||
} else {
|
||||
memcpy(out.data(), in, out_size);
|
||||
|
@ -344,7 +377,7 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
|
|||
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
|
||||
PNG_FILTER_TYPE_BASE);
|
||||
if (count == 0) {
|
||||
if (count == 0 && !encode_extra_channels) {
|
||||
if (!MaybeAddSRGB(ppf.color_encoding, png_ptr, info_ptr)) {
|
||||
MaybeAddCICP(ppf.color_encoding, png_ptr, info_ptr);
|
||||
if (!ppf.icc.empty()) {
|
||||
|
|
|
@ -390,7 +390,7 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
|
|||
// before the call to setjmp().
|
||||
std::vector<uint8_t> pixels;
|
||||
unsigned char* output_buffer = nullptr;
|
||||
unsigned long output_size = 0;
|
||||
unsigned long output_size = 0; // NOLINT
|
||||
std::vector<uint8_t> row_bytes;
|
||||
size_t rowlen = RoundUpTo(ppf.info.xsize, MaxVectorSize());
|
||||
hwy::AlignedFreeUniquePtr<float[]> xyb_tmp =
|
||||
|
|
|
@ -276,7 +276,7 @@ Status EncodeWithLibJpeg(const PackedImage& image, const JxlBasicInfo& info,
|
|||
cinfo.err = jpeg_std_error(&jerr);
|
||||
jpeg_create_compress(&cinfo);
|
||||
unsigned char* buffer = nullptr;
|
||||
unsigned long size = 0;
|
||||
unsigned long size = 0; // NOLINT
|
||||
jpeg_mem_dest(&cinfo, &buffer, &size);
|
||||
cinfo.image_width = image.xsize;
|
||||
cinfo.image_height = image.ysize;
|
||||
|
|
|
@ -87,8 +87,8 @@ class PNMEncoder : public BasePNMEncoder {
|
|||
}
|
||||
|
||||
private:
|
||||
Status EncodeImage(const PackedImage& image, size_t bits_per_sample,
|
||||
std::vector<uint8_t>* bytes) const {
|
||||
static Status EncodeImage(const PackedImage& image, size_t bits_per_sample,
|
||||
std::vector<uint8_t>* bytes) {
|
||||
uint32_t maxval = (1u << bits_per_sample) - 1;
|
||||
char type = image.format.num_channels == 1 ? '5' : '6';
|
||||
char header[kMaxHeaderSize];
|
||||
|
@ -161,8 +161,8 @@ class PFMEncoder : public BasePNMEncoder {
|
|||
}
|
||||
|
||||
private:
|
||||
Status EncodeImage(const PackedImage& image,
|
||||
std::vector<uint8_t>* bytes) const {
|
||||
static Status EncodeImage(const PackedImage& image,
|
||||
std::vector<uint8_t>* bytes) {
|
||||
char type = image.format.num_channels == 1 ? 'f' : 'F';
|
||||
double scale = image.format.endianness == JXL_LITTLE_ENDIAN ? -1.0 : 1.0;
|
||||
char header[kMaxHeaderSize];
|
||||
|
|
|
@ -18,10 +18,10 @@ class MemoryMappedFile {
|
|||
static StatusOr<MemoryMappedFile> Init(const char* path);
|
||||
const uint8_t* data() const;
|
||||
size_t size() const;
|
||||
MemoryMappedFile();
|
||||
~MemoryMappedFile();
|
||||
MemoryMappedFile(MemoryMappedFile&&) noexcept;
|
||||
MemoryMappedFile& operator=(MemoryMappedFile&&) noexcept;
|
||||
MemoryMappedFile(); // NOLINT
|
||||
~MemoryMappedFile(); // NOLINT
|
||||
MemoryMappedFile(MemoryMappedFile&&) noexcept; // NOLINT
|
||||
MemoryMappedFile& operator=(MemoryMappedFile&&) noexcept; // NOLINT
|
||||
|
||||
private:
|
||||
std::unique_ptr<MemoryMappedFileImpl> impl_;
|
||||
|
|
|
@ -135,19 +135,25 @@ bool CheckColorSpaceComponents(int num_components, J_COLOR_SPACE colorspace) {
|
|||
return num_components == 1;
|
||||
case JCS_RGB:
|
||||
case JCS_YCbCr:
|
||||
#ifdef JCS_EXTENSIONS
|
||||
case JCS_EXT_RGB:
|
||||
case JCS_EXT_BGR:
|
||||
#endif
|
||||
return num_components == 3;
|
||||
case JCS_CMYK:
|
||||
case JCS_YCCK:
|
||||
#ifdef JCS_EXTENSIONS
|
||||
case JCS_EXT_RGBX:
|
||||
case JCS_EXT_BGRX:
|
||||
case JCS_EXT_XBGR:
|
||||
case JCS_EXT_XRGB:
|
||||
#endif
|
||||
#ifdef JCS_ALPHA_EXTENSIONS
|
||||
case JCS_EXT_RGBA:
|
||||
case JCS_EXT_BGRA:
|
||||
case JCS_EXT_ABGR:
|
||||
case JCS_EXT_ARGB:
|
||||
#endif
|
||||
return num_components == 4;
|
||||
default:
|
||||
// Unrecognized colorspaces can have any number of channels, since no
|
||||
|
|
|
@ -36,7 +36,7 @@ void jpegli_CreateDecompress(j_decompress_ptr cinfo, int version,
|
|||
void jpegli_stdio_src(j_decompress_ptr cinfo, FILE *infile);
|
||||
|
||||
void jpegli_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer,
|
||||
unsigned long insize);
|
||||
unsigned long insize /* NOLINT */);
|
||||
|
||||
int jpegli_read_header(j_decompress_ptr cinfo, boolean require_image);
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
#include "lib/jpegli/decode.h"
|
||||
|
@ -78,7 +78,8 @@ class SourceManager {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
|
||||
static void skip_input_data(j_decompress_ptr cinfo,
|
||||
long num_bytes /* NOLINT */) {
|
||||
auto* src = reinterpret_cast<SourceManager*>(cinfo->src);
|
||||
if (num_bytes <= 0) {
|
||||
return;
|
||||
|
@ -447,7 +448,7 @@ std::vector<TestConfig> GenerateBasicConfigs() {
|
|||
TEST(DecodeAPITest, ReuseCinfoSameMemSource) {
|
||||
std::vector<TestConfig> all_configs = GenerateBasicConfigs();
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
{
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
|
@ -502,7 +503,7 @@ TEST(DecodeAPITest, ReuseCinfoSameStdSource) {
|
|||
EXPECT_TRUE(try_catch_block());
|
||||
jpegli_destroy_compress(&cinfo);
|
||||
}
|
||||
rewind(tmpf);
|
||||
fseek(tmpf, 0, SEEK_SET);
|
||||
std::vector<TestImage> all_outputs(all_configs.size());
|
||||
{
|
||||
jpeg_decompress_struct cinfo;
|
||||
|
@ -527,9 +528,9 @@ TEST(DecodeAPITest, ReuseCinfoSameStdSource) {
|
|||
|
||||
TEST(DecodeAPITest, AbbreviatedStreams) {
|
||||
uint8_t* table_stream = nullptr;
|
||||
unsigned long table_stream_size = 0;
|
||||
unsigned long table_stream_size = 0; // NOLINT
|
||||
uint8_t* data_stream = nullptr;
|
||||
unsigned long data_stream_size = 0;
|
||||
unsigned long data_stream_size = 0; // NOLINT
|
||||
{
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
|
|
|
@ -52,7 +52,7 @@ struct MemoryDestinationManager {
|
|||
jpeg_destination_mgr pub;
|
||||
// Output buffer supplied by the application
|
||||
uint8_t** output;
|
||||
unsigned long* output_size;
|
||||
unsigned long* output_size; // NOLINT
|
||||
// Output buffer allocated by us.
|
||||
uint8_t* temp_buffer;
|
||||
// Current output buffer (either application supplied or allocated by us).
|
||||
|
@ -113,7 +113,7 @@ void jpegli_stdio_dest(j_compress_ptr cinfo, FILE* outfile) {
|
|||
}
|
||||
|
||||
void jpegli_mem_dest(j_compress_ptr cinfo, unsigned char** outbuffer,
|
||||
unsigned long* outsize) {
|
||||
unsigned long* outsize /* NOLINT */) {
|
||||
if (outbuffer == nullptr || outsize == nullptr) {
|
||||
JPEGLI_ERROR("jpegli_mem_dest: Invalid destination.");
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ void jpegli_CreateCompress(j_compress_ptr cinfo, int version,
|
|||
void jpegli_stdio_dest(j_compress_ptr cinfo, FILE* outfile);
|
||||
|
||||
void jpegli_mem_dest(j_compress_ptr cinfo, unsigned char** outbuffer,
|
||||
unsigned long* outsize);
|
||||
unsigned long* outsize /* NOLINT */);
|
||||
|
||||
void jpegli_set_defaults(j_compress_ptr cinfo);
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ TEST(EncodeAPITest, ReuseCinfoSameImageTwice) {
|
|||
CompressParams jparams;
|
||||
GenerateInput(PIXELS, jparams, &input);
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
std::vector<uint8_t> compressed0;
|
||||
std::vector<uint8_t> compressed1;
|
||||
jpeg_compress_struct cinfo;
|
||||
|
@ -117,7 +117,7 @@ std::vector<TestConfig> GenerateBasicConfigs() {
|
|||
TEST(EncodeAPITest, ReuseCinfoSameMemOutput) {
|
||||
std::vector<TestConfig> all_configs = GenerateBasicConfigs();
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
{
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
|
@ -161,7 +161,7 @@ TEST(EncodeAPITest, ReuseCinfoSameStdOutput) {
|
|||
jpegli_destroy_compress(&cinfo);
|
||||
}
|
||||
size_t total_size = ftell(tmpf);
|
||||
rewind(tmpf);
|
||||
fseek(tmpf, 0, SEEK_SET);
|
||||
std::vector<uint8_t> compressed(total_size);
|
||||
JXL_CHECK(total_size == fread(compressed.data(), 1, total_size, tmpf));
|
||||
fclose(tmpf);
|
||||
|
@ -181,7 +181,7 @@ TEST(EncodeAPITest, ReuseCinfoChangeParams) {
|
|||
CompressParams jparams;
|
||||
DecompressParams dparams;
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
std::vector<uint8_t> compressed;
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto max_rms = [](int q, int hs, int vs) {
|
||||
|
@ -246,9 +246,9 @@ TEST(EncodeAPITest, ReuseCinfoChangeParams) {
|
|||
|
||||
TEST(EncodeAPITest, AbbreviatedStreams) {
|
||||
uint8_t* table_stream = nullptr;
|
||||
unsigned long table_stream_size = 0;
|
||||
unsigned long table_stream_size = 0; // NOLINT
|
||||
uint8_t* data_stream = nullptr;
|
||||
unsigned long data_stream_size = 0;
|
||||
unsigned long data_stream_size = 0; // NOLINT
|
||||
{
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, MinimalSuccess) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
{
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
|
@ -64,7 +64,7 @@ TEST(EncoderErrorHandlingTest, NoDestination) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NoImageDimensions) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -82,7 +82,7 @@ TEST(EncoderErrorHandlingTest, NoImageDimensions) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, ImageTooBig) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -102,7 +102,7 @@ TEST(EncoderErrorHandlingTest, ImageTooBig) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NoInputComponents) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -121,7 +121,7 @@ TEST(EncoderErrorHandlingTest, NoInputComponents) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, TooManyInputComponents) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -141,7 +141,7 @@ TEST(EncoderErrorHandlingTest, TooManyInputComponents) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NoSetDefaults) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -164,7 +164,7 @@ TEST(EncoderErrorHandlingTest, NoSetDefaults) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NoStartCompress) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -186,7 +186,7 @@ TEST(EncoderErrorHandlingTest, NoStartCompress) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NoWriteScanlines) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -207,7 +207,7 @@ TEST(EncoderErrorHandlingTest, NoWriteScanlines) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NoWriteAllScanlines) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -231,7 +231,7 @@ TEST(EncoderErrorHandlingTest, NoWriteAllScanlines) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidQuantValue) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -260,7 +260,7 @@ TEST(EncoderErrorHandlingTest, InvalidQuantValue) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidQuantTableIndex) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -285,7 +285,7 @@ TEST(EncoderErrorHandlingTest, InvalidQuantTableIndex) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch1) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -306,7 +306,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch1) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch2) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -327,7 +327,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch2) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch3) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -353,7 +353,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch3) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch4) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -378,7 +378,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch4) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch5) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -403,7 +403,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch5) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch6) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -429,7 +429,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch6) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidColorTransform) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -455,7 +455,7 @@ TEST(EncoderErrorHandlingTest, InvalidColorTransform) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, DuplicateComponentIds) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -477,7 +477,7 @@ TEST(EncoderErrorHandlingTest, DuplicateComponentIds) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidComponentIndex) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -498,7 +498,7 @@ TEST(EncoderErrorHandlingTest, InvalidComponentIndex) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, ArithmeticCoding) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -519,7 +519,7 @@ TEST(EncoderErrorHandlingTest, ArithmeticCoding) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, CCIR601Sampling) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -540,7 +540,7 @@ TEST(EncoderErrorHandlingTest, CCIR601Sampling) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript1) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -563,7 +563,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript1) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript2) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -586,7 +586,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript2) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript3) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -609,7 +609,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript3) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript4) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -632,7 +632,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript4) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript5) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -655,7 +655,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript5) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript6) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -678,7 +678,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript6) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript7) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -701,7 +701,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript7) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript8) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -726,7 +726,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript8) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript9) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -751,7 +751,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript9) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript10) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -776,7 +776,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript10) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript11) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -801,7 +801,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript11) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript12) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -826,7 +826,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript12) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, InvalidScanScript13) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -854,7 +854,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript13) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, MCUSizeTooBig) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -877,7 +877,7 @@ TEST(EncoderErrorHandlingTest, MCUSizeTooBig) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, RestartIntervalTooBig) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -898,7 +898,7 @@ TEST(EncoderErrorHandlingTest, RestartIntervalTooBig) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, SamplingFactorTooBig) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
@ -919,7 +919,7 @@ TEST(EncoderErrorHandlingTest, SamplingFactorTooBig) {
|
|||
|
||||
TEST(EncoderErrorHandlingTest, NonIntegralSamplingRatio) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
|
|
@ -80,7 +80,8 @@ struct SourceManager {
|
|||
|
||||
static boolean fill_input_buffer(j_decompress_ptr cinfo) { return FALSE; }
|
||||
|
||||
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
|
||||
static void skip_input_data(j_decompress_ptr cinfo,
|
||||
long num_bytes /* NOLINT*/) {
|
||||
auto* src = reinterpret_cast<SourceManager*>(cinfo->src);
|
||||
if (num_bytes <= 0) {
|
||||
return;
|
||||
|
|
|
@ -38,7 +38,7 @@ void jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile) {
|
|||
}
|
||||
|
||||
void jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer,
|
||||
unsigned long insize) {
|
||||
unsigned long insize /* NOLINT */) {
|
||||
jpegli_mem_src(cinfo, inbuffer, insize);
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ void jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile) {
|
|||
}
|
||||
|
||||
void jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer,
|
||||
unsigned long *outsize) {
|
||||
unsigned long *outsize /* NOLINT */) {
|
||||
jpegli_mem_dest(cinfo, outbuffer, outsize);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,10 @@ namespace jpegli {
|
|||
void init_mem_source(j_decompress_ptr cinfo) {}
|
||||
void init_stdio_source(j_decompress_ptr cinfo) {}
|
||||
|
||||
void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
|
||||
void skip_input_data(j_decompress_ptr cinfo, long num_bytes /* NOLINT */) {
|
||||
if (num_bytes <= 0) return;
|
||||
while (num_bytes > static_cast<long>(cinfo->src->bytes_in_buffer)) {
|
||||
while (num_bytes >
|
||||
static_cast<long>(cinfo->src->bytes_in_buffer)) { // NOLINT
|
||||
num_bytes -= cinfo->src->bytes_in_buffer;
|
||||
(*cinfo->src->fill_input_buffer)(cinfo);
|
||||
}
|
||||
|
@ -53,7 +54,7 @@ struct StdioSourceManager {
|
|||
} // namespace jpegli
|
||||
|
||||
void jpegli_mem_src(j_decompress_ptr cinfo, const unsigned char* inbuffer,
|
||||
unsigned long insize) {
|
||||
unsigned long insize /* NOLINT */) {
|
||||
if (cinfo->src && cinfo->src->init_source != jpegli::init_mem_source) {
|
||||
JPEGLI_ERROR("jpegli_mem_src: a different source manager was already set");
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ FILE* MemOpen(const std::vector<uint8_t>& data) {
|
|||
FILE* src = tmpfile();
|
||||
if (!src) return nullptr;
|
||||
fwrite(data.data(), 1, data.size(), src);
|
||||
rewind(src);
|
||||
fseek(src, 0, SEEK_SET);
|
||||
return src;
|
||||
}
|
||||
} // namespace
|
||||
|
|
|
@ -28,7 +28,8 @@ struct SourceManager {
|
|||
|
||||
static void init_source(j_decompress_ptr cinfo) {}
|
||||
static boolean fill_input_buffer(j_decompress_ptr cinfo) { return FALSE; }
|
||||
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {}
|
||||
static void skip_input_data(j_decompress_ptr cinfo,
|
||||
long num_bytes /* NOLINT */) {}
|
||||
static void term_source(j_decompress_ptr cinfo) {}
|
||||
};
|
||||
|
||||
|
|
|
@ -673,7 +673,7 @@ void EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
|
|||
bool EncodeWithJpegli(const TestImage& input, const CompressParams& jparams,
|
||||
std::vector<uint8_t>* compressed) {
|
||||
uint8_t* buffer = nullptr;
|
||||
unsigned long buffer_size = 0;
|
||||
unsigned long buffer_size = 0; // NOLINT
|
||||
jpeg_compress_struct cinfo;
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
|
|
|
@ -20,7 +20,7 @@ void TranscodeWithJpegli(const std::vector<uint8_t>& jpeg_input,
|
|||
jpeg_decompress_struct dinfo = {};
|
||||
jpeg_compress_struct cinfo = {};
|
||||
uint8_t* transcoded_data = nullptr;
|
||||
unsigned long transcoded_size;
|
||||
unsigned long transcoded_size; // NOLINT
|
||||
const auto try_catch_block = [&]() -> bool {
|
||||
ERROR_HANDLER_SETUP(jpegli);
|
||||
dinfo.err = cinfo.err;
|
||||
|
|
|
@ -80,10 +80,10 @@ foreach(path ${JPEGXL_INTERNAL_PUBLIC_HEADERS})
|
|||
endforeach()
|
||||
|
||||
add_library(jxl_base INTERFACE)
|
||||
target_include_directories(jxl_base SYSTEM INTERFACE
|
||||
target_include_directories(jxl_base SYSTEM BEFORE INTERFACE
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||
)
|
||||
target_include_directories(jxl_base INTERFACE
|
||||
target_include_directories(jxl_base BEFORE INTERFACE
|
||||
${PROJECT_SOURCE_DIR}
|
||||
${JXL_HWY_INCLUDE_DIRS}
|
||||
)
|
||||
|
@ -104,7 +104,7 @@ add_library(jxl_dec-obj OBJECT ${JPEGXL_INTERNAL_DEC_SOURCES})
|
|||
target_compile_options(jxl_dec-obj PRIVATE ${JPEGXL_INTERNAL_FLAGS})
|
||||
target_compile_options(jxl_dec-obj PUBLIC ${JPEGXL_COVERAGE_FLAGS})
|
||||
set_property(TARGET jxl_dec-obj PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
target_include_directories(jxl_dec-obj PUBLIC
|
||||
target_include_directories(jxl_dec-obj BEFORE PUBLIC
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>"
|
||||
"${JXL_HWY_INCLUDE_DIRS}"
|
||||
"$<BUILD_INTERFACE:$<TARGET_PROPERTY:brotlicommon,INTERFACE_INCLUDE_DIRECTORIES>>"
|
||||
|
@ -119,7 +119,7 @@ add_library(jxl_enc-obj OBJECT ${JPEGXL_INTERNAL_ENC_SOURCES})
|
|||
target_compile_options(jxl_enc-obj PRIVATE ${JPEGXL_INTERNAL_FLAGS})
|
||||
target_compile_options(jxl_enc-obj PUBLIC ${JPEGXL_COVERAGE_FLAGS})
|
||||
set_property(TARGET jxl_enc-obj PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
target_include_directories(jxl_enc-obj PUBLIC
|
||||
target_include_directories(jxl_enc-obj BEFORE PUBLIC
|
||||
${PROJECT_SOURCE_DIR}
|
||||
${JXL_HWY_INCLUDE_DIRS}
|
||||
$<TARGET_PROPERTY:brotlicommon,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
|
@ -172,7 +172,7 @@ target_link_libraries(jxl-internal PUBLIC
|
|||
jxl_cms
|
||||
jxl_base
|
||||
)
|
||||
target_include_directories(jxl-internal PUBLIC
|
||||
target_include_directories(jxl-internal BEFORE PUBLIC
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>")
|
||||
|
||||
target_compile_definitions(jxl-internal INTERFACE -DJXL_STATIC_DEFINE)
|
||||
|
|
|
@ -13,6 +13,16 @@
|
|||
namespace jxl {
|
||||
namespace {
|
||||
|
||||
AlphaBlendingInputLayer makeAbil(const Color& rgb, const float& a) {
|
||||
const float* data = rgb.data();
|
||||
return {data, data + 1, data + 2, &a};
|
||||
}
|
||||
|
||||
AlphaBlendingOutput makeAbo(Color& rgb, float& a) {
|
||||
float* data = rgb.data();
|
||||
return {data, data + 1, data + 2, &a};
|
||||
}
|
||||
|
||||
TEST(AlphaTest, BlendingWithNonPremultiplied) {
|
||||
const Color bg_rgb{100, 110, 120};
|
||||
const float bg_a = 180.f / 255;
|
||||
|
@ -22,16 +32,16 @@ TEST(AlphaTest, BlendingWithNonPremultiplied) {
|
|||
Color out_rgb;
|
||||
float out_a;
|
||||
PerformAlphaBlending(
|
||||
/*bg=*/{&bg_rgb[0], &bg_rgb[1], &bg_rgb[2], &bg_a},
|
||||
/*fg=*/{&fg_rgb[0], &fg_rgb[1], &fg_rgb[2], &fg_a},
|
||||
/*out=*/{&out_rgb[0], &out_rgb[1], &out_rgb[2], &out_a}, 1,
|
||||
/*bg=*/makeAbil(bg_rgb, bg_a),
|
||||
/*fg=*/makeAbil(fg_rgb, fg_a),
|
||||
/*out=*/makeAbo(out_rgb, out_a), 1,
|
||||
/*alpha_is_premultiplied=*/false, /*clamp=*/false);
|
||||
EXPECT_ARRAY_NEAR(out_rgb, (Color{77.2f, 83.0f, 90.6f}), 0.05f);
|
||||
EXPECT_NEAR(out_a, 3174.f / 4095, 1e-5);
|
||||
PerformAlphaBlending(
|
||||
/*bg=*/{&bg_rgb[0], &bg_rgb[1], &bg_rgb[2], &bg_a},
|
||||
/*fg=*/{&fg_rgb[0], &fg_rgb[1], &fg_rgb[2], &fg_a2},
|
||||
/*out=*/{&out_rgb[0], &out_rgb[1], &out_rgb[2], &out_a}, 1,
|
||||
/*bg=*/makeAbil(bg_rgb, bg_a),
|
||||
/*fg=*/makeAbil(fg_rgb, fg_a2),
|
||||
/*out=*/makeAbo(out_rgb, out_a), 1,
|
||||
/*alpha_is_premultiplied=*/false, /*clamp=*/true);
|
||||
EXPECT_ARRAY_NEAR(out_rgb, fg_rgb, 0.05f);
|
||||
EXPECT_NEAR(out_a, 1.0f, 1e-5);
|
||||
|
@ -46,16 +56,16 @@ TEST(AlphaTest, BlendingWithPremultiplied) {
|
|||
Color out_rgb;
|
||||
float out_a;
|
||||
PerformAlphaBlending(
|
||||
/*bg=*/{&bg_rgb[0], &bg_rgb[1], &bg_rgb[2], &bg_a},
|
||||
/*fg=*/{&fg_rgb[0], &fg_rgb[1], &fg_rgb[2], &fg_a},
|
||||
/*out=*/{&out_rgb[0], &out_rgb[1], &out_rgb[2], &out_a}, 1,
|
||||
/*bg=*/makeAbil(bg_rgb, bg_a),
|
||||
/*fg=*/makeAbil(fg_rgb, fg_a),
|
||||
/*out=*/makeAbo(out_rgb, out_a), 1,
|
||||
/*alpha_is_premultiplied=*/true, /*clamp=*/false);
|
||||
EXPECT_ARRAY_NEAR(out_rgb, (Color{101.5f, 105.1f, 114.8f}), 0.05f);
|
||||
EXPECT_NEAR(out_a, 3174.f / 4095, 1e-5);
|
||||
PerformAlphaBlending(
|
||||
/*bg=*/{&bg_rgb[0], &bg_rgb[1], &bg_rgb[2], &bg_a},
|
||||
/*fg=*/{&fg_rgb[0], &fg_rgb[1], &fg_rgb[2], &fg_a2},
|
||||
/*out=*/{&out_rgb[0], &out_rgb[1], &out_rgb[2], &out_a}, 1,
|
||||
/*bg=*/makeAbil(bg_rgb, bg_a),
|
||||
/*fg=*/makeAbil(fg_rgb, fg_a2),
|
||||
/*out=*/makeAbo(out_rgb, out_a), 1,
|
||||
/*alpha_is_premultiplied=*/true, /*clamp=*/true);
|
||||
EXPECT_ARRAY_NEAR(out_rgb, fg_rgb, 0.05f);
|
||||
EXPECT_NEAR(out_a, 1.0f, 1e-5);
|
||||
|
|
|
@ -53,7 +53,7 @@ struct Symbol {
|
|||
TEST(BitReaderTest, TestRoundTrip) {
|
||||
test::ThreadPoolForTests pool(8);
|
||||
EXPECT_TRUE(RunOnPool(
|
||||
&pool, 0, 1000, ThreadPool::NoInit,
|
||||
pool.get(), 0, 1000, ThreadPool::NoInit,
|
||||
[](const uint32_t task, size_t /* thread */) {
|
||||
constexpr size_t kMaxBits = 8000;
|
||||
BitWriter writer;
|
||||
|
@ -87,7 +87,7 @@ TEST(BitReaderTest, TestRoundTrip) {
|
|||
TEST(BitReaderTest, TestSkip) {
|
||||
test::ThreadPoolForTests pool(8);
|
||||
EXPECT_TRUE(RunOnPool(
|
||||
&pool, 0, 96, ThreadPool::NoInit,
|
||||
pool.get(), 0, 96, ThreadPool::NoInit,
|
||||
[](const uint32_t task, size_t /* thread */) {
|
||||
constexpr size_t kSize = 100;
|
||||
|
||||
|
|
|
@ -8,12 +8,10 @@
|
|||
#ifndef LIB_JXL_BUTTERAUGLI_BUTTERAUGLI_H_
|
||||
#define LIB_JXL_BUTTERAUGLI_BUTTERAUGLI_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
|
@ -21,7 +19,10 @@
|
|||
#include "lib/jxl/base/status.h"
|
||||
#include "lib/jxl/image.h"
|
||||
|
||||
#if !defined(BUTTERAUGLI_ENABLE_CHECKS)
|
||||
#define BUTTERAUGLI_ENABLE_CHECKS 0
|
||||
#endif
|
||||
|
||||
#define BUTTERAUGLI_RESTRICT JXL_RESTRICT
|
||||
|
||||
// This is the main interface to butteraugli image similarity
|
||||
|
|
|
@ -128,11 +128,12 @@ void* CacheAligned::Allocate(const size_t payload_size, size_t offset) {
|
|||
const uintptr_t payload = aligned + offset; // still aligned
|
||||
|
||||
// Stash `allocated` and payload_size inside header for use by Free().
|
||||
AllocationHeader* header = reinterpret_cast<AllocationHeader*>(payload) - 1;
|
||||
AllocationHeader* header =
|
||||
reinterpret_cast<AllocationHeader*>(payload) - 1; // NOLINT
|
||||
header->allocated = allocated;
|
||||
header->allocated_size = allocated_size;
|
||||
|
||||
return JXL_ASSUME_ALIGNED(reinterpret_cast<void*>(payload), 64);
|
||||
return JXL_ASSUME_ALIGNED(reinterpret_cast<void*>(payload), 64); // NOLINT
|
||||
}
|
||||
|
||||
void CacheAligned::Free(const void* aligned_pointer) {
|
||||
|
@ -142,7 +143,7 @@ void CacheAligned::Free(const void* aligned_pointer) {
|
|||
const uintptr_t payload = reinterpret_cast<uintptr_t>(aligned_pointer);
|
||||
JXL_ASSERT(payload % kAlignment == 0);
|
||||
const AllocationHeader* header =
|
||||
reinterpret_cast<const AllocationHeader*>(payload) - 1;
|
||||
reinterpret_cast<const AllocationHeader*>(payload) - 1; // NOLINT
|
||||
|
||||
// Subtract (2's complement negation).
|
||||
bytes_in_use.fetch_add(~header->allocated_size + 1,
|
||||
|
|
|
@ -183,12 +183,12 @@ static Status ToneMapPixel(const JxlColorEncoding& c, const float in[3],
|
|||
const float f_y = lab_f(xyz[1] / kYn);
|
||||
const float f_z = lab_f(xyz[2] / kZn);
|
||||
|
||||
pcslab_out[0] =
|
||||
static_cast<uint8_t>(.5f + 255.f * Clamp1(1.16f * f_y - .16f, 0.f, 1.f));
|
||||
pcslab_out[0] = static_cast<uint8_t>(
|
||||
std::lroundf(255.f * Clamp1(1.16f * f_y - .16f, 0.f, 1.f)));
|
||||
pcslab_out[1] = static_cast<uint8_t>(
|
||||
.5f + 128.f + Clamp1(500 * (f_x - f_y), -128.f, 127.f));
|
||||
std::lroundf(128.f + Clamp1(500 * (f_x - f_y), -128.f, 127.f)));
|
||||
pcslab_out[2] = static_cast<uint8_t>(
|
||||
.5f + 128.f + Clamp1(200 * (f_y - f_z), -128.f, 127.f));
|
||||
std::lroundf(128.f + Clamp1(200 * (f_y - f_z), -128.f, 127.f)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -581,7 +581,8 @@ static void CreateICCCurvCurvTag(const std::vector<uint16_t>& curve,
|
|||
}
|
||||
|
||||
// Writes 12 + 4*params.size() bytes
|
||||
static Status CreateICCCurvParaTag(std::vector<float> params, size_t curve_type,
|
||||
static Status CreateICCCurvParaTag(const std::vector<float>& params,
|
||||
size_t curve_type,
|
||||
std::vector<uint8_t>* tags) {
|
||||
WriteICCTag("para", tags->size(), tags);
|
||||
WriteICCUint32(0, tags->size(), tags);
|
||||
|
@ -637,7 +638,7 @@ static Status CreateICCLutAtoBTagForXYB(std::vector<uint8_t>* tags) {
|
|||
for (size_t ib = 0; ib < 2; ++ib) {
|
||||
const jxl::cms::ColorCube0D& out_f = cube[ix][iy][ib];
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
int32_t val = static_cast<int32_t>(0.5f + 65535 * out_f[i]);
|
||||
int32_t val = static_cast<int32_t>(std::lroundf(65535 * out_f[i]));
|
||||
JXL_DASSERT(val >= 0 && val <= 65535);
|
||||
WriteICCUint16(val, tags->size(), tags);
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ class Rec2408ToneMapperBase {
|
|||
explicit Rec2408ToneMapperBase(std::pair<float, float> source_range,
|
||||
std::pair<float, float> target_range,
|
||||
const Vector3& primaries_luminances)
|
||||
: source_range_(source_range),
|
||||
target_range_(target_range),
|
||||
: source_range_(std::move(source_range)),
|
||||
target_range_(std::move(target_range)),
|
||||
red_Y_(primaries_luminances[0]),
|
||||
green_Y_(primaries_luminances[1]),
|
||||
blue_Y_(primaries_luminances[2]) {}
|
||||
|
@ -56,7 +56,7 @@ class Rec2408ToneMapperBase {
|
|||
}
|
||||
|
||||
protected:
|
||||
float InvEOTF(const float luminance) const {
|
||||
static float InvEOTF(const float luminance) {
|
||||
return TF_PQ_Base::EncodedFromDisplay(/*display_intensity_target=*/1.0,
|
||||
luminance);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ class TF_HLG : TF_HLG_Base {
|
|||
|
||||
class TF_709 {
|
||||
public:
|
||||
JXL_INLINE double EncodedFromDisplay(const double d) const {
|
||||
static JXL_INLINE double EncodedFromDisplay(const double d) {
|
||||
if (d < kThresh) return kMulLow * d;
|
||||
return kMulHi * std::pow(d, kPowHi) + kSub;
|
||||
}
|
||||
|
|
|
@ -434,7 +434,7 @@ TEST_F(ColorManagementTest, GoldenXYBCube) {
|
|||
for (size_t ib = 0; ib < 2; ++ib) {
|
||||
const jxl::cms::ColorCube0D& out_f = cube[ix][iy][ib];
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
int32_t val = static_cast<int32_t>(0.5f + 65535 * out_f[i]);
|
||||
int32_t val = static_cast<int32_t>(std::lroundf(65535 * out_f[i]));
|
||||
ASSERT_TRUE(val >= 0 && val <= 65535);
|
||||
actual.push_back(val);
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ void TestConvolve() {
|
|||
test::ThreadPoolForTests pool(4);
|
||||
EXPECT_EQ(true,
|
||||
RunOnPool(
|
||||
&pool, kConvolveMaxRadius, 40, ThreadPool::NoInit,
|
||||
pool.get(), kConvolveMaxRadius, 40, ThreadPool::NoInit,
|
||||
[](const uint32_t task, size_t /*thread*/) {
|
||||
const size_t xsize = task;
|
||||
Rng rng(129 + 13 * xsize);
|
||||
|
@ -176,15 +176,15 @@ void TestConvolve() {
|
|||
|
||||
JXL_DEBUG(JXL_DEBUG_CONVOLVE, "Sym3------------------");
|
||||
VerifySymmetric3(xsize, ysize, null_pool, &rng);
|
||||
VerifySymmetric3(xsize, ysize, &pool3, &rng);
|
||||
VerifySymmetric3(xsize, ysize, pool3.get(), &rng);
|
||||
|
||||
JXL_DEBUG(JXL_DEBUG_CONVOLVE, "Sym5------------------");
|
||||
VerifySymmetric5(xsize, ysize, null_pool, &rng);
|
||||
VerifySymmetric5(xsize, ysize, &pool3, &rng);
|
||||
VerifySymmetric5(xsize, ysize, pool3.get(), &rng);
|
||||
|
||||
JXL_DEBUG(JXL_DEBUG_CONVOLVE, "Sep5------------------");
|
||||
VerifySeparable5(xsize, ysize, null_pool, &rng);
|
||||
VerifySeparable5(xsize, ysize, &pool3, &rng);
|
||||
VerifySeparable5(xsize, ysize, pool3.get(), &rng);
|
||||
}
|
||||
},
|
||||
"TestConvolve"));
|
||||
|
|
|
@ -22,7 +22,7 @@ static inline double alpha(int u) { return u == 0 ? 0.7071067811865475 : 1.0; }
|
|||
|
||||
// N-DCT on M columns, divided by sqrt(N). Matches the definition in the spec.
|
||||
template <size_t N, size_t M>
|
||||
void DCT1D(double block[N * M], double out[N * M]) {
|
||||
void DCT1D(const double block[N * M], double out[N * M]) {
|
||||
std::vector<double> matrix(N * N);
|
||||
const double scale = std::sqrt(2.0) / N;
|
||||
for (size_t y = 0; y < N; y++) {
|
||||
|
@ -43,7 +43,7 @@ void DCT1D(double block[N * M], double out[N * M]) {
|
|||
// N-IDCT on M columns, multiplied by sqrt(N). Matches the definition in the
|
||||
// spec.
|
||||
template <size_t N, size_t M>
|
||||
void IDCT1D(double block[N * M], double out[N * M]) {
|
||||
void IDCT1D(const double block[N * M], double out[N * M]) {
|
||||
std::vector<double> matrix(N * N);
|
||||
const double scale = std::sqrt(2.0);
|
||||
for (size_t y = 0; y < N; y++) {
|
||||
|
@ -63,7 +63,7 @@ void IDCT1D(double block[N * M], double out[N * M]) {
|
|||
}
|
||||
|
||||
template <size_t N, size_t M>
|
||||
void TransposeBlock(double in[N * M], double out[M * N]) {
|
||||
void TransposeBlock(const double in[N * M], double out[M * N]) {
|
||||
for (size_t x = 0; x < N; x++) {
|
||||
for (size_t y = 0; y < M; y++) {
|
||||
out[y * N + x] = in[x * M + y];
|
||||
|
|
|
@ -160,7 +160,7 @@ void TestInverseT(float accuracy) {
|
|||
test::ThreadPoolForTests pool(N < 32 ? 0 : 8);
|
||||
enum { kBlockSize = N * N };
|
||||
EXPECT_TRUE(RunOnPool(
|
||||
&pool, 0, kBlockSize, ThreadPool::NoInit,
|
||||
pool.get(), 0, kBlockSize, ThreadPool::NoInit,
|
||||
[accuracy](const uint32_t task, size_t /*thread*/) {
|
||||
const size_t i = static_cast<size_t>(task);
|
||||
HWY_ALIGN float x[kBlockSize] = {0.0f};
|
||||
|
|
|
@ -125,8 +125,8 @@ Status PassesDecoderState::PreparePipeline(const FrameHeader& frame_header,
|
|||
|
||||
if (frame_header.CanBeReferenced() &&
|
||||
frame_header.save_before_color_transform) {
|
||||
builder.AddStage(GetWriteToImageBundleStage(
|
||||
&frame_storage_for_referencing, output_encoding_info.color_encoding));
|
||||
builder.AddStage(GetWriteToImageBundleStage(&frame_storage_for_referencing,
|
||||
output_encoding_info));
|
||||
}
|
||||
|
||||
bool has_alpha = false;
|
||||
|
@ -181,7 +181,7 @@ Status PassesDecoderState::PreparePipeline(const FrameHeader& frame_header,
|
|||
linear = false;
|
||||
}
|
||||
builder.AddStage(GetWriteToImageBundleStage(
|
||||
&frame_storage_for_referencing, output_encoding_info.color_encoding));
|
||||
&frame_storage_for_referencing, output_encoding_info));
|
||||
}
|
||||
|
||||
if (options.render_spotcolors &&
|
||||
|
@ -228,7 +228,7 @@ Status PassesDecoderState::PreparePipeline(const FrameHeader& frame_header,
|
|||
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
|
||||
// to obtain a 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
|
||||
|
@ -255,8 +255,8 @@ Status PassesDecoderState::PreparePipeline(const FrameHeader& frame_header,
|
|||
has_alpha, unpremul_alpha, alpha_c,
|
||||
undo_orientation, extra_output));
|
||||
} else {
|
||||
builder.AddStage(GetWriteToImageBundleStage(
|
||||
decoded, output_encoding_info.color_encoding));
|
||||
builder.AddStage(
|
||||
GetWriteToImageBundleStage(decoded, output_encoding_info));
|
||||
}
|
||||
}
|
||||
JXL_ASSIGN_OR_RETURN(render_pipeline,
|
||||
|
|
|
@ -362,7 +362,7 @@ Status ModularFrameDecoder::DecodeGroup(
|
|||
// Undo global transforms that have been pushed to the group level
|
||||
if (!use_full_image) {
|
||||
JXL_ASSERT(render_pipeline_input);
|
||||
for (auto t : global_transform) {
|
||||
for (const auto& t : global_transform) {
|
||||
JXL_RETURN_IF_ERROR(t.Inverse(gi, global_header.wp_header));
|
||||
}
|
||||
JXL_RETURN_IF_ERROR(ModularImageToDecodedRect(
|
||||
|
|
|
@ -2475,7 +2475,7 @@ void TestPartialStream(bool reconstructible_jpeg) {
|
|||
TEST(DecodeTest, PixelPartialTest) { TestPartialStream(false); }
|
||||
|
||||
// Tests the return status when trying to decode JPEG bytes on incomplete file.
|
||||
TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGPartialTest)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(DecodeTest, JPEGPartialTest) {
|
||||
TEST_LIBJPEG_SUPPORT();
|
||||
TestPartialStream(true);
|
||||
}
|
||||
|
@ -4195,7 +4195,7 @@ TEST(DecodeTest, InputHandlingTestOneShot) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(InputHandlingTestJPEGOneshot)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(DecodeTest, InputHandlingTestJPEGOneshot) {
|
||||
TEST_LIBJPEG_SUPPORT();
|
||||
size_t xsize = 123;
|
||||
size_t ysize = 77;
|
||||
|
@ -4976,7 +4976,7 @@ void VerifyJPEGReconstruction(jxl::Span<const uint8_t> container,
|
|||
EXPECT_EQ(0, memcmp(reconstructed_buffer.data(), jpeg_bytes.data(), used));
|
||||
}
|
||||
|
||||
TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructTestCodestream)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(DecodeTest, JPEGReconstructTestCodestream) {
|
||||
TEST_LIBJPEG_SUPPORT();
|
||||
size_t xsize = 123;
|
||||
size_t ysize = 77;
|
||||
|
@ -4994,7 +4994,7 @@ TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructTestCodestream)) {
|
|||
VerifyJPEGReconstruction(jxl::Bytes(compressed), jxl::Bytes(jpeg_codestream));
|
||||
}
|
||||
|
||||
TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionTest)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(DecodeTest, JPEGReconstructionTest) {
|
||||
const std::string jpeg_path = "jxl/flower/flower.png.im_q85_420.jpg";
|
||||
const std::vector<uint8_t> orig = jxl::test::ReadTestData(jpeg_path);
|
||||
jxl::CodecInOut orig_io;
|
||||
|
@ -5024,7 +5024,7 @@ TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionTest)) {
|
|||
VerifyJPEGReconstruction(jxl::Bytes(container), jxl::Bytes(orig));
|
||||
}
|
||||
|
||||
TEST(DecodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionMetadataTest)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(DecodeTest, JPEGReconstructionMetadataTest) {
|
||||
const std::string jpeg_path = "jxl/jpeg_reconstruction/1x1_exif_xmp.jpg";
|
||||
const std::string jxl_path = "jxl/jpeg_reconstruction/1x1_exif_xmp.jxl";
|
||||
const std::vector<uint8_t> jpeg = jxl::test::ReadTestData(jpeg_path);
|
||||
|
@ -5135,7 +5135,7 @@ TEST(DecodeTest, ExtentedBoxSizeTest) {
|
|||
JxlDecoderDestroy(dec);
|
||||
}
|
||||
|
||||
TEST(DecodeTest, JXL_BOXES_TEST(BoxTest)) {
|
||||
JXL_BOXES_TEST(DecodeTest, BoxTest) {
|
||||
size_t xsize = 1;
|
||||
size_t ysize = 1;
|
||||
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0);
|
||||
|
@ -5212,7 +5212,7 @@ TEST(DecodeTest, JXL_BOXES_TEST(BoxTest)) {
|
|||
JxlDecoderDestroy(dec);
|
||||
}
|
||||
|
||||
TEST(DecodeTest, JXL_BOXES_TEST(ExifBrobBoxTest)) {
|
||||
JXL_BOXES_TEST(DecodeTest, ExifBrobBoxTest) {
|
||||
size_t xsize = 1;
|
||||
size_t ysize = 1;
|
||||
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0);
|
||||
|
@ -5394,7 +5394,7 @@ TEST(DecodeTest, JXL_BOXES_TEST(ExifBrobBoxTest)) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(DecodeTest, JXL_BOXES_TEST(PartialCodestreamBoxTest)) {
|
||||
JXL_BOXES_TEST(DecodeTest, PartialCodestreamBoxTest) {
|
||||
size_t xsize = 23;
|
||||
size_t ysize = 81;
|
||||
std::vector<uint8_t> pixels = jxl::test::GetSomeTestImage(xsize, ysize, 4, 0);
|
||||
|
|
|
@ -149,9 +149,9 @@ Status ProcessTile(const CompressParams& cparams,
|
|||
float* JXL_RESTRICT row_out = sqrsum_00_row + y * sqrsum_00_stride;
|
||||
for (size_t x = 0; x < rect.xsize() * 2; x++) {
|
||||
auto sum = Zero(df4);
|
||||
for (size_t iy = 0; iy < 4; iy++) {
|
||||
for (auto& row : rows_in) {
|
||||
for (size_t ix = 0; ix < 4; ix += Lanes(df4)) {
|
||||
sum = Add(sum, LoadU(df4, rows_in[iy] + x * 4 + ix + 2));
|
||||
sum = Add(sum, LoadU(df4, row + x * 4 + ix + 2));
|
||||
}
|
||||
}
|
||||
row_out[x] = GetLane(Sqrt(SumOfLanes(df4, sum))) * (1.0f / 4.0f);
|
||||
|
|
|
@ -202,8 +202,8 @@ size_t TOCBucket(size_t group_size) {
|
|||
|
||||
size_t TOCSize(const std::vector<size_t>& group_sizes) {
|
||||
size_t toc_bits = 0;
|
||||
for (size_t i = 0; i < group_sizes.size(); i++) {
|
||||
toc_bits += kTOCBits[TOCBucket(group_sizes[i])];
|
||||
for (size_t group_size : group_sizes) {
|
||||
toc_bits += kTOCBits[TOCBucket(group_size)];
|
||||
}
|
||||
return (toc_bits + 7) / 8;
|
||||
}
|
||||
|
@ -328,8 +328,8 @@ struct PrefixCode {
|
|||
template <typename T>
|
||||
static void ComputeCodeLengthsNonZeroImpl(const uint64_t* freqs, size_t n,
|
||||
size_t precision, T infty,
|
||||
uint8_t* min_limit,
|
||||
uint8_t* max_limit,
|
||||
const uint8_t* min_limit,
|
||||
const uint8_t* max_limit,
|
||||
uint8_t* nbits) {
|
||||
assert(precision < 15);
|
||||
assert(n <= kMaxNumSymbols);
|
||||
|
@ -454,8 +454,8 @@ struct PrefixCode {
|
|||
uint8_t min_lengths[kNumLZ77] = {};
|
||||
uint8_t l = 15 - level1_nbits[numraw];
|
||||
uint8_t max_lengths[kNumLZ77];
|
||||
for (size_t i = 0; i < kNumLZ77; i++) {
|
||||
max_lengths[i] = l;
|
||||
for (uint8_t& max_length : max_lengths) {
|
||||
max_length = l;
|
||||
}
|
||||
size_t num_lz77 = kNumLZ77;
|
||||
while (num_lz77 > 0 && lz77_counts[num_lz77 - 1] == 0) num_lz77--;
|
||||
|
@ -487,11 +487,11 @@ struct PrefixCode {
|
|||
void WriteTo(BitWriter* writer) const {
|
||||
uint64_t code_length_counts[18] = {};
|
||||
code_length_counts[17] = 3 + 2 * (kNumLZ77 - 1);
|
||||
for (size_t i = 0; i < kNumRawSymbols; i++) {
|
||||
code_length_counts[raw_nbits[i]]++;
|
||||
for (uint8_t raw_nbit : raw_nbits) {
|
||||
code_length_counts[raw_nbit]++;
|
||||
}
|
||||
for (size_t i = 0; i < kNumLZ77; i++) {
|
||||
code_length_counts[lz77_nbits[i]]++;
|
||||
for (uint8_t lz77_nbit : lz77_nbits) {
|
||||
code_length_counts[lz77_nbit]++;
|
||||
}
|
||||
uint8_t code_length_nbits[18] = {};
|
||||
uint8_t code_length_nbits_min[18] = {};
|
||||
|
@ -527,9 +527,8 @@ struct PrefixCode {
|
|||
code_length_bits, 18);
|
||||
// Encode raw bit code lengths.
|
||||
// Max bits written in this loop: 19 * 5 = 95
|
||||
for (size_t i = 0; i < kNumRawSymbols; i++) {
|
||||
writer->Write(code_length_nbits[raw_nbits[i]],
|
||||
code_length_bits[raw_nbits[i]]);
|
||||
for (uint8_t raw_nbit : raw_nbits) {
|
||||
writer->Write(code_length_nbits[raw_nbit], code_length_bits[raw_nbit]);
|
||||
}
|
||||
size_t num_lz77 = kNumLZ77;
|
||||
while (lz77_nbits[num_lz77 - 1] == 0) {
|
||||
|
@ -590,8 +589,8 @@ struct JxlFastLosslessFrameState {
|
|||
|
||||
size_t JxlFastLosslessOutputSize(const JxlFastLosslessFrameState* frame) {
|
||||
size_t total_size_groups = 0;
|
||||
for (size_t i = 0; i < frame->group_data.size(); i++) {
|
||||
total_size_groups += SectionSize(frame->group_data[i]);
|
||||
for (const auto& section : frame->group_data) {
|
||||
total_size_groups += SectionSize(section);
|
||||
}
|
||||
return frame->header.bytes_written + total_size_groups;
|
||||
}
|
||||
|
@ -719,11 +718,10 @@ void JxlFastLosslessPrepareHeader(JxlFastLosslessFrameState* frame,
|
|||
output->Write(1, 0); // No TOC permutation
|
||||
output->ZeroPadToByte(); // TOC is byte-aligned.
|
||||
assert(add_image_header || output->bytes_written <= kMaxFrameHeaderSize);
|
||||
for (size_t i = 0; i < frame->group_sizes.size(); i++) {
|
||||
size_t sz = frame->group_sizes[i];
|
||||
size_t bucket = TOCBucket(sz);
|
||||
for (size_t group_size : frame->group_sizes) {
|
||||
size_t bucket = TOCBucket(group_size);
|
||||
output->Write(2, bucket);
|
||||
output->Write(kTOCBits[bucket] - 2, sz - kGroupSizeOffset[bucket]);
|
||||
output->Write(kTOCBits[bucket] - 2, group_size - kGroupSizeOffset[bucket]);
|
||||
}
|
||||
output->ZeroPadToByte(); // Groups are byte-aligned.
|
||||
}
|
||||
|
|
|
@ -1786,8 +1786,8 @@ size_t TOCBucket(size_t group_size) {
|
|||
|
||||
size_t TOCSize(const std::vector<size_t>& group_sizes) {
|
||||
size_t toc_bits = 0;
|
||||
for (size_t i = 0; i < group_sizes.size(); i++) {
|
||||
toc_bits += kTOCBits[TOCBucket(group_sizes[i])];
|
||||
for (size_t group_size : group_sizes) {
|
||||
toc_bits += kTOCBits[TOCBucket(group_size)];
|
||||
}
|
||||
return (toc_bits + 7) / 8;
|
||||
}
|
||||
|
@ -1795,8 +1795,8 @@ size_t TOCSize(const std::vector<size_t>& group_sizes) {
|
|||
PaddedBytes EncodeTOC(const std::vector<size_t>& group_sizes, AuxOut* aux_out) {
|
||||
BitWriter writer;
|
||||
BitWriter::Allotment allotment(&writer, 32 * group_sizes.size());
|
||||
for (size_t i = 0; i < group_sizes.size(); i++) {
|
||||
JXL_CHECK(U32Coder::Write(kTocDist, group_sizes[i], &writer));
|
||||
for (size_t group_size : group_sizes) {
|
||||
JXL_CHECK(U32Coder::Write(kTocDist, group_size, &writer));
|
||||
}
|
||||
writer.ZeroPadToByte(); // before first group
|
||||
allotment.ReclaimAndCharge(&writer, kLayerTOC, aux_out);
|
||||
|
@ -1854,13 +1854,13 @@ void RemoveUnusedHistograms(std::vector<uint8_t>& context_map,
|
|||
EntropyEncodingData& codes) {
|
||||
std::vector<int> remap(256, -1);
|
||||
std::vector<uint8_t> inv_remap;
|
||||
for (size_t i = 0; i < context_map.size(); ++i) {
|
||||
const uint8_t histo_ix = context_map[i];
|
||||
for (uint8_t& context : context_map) {
|
||||
const uint8_t histo_ix = context;
|
||||
if (remap[histo_ix] == -1) {
|
||||
remap[histo_ix] = inv_remap.size();
|
||||
inv_remap.push_back(histo_ix);
|
||||
}
|
||||
context_map[i] = remap[histo_ix];
|
||||
context = remap[histo_ix];
|
||||
}
|
||||
EntropyEncodingData new_codes;
|
||||
new_codes.use_prefix_code = codes.use_prefix_code;
|
||||
|
|
|
@ -43,7 +43,7 @@ using hwy::HWY_NAMESPACE::Round;
|
|||
void QuantizeBlockAC(const Quantizer& quantizer, const bool error_diffusion,
|
||||
size_t c, float qm_multiplier, size_t quant_kind,
|
||||
size_t xsize, size_t ysize, float* thresholds,
|
||||
const float* JXL_RESTRICT block_in, int32_t* quant,
|
||||
const float* JXL_RESTRICT block_in, const int32_t* quant,
|
||||
int32_t* JXL_RESTRICT block_out) {
|
||||
const float* JXL_RESTRICT qm = quantizer.InvDequantMatrix(quant_kind, c);
|
||||
float qac = quantizer.Scale() * (*quant);
|
||||
|
@ -322,10 +322,8 @@ void QuantizeRoundtripYBlockAC(PassesEncoderState* enc_state, const size_t size,
|
|||
int quant_orig = *quant;
|
||||
float val[3] = {enc_state->x_qm_multiplier, 1.0f,
|
||||
enc_state->b_qm_multiplier};
|
||||
int clut[3] = {1, 0, 2};
|
||||
for (int ii = 0; ii < 3; ++ii) {
|
||||
for (int c : {1, 0, 2}) {
|
||||
float thres[4] = {0.58f, 0.64f, 0.64f, 0.64f};
|
||||
int c = clut[ii];
|
||||
*quant = quant_orig;
|
||||
AdjustQuantBlockAC(quantizer, c, val[c], quant_kind, xsize, ysize,
|
||||
&thres[0], inout + c * size, quant);
|
||||
|
|
|
@ -127,8 +127,8 @@ Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result) {
|
|||
}
|
||||
if (size <= kICCHeaderSize) {
|
||||
EncodeVarInt(0, result); // 0 commands
|
||||
for (size_t i = 0; i < data.size(); i++) {
|
||||
result->push_back(data[i]);
|
||||
for (uint8_t b : data) {
|
||||
result->push_back(b);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -403,11 +403,11 @@ Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result) {
|
|||
data.push_back(icc[last0++]);
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < commands_add.size(); i++) {
|
||||
commands.push_back(commands_add[i]);
|
||||
for (uint8_t b : commands_add) {
|
||||
commands.push_back(b);
|
||||
}
|
||||
for (size_t i = 0; i < data_add.size(); i++) {
|
||||
data.push_back(data_add[i]);
|
||||
for (uint8_t b : data_add) {
|
||||
data.push_back(b);
|
||||
}
|
||||
last0 = pos;
|
||||
}
|
||||
|
@ -417,11 +417,11 @@ Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result) {
|
|||
}
|
||||
|
||||
EncodeVarInt(commands.size(), result);
|
||||
for (size_t i = 0; i < commands.size(); i++) {
|
||||
result->push_back(commands[i]);
|
||||
for (uint8_t b : commands) {
|
||||
result->push_back(b);
|
||||
}
|
||||
for (size_t i = 0; i < data.size(); i++) {
|
||||
result->push_back(data[i]);
|
||||
for (uint8_t b : data) {
|
||||
result->push_back(b);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -300,13 +300,12 @@ bool do_transform(Image& image, const Transform& tr,
|
|||
|
||||
bool maybe_do_transform(Image& image, const Transform& tr,
|
||||
const CompressParams& cparams,
|
||||
const weighted::Header& wp_header,
|
||||
const weighted::Header& wp_header, float cost_before,
|
||||
jxl::ThreadPool* pool = nullptr,
|
||||
bool force_jxlart = false) {
|
||||
if (force_jxlart || cparams.speed_tier >= SpeedTier::kSquirrel) {
|
||||
return do_transform(image, tr, wp_header, pool, force_jxlart);
|
||||
}
|
||||
float cost_before = EstimateCost(image);
|
||||
bool did_it = do_transform(image, tr, wp_header, pool);
|
||||
if (did_it) {
|
||||
float cost_after = EstimateCost(image);
|
||||
|
@ -321,6 +320,110 @@ bool maybe_do_transform(Image& image, const Transform& tr,
|
|||
return did_it;
|
||||
}
|
||||
|
||||
void try_palettes(Image& gi, int& max_bitdepth, int& maxval,
|
||||
const CompressParams& cparams_, float channel_colors_percent,
|
||||
jxl::ThreadPool* pool = nullptr) {
|
||||
float cost_before = 0.f;
|
||||
size_t did_palette = 0;
|
||||
float nb_pixels = gi.channel[0].w * gi.channel[0].h;
|
||||
int nb_chans = gi.channel.size() - gi.nb_meta_channels;
|
||||
// arbitrary estimate: 4.8 bpp for 8-bit RGB
|
||||
float arbitrary_bpp_estimate = 0.2f * gi.bitdepth * nb_chans;
|
||||
|
||||
if (cparams_.palette_colors != 0 || cparams_.lossy_palette) {
|
||||
// when not estimating, assume some arbitrary bpp
|
||||
cost_before = cparams_.speed_tier <= SpeedTier::kSquirrel
|
||||
? EstimateCost(gi)
|
||||
: nb_pixels * arbitrary_bpp_estimate;
|
||||
// all-channel palette (e.g. RGBA)
|
||||
if (nb_chans > 1) {
|
||||
Transform maybe_palette(TransformId::kPalette);
|
||||
maybe_palette.begin_c = gi.nb_meta_channels;
|
||||
maybe_palette.num_c = nb_chans;
|
||||
// Heuristic choice of max colors for a palette:
|
||||
// max_colors = nb_pixels * estimated_bpp_without_palette * 0.0005 +
|
||||
// + nb_pixels / 128 + 128
|
||||
// (estimated_bpp_without_palette = cost_before / nb_pixels)
|
||||
// Rationale: small image with large palette is not effective;
|
||||
// also if the entropy (estimated bpp) is low (e.g. mostly solid/gradient
|
||||
// areas), palette is less useful and may even be counterproductive.
|
||||
maybe_palette.nb_colors = std::min(
|
||||
static_cast<int>(cost_before * 0.0005f + nb_pixels / 128 + 128),
|
||||
std::abs(cparams_.palette_colors));
|
||||
maybe_palette.ordered_palette = cparams_.palette_colors >= 0;
|
||||
maybe_palette.lossy_palette =
|
||||
(cparams_.lossy_palette && maybe_palette.num_c == 3);
|
||||
if (maybe_palette.lossy_palette) {
|
||||
maybe_palette.predictor = Predictor::Average4;
|
||||
}
|
||||
// TODO(veluca): use a custom weighted header if using the weighted
|
||||
// predictor.
|
||||
if (maybe_do_transform(gi, maybe_palette, cparams_, weighted::Header(),
|
||||
cost_before, pool, cparams_.options.zero_tokens)) {
|
||||
did_palette = 1;
|
||||
};
|
||||
}
|
||||
// all-minus-one-channel palette (RGB with separate alpha, or CMY with
|
||||
// separate K)
|
||||
if (!did_palette && nb_chans > 3) {
|
||||
Transform maybe_palette_3(TransformId::kPalette);
|
||||
maybe_palette_3.begin_c = gi.nb_meta_channels;
|
||||
maybe_palette_3.num_c = nb_chans - 1;
|
||||
maybe_palette_3.nb_colors = std::min(
|
||||
static_cast<int>(cost_before * 0.0005f + nb_pixels / 128 + 128),
|
||||
std::abs(cparams_.palette_colors));
|
||||
maybe_palette_3.ordered_palette = cparams_.palette_colors >= 0;
|
||||
maybe_palette_3.lossy_palette = cparams_.lossy_palette;
|
||||
if (maybe_palette_3.lossy_palette) {
|
||||
maybe_palette_3.predictor = Predictor::Average4;
|
||||
}
|
||||
if (maybe_do_transform(gi, maybe_palette_3, cparams_, weighted::Header(),
|
||||
cost_before, pool, cparams_.options.zero_tokens)) {
|
||||
did_palette = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (channel_colors_percent > 0) {
|
||||
// single channel palette (like FLIF's ChannelCompact)
|
||||
size_t nb_channels = gi.channel.size() - gi.nb_meta_channels - did_palette;
|
||||
int orig_bitdepth = max_bitdepth;
|
||||
max_bitdepth = 0;
|
||||
if (nb_channels > 0 && (did_palette || cost_before == 0)) {
|
||||
cost_before =
|
||||
cparams_.speed_tier < SpeedTier::kSquirrel ? EstimateCost(gi) : 0;
|
||||
}
|
||||
for (size_t i = did_palette; i < nb_channels + did_palette; i++) {
|
||||
int32_t min;
|
||||
int32_t max;
|
||||
compute_minmax(gi.channel[gi.nb_meta_channels + i], &min, &max);
|
||||
int64_t colors = static_cast<int64_t>(max) - min + 1;
|
||||
JXL_DEBUG_V(10, "Channel %" PRIuS ": range=%i..%i", i, min, max);
|
||||
Transform maybe_palette_1(TransformId::kPalette);
|
||||
maybe_palette_1.begin_c = i + gi.nb_meta_channels;
|
||||
maybe_palette_1.num_c = 1;
|
||||
// simple heuristic: if less than X percent of the values in the range
|
||||
// actually occur, it is probably worth it to do a compaction
|
||||
// (but only if the channel palette is less than 6% the size of the
|
||||
// image itself)
|
||||
maybe_palette_1.nb_colors =
|
||||
std::min(static_cast<int>(nb_pixels / 16),
|
||||
static_cast<int>(channel_colors_percent / 100. * colors));
|
||||
if (maybe_do_transform(gi, maybe_palette_1, cparams_, weighted::Header(),
|
||||
cost_before, pool)) {
|
||||
// effective bit depth is lower, adjust quantization accordingly
|
||||
compute_minmax(gi.channel[gi.nb_meta_channels + i], &min, &max);
|
||||
if (max < maxval) maxval = max;
|
||||
int ch_bitdepth =
|
||||
(max > 0 ? CeilLog2Nonzero(static_cast<uint32_t>(max)) : 0);
|
||||
if (ch_bitdepth > max_bitdepth) max_bitdepth = ch_bitdepth;
|
||||
} else {
|
||||
max_bitdepth = orig_bitdepth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ModularFrameEncoder::ModularFrameEncoder(const FrameHeader& frame_header,
|
||||
|
@ -479,7 +582,6 @@ ModularFrameEncoder::ModularFrameEncoder(const FrameHeader& frame_header,
|
|||
cparams_.options.predictor = Predictor::Gradient;
|
||||
}
|
||||
} else {
|
||||
delta_pred_ = cparams_.options.predictor;
|
||||
if (cparams_.lossy_palette) cparams_.options.predictor = Predictor::Zero;
|
||||
}
|
||||
if (!cparams_.ModularPartIsLossless()) {
|
||||
|
@ -624,6 +726,7 @@ Status ModularFrameEncoder::ComputeEncodingData(
|
|||
pixel_type* const JXL_RESTRICT row_out = gi.channel[c_out].Row(y);
|
||||
pixel_type* const JXL_RESTRICT row_Y = gi.channel[0].Row(y);
|
||||
for (size_t x = 0; x < xsize; ++x) {
|
||||
// TODO(eustas): check if std::roundf is appropriate
|
||||
row_out[x] = row_in[x] * factor + 0.5f;
|
||||
row_out[x] -= row_Y[x];
|
||||
// zero the lsb of B
|
||||
|
@ -720,81 +823,16 @@ Status ModularFrameEncoder::ComputeEncodingData(
|
|||
cparams_.lossy_palette = false;
|
||||
}
|
||||
|
||||
// Global palette
|
||||
if ((cparams_.palette_colors != 0 || cparams_.lossy_palette) && !groupwise) {
|
||||
// all-channel palette (e.g. RGBA)
|
||||
if (gi.channel.size() - gi.nb_meta_channels > 1) {
|
||||
Transform maybe_palette(TransformId::kPalette);
|
||||
maybe_palette.begin_c = gi.nb_meta_channels;
|
||||
maybe_palette.num_c = gi.channel.size() - gi.nb_meta_channels;
|
||||
maybe_palette.nb_colors = std::min(static_cast<int>(xsize * ysize / 2),
|
||||
std::abs(cparams_.palette_colors));
|
||||
maybe_palette.ordered_palette = cparams_.palette_colors >= 0;
|
||||
maybe_palette.lossy_palette =
|
||||
(cparams_.lossy_palette && maybe_palette.num_c == 3);
|
||||
if (maybe_palette.lossy_palette) {
|
||||
maybe_palette.predictor = delta_pred_;
|
||||
}
|
||||
// TODO(veluca): use a custom weighted header if using the weighted
|
||||
// predictor.
|
||||
maybe_do_transform(gi, maybe_palette, cparams_, weighted::Header(), pool,
|
||||
cparams_.options.zero_tokens);
|
||||
}
|
||||
// all-minus-one-channel palette (RGB with separate alpha, or CMY with
|
||||
// separate K)
|
||||
if (gi.channel.size() - gi.nb_meta_channels > 3) {
|
||||
Transform maybe_palette_3(TransformId::kPalette);
|
||||
maybe_palette_3.begin_c = gi.nb_meta_channels;
|
||||
maybe_palette_3.num_c = gi.channel.size() - gi.nb_meta_channels - 1;
|
||||
maybe_palette_3.nb_colors = std::min(static_cast<int>(xsize * ysize / 3),
|
||||
std::abs(cparams_.palette_colors));
|
||||
maybe_palette_3.ordered_palette = cparams_.palette_colors >= 0;
|
||||
maybe_palette_3.lossy_palette = cparams_.lossy_palette;
|
||||
if (maybe_palette_3.lossy_palette) {
|
||||
maybe_palette_3.predictor = delta_pred_;
|
||||
}
|
||||
maybe_do_transform(gi, maybe_palette_3, cparams_, weighted::Header(),
|
||||
pool, cparams_.options.zero_tokens);
|
||||
}
|
||||
}
|
||||
|
||||
// Global channel palette
|
||||
if (!groupwise && cparams_.channel_colors_pre_transform_percent > 0 &&
|
||||
!cparams_.lossy_palette &&
|
||||
// Global palette transforms
|
||||
float channel_colors_percent = 0;
|
||||
if (!cparams_.lossy_palette &&
|
||||
(cparams_.speed_tier <= SpeedTier::kThunder ||
|
||||
(do_color && metadata.bit_depth.bits_per_sample > 8))) {
|
||||
// single channel palette (like FLIF's ChannelCompact)
|
||||
size_t nb_channels = gi.channel.size() - gi.nb_meta_channels;
|
||||
int orig_bitdepth = max_bitdepth;
|
||||
max_bitdepth = 0;
|
||||
for (size_t i = 0; i < nb_channels; i++) {
|
||||
int32_t min;
|
||||
int32_t max;
|
||||
compute_minmax(gi.channel[gi.nb_meta_channels + i], &min, &max);
|
||||
int64_t colors = static_cast<int64_t>(max) - min + 1;
|
||||
JXL_DEBUG_V(10, "Channel %" PRIuS ": range=%i..%i", i, min, max);
|
||||
Transform maybe_palette_1(TransformId::kPalette);
|
||||
maybe_palette_1.begin_c = i + gi.nb_meta_channels;
|
||||
maybe_palette_1.num_c = 1;
|
||||
// simple heuristic: if less than X percent of the values in the range
|
||||
// actually occur, it is probably worth it to do a compaction
|
||||
// (but only if the channel palette is less than 6% the size of the
|
||||
// image itself)
|
||||
maybe_palette_1.nb_colors = std::min(
|
||||
static_cast<int>(xsize * ysize / 16),
|
||||
static_cast<int>(cparams_.channel_colors_pre_transform_percent /
|
||||
100. * colors));
|
||||
if (maybe_do_transform(gi, maybe_palette_1, cparams_, weighted::Header(),
|
||||
pool)) {
|
||||
// effective bit depth is lower, adjust quantization accordingly
|
||||
compute_minmax(gi.channel[gi.nb_meta_channels + i], &min, &max);
|
||||
if (max < maxval) maxval = max;
|
||||
int ch_bitdepth =
|
||||
(max > 0 ? CeilLog2Nonzero(static_cast<uint32_t>(max)) : 0);
|
||||
if (ch_bitdepth > max_bitdepth) max_bitdepth = ch_bitdepth;
|
||||
} else
|
||||
max_bitdepth = orig_bitdepth;
|
||||
}
|
||||
channel_colors_percent = cparams_.channel_colors_pre_transform_percent;
|
||||
}
|
||||
if (!groupwise) {
|
||||
try_palettes(gi, max_bitdepth, maxval, cparams_, channel_colors_percent,
|
||||
pool);
|
||||
}
|
||||
|
||||
// don't do an RCT if we're short on bits
|
||||
|
@ -1318,61 +1356,17 @@ Status ModularFrameEncoder::PrepareStreamParams(const Rect& rect,
|
|||
if (gi.channel.empty()) return true;
|
||||
// Do some per-group transforms
|
||||
|
||||
// Local palette
|
||||
// Local palette transforms
|
||||
// TODO(veluca): make this work with quantize-after-prediction in lossy
|
||||
// mode.
|
||||
if (cparams_.butteraugli_distance == 0.f && cparams_.palette_colors != 0 &&
|
||||
if (cparams_.butteraugli_distance == 0.f && !cparams_.lossy_palette &&
|
||||
cparams_.speed_tier < SpeedTier::kCheetah) {
|
||||
// all-channel palette (e.g. RGBA)
|
||||
if (gi.channel.size() - gi.nb_meta_channels > 1) {
|
||||
Transform maybe_palette(TransformId::kPalette);
|
||||
maybe_palette.begin_c = gi.nb_meta_channels;
|
||||
maybe_palette.num_c = gi.channel.size() - gi.nb_meta_channels;
|
||||
maybe_palette.nb_colors = std::abs(cparams_.palette_colors);
|
||||
maybe_palette.ordered_palette = cparams_.palette_colors >= 0;
|
||||
maybe_do_transform(gi, maybe_palette, cparams_, weighted::Header());
|
||||
}
|
||||
// all-minus-one-channel palette (RGB with separate alpha, or CMY with
|
||||
// separate K)
|
||||
if (gi.channel.size() - gi.nb_meta_channels > 3) {
|
||||
Transform maybe_palette_3(TransformId::kPalette);
|
||||
maybe_palette_3.begin_c = gi.nb_meta_channels;
|
||||
maybe_palette_3.num_c = gi.channel.size() - gi.nb_meta_channels - 1;
|
||||
maybe_palette_3.nb_colors = std::abs(cparams_.palette_colors);
|
||||
maybe_palette_3.ordered_palette = cparams_.palette_colors >= 0;
|
||||
maybe_palette_3.lossy_palette = cparams_.lossy_palette;
|
||||
if (maybe_palette_3.lossy_palette) {
|
||||
maybe_palette_3.predictor = Predictor::Weighted;
|
||||
}
|
||||
maybe_do_transform(gi, maybe_palette_3, cparams_, weighted::Header());
|
||||
}
|
||||
}
|
||||
|
||||
// Local channel palette
|
||||
if (cparams_.channel_colors_percent > 0 &&
|
||||
cparams_.butteraugli_distance == 0.f && !cparams_.lossy_palette &&
|
||||
cparams_.speed_tier < SpeedTier::kCheetah &&
|
||||
!(cparams_.responsive && cparams_.decoding_speed_tier >= 1)) {
|
||||
// single channel palette (like FLIF's ChannelCompact)
|
||||
size_t nb_channels = gi.channel.size() - gi.nb_meta_channels;
|
||||
for (size_t i = 0; i < nb_channels; i++) {
|
||||
int32_t min;
|
||||
int32_t max;
|
||||
compute_minmax(gi.channel[gi.nb_meta_channels + i], &min, &max);
|
||||
int64_t colors = static_cast<int64_t>(max) - min + 1;
|
||||
JXL_DEBUG_V(10, "Channel %" PRIuS ": range=%i..%i", i, min, max);
|
||||
Transform maybe_palette_1(TransformId::kPalette);
|
||||
maybe_palette_1.begin_c = i + gi.nb_meta_channels;
|
||||
maybe_palette_1.num_c = 1;
|
||||
// simple heuristic: if less than X percent of the values in the range
|
||||
// actually occur, it is probably worth it to do a compaction
|
||||
// (but only if the channel palette is less than 80% the size of the
|
||||
// image itself)
|
||||
maybe_palette_1.nb_colors = std::min(
|
||||
static_cast<int>(xsize * ysize * 0.8),
|
||||
static_cast<int>(cparams_.channel_colors_percent / 100. * colors));
|
||||
maybe_do_transform(gi, maybe_palette_1, cparams_, weighted::Header());
|
||||
int max_bitdepth = 0, maxval = 0; // don't care about that here
|
||||
float channel_color_percent = 0;
|
||||
if (!(cparams_.responsive && cparams_.decoding_speed_tier >= 1)) {
|
||||
channel_color_percent = cparams_.channel_colors_percent;
|
||||
}
|
||||
try_palettes(gi, max_bitdepth, maxval, cparams_, channel_color_percent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,6 @@ class ModularFrameEncoder {
|
|||
std::vector<size_t> tree_splits_;
|
||||
std::vector<std::vector<uint32_t>> gi_channel_;
|
||||
std::vector<size_t> image_widths_;
|
||||
Predictor delta_pred_ = Predictor::Average4;
|
||||
|
||||
struct GroupParams {
|
||||
Rect rect;
|
||||
|
|
|
@ -106,9 +106,12 @@ struct CompressParams {
|
|||
|
||||
// modular mode options below
|
||||
ModularOptions options;
|
||||
|
||||
// TODO(eustas): use Override?
|
||||
int responsive = -1;
|
||||
int colorspace = -1;
|
||||
int move_to_front_from_channel = -1;
|
||||
|
||||
// Use Global channel palette if #colors < this percentage of range
|
||||
float channel_colors_pre_transform_percent = 95.f;
|
||||
// Use Local channel palette if #colors < this percentage of range
|
||||
|
|
|
@ -237,9 +237,9 @@ StatusOr<std::vector<PatchInfo>> FindTextLikePatches(
|
|||
|
||||
auto is_same = [&opsin_rows, opsin_stride](std::pair<uint32_t, uint32_t> p1,
|
||||
std::pair<uint32_t, uint32_t> p2) {
|
||||
for (size_t c = 0; c < 3; c++) {
|
||||
float v1 = opsin_rows[c][p1.second * opsin_stride + p1.first];
|
||||
float v2 = opsin_rows[c][p2.second * opsin_stride + p2.first];
|
||||
for (auto& opsin_row : opsin_rows) {
|
||||
float v1 = opsin_row[p1.second * opsin_stride + p1.first];
|
||||
float v2 = opsin_row[p2.second * opsin_stride + p2.first];
|
||||
if (std::fabs(v1 - v2) > 1e-4) {
|
||||
return false;
|
||||
}
|
||||
|
@ -556,8 +556,8 @@ StatusOr<std::vector<PatchInfo>> FindTextLikePatches(
|
|||
|
||||
size_t max_patch_size = 0;
|
||||
|
||||
for (size_t i = 0; i < info.size(); i++) {
|
||||
size_t pixels = info[i].first.xsize * info[i].first.ysize;
|
||||
for (const auto& patch : info) {
|
||||
size_t pixels = patch.first.xsize * patch.first.ysize;
|
||||
if (pixels > max_patch_size) max_patch_size = pixels;
|
||||
}
|
||||
|
||||
|
@ -605,10 +605,10 @@ Status FindBestPatchDictionary(const Image3F& opsin,
|
|||
size_t max_y_size = 0;
|
||||
size_t total_pixels = 0;
|
||||
|
||||
for (size_t i = 0; i < info.size(); i++) {
|
||||
size_t pixels = info[i].first.xsize * info[i].first.ysize;
|
||||
if (max_x_size < info[i].first.xsize) max_x_size = info[i].first.xsize;
|
||||
if (max_y_size < info[i].first.ysize) max_y_size = info[i].first.ysize;
|
||||
for (const auto& patch : info) {
|
||||
size_t pixels = patch.first.xsize * patch.first.ysize;
|
||||
if (max_x_size < patch.first.xsize) max_x_size = patch.first.xsize;
|
||||
if (max_y_size < patch.first.ysize) max_y_size = patch.first.ysize;
|
||||
total_pixels += pixels;
|
||||
}
|
||||
|
||||
|
|
|
@ -116,9 +116,9 @@ Status DequantMatricesEncode(const DequantMatrices& matrices, BitWriter* writer,
|
|||
bool all_default = true;
|
||||
const std::vector<QuantEncoding>& encodings = matrices.encodings();
|
||||
|
||||
for (size_t i = 0; i < encodings.size(); i++) {
|
||||
if (encodings[i].mode != QuantEncoding::kQuantModeLibrary ||
|
||||
encodings[i].predefined != 0) {
|
||||
for (const auto& encoding : encodings) {
|
||||
if (encoding.mode != QuantEncoding::kQuantModeLibrary ||
|
||||
encoding.predefined != 0) {
|
||||
all_default = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ class QuantizedSplineEncoder {
|
|||
tokens->emplace_back(kDCTContext, PackSigned(dct[i]));
|
||||
}
|
||||
};
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
encode_dct(spline.color_dct_[c]);
|
||||
for (const auto& dct : spline.color_dct_) {
|
||||
encode_dct(dct);
|
||||
}
|
||||
encode_dct(spline.sigma_dct_);
|
||||
}
|
||||
|
|
|
@ -32,9 +32,9 @@ Status WriteGroupOffsets(const std::vector<BitWriter>& group_codes,
|
|||
}
|
||||
writer->ZeroPadToByte(); // before TOC entries
|
||||
|
||||
for (size_t i = 0; i < group_codes.size(); i++) {
|
||||
JXL_ASSERT(group_codes[i].BitsWritten() % kBitsPerByte == 0);
|
||||
const size_t group_size = group_codes[i].BitsWritten() / kBitsPerByte;
|
||||
for (const auto& bw : group_codes) {
|
||||
JXL_ASSERT(bw.BitsWritten() % kBitsPerByte == 0);
|
||||
const size_t group_size = bw.BitsWritten() / kBitsPerByte;
|
||||
JXL_RETURN_IF_ERROR(U32Coder::Write(kTocDist, group_size, writer));
|
||||
}
|
||||
writer->ZeroPadToByte(); // before first group
|
||||
|
|
|
@ -549,8 +549,8 @@ int VerifyLevelSettings(const JxlEncoder* enc, std::string* debug_string) {
|
|||
if (debug_string) *debug_string = "Too many extra channels";
|
||||
return 10;
|
||||
}
|
||||
for (size_t i = 0; i < m.extra_channel_info.size(); ++i) {
|
||||
if (m.extra_channel_info[i].type == jxl::ExtraChannel::kBlack) {
|
||||
for (const auto& eci : m.extra_channel_info) {
|
||||
if (eci.type == jxl::ExtraChannel::kBlack) {
|
||||
if (debug_string) *debug_string = "CMYK channel not allowed";
|
||||
return 10;
|
||||
}
|
||||
|
@ -1514,6 +1514,10 @@ float JxlEncoderDistanceFromQuality(float quality) {
|
|||
JxlEncoderStatus JxlEncoderFrameSettingsSetOption(
|
||||
JxlEncoderFrameSettings* frame_settings, JxlEncoderFrameSettingId option,
|
||||
int64_t value) {
|
||||
// Tri-state to bool convertors.
|
||||
const auto default_to_true = [](int64_t v) { return v != 0; };
|
||||
const auto default_to_false = [](int64_t v) { return v == 1; };
|
||||
|
||||
// check if value is -1, 0 or 1 for Override-type options
|
||||
switch (option) {
|
||||
case JXL_ENC_FRAME_SETTING_NOISE:
|
||||
|
@ -1680,7 +1684,7 @@ JxlEncoderStatus JxlEncoderFrameSettingsSetOption(
|
|||
// See the logic in cjxl. Similar for other settings. This should be
|
||||
// handled in the encoder during JxlEncoderProcessOutput (or,
|
||||
// alternatively, in the cjxl binary like now)
|
||||
frame_settings->values.cparams.lossy_palette = (value == 1);
|
||||
frame_settings->values.cparams.lossy_palette = default_to_false(value);
|
||||
break;
|
||||
case JXL_ENC_FRAME_SETTING_COLOR_TRANSFORM:
|
||||
if (value < -1 || value > 2) {
|
||||
|
@ -1734,11 +1738,8 @@ JxlEncoderStatus JxlEncoderFrameSettingsSetOption(
|
|||
}
|
||||
break;
|
||||
case JXL_ENC_FRAME_SETTING_JPEG_RECON_CFL:
|
||||
if (value == -1) {
|
||||
frame_settings->values.cparams.force_cfl_jpeg_recompression = true;
|
||||
} else {
|
||||
frame_settings->values.cparams.force_cfl_jpeg_recompression = value;
|
||||
}
|
||||
frame_settings->values.cparams.force_cfl_jpeg_recompression =
|
||||
default_to_true(value);
|
||||
break;
|
||||
case JXL_ENC_FRAME_INDEX_BOX:
|
||||
if (value < 0 || value > 1) {
|
||||
|
@ -1752,7 +1753,8 @@ JxlEncoderStatus JxlEncoderFrameSettingsSetOption(
|
|||
"Float option, try setting it with "
|
||||
"JxlEncoderFrameSettingsSetFloatOption");
|
||||
case JXL_ENC_FRAME_SETTING_JPEG_COMPRESS_BOXES:
|
||||
frame_settings->values.cparams.jpeg_compress_boxes = value;
|
||||
frame_settings->values.cparams.jpeg_compress_boxes =
|
||||
default_to_true(value);
|
||||
break;
|
||||
case JXL_ENC_FRAME_SETTING_BUFFERING:
|
||||
if (value < -1 || value > 3) {
|
||||
|
@ -1762,20 +1764,21 @@ JxlEncoderStatus JxlEncoderFrameSettingsSetOption(
|
|||
frame_settings->values.cparams.buffering = value;
|
||||
break;
|
||||
case JXL_ENC_FRAME_SETTING_JPEG_KEEP_EXIF:
|
||||
frame_settings->values.cparams.jpeg_keep_exif = value;
|
||||
frame_settings->values.cparams.jpeg_keep_exif = default_to_true(value);
|
||||
break;
|
||||
case JXL_ENC_FRAME_SETTING_JPEG_KEEP_XMP:
|
||||
frame_settings->values.cparams.jpeg_keep_xmp = value;
|
||||
frame_settings->values.cparams.jpeg_keep_xmp = default_to_true(value);
|
||||
break;
|
||||
case JXL_ENC_FRAME_SETTING_JPEG_KEEP_JUMBF:
|
||||
frame_settings->values.cparams.jpeg_keep_jumbf = value;
|
||||
frame_settings->values.cparams.jpeg_keep_jumbf = default_to_true(value);
|
||||
break;
|
||||
case JXL_ENC_FRAME_SETTING_USE_FULL_IMAGE_HEURISTICS:
|
||||
if (value < 0 || value > 1) {
|
||||
return JXL_API_ERROR(frame_settings->enc, JXL_ENC_ERR_NOT_SUPPORTED,
|
||||
"Option value has to be 0 or 1");
|
||||
}
|
||||
frame_settings->values.cparams.use_full_image_heuristics = value;
|
||||
frame_settings->values.cparams.use_full_image_heuristics =
|
||||
default_to_false(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -304,7 +304,7 @@ TEST(EncodeTest, CmsTest) {
|
|||
EXPECT_TRUE(cms_called);
|
||||
}
|
||||
|
||||
TEST(EncodeTest, frame_settingsTest) {
|
||||
TEST(EncodeTest, FrameSettingsTest) {
|
||||
{
|
||||
JxlEncoderPtr enc = JxlEncoderMake(nullptr);
|
||||
EXPECT_NE(nullptr, enc.get());
|
||||
|
@ -451,7 +451,7 @@ TEST(EncodeTest, frame_settingsTest) {
|
|||
JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
|
||||
EXPECT_EQ(JXL_ENC_SUCCESS,
|
||||
JxlEncoderSetFrameLossless(frame_settings, JXL_TRUE));
|
||||
VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 3000, false);
|
||||
VerifyFrameEncoding(63, 129, enc.get(), frame_settings, 3600, false);
|
||||
EXPECT_EQ(true, enc->last_used_cparams.IsLossless());
|
||||
}
|
||||
|
||||
|
@ -838,20 +838,20 @@ TEST(EncodeTest, SingleFrameBoundedJXLCTest) {
|
|||
bool found_jxlc = false;
|
||||
bool found_jxlp = false;
|
||||
// The encoder is allowed to either emit a jxlc or one or more jxlp.
|
||||
for (size_t i = 0; i < container.boxes.size(); ++i) {
|
||||
if (memcmp("jxlc", container.boxes[i].type, 4) == 0) {
|
||||
for (const auto& box : container.boxes) {
|
||||
if (memcmp("jxlc", box.type, 4) == 0) {
|
||||
EXPECT_EQ(false, found_jxlc); // Max 1 jxlc
|
||||
EXPECT_EQ(false, found_jxlp); // Can't mix jxlc and jxlp
|
||||
found_jxlc = true;
|
||||
}
|
||||
if (memcmp("jxlp", container.boxes[i].type, 4) == 0) {
|
||||
if (memcmp("jxlp", box.type, 4) == 0) {
|
||||
EXPECT_EQ(false, found_jxlc); // Can't mix jxlc and jxlp
|
||||
found_jxlp = true;
|
||||
}
|
||||
// The encoder shouldn't create an unbounded box in this case, with the
|
||||
// single frame it knows the full size in time, so can help make decoding
|
||||
// more efficient by giving the full box size of the final box.
|
||||
EXPECT_EQ(true, container.boxes[i].data_size_given);
|
||||
EXPECT_EQ(true, box.data_size_given);
|
||||
}
|
||||
EXPECT_EQ(true, found_jxlc || found_jxlp);
|
||||
}
|
||||
|
@ -940,7 +940,7 @@ TEST(EncodeTest, CodestreamLevelVerificationTest) {
|
|||
EXPECT_EQ(JXL_ENC_ERROR, JxlEncoderSetBasicInfo(enc.get(), &basic_info));
|
||||
}
|
||||
|
||||
TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionTest)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(EncodeTest, JPEGReconstructionTest) {
|
||||
const std::string jpeg_path = "jxl/flower/flower.png.im_q85_420.jpg";
|
||||
const std::vector<uint8_t> orig = jxl::test::ReadTestData(jpeg_path);
|
||||
|
||||
|
@ -980,7 +980,7 @@ TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGReconstructionTest)) {
|
|||
EXPECT_EQ(0, memcmp(decoded_jpeg_bytes.data(), orig.data(), orig.size()));
|
||||
}
|
||||
|
||||
TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(ProgressiveJPEGReconstructionTest)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(EncodeTest, ProgressiveJPEGReconstructionTest) {
|
||||
const std::string jpeg_path = "jxl/flower/flower.png.im_q85_420.jpg";
|
||||
const std::vector<uint8_t> orig = jxl::test::ReadTestData(jpeg_path);
|
||||
|
||||
|
@ -1345,7 +1345,7 @@ TEST(EncodeTest, CroppedFrameTest) {
|
|||
struct EncodeBoxTest : public testing::TestWithParam<std::tuple<bool, size_t>> {
|
||||
};
|
||||
|
||||
TEST_P(EncodeBoxTest, JXL_BOXES_TEST(BoxTest)) {
|
||||
JXL_BOXES_TEST_P(EncodeBoxTest, BoxTest) {
|
||||
// Test with uncompressed boxes and with brob boxes
|
||||
bool compress_box = std::get<0>(GetParam());
|
||||
size_t xml_box_size = std::get<1>(GetParam());
|
||||
|
@ -1485,7 +1485,7 @@ JXL_GTEST_INSTANTIATE_TEST_SUITE_P(
|
|||
jxl::kLargeBoxContentSizeThreshold + 77)),
|
||||
nameBoxTest);
|
||||
|
||||
TEST(EncodeTest, JXL_TRANSCODE_JPEG_TEST(JPEGFrameTest)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(EncodeTest, JPEGFrameTest) {
|
||||
TEST_LIBJPEG_SUPPORT();
|
||||
for (int skip_basic_info = 0; skip_basic_info < 2; skip_basic_info++) {
|
||||
for (int skip_color_encoding = 0; skip_color_encoding < 2;
|
||||
|
|
|
@ -27,7 +27,7 @@ TEST(EntropyCoderTest, PackUnpack) {
|
|||
struct MockBitReader {
|
||||
uint32_t nbits, bits;
|
||||
void Consume(uint32_t nbits) {}
|
||||
uint32_t PeekBits(uint32_t n) {
|
||||
uint32_t PeekBits(uint32_t n) const {
|
||||
EXPECT_EQ(n, nbits);
|
||||
return bits;
|
||||
}
|
||||
|
|
|
@ -186,13 +186,13 @@ constexpr bool fast_mode = true;
|
|||
TEST(GradientTest, SteepGradient) {
|
||||
test::ThreadPoolForTests pool(8);
|
||||
// Relatively steep gradients, colors from the sky of stp.png
|
||||
TestGradient(&pool, 0xd99d58, 0x889ab1, 512, 512, 90, fast_mode, 3.0);
|
||||
TestGradient(pool.get(), 0xd99d58, 0x889ab1, 512, 512, 90, fast_mode, 3.0);
|
||||
}
|
||||
|
||||
TEST(GradientTest, SubtleGradient) {
|
||||
test::ThreadPoolForTests pool(8);
|
||||
// Very subtle gradient
|
||||
TestGradient(&pool, 0xb89b7b, 0xa89b8d, 512, 512, 90, fast_mode, 4.0);
|
||||
TestGradient(pool.get(), 0xb89b7b, 0xa89b8d, 512, 512, 90, fast_mode, 4.0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -28,7 +28,7 @@ struct ICCReader {
|
|||
}
|
||||
|
||||
private:
|
||||
Status CheckEOI(BitReader* reader);
|
||||
static Status CheckEOI(BitReader* reader);
|
||||
size_t i_ = 0;
|
||||
size_t bits_to_skip_ = 0;
|
||||
size_t used_bits_base_ = 0;
|
||||
|
|
|
@ -106,15 +106,14 @@ Status DecodeJPEGData(Span<const uint8_t> encoded, JPEGData* jpeg_data) {
|
|||
}
|
||||
}
|
||||
// TODO(eustas): actually inject ICC profile and check it fits perfectly.
|
||||
for (size_t i = 0; i < jpeg_data->com_data.size(); i++) {
|
||||
auto& marker = jpeg_data->com_data[i];
|
||||
for (auto& marker : jpeg_data->com_data) {
|
||||
JXL_RETURN_IF_ERROR(br_read(marker));
|
||||
if (marker[1] * 256u + marker[2] + 1u != marker.size()) {
|
||||
return JXL_FAILURE("Incorrect marker size");
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < jpeg_data->inter_marker_data.size(); i++) {
|
||||
JXL_RETURN_IF_ERROR(br_read(jpeg_data->inter_marker_data[i]));
|
||||
for (auto& data : jpeg_data->inter_marker_data) {
|
||||
JXL_RETURN_IF_ERROR(br_read(data));
|
||||
}
|
||||
JXL_RETURN_IF_ERROR(br_read(jpeg_data->tail_data));
|
||||
|
||||
|
|
|
@ -385,8 +385,8 @@ bool EncodeDHT(const JPEGData& jpg, SerializationState* state) {
|
|||
for (size_t i = state->dht_index; i < huffman_code.size(); ++i) {
|
||||
const JPEGHuffmanCode& huff = huffman_code[i];
|
||||
marker_len += kJpegHuffmanMaxBitLength;
|
||||
for (size_t j = 0; j < huff.counts.size(); ++j) {
|
||||
marker_len += huff.counts[j];
|
||||
for (uint32_t count : huff.counts) {
|
||||
marker_len += count;
|
||||
}
|
||||
if (huff.is_last) break;
|
||||
}
|
||||
|
|
|
@ -173,8 +173,7 @@ Status ParseChunkedMarker(const jpeg::JPEGData& src, uint8_t marker_type,
|
|||
}
|
||||
|
||||
Status SetBlobsFromJpegData(const jpeg::JPEGData& jpeg_data, Blobs* blobs) {
|
||||
for (size_t i = 0; i < jpeg_data.app_data.size(); i++) {
|
||||
const auto& marker = jpeg_data.app_data[i];
|
||||
for (const auto& marker : jpeg_data.app_data) {
|
||||
if (marker.empty() || marker[0] != kApp1) {
|
||||
continue;
|
||||
}
|
||||
|
@ -318,11 +317,11 @@ Status EncodeJPEGData(JPEGData& jpeg_data, std::vector<uint8_t>* bytes,
|
|||
}
|
||||
total_data += jpeg_data.app_data[i].size();
|
||||
}
|
||||
for (size_t i = 0; i < jpeg_data.com_data.size(); i++) {
|
||||
total_data += jpeg_data.com_data[i].size();
|
||||
for (const auto& data : jpeg_data.com_data) {
|
||||
total_data += data.size();
|
||||
}
|
||||
for (size_t i = 0; i < jpeg_data.inter_marker_data.size(); i++) {
|
||||
total_data += jpeg_data.inter_marker_data[i].size();
|
||||
for (const auto& data : jpeg_data.inter_marker_data) {
|
||||
total_data += data.size();
|
||||
}
|
||||
total_data += jpeg_data.tail_data.size();
|
||||
size_t brotli_capacity = BrotliEncoderMaxCompressedSize(total_data);
|
||||
|
@ -365,11 +364,11 @@ Status EncodeJPEGData(JPEGData& jpeg_data, std::vector<uint8_t>* bytes,
|
|||
}
|
||||
br_append(jpeg_data.app_data[i], /*last=*/false);
|
||||
}
|
||||
for (size_t i = 0; i < jpeg_data.com_data.size(); i++) {
|
||||
br_append(jpeg_data.com_data[i], /*last=*/false);
|
||||
for (const auto& data : jpeg_data.com_data) {
|
||||
br_append(data, /*last=*/false);
|
||||
}
|
||||
for (size_t i = 0; i < jpeg_data.inter_marker_data.size(); i++) {
|
||||
br_append(jpeg_data.inter_marker_data[i], /*last=*/false);
|
||||
for (const auto& data : jpeg_data.inter_marker_data) {
|
||||
br_append(data, /*last=*/false);
|
||||
}
|
||||
br_append(jpeg_data.tail_data, /*last=*/true);
|
||||
BrotliEncoderDestroyInstance(brotli_enc);
|
||||
|
|
|
@ -92,21 +92,21 @@ bool ProcessSOF(const uint8_t* data, const size_t len, JpegReadMode mode,
|
|||
std::vector<bool> ids_seen(256, false);
|
||||
int max_h_samp_factor = 1;
|
||||
int max_v_samp_factor = 1;
|
||||
for (size_t i = 0; i < jpg->components.size(); ++i) {
|
||||
for (auto& component : jpg->components) {
|
||||
const int id = ReadUint8(data, pos);
|
||||
if (ids_seen[id]) { // (cf. section B.2.2, syntax of Ci)
|
||||
return JXL_FAILURE("Duplicate ID %d in SOF.", id);
|
||||
}
|
||||
ids_seen[id] = true;
|
||||
jpg->components[i].id = id;
|
||||
component.id = id;
|
||||
int factor = ReadUint8(data, pos);
|
||||
int h_samp_factor = factor >> 4;
|
||||
int v_samp_factor = factor & 0xf;
|
||||
JXL_JPEG_VERIFY_INPUT(h_samp_factor, 1, kBrunsliMaxSampling, SAMP_FACTOR);
|
||||
JXL_JPEG_VERIFY_INPUT(v_samp_factor, 1, kBrunsliMaxSampling, SAMP_FACTOR);
|
||||
jpg->components[i].h_samp_factor = h_samp_factor;
|
||||
jpg->components[i].v_samp_factor = v_samp_factor;
|
||||
jpg->components[i].quant_idx = ReadUint8(data, pos);
|
||||
component.h_samp_factor = h_samp_factor;
|
||||
component.v_samp_factor = v_samp_factor;
|
||||
component.quant_idx = ReadUint8(data, pos);
|
||||
max_h_samp_factor = std::max(max_h_samp_factor, h_samp_factor);
|
||||
max_v_samp_factor = std::max(max_v_samp_factor, v_samp_factor);
|
||||
}
|
||||
|
@ -116,18 +116,17 @@ bool ProcessSOF(const uint8_t* data, const size_t len, JpegReadMode mode,
|
|||
int MCU_rows = DivCeil(jpg->height, max_v_samp_factor * 8);
|
||||
int MCU_cols = DivCeil(jpg->width, max_h_samp_factor * 8);
|
||||
// Compute the block dimensions for each component.
|
||||
for (size_t i = 0; i < jpg->components.size(); ++i) {
|
||||
JPEGComponent* c = &jpg->components[i];
|
||||
if (max_h_samp_factor % c->h_samp_factor != 0 ||
|
||||
max_v_samp_factor % c->v_samp_factor != 0) {
|
||||
for (JPEGComponent& c : jpg->components) {
|
||||
if (max_h_samp_factor % c.h_samp_factor != 0 ||
|
||||
max_v_samp_factor % c.v_samp_factor != 0) {
|
||||
return JXL_FAILURE("Non-integral subsampling ratios.");
|
||||
}
|
||||
c->width_in_blocks = MCU_cols * c->h_samp_factor;
|
||||
c->height_in_blocks = MCU_rows * c->v_samp_factor;
|
||||
c.width_in_blocks = MCU_cols * c.h_samp_factor;
|
||||
c.height_in_blocks = MCU_rows * c.v_samp_factor;
|
||||
const uint64_t num_blocks =
|
||||
static_cast<uint64_t>(c->width_in_blocks) * c->height_in_blocks;
|
||||
static_cast<uint64_t>(c.width_in_blocks) * c.height_in_blocks;
|
||||
if (mode == JpegReadMode::kReadAll) {
|
||||
c->coeffs.resize(num_blocks * kDCTBlockSize);
|
||||
c.coeffs.resize(num_blocks * kDCTBlockSize);
|
||||
}
|
||||
}
|
||||
JXL_JPEG_VERIFY_MARKER_END();
|
||||
|
@ -192,8 +191,8 @@ bool ProcessSOS(const uint8_t* data, const size_t len, size_t* pos,
|
|||
for (size_t i = 0; i < comps_in_scan; ++i) {
|
||||
bool found_dc_table = false;
|
||||
bool found_ac_table = false;
|
||||
for (size_t j = 0; j < jpg->huffman_code.size(); ++j) {
|
||||
uint32_t slot_id = jpg->huffman_code[j].slot_id;
|
||||
for (const auto& code : jpg->huffman_code) {
|
||||
uint32_t slot_id = code.slot_id;
|
||||
if (slot_id == scan_info.components[i].dc_tbl_idx) {
|
||||
found_dc_table = true;
|
||||
} else if (slot_id == scan_info.components[i].ac_tbl_idx + 16) {
|
||||
|
@ -757,11 +756,9 @@ bool ProcessScan(const uint8_t* data, const size_t len,
|
|||
bool is_interleaved = (scan_info->num_components > 1);
|
||||
int max_h_samp_factor = 1;
|
||||
int max_v_samp_factor = 1;
|
||||
for (size_t i = 0; i < jpg->components.size(); ++i) {
|
||||
max_h_samp_factor =
|
||||
std::max(max_h_samp_factor, jpg->components[i].h_samp_factor);
|
||||
max_v_samp_factor =
|
||||
std::max(max_v_samp_factor, jpg->components[i].v_samp_factor);
|
||||
for (const auto& component : jpg->components) {
|
||||
max_h_samp_factor = std::max(max_h_samp_factor, component.h_samp_factor);
|
||||
max_v_samp_factor = std::max(max_v_samp_factor, component.v_samp_factor);
|
||||
}
|
||||
|
||||
int MCU_rows = DivCeil(jpg->height, max_v_samp_factor * 8);
|
||||
|
|
|
@ -78,8 +78,8 @@ Status JPEGData::VisitFields(Visitor* visitor) {
|
|||
if (marker_order.size() > 16384) {
|
||||
return JXL_FAILURE("Too many markers: %" PRIuS "\n", marker_order.size());
|
||||
}
|
||||
for (size_t i = 0; i < marker_order.size(); i++) {
|
||||
JXL_RETURN_IF_ERROR(VisitMarker(&marker_order[i], visitor, &info));
|
||||
for (uint8_t& marker : marker_order) {
|
||||
JXL_RETURN_IF_ERROR(VisitMarker(&marker, visitor, &info));
|
||||
}
|
||||
if (!marker_order.empty()) {
|
||||
// Last marker should always be EOI marker.
|
||||
|
@ -175,8 +175,8 @@ Status JPEGData::VisitFields(Visitor* visitor) {
|
|||
components.resize(num_components);
|
||||
}
|
||||
if (component_type == JPEGComponentType::kCustom) {
|
||||
for (size_t i = 0; i < components.size(); i++) {
|
||||
JXL_RETURN_IF_ERROR(visitor->Bits(8, 0, &components[i].id));
|
||||
for (auto& component : components) {
|
||||
JXL_RETURN_IF_ERROR(visitor->Bits(8, 0, &component.id));
|
||||
}
|
||||
} else if (component_type == JPEGComponentType::kGray) {
|
||||
components[0].id = 1;
|
||||
|
@ -322,11 +322,11 @@ Status JPEGData::VisitFields(Visitor* visitor) {
|
|||
scan.extra_zero_runs.resize(num_extra_zero_runs);
|
||||
}
|
||||
last_block_idx = -1;
|
||||
for (size_t i = 0; i < scan.extra_zero_runs.size(); ++i) {
|
||||
uint32_t& block_idx = scan.extra_zero_runs[i].block_idx;
|
||||
JXL_RETURN_IF_ERROR(visitor->U32(
|
||||
Val(1), BitsOffset(2, 2), BitsOffset(4, 5), BitsOffset(8, 20), 1,
|
||||
&scan.extra_zero_runs[i].num_extra_zero_runs));
|
||||
for (auto& extra_zero_run : scan.extra_zero_runs) {
|
||||
uint32_t& block_idx = extra_zero_run.block_idx;
|
||||
JXL_RETURN_IF_ERROR(visitor->U32(Val(1), BitsOffset(2, 2),
|
||||
BitsOffset(4, 5), BitsOffset(8, 20), 1,
|
||||
&extra_zero_run.num_extra_zero_runs));
|
||||
block_idx -= last_block_idx + 1;
|
||||
JXL_RETURN_IF_ERROR(visitor->U32(Val(0), BitsOffset(3, 1),
|
||||
BitsOffset(5, 9), BitsOffset(28, 41), 0,
|
||||
|
|
|
@ -179,7 +179,8 @@ TEST(JxlTest, RoundtripResample2MT) {
|
|||
cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 3); // kFalcon
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 203300, 2000);
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 203300,
|
||||
2000);
|
||||
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 340);
|
||||
}
|
||||
|
||||
|
@ -286,8 +287,8 @@ TEST(JxlTest, RoundtripMultiGroup) {
|
|||
cparams.distance = target_distance;
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), expected_size,
|
||||
700);
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out),
|
||||
expected_size, 700);
|
||||
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out),
|
||||
expected_distance);
|
||||
};
|
||||
|
@ -302,7 +303,7 @@ TEST(JxlTest, RoundtripRGBToGrayscale) {
|
|||
ThreadPoolForTests pool(4);
|
||||
const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
|
||||
CodecInOut io;
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool));
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
|
||||
io.ShrinkTo(600, 1024);
|
||||
|
||||
CompressParams cparams;
|
||||
|
@ -316,7 +317,7 @@ TEST(JxlTest, RoundtripRGBToGrayscale) {
|
|||
EXPECT_FALSE(io.Main().IsGray());
|
||||
size_t compressed_size;
|
||||
JXL_EXPECT_OK(
|
||||
Roundtrip(&io, cparams, dparams, &io2, _, &compressed_size, &pool));
|
||||
Roundtrip(&io, cparams, dparams, &io2, _, &compressed_size, pool.get()));
|
||||
EXPECT_LE(compressed_size, 65000u);
|
||||
EXPECT_TRUE(io2.Main().IsGray());
|
||||
|
||||
|
@ -341,7 +342,7 @@ TEST(JxlTest, RoundtripRGBToGrayscale) {
|
|||
EXPECT_SLIGHTLY_BELOW(
|
||||
ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
|
||||
*JxlGetDefaultCms(),
|
||||
/*distmap=*/nullptr, &pool),
|
||||
/*distmap=*/nullptr, pool.get()),
|
||||
1.4);
|
||||
}
|
||||
|
||||
|
@ -355,11 +356,12 @@ TEST(JxlTest, RoundtripLargeFast) {
|
|||
cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 7); // kSquirrel
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 503000, 12000);
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 503000,
|
||||
12000);
|
||||
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 78);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_X86_64_TEST(RoundtripLargeEmptyModular)) {
|
||||
JXL_X86_64_TEST(JxlTest, RoundtripLargeEmptyModular) {
|
||||
ThreadPoolForTests pool(8);
|
||||
TestImage t;
|
||||
t.SetDimensions(4096, 4096).SetDataType(JXL_TYPE_UINT8).SetChannels(4);
|
||||
|
@ -380,7 +382,7 @@ TEST(JxlTest, JXL_X86_64_TEST(RoundtripLargeEmptyModular)) {
|
|||
cparams.AddOption(JXL_ENC_FRAME_SETTING_DECODING_SPEED, 2);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 3474795,
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 3474795,
|
||||
100000);
|
||||
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out),
|
||||
#if JXL_HIGH_PRECISION
|
||||
|
@ -403,8 +405,8 @@ TEST(JxlTest, RoundtripOutputColorSpace) {
|
|||
JXLDecompressParams dparams;
|
||||
dparams.color_space = "RGB_D65_DCI_Rel_709";
|
||||
PackedPixelFile ppf_out;
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), 503000,
|
||||
12000);
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out),
|
||||
503000, 12000);
|
||||
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 78);
|
||||
}
|
||||
|
||||
|
@ -421,7 +423,8 @@ TEST(JxlTest, RoundtripDotsForceEpf) {
|
|||
cparams.AddOption(JXL_ENC_FRAME_SETTING_DOTS, 1);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 41355, 300);
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 41355,
|
||||
300);
|
||||
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 18);
|
||||
}
|
||||
|
||||
|
@ -443,10 +446,10 @@ TEST(JxlTest, RoundtripD2Consistent) {
|
|||
t.SetDimensions(xsize, 15);
|
||||
|
||||
PackedPixelFile ppf2;
|
||||
const size_t size2 = Roundtrip(t.ppf(), cparams, {}, &pool, &ppf2);
|
||||
const size_t size2 = Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf2);
|
||||
|
||||
PackedPixelFile ppf3;
|
||||
const size_t size3 = Roundtrip(t.ppf(), cparams, {}, &pool, &ppf3);
|
||||
const size_t size3 = Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf3);
|
||||
|
||||
// Exact same compressed size.
|
||||
EXPECT_EQ(size2, size3);
|
||||
|
@ -471,7 +474,7 @@ TEST(JxlTest, RoundtripLargeConsistent) {
|
|||
auto roundtrip_and_compare = [&]() {
|
||||
ThreadPoolForTests pool(8);
|
||||
PackedPixelFile ppf2;
|
||||
size_t size = Roundtrip(t.ppf(), cparams, {}, &pool, &ppf2);
|
||||
size_t size = Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf2);
|
||||
double dist = ComputeDistance2(t.ppf(), ppf2);
|
||||
return std::tuple<size_t, double>(size, dist);
|
||||
};
|
||||
|
@ -985,7 +988,7 @@ TEST(JxlTest, RoundtripAlpha16) {
|
|||
PackedPixelFile ppf_out;
|
||||
// TODO(szabadka) Investigate big size difference on i686
|
||||
// This still keeps happening (2023-04-18).
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 3666, 120);
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 3666, 120);
|
||||
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.65);
|
||||
}
|
||||
|
||||
|
@ -1000,7 +1003,7 @@ JXLCompressParams CompressParamsForLossless() {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8)) {
|
||||
JXL_SLOW_TEST(JxlTest, RoundtripLossless8) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("external/wesaturate/500px/tmshre_riaphotographs_srgb8.png");
|
||||
|
@ -1012,11 +1015,11 @@ TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8)) {
|
|||
dparams.accepted_formats.push_back(t.ppf().frames[0].color.format);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), 223058);
|
||||
EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out), 223058);
|
||||
EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8ThunderGradient)) {
|
||||
JXL_SLOW_TEST(JxlTest, RoundtripLossless8ThunderGradient) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("external/wesaturate/500px/tmshre_riaphotographs_srgb8.png");
|
||||
|
@ -1030,11 +1033,11 @@ TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8ThunderGradient)) {
|
|||
dparams.accepted_formats.push_back(t.ppf().frames[0].color.format);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), 261684);
|
||||
EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out), 261684);
|
||||
EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8LightningGradient)) {
|
||||
JXL_SLOW_TEST(JxlTest, RoundtripLossless8LightningGradient) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("external/wesaturate/500px/tmshre_riaphotographs_srgb8.png");
|
||||
|
@ -1048,12 +1051,12 @@ TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8LightningGradient)) {
|
|||
|
||||
PackedPixelFile ppf_out;
|
||||
// Lax comparison because different SIMD will cause different compression.
|
||||
EXPECT_SLIGHTLY_BELOW(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out),
|
||||
286848u);
|
||||
EXPECT_SLIGHTLY_BELOW(
|
||||
Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out), 286848u);
|
||||
EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8Falcon)) {
|
||||
JXL_SLOW_TEST(JxlTest, RoundtripLossless8Falcon) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("external/wesaturate/500px/tmshre_riaphotographs_srgb8.png");
|
||||
|
@ -1066,7 +1069,7 @@ TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8Falcon)) {
|
|||
dparams.accepted_formats.push_back(t.ppf().frames[0].color.format);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), 230766);
|
||||
EXPECT_EQ(Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out), 230766);
|
||||
EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0);
|
||||
}
|
||||
|
||||
|
@ -1348,15 +1351,15 @@ void RoundtripJpegToPixels(const std::vector<uint8_t>& jpeg_in,
|
|||
nullptr, ppf_out, nullptr));
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression444)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression444) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/flower/flower.png.im_q85_444.jpg");
|
||||
// JPEG size is 696,659 bytes.
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 568891u, 20);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 568891u, 20);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionToPixels) {
|
||||
TEST_LIBJPEG_SUPPORT();
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
|
@ -1365,11 +1368,11 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels)) {
|
|||
t.DecodeFromBytes(orig);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
RoundtripJpegToPixels(orig, {}, &pool, &ppf_out);
|
||||
RoundtripJpegToPixels(orig, {}, pool.get(), &ppf_out);
|
||||
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 12);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionToPixels420) {
|
||||
TEST_LIBJPEG_SUPPORT();
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
|
@ -1378,12 +1381,12 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420)) {
|
|||
t.DecodeFromBytes(orig);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
RoundtripJpegToPixels(orig, {}, &pool, &ppf_out);
|
||||
RoundtripJpegToPixels(orig, {}, pool.get(), &ppf_out);
|
||||
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 11);
|
||||
}
|
||||
|
||||
TEST(JxlTest,
|
||||
JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420EarlyFlush)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest,
|
||||
RoundtripJpegRecompressionToPixels420EarlyFlush) {
|
||||
TEST_LIBJPEG_SUPPORT();
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
|
@ -1395,12 +1398,11 @@ TEST(JxlTest,
|
|||
dparams.max_downsampling = 8;
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
RoundtripJpegToPixels(orig, dparams, &pool, &ppf_out);
|
||||
RoundtripJpegToPixels(orig, dparams, pool.get(), &ppf_out);
|
||||
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 4410);
|
||||
}
|
||||
|
||||
TEST(JxlTest,
|
||||
JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420Mul16)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionToPixels420Mul16) {
|
||||
TEST_LIBJPEG_SUPPORT();
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
|
@ -1409,12 +1411,11 @@ TEST(JxlTest,
|
|||
t.DecodeFromBytes(orig);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
RoundtripJpegToPixels(orig, {}, &pool, &ppf_out);
|
||||
RoundtripJpegToPixels(orig, {}, pool.get(), &ppf_out);
|
||||
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 4);
|
||||
}
|
||||
|
||||
TEST(JxlTest,
|
||||
JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels_asymmetric)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionToPixelsAsymmetric) {
|
||||
TEST_LIBJPEG_SUPPORT();
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
|
@ -1423,102 +1424,100 @@ TEST(JxlTest,
|
|||
t.DecodeFromBytes(orig);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
RoundtripJpegToPixels(orig, {}, &pool, &ppf_out);
|
||||
RoundtripJpegToPixels(orig, {}, pool.get(), &ppf_out);
|
||||
EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 10);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionGray)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionGray) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/flower/flower.png.im_q85_gray.jpg");
|
||||
// JPEG size is 456,528 bytes.
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 387496u, 200);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 387496u, 200);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression420)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression420) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/flower/flower.png.im_q85_420.jpg");
|
||||
// JPEG size is 546,797 bytes.
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 455510u, 20);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 455510u, 20);
|
||||
}
|
||||
|
||||
TEST(JxlTest,
|
||||
JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression_luma_subsample)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionLumaSubsample) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/flower/flower.png.im_q85_luma_subsample.jpg");
|
||||
// JPEG size is 400,724 bytes.
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 325310u, 20);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 325310u, 20);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression444_12)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression444wh12) {
|
||||
// 444 JPEG that has an interesting sampling-factor (1x2, 1x2, 1x2).
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/flower/flower.png.im_q85_444_1x2.jpg");
|
||||
// JPEG size is 703,874 bytes.
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 569630u, 20);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 569630u, 20);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression422)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression422) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/flower/flower.png.im_q85_422.jpg");
|
||||
// JPEG size is 522,057 bytes.
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 499236u, 20);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 499236u, 20);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression440)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression440) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/flower/flower.png.im_q85_440.jpg");
|
||||
// JPEG size is 603,623 bytes.
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 501101u, 20);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 501101u, 20);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression_asymmetric)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionAsymmetric) {
|
||||
// 2x vertical downsample of one chroma channel, 2x horizontal downsample of
|
||||
// the other.
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/flower/flower.png.im_q85_asymmetric.jpg");
|
||||
// JPEG size is 604,601 bytes.
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 500548u, 20);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 500548u, 20);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression420Progr)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompression420Progr) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/flower/flower.png.im_q85_420_progr.jpg");
|
||||
// JPEG size is 522,057 bytes.
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 455454u, 20);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 455454u, 20);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionMetadata)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionMetadata) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/jpeg_reconstruction/1x1_exif_xmp.jpg");
|
||||
// JPEG size is 4290 bytes
|
||||
// 1370 on 386, so higher margin.
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 1334u, 100);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 1334u, 100);
|
||||
}
|
||||
|
||||
TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionRestarts)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionRestarts) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/jpeg_reconstruction/bicycles_restarts.jpg");
|
||||
// JPEG size is 87478 bytes
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 76054u, 30);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 76054u, 30);
|
||||
}
|
||||
|
||||
TEST(JxlTest,
|
||||
JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionOrientationICC)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(JxlTest, RoundtripJpegRecompressionOrientationICC) {
|
||||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("jxl/jpeg_reconstruction/sideways_bench.jpg");
|
||||
// JPEG size is 15252 bytes
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, &pool), 12000u, 470);
|
||||
EXPECT_NEAR(RoundtripJpeg(orig, pool.get()), 12000u, 470);
|
||||
// TODO(jon): investigate why 'Cross-compiling i686-linux-gnu' produces a
|
||||
// larger result
|
||||
}
|
||||
|
@ -1535,7 +1534,8 @@ TEST(JxlTest, RoundtripProgressive) {
|
|||
cparams.AddOption(JXL_ENC_FRAME_SETTING_RESPONSIVE, 1);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 70544, 750);
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 70544,
|
||||
750);
|
||||
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.4);
|
||||
}
|
||||
|
||||
|
@ -1552,7 +1552,8 @@ TEST(JxlTest, RoundtripProgressiveLevel2Slow) {
|
|||
cparams.AddOption(JXL_ENC_FRAME_SETTING_RESPONSIVE, 1);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 76666, 1000);
|
||||
EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool.get(), &ppf_out), 76666,
|
||||
1000);
|
||||
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.17);
|
||||
}
|
||||
|
||||
|
@ -1639,7 +1640,7 @@ TEST_P(JxlTest, LosslessSmallFewColors) {
|
|||
dparams.accepted_formats.push_back(t.ppf().frames[0].color.format);
|
||||
|
||||
PackedPixelFile ppf_out;
|
||||
Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out);
|
||||
Roundtrip(t.ppf(), cparams, dparams, pool.get(), &ppf_out);
|
||||
EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0);
|
||||
}
|
||||
|
||||
|
@ -1708,7 +1709,7 @@ TEST_P(JxlStreamingTest, Roundtrip) {
|
|||
|
||||
ThreadPoolForTests pool(8);
|
||||
PackedPixelFile ppf_out;
|
||||
Roundtrip(image.ppf(), cparams, {}, &pool, &ppf_out);
|
||||
Roundtrip(image.ppf(), cparams, {}, pool.get(), &ppf_out);
|
||||
EXPECT_GT(jxl::test::ComputePSNR(image.ppf(), ppf_out), p.max_psnr());
|
||||
}
|
||||
|
||||
|
@ -1763,7 +1764,7 @@ class JxlStreamingEncodingTest
|
|||
: public ::testing::TestWithParam<StreamingEncodingTestParam> {};
|
||||
|
||||
// This is broken on mingw32, so we only enable it for x86_64 now.
|
||||
TEST_P(JxlStreamingEncodingTest, JXL_X86_64_TEST(StreamingSamePixels)) {
|
||||
JXL_X86_64_TEST_P(JxlStreamingEncodingTest, StreamingSamePixels) {
|
||||
const auto param = GetParam();
|
||||
|
||||
const std::vector<uint8_t> orig = ReadTestData(param.file);
|
||||
|
@ -1780,11 +1781,11 @@ TEST_P(JxlStreamingEncodingTest, JXL_X86_64_TEST(StreamingSamePixels)) {
|
|||
|
||||
ThreadPoolForTests pool(8);
|
||||
PackedPixelFile ppf_out;
|
||||
Roundtrip(image.ppf(), cparams, {}, &pool, &ppf_out);
|
||||
Roundtrip(image.ppf(), cparams, {}, pool.get(), &ppf_out);
|
||||
|
||||
cparams.AddOption(JXL_ENC_FRAME_SETTING_BUFFERING, 3);
|
||||
PackedPixelFile ppf_out_streaming;
|
||||
Roundtrip(image.ppf(), cparams, {}, &pool, &ppf_out_streaming);
|
||||
Roundtrip(image.ppf(), cparams, {}, pool.get(), &ppf_out_streaming);
|
||||
|
||||
EXPECT_TRUE(jxl::test::SamePixels(ppf_out, ppf_out_streaming));
|
||||
}
|
||||
|
|
|
@ -88,10 +88,10 @@ void RoundtripSizeRange(ThreadPool* pool, uint32_t begin, uint32_t end) {
|
|||
TEST(LehmerCodeTest, TestRoundtrips) {
|
||||
test::ThreadPoolForTests pool(8);
|
||||
|
||||
RoundtripSizeRange<uint16_t>(&pool, 1, 1026);
|
||||
RoundtripSizeRange<uint16_t>(pool.get(), 1, 1026);
|
||||
|
||||
// Ensures PermutationT can fit > 16 bit values.
|
||||
RoundtripSizeRange<uint32_t>(&pool, 65536, 65540);
|
||||
RoundtripSizeRange<uint32_t>(pool.get(), 65536, 65540);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -63,7 +63,7 @@ struct State {
|
|||
pixel_type_w pred = 0; // *before* removing the added bits.
|
||||
std::vector<uint32_t> pred_errors[kNumPredictors];
|
||||
std::vector<int32_t> error;
|
||||
const Header header;
|
||||
const Header &header;
|
||||
|
||||
// Allows to approximate division by a number from 1 to 64.
|
||||
// for (int i = 0; i < 64; i++) divlookup[i] = (1 << 24) / (i + 1);
|
||||
|
@ -82,7 +82,7 @@ struct State {
|
|||
return static_cast<uint64_t>(x) << kPredExtraBits;
|
||||
}
|
||||
|
||||
State(Header header, size_t xsize, size_t ysize) : header(header) {
|
||||
State(const 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 (auto &pred_error : pred_errors) {
|
||||
|
|
|
@ -197,7 +197,7 @@ void FindBestSplit(TreeSamples &tree_samples, float threshold,
|
|||
float rcost = std::numeric_limits<float>::max();
|
||||
Predictor lpred = Predictor::Zero;
|
||||
Predictor rpred = Predictor::Zero;
|
||||
float Cost() { return lcost + rcost; }
|
||||
float Cost() const { return lcost + rcost; }
|
||||
};
|
||||
|
||||
SplitInfo best_split_static_constant;
|
||||
|
@ -242,14 +242,14 @@ void FindBestSplit(TreeSamples &tree_samples, float threshold,
|
|||
// The multiplier ranges cut halfway through the current ranges of static
|
||||
// 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++) {
|
||||
for (const auto &mmi : mul_info) {
|
||||
uint32_t axis;
|
||||
uint32_t val;
|
||||
IntersectionType t =
|
||||
BoxIntersects(static_prop_range, mul_info[i].range, axis, val);
|
||||
BoxIntersects(static_prop_range, mmi.range, axis, val);
|
||||
if (t == IntersectionType::kNone) continue;
|
||||
if (t == IntersectionType::kInside) {
|
||||
(*tree)[pos].multiplier = mul_info[i].multiplier;
|
||||
(*tree)[pos].multiplier = mmi.multiplier;
|
||||
break;
|
||||
}
|
||||
if (t == IntersectionType::kPartial) {
|
||||
|
|
|
@ -113,7 +113,7 @@ FlatTree FilterTree(const Tree &global_tree,
|
|||
}
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < 2; j++) mark_property(flat.properties[j]);
|
||||
for (int16_t property : flat.properties) mark_property(property);
|
||||
mark_property(flat.property0);
|
||||
output.push_back(flat);
|
||||
}
|
||||
|
@ -159,9 +159,9 @@ Status DecodeModularChannelMAANS(BitReader *br, ANSSymbolReader *reader,
|
|||
|
||||
// From here on, tree lookup returns a *clustered* context ID.
|
||||
// This avoids an extra memory lookup after tree traversal.
|
||||
for (size_t i = 0; i < tree.size(); i++) {
|
||||
if (tree[i].property0 == -1) {
|
||||
tree[i].childID = context_map[tree[i].childID];
|
||||
for (auto &node : tree) {
|
||||
if (node.property0 == -1) {
|
||||
node.childID = context_map[node.childID];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -538,8 +538,8 @@ Status ModularDecode(BitReader *br, Image &image, GroupHeader &header,
|
|||
// Don't do/undo transforms if header is incomplete.
|
||||
header.transforms.clear();
|
||||
image.transform = header.transforms;
|
||||
for (size_t c = 0; c < image.channel.size(); c++) {
|
||||
ZeroFillImage(&image.channel[c].plane);
|
||||
for (auto &ch : image.channel) {
|
||||
ZeroFillImage(&ch.plane);
|
||||
}
|
||||
return Status(StatusCode::kNotEnoughBytes);
|
||||
}
|
||||
|
|
|
@ -68,8 +68,8 @@ static int QuantizeColorToImplicitPaletteIndex(
|
|||
int index = 0;
|
||||
if (high_quality) {
|
||||
int multiplier = 1;
|
||||
for (size_t c = 0; c < color.size(); c++) {
|
||||
int quantized = ((kLargeCube - 1) * color[c] + (1 << (bit_depth - 1))) /
|
||||
for (int value : color) {
|
||||
int quantized = ((kLargeCube - 1) * value + (1 << (bit_depth - 1))) /
|
||||
((1 << bit_depth) - 1);
|
||||
JXL_ASSERT((quantized % kLargeCube) == quantized);
|
||||
index += quantized * multiplier;
|
||||
|
@ -78,8 +78,7 @@ static int QuantizeColorToImplicitPaletteIndex(
|
|||
return index + palette_size + kLargeCubeOffset;
|
||||
} else {
|
||||
int multiplier = 1;
|
||||
for (size_t c = 0; c < color.size(); c++) {
|
||||
int value = color[c];
|
||||
for (int value : color) {
|
||||
value -= 1 << (std::max(0, bit_depth - 3));
|
||||
value = std::max(0, value);
|
||||
int quantized = ((kLargeCube - 1) * value + (1 << (bit_depth - 1))) /
|
||||
|
@ -171,6 +170,7 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
|
|||
|
||||
size_t w = input.channel[begin_c].w;
|
||||
size_t h = input.channel[begin_c].h;
|
||||
if (!lossy && nb_colors < 2) return false;
|
||||
|
||||
if (!lossy && nb == 1) {
|
||||
// Channel palette special case
|
||||
|
@ -321,6 +321,20 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
|
|||
}
|
||||
}
|
||||
|
||||
std::map<std::vector<pixel_type>, bool> implicit_color;
|
||||
std::vector<std::vector<pixel_type>> implicit_colors;
|
||||
implicit_colors.reserve(palette_internal::kImplicitPaletteSize);
|
||||
for (size_t k = 0; k < palette_internal::kImplicitPaletteSize; k++) {
|
||||
for (size_t i = 0; i < nb; i++) {
|
||||
color[i] = palette_internal::GetPaletteValue(nullptr, k, i, 0, 0,
|
||||
input.bitdepth);
|
||||
}
|
||||
implicit_color[color] = true;
|
||||
implicit_colors.push_back(color);
|
||||
}
|
||||
|
||||
std::map<std::vector<pixel_type>, size_t> color_freq_map;
|
||||
uint32_t implicit_colors_used = 0;
|
||||
for (size_t y = 0; y < h; y++) {
|
||||
for (uint32_t c = 0; c < nb; c++) {
|
||||
p_in[c] = input.channel[begin_c + c].Row(y);
|
||||
|
@ -332,15 +346,39 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
|
|||
}
|
||||
const bool new_color = candidate_palette.insert(color).second;
|
||||
if (new_color) {
|
||||
candidate_palette_imageorder.push_back(color);
|
||||
}
|
||||
if (candidate_palette.size() > nb_colors) {
|
||||
return false; // too many colors
|
||||
if (implicit_color[color]) {
|
||||
implicit_colors_used++;
|
||||
} else {
|
||||
candidate_palette_imageorder.push_back(color);
|
||||
if (candidate_palette_imageorder.size() > nb_colors) {
|
||||
return false; // too many colors
|
||||
}
|
||||
}
|
||||
}
|
||||
color_freq_map[color] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
nb_colors = nb_deltas + candidate_palette.size();
|
||||
nb_colors = nb_deltas + candidate_palette_imageorder.size();
|
||||
|
||||
// not useful to make a single-color palette
|
||||
if (!lossy && nb_colors + implicit_colors_used == 1) return false;
|
||||
// TODO(jon): if this happens (e.g. solid white group), special-case it for
|
||||
// faster encode
|
||||
|
||||
for (size_t k = 0; k < palette_internal::kImplicitPaletteSize; k++) {
|
||||
color = implicit_colors[k];
|
||||
// still add the color to the explicit palette if it is frequent enough
|
||||
if (color_freq_map[color] > 10) {
|
||||
nb_colors++;
|
||||
candidate_palette_imageorder.push_back(color);
|
||||
}
|
||||
}
|
||||
for (size_t k = 0; k < palette_internal::kImplicitPaletteSize; k++) {
|
||||
color = implicit_colors[k];
|
||||
inv_palette[color] = nb_colors + k;
|
||||
}
|
||||
|
||||
JXL_DEBUG_V(6, "Channels %i-%i can be represented using a %i-color palette.",
|
||||
begin_c, end_c, nb_colors);
|
||||
|
||||
|
@ -360,25 +398,33 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Separate the palette in two buckets, first the common colors, then the
|
||||
// rare colors.
|
||||
// Within each bucket, the colors are sorted on luma (times alpha).
|
||||
float freq_threshold = 4; // arbitrary threshold
|
||||
int x = 0;
|
||||
if (ordered && nb >= 3) {
|
||||
JXL_DEBUG_V(7, "Palette of %i colors, using luma order", nb_colors);
|
||||
// sort on luma (multiplied by alpha if available)
|
||||
std::sort(candidate_palette_imageorder.begin(),
|
||||
candidate_palette_imageorder.end(),
|
||||
[](std::vector<pixel_type> ap, std::vector<pixel_type> bp) {
|
||||
[&](std::vector<pixel_type> ap, std::vector<pixel_type> bp) {
|
||||
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);
|
||||
if (bp.size() > 3) by *= 1.f + bp[3];
|
||||
// put common colors first, transparent dark to opaque bright,
|
||||
// then rare colors, bright to dark
|
||||
ay = color_freq_map[ap] > freq_threshold ? -ay : ay;
|
||||
by = color_freq_map[bp] > freq_threshold ? -by : by;
|
||||
return ay < by;
|
||||
});
|
||||
} else {
|
||||
JXL_DEBUG_V(7, "Palette of %i colors, using image order", nb_colors);
|
||||
}
|
||||
|
||||
for (auto pcol : candidate_palette_imageorder) {
|
||||
JXL_DEBUG_V(9, " Color %i : ", x);
|
||||
for (size_t i = 0; i < nb; i++) {
|
||||
|
@ -398,10 +444,10 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
|
|||
// beneficial for both precision and encoding speed.
|
||||
std::vector<std::vector<float>> error_row[3];
|
||||
if (lossy) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
error_row[i].resize(nb);
|
||||
for (auto &row : error_row) {
|
||||
row.resize(nb);
|
||||
for (size_t c = 0; c < nb; ++c) {
|
||||
error_row[i][c].resize(w + 4);
|
||||
row[c].resize(w + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -424,13 +470,11 @@ Status FwdPaletteIteration(Image &input, uint32_t begin_c, uint32_t end_c,
|
|||
std::vector<pixel_type> ideal_residual(nb, 0);
|
||||
std::vector<pixel_type> quantized_val(nb);
|
||||
std::vector<pixel_type> predictions(nb);
|
||||
static const double kDiffusionMultiplier[] = {0.55, 0.75};
|
||||
for (int diffusion_index = 0; diffusion_index < 2; ++diffusion_index) {
|
||||
for (double diffusion_multiplier : {0.55, 0.75}) {
|
||||
for (size_t c = 0; c < nb; c++) {
|
||||
color_with_error[c] =
|
||||
p_in[c][x] + (palette_iteration_data.final_run ? 1 : 0) *
|
||||
kDiffusionMultiplier[diffusion_index] *
|
||||
error_row[0][c][x + 2];
|
||||
diffusion_multiplier * error_row[0][c][x + 2];
|
||||
color[c] = Clamp1(lroundf(color_with_error[c]), 0l,
|
||||
(1l << input.bitdepth) - 1);
|
||||
}
|
||||
|
|
|
@ -124,13 +124,13 @@ Status FwdSqueeze(Image &input, std::vector<SqueezeParams> parameters,
|
|||
}
|
||||
// if nothing to do, don't do squeeze
|
||||
if (parameters.empty()) return false;
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
for (auto ¶meter : parameters) {
|
||||
JXL_RETURN_IF_ERROR(
|
||||
CheckMetaSqueezeParams(parameters[i], input.channel.size()));
|
||||
bool horizontal = parameters[i].horizontal;
|
||||
bool in_place = parameters[i].in_place;
|
||||
uint32_t beginc = parameters[i].begin_c;
|
||||
uint32_t endc = parameters[i].begin_c + parameters[i].num_c - 1;
|
||||
CheckMetaSqueezeParams(parameter, input.channel.size()));
|
||||
bool horizontal = parameter.horizontal;
|
||||
bool in_place = parameter.in_place;
|
||||
uint32_t beginc = parameter.begin_c;
|
||||
uint32_t endc = parameter.begin_c + parameter.num_c - 1;
|
||||
uint32_t offset;
|
||||
if (in_place) {
|
||||
offset = endc + 1;
|
||||
|
|
|
@ -30,6 +30,8 @@ static constexpr int kSmallCube = 4;
|
|||
static constexpr int kSmallCubeBits = 2;
|
||||
// kSmallCube ** 3
|
||||
static constexpr int kLargeCubeOffset = kSmallCube * kSmallCube * kSmallCube;
|
||||
static constexpr int kImplicitPaletteSize =
|
||||
kLargeCubeOffset + kLargeCube * kLargeCube * kLargeCube;
|
||||
|
||||
static inline pixel_type Scale(uint64_t value, uint64_t bit_depth,
|
||||
uint64_t denom) {
|
||||
|
|
|
@ -385,21 +385,21 @@ void DefaultSqueezeParameters(std::vector<SqueezeParams> *parameters,
|
|||
params.in_place = true;
|
||||
|
||||
if (!wide) {
|
||||
if (h > JXL_MAX_FIRST_PREVIEW_SIZE) {
|
||||
if (h > kMaxFirstPreviewSize) {
|
||||
params.horizontal = false;
|
||||
parameters->push_back(params);
|
||||
h = (h + 1) / 2;
|
||||
JXL_DEBUG_V(7, "Vertical (%" PRIuS "x%" PRIuS "), ", w, h);
|
||||
}
|
||||
}
|
||||
while (w > JXL_MAX_FIRST_PREVIEW_SIZE || h > JXL_MAX_FIRST_PREVIEW_SIZE) {
|
||||
if (w > JXL_MAX_FIRST_PREVIEW_SIZE) {
|
||||
while (w > kMaxFirstPreviewSize || h > kMaxFirstPreviewSize) {
|
||||
if (w > kMaxFirstPreviewSize) {
|
||||
params.horizontal = true;
|
||||
parameters->push_back(params);
|
||||
w = (w + 1) / 2;
|
||||
JXL_DEBUG_V(7, "Horizontal (%" PRIuS "x%" PRIuS "), ", w, h);
|
||||
}
|
||||
if (h > JXL_MAX_FIRST_PREVIEW_SIZE) {
|
||||
if (h > kMaxFirstPreviewSize) {
|
||||
params.horizontal = false;
|
||||
parameters->push_back(params);
|
||||
h = (h + 1) / 2;
|
||||
|
@ -424,13 +424,13 @@ Status MetaSqueeze(Image &image, std::vector<SqueezeParams> *parameters) {
|
|||
DefaultSqueezeParameters(parameters, image);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < parameters->size(); i++) {
|
||||
for (auto ¶meter : *parameters) {
|
||||
JXL_RETURN_IF_ERROR(
|
||||
CheckMetaSqueezeParams((*parameters)[i], image.channel.size()));
|
||||
bool horizontal = (*parameters)[i].horizontal;
|
||||
bool in_place = (*parameters)[i].in_place;
|
||||
uint32_t beginc = (*parameters)[i].begin_c;
|
||||
uint32_t endc = (*parameters)[i].begin_c + (*parameters)[i].num_c - 1;
|
||||
CheckMetaSqueezeParams(parameter, image.channel.size()));
|
||||
bool horizontal = parameter.horizontal;
|
||||
bool in_place = parameter.in_place;
|
||||
uint32_t beginc = parameter.begin_c;
|
||||
uint32_t endc = parameter.begin_c + parameter.num_c - 1;
|
||||
|
||||
uint32_t offset;
|
||||
if (beginc < image.nb_meta_channels) {
|
||||
|
@ -441,7 +441,7 @@ Status MetaSqueeze(Image &image, std::vector<SqueezeParams> *parameters) {
|
|||
return JXL_FAILURE(
|
||||
"Invalid squeeze: meta channels require in-place residuals");
|
||||
}
|
||||
image.nb_meta_channels += (*parameters)[i].num_c;
|
||||
image.nb_meta_channels += parameter.num_c;
|
||||
}
|
||||
if (in_place) {
|
||||
offset = endc + 1;
|
||||
|
|
|
@ -29,10 +29,10 @@
|
|||
#include "lib/jxl/modular/modular_image.h"
|
||||
#include "lib/jxl/modular/transform/transform.h"
|
||||
|
||||
#define JXL_MAX_FIRST_PREVIEW_SIZE 8
|
||||
|
||||
namespace jxl {
|
||||
|
||||
constexpr size_t kMaxFirstPreviewSize = 8;
|
||||
|
||||
/*
|
||||
int avg=(A+B)>>1;
|
||||
int diff=(A-B);
|
||||
|
|
|
@ -23,7 +23,7 @@ Transform::Transform(TransformId id) {
|
|||
}
|
||||
|
||||
Status Transform::Inverse(Image &input, const weighted::Header &wp_header,
|
||||
ThreadPool *pool) {
|
||||
ThreadPool *pool) const {
|
||||
JXL_DEBUG_V(6, "Input channels (%" PRIuS ", %" PRIuS " meta): ",
|
||||
input.channel.size(), input.nb_meta_channels);
|
||||
switch (id) {
|
||||
|
|
|
@ -134,7 +134,7 @@ class Transform : public Fields {
|
|||
JXL_FIELDS_NAME(Transform)
|
||||
|
||||
Status Inverse(Image &input, const weighted::Header &wp_header,
|
||||
ThreadPool *pool = nullptr);
|
||||
ThreadPool *pool = nullptr) const;
|
||||
Status MetaApply(Image &input);
|
||||
};
|
||||
|
||||
|
|
|
@ -80,15 +80,15 @@ void TestLosslessGroups(size_t group_size_shift) {
|
|||
|
||||
TEST(ModularTest, RoundtripLosslessGroups128) { TestLosslessGroups(0); }
|
||||
|
||||
TEST(ModularTest, JXL_TSAN_SLOW_TEST(RoundtripLosslessGroups512)) {
|
||||
JXL_TSAN_SLOW_TEST(ModularTest, RoundtripLosslessGroups512) {
|
||||
TestLosslessGroups(2);
|
||||
}
|
||||
|
||||
TEST(ModularTest, JXL_TSAN_SLOW_TEST(RoundtripLosslessGroups1024)) {
|
||||
JXL_TSAN_SLOW_TEST(ModularTest, RoundtripLosslessGroups1024) {
|
||||
TestLosslessGroups(3);
|
||||
}
|
||||
|
||||
TEST(ModularTest, RoundtripLosslessCustomWP_PermuteRCT) {
|
||||
TEST(ModularTest, RoundtripLosslessCustomWpPermuteRCT) {
|
||||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("external/wesaturate/500px/u76c0g_bliznaca_srgb8.png");
|
||||
TestImage t;
|
||||
|
@ -144,6 +144,7 @@ TEST(ModularTest, RoundtripLossyDeltaPaletteWP) {
|
|||
cparams.SetLossless();
|
||||
cparams.lossy_palette = true;
|
||||
cparams.palette_colors = 0;
|
||||
// TODO(jon): this is currently ignored, and Avg4 is always used instead
|
||||
cparams.options.predictor = jxl::Predictor::Weighted;
|
||||
|
||||
CodecInOut io_out;
|
||||
|
@ -154,12 +155,12 @@ TEST(ModularTest, RoundtripLossyDeltaPaletteWP) {
|
|||
|
||||
size_t compressed_size;
|
||||
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io_out, _, &compressed_size));
|
||||
EXPECT_LE(compressed_size, 7000u);
|
||||
EXPECT_LE(compressed_size, 6500u);
|
||||
EXPECT_SLIGHTLY_BELOW(
|
||||
ButteraugliDistance(io.frames, io_out.frames, ButteraugliParams(),
|
||||
*JxlGetDefaultCms(),
|
||||
/*distmap=*/nullptr),
|
||||
10.1);
|
||||
1.5);
|
||||
}
|
||||
|
||||
TEST(ModularTest, RoundtripLossy) {
|
||||
|
@ -346,8 +347,8 @@ TEST_P(ModularTestParam, RoundtripLossless) {
|
|||
const float* in = io.Main().color()->PlaneRow(c, y);
|
||||
const float* out = io2.Main().color()->PlaneRow(c, y);
|
||||
for (size_t x = 0; x < xsize; x++) {
|
||||
uint32_t uin = in[x] * factor + 0.5;
|
||||
uint32_t uout = out[x] * factor + 0.5;
|
||||
uint32_t uin = std::lroundf(in[x] * factor);
|
||||
uint32_t uout = std::lroundf(out[x] * factor);
|
||||
// check that the integer values are identical
|
||||
if (uin != uout) different++;
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ TEST(PassesTest, RoundtripMultiGroupPasses) {
|
|||
CodecInOut io;
|
||||
{
|
||||
ThreadPoolForTests pool(4);
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool));
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
|
||||
}
|
||||
io.ShrinkTo(600, 1024); // partial X, full Y group
|
||||
|
||||
|
@ -92,11 +92,11 @@ TEST(PassesTest, RoundtripMultiGroupPasses) {
|
|||
cparams.SetCms(*JxlGetDefaultCms());
|
||||
CodecInOut io2;
|
||||
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _,
|
||||
/* compressed_size */ nullptr, &pool));
|
||||
/* compressed_size */ nullptr, pool.get()));
|
||||
EXPECT_SLIGHTLY_BELOW(
|
||||
ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(),
|
||||
*JxlGetDefaultCms(),
|
||||
/*distmap=*/nullptr, &pool),
|
||||
/*distmap=*/nullptr, pool.get()),
|
||||
target_distance + threshold);
|
||||
};
|
||||
|
||||
|
@ -108,7 +108,7 @@ TEST(PassesTest, RoundtripLargeFastPasses) {
|
|||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
|
||||
CodecInOut io;
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool));
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
|
||||
|
||||
CompressParams cparams;
|
||||
cparams.speed_tier = SpeedTier::kSquirrel;
|
||||
|
@ -117,7 +117,7 @@ TEST(PassesTest, RoundtripLargeFastPasses) {
|
|||
|
||||
CodecInOut io2;
|
||||
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _,
|
||||
/* compressed_size */ nullptr, &pool));
|
||||
/* compressed_size */ nullptr, pool.get()));
|
||||
}
|
||||
|
||||
// Checks for differing size/distance in two consecutive runs of distance 2,
|
||||
|
@ -127,7 +127,7 @@ TEST(PassesTest, RoundtripProgressiveConsistent) {
|
|||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
|
||||
CodecInOut io;
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool));
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
|
||||
|
||||
CompressParams cparams;
|
||||
cparams.speed_tier = SpeedTier::kSquirrel;
|
||||
|
@ -141,11 +141,11 @@ TEST(PassesTest, RoundtripProgressiveConsistent) {
|
|||
|
||||
CodecInOut io2;
|
||||
size_t size2;
|
||||
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _, &size2, &pool));
|
||||
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io2, _, &size2, pool.get()));
|
||||
|
||||
CodecInOut io3;
|
||||
size_t size3;
|
||||
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io3, _, &size3, &pool));
|
||||
JXL_EXPECT_OK(Roundtrip(&io, cparams, {}, &io3, _, &size3, pool.get()));
|
||||
|
||||
// Exact same compressed size.
|
||||
EXPECT_EQ(size2, size3);
|
||||
|
@ -153,10 +153,10 @@ TEST(PassesTest, RoundtripProgressiveConsistent) {
|
|||
// Exact same distance.
|
||||
const float dist2 = ButteraugliDistance(
|
||||
io.frames, io2.frames, ButteraugliParams(), *JxlGetDefaultCms(),
|
||||
/*distmap=*/nullptr, &pool);
|
||||
/*distmap=*/nullptr, pool.get());
|
||||
const float dist3 = ButteraugliDistance(
|
||||
io.frames, io3.frames, ButteraugliParams(), *JxlGetDefaultCms(),
|
||||
/*distmap=*/nullptr, &pool);
|
||||
/*distmap=*/nullptr, pool.get());
|
||||
EXPECT_EQ(dist2, dist3);
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ TEST(PassesTest, AllDownsampleFeasible) {
|
|||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("external/wesaturate/500px/u76c0g_bliznaca_srgb8.png");
|
||||
CodecInOut io;
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool));
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
|
||||
|
||||
std::vector<uint8_t> compressed;
|
||||
|
||||
|
@ -174,7 +174,7 @@ TEST(PassesTest, AllDownsampleFeasible) {
|
|||
cparams.speed_tier = SpeedTier::kSquirrel;
|
||||
cparams.progressive_mode = Override::kOn;
|
||||
cparams.butteraugli_distance = 1.0;
|
||||
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool));
|
||||
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get()));
|
||||
|
||||
EXPECT_LE(compressed.size(), 240000u);
|
||||
float target_butteraugli[9] = {};
|
||||
|
@ -202,7 +202,7 @@ TEST(PassesTest, AllDownsampleFeasible) {
|
|||
target_butteraugli[downsampling])
|
||||
<< "downsampling: " << downsampling;
|
||||
};
|
||||
EXPECT_TRUE(RunOnPool(&pool, 0, downsamplings.size(), ThreadPool::NoInit,
|
||||
EXPECT_TRUE(RunOnPool(pool.get(), 0, downsamplings.size(), ThreadPool::NoInit,
|
||||
check, "TestDownsampling"));
|
||||
}
|
||||
|
||||
|
@ -211,7 +211,7 @@ TEST(PassesTest, AllDownsampleFeasibleQProgressive) {
|
|||
const std::vector<uint8_t> orig =
|
||||
ReadTestData("external/wesaturate/500px/u76c0g_bliznaca_srgb8.png");
|
||||
CodecInOut io;
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool));
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
|
||||
|
||||
std::vector<uint8_t> compressed;
|
||||
|
||||
|
@ -219,7 +219,7 @@ TEST(PassesTest, AllDownsampleFeasibleQProgressive) {
|
|||
cparams.speed_tier = SpeedTier::kSquirrel;
|
||||
cparams.qprogressive_mode = Override::kOn;
|
||||
cparams.butteraugli_distance = 1.0;
|
||||
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool));
|
||||
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get()));
|
||||
|
||||
EXPECT_LE(compressed.size(), 220000u);
|
||||
|
||||
|
@ -247,7 +247,7 @@ TEST(PassesTest, AllDownsampleFeasibleQProgressive) {
|
|||
target_butteraugli[downsampling])
|
||||
<< "downsampling: " << downsampling;
|
||||
};
|
||||
EXPECT_TRUE(RunOnPool(&pool, 0, downsamplings.size(), ThreadPool::NoInit,
|
||||
EXPECT_TRUE(RunOnPool(pool.get(), 0, downsamplings.size(), ThreadPool::NoInit,
|
||||
check, "TestQProgressive"));
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectlyGrayscale) {
|
|||
const std::vector<uint8_t> orig = ReadTestData(
|
||||
"external/wesaturate/500px/cvo9xd_keong_macan_grayscale.png");
|
||||
CodecInOut io_orig;
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, &pool));
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, pool.get()));
|
||||
Rect rect(0, 0, io_orig.xsize(), 128);
|
||||
// need 2 DC groups for the DC frame to actually be progressive.
|
||||
JXL_ASSIGN_OR_DIE(Image3F large, Image3F::Create(4242, rect.ysize()));
|
||||
|
@ -274,7 +274,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectlyGrayscale) {
|
|||
cparams.responsive = JXL_TRUE;
|
||||
cparams.qprogressive_mode = Override::kOn;
|
||||
cparams.butteraugli_distance = 1.0;
|
||||
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool));
|
||||
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get()));
|
||||
|
||||
EXPECT_LE(compressed.size(), 10000u);
|
||||
|
||||
|
@ -300,7 +300,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectly) {
|
|||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
|
||||
CodecInOut io_orig;
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, &pool));
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_orig, pool.get()));
|
||||
Rect rect(0, 0, io_orig.xsize(), 128);
|
||||
// need 2 DC groups for the DC frame to actually be progressive.
|
||||
JXL_ASSIGN_OR_DIE(Image3F large, Image3F::Create(4242, rect.ysize()));
|
||||
|
@ -317,7 +317,7 @@ TEST(PassesTest, ProgressiveDownsample2DegradesCorrectly) {
|
|||
cparams.responsive = JXL_TRUE;
|
||||
cparams.qprogressive_mode = Override::kOn;
|
||||
cparams.butteraugli_distance = 1.0;
|
||||
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool));
|
||||
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get()));
|
||||
|
||||
EXPECT_LE(compressed.size(), 220000u);
|
||||
|
||||
|
@ -343,7 +343,7 @@ TEST(PassesTest, NonProgressiveDCImage) {
|
|||
ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png");
|
||||
CodecInOut io;
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, &pool));
|
||||
ASSERT_TRUE(SetFromBytes(Bytes(orig), &io, pool.get()));
|
||||
|
||||
std::vector<uint8_t> compressed;
|
||||
|
||||
|
@ -351,14 +351,15 @@ TEST(PassesTest, NonProgressiveDCImage) {
|
|||
cparams.speed_tier = SpeedTier::kSquirrel;
|
||||
cparams.progressive_mode = Override::kOff;
|
||||
cparams.butteraugli_distance = 2.0;
|
||||
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, &pool));
|
||||
ASSERT_TRUE(test::EncodeFile(cparams, &io, &compressed, pool.get()));
|
||||
|
||||
// Even in non-progressive mode, it should be possible to return a DC-only
|
||||
// image.
|
||||
extras::JXLDecompressParams dparams;
|
||||
dparams.max_downsampling = 100;
|
||||
CodecInOut output;
|
||||
ASSERT_TRUE(test::DecodeFile(dparams, Bytes(compressed), &output, &pool));
|
||||
ASSERT_TRUE(
|
||||
test::DecodeFile(dparams, Bytes(compressed), &output, pool.get()));
|
||||
EXPECT_EQ(output.xsize(), io.xsize());
|
||||
EXPECT_EQ(output.ysize(), io.ysize());
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ TEST(QuantWeightsTest, RAW) {
|
|||
QuantEncoding::Library(0));
|
||||
std::vector<int> matrix(3 * 32 * 32);
|
||||
Rng rng(0);
|
||||
for (size_t i = 0; i < matrix.size(); i++) matrix[i] = rng.UniformI(1, 256);
|
||||
for (int& v : matrix) v = rng.UniformI(1, 256);
|
||||
encodings[DequantMatrices::kQuantTable[AcStrategy::DCT32X32]] =
|
||||
QuantEncoding::RAW(matrix, 2);
|
||||
RoundtripMatrices(encodings);
|
||||
|
|
|
@ -20,7 +20,7 @@ void RenderPipeline::Builder::AddStage(
|
|||
StatusOr<std::unique_ptr<RenderPipeline>> RenderPipeline::Builder::Finalize(
|
||||
FrameDimensions frame_dimensions) && {
|
||||
#if JXL_ENABLE_ASSERT
|
||||
// Check that the last stage is not an kInOut stage for any channel, and that
|
||||
// Check that the last stage is not a kInOut stage for any channel, and that
|
||||
// there is at least one stage.
|
||||
JXL_ASSERT(!stages_.empty());
|
||||
for (size_t c = 0; c < num_c_; c++) {
|
||||
|
|
|
@ -22,12 +22,12 @@ Status SimpleRenderPipeline::PrepareForThreadsInternal(size_t num,
|
|||
auto ch_size = [](size_t frame_size, size_t shift) {
|
||||
return DivCeil(frame_size, 1 << shift) + kRenderPipelineXOffset * 2;
|
||||
};
|
||||
for (size_t c = 0; c < channel_shifts_[0].size(); c++) {
|
||||
for (auto& entry : channel_shifts_[0]) {
|
||||
JXL_ASSIGN_OR_RETURN(
|
||||
ImageF ch, ImageF::Create(ch_size(frame_dimensions_.xsize_upsampled,
|
||||
channel_shifts_[0][c].first),
|
||||
ch_size(frame_dimensions_.ysize_upsampled,
|
||||
channel_shifts_[0][c].second)));
|
||||
ImageF ch,
|
||||
ImageF::Create(
|
||||
ch_size(frame_dimensions_.xsize_upsampled, entry.first),
|
||||
ch_size(frame_dimensions_.ysize_upsampled, entry.second)));
|
||||
channel_data_.push_back(std::move(ch));
|
||||
msan::PoisonImage(channel_data_.back());
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class CmsStage : public RenderPipelineStage {
|
|||
size_t xextra, size_t xsize, size_t xpos, size_t ypos,
|
||||
size_t thread_id) const final {
|
||||
JXL_ASSERT(xsize <= xsize_);
|
||||
// TODO(firsching): handle grey case seperately
|
||||
// TODO(firsching): handle grey case separately
|
||||
// interleave
|
||||
float* JXL_RESTRICT row0 = GetInputRow(input_rows, 0, 0);
|
||||
float* JXL_RESTRICT row1 = GetInputRow(input_rows, 1, 0);
|
||||
|
|
|
@ -40,10 +40,10 @@ JXL_INLINE Vec<DF> Weight(Vec<DF> sad, Vec<DF> inv_sigma, Vec<DF> thres) {
|
|||
// this filter a 7x7 filter.
|
||||
class EPF0Stage : public RenderPipelineStage {
|
||||
public:
|
||||
EPF0Stage(const LoopFilter& lf, const ImageF& sigma)
|
||||
EPF0Stage(LoopFilter lf, const ImageF& sigma)
|
||||
: RenderPipelineStage(RenderPipelineStage::Settings::Symmetric(
|
||||
/*shift=*/0, /*border=*/3)),
|
||||
lf_(lf),
|
||||
lf_(std::move(lf)),
|
||||
sigma_(&sigma) {}
|
||||
|
||||
template <bool aligned>
|
||||
|
@ -72,7 +72,7 @@ class EPF0Stage : public RenderPipelineStage {
|
|||
DF df;
|
||||
|
||||
using V = decltype(Zero(df));
|
||||
V t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, tA, tB;
|
||||
V t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, tA, tB; // NOLINT
|
||||
V* sads[12] = {&t0, &t1, &t2, &t3, &t4, &t5, &t6, &t7, &t8, &t9, &tA, &tB};
|
||||
|
||||
xextra = RoundUpTo(xextra, Lanes(df));
|
||||
|
@ -114,7 +114,7 @@ class EPF0Stage : public RenderPipelineStage {
|
|||
const auto sm = Load(df, sad_mul + ix);
|
||||
const auto inv_sigma = Mul(Set(df, row_sigma[bx]), sm);
|
||||
|
||||
for (size_t i = 0; i < 12; i++) *sads[i] = Zero(df);
|
||||
for (auto& sad : sads) *sad = Zero(df);
|
||||
constexpr std::array<int, 2> sads_off[12] = {
|
||||
{{-2, 0}}, {{-1, -1}}, {{-1, 0}}, {{-1, 1}}, {{0, -2}}, {{0, -1}},
|
||||
{{0, 1}}, {{0, 2}}, {{1, -1}}, {{1, 0}}, {{1, 1}}, {{2, 0}},
|
||||
|
@ -128,12 +128,10 @@ class EPF0Stage : public RenderPipelineStage {
|
|||
auto sad = Zero(df);
|
||||
constexpr std::array<int, 2> plus_off[] = {
|
||||
{{0, 0}}, {{-1, 0}}, {{0, -1}}, {{1, 0}}, {{0, 1}}};
|
||||
for (size_t j = 0; j < 5; j++) {
|
||||
const auto r11 =
|
||||
LoadU(df, rows[c][3 + plus_off[j][0]] + x + plus_off[j][1]);
|
||||
const auto c11 =
|
||||
LoadU(df, rows[c][3 + sads_off[i][0] + plus_off[j][0]] + x +
|
||||
sads_off[i][1] + plus_off[j][1]);
|
||||
for (const auto& off : plus_off) {
|
||||
const auto r11 = LoadU(df, rows[c][3 + off[0]] + x + off[1]);
|
||||
const auto c11 = LoadU(df, rows[c][3 + sads_off[i][0] + off[0]] +
|
||||
x + sads_off[i][1] + off[1]);
|
||||
sad = Add(sad, AbsDiff(r11, c11));
|
||||
}
|
||||
*sads[i] = MulAdd(sad, scale, *sads[i]);
|
||||
|
@ -181,10 +179,10 @@ class EPF0Stage : public RenderPipelineStage {
|
|||
// makes this filter a 5x5 filter.
|
||||
class EPF1Stage : public RenderPipelineStage {
|
||||
public:
|
||||
EPF1Stage(const LoopFilter& lf, const ImageF& sigma)
|
||||
EPF1Stage(LoopFilter lf, const ImageF& sigma)
|
||||
: RenderPipelineStage(RenderPipelineStage::Settings::Symmetric(
|
||||
/*shift=*/0, /*border=*/2)),
|
||||
lf_(lf),
|
||||
lf_(std::move(lf)),
|
||||
sigma_(&sigma) {}
|
||||
|
||||
template <bool aligned>
|
||||
|
@ -362,10 +360,10 @@ class EPF1Stage : public RenderPipelineStage {
|
|||
// filter.
|
||||
class EPF2Stage : public RenderPipelineStage {
|
||||
public:
|
||||
EPF2Stage(const LoopFilter& lf, const ImageF& sigma)
|
||||
EPF2Stage(LoopFilter lf, const ImageF& sigma)
|
||||
: RenderPipelineStage(RenderPipelineStage::Settings::Symmetric(
|
||||
/*shift=*/0, /*border=*/1)),
|
||||
lf_(lf),
|
||||
lf_(std::move(lf)),
|
||||
sigma_(&sigma) {}
|
||||
|
||||
template <bool aligned>
|
||||
|
|
|
@ -110,7 +110,7 @@ class UpsamplingStage : public RenderPipelineStage {
|
|||
ssize_t x0, ssize_t x1) const {
|
||||
static HWY_FULL(float) df;
|
||||
using V = hwy::HWY_NAMESPACE::Vec<HWY_FULL(float)>;
|
||||
V ups0, ups1, ups2, ups3, ups4, ups5, ups6, ups7;
|
||||
V ups0, ups1, ups2, ups3, ups4, ups5, ups6, ups7; // NOLINT
|
||||
(void)ups2, (void)ups3, (void)ups4, (void)ups5, (void)ups6, (void)ups7;
|
||||
// Once we have C++17 available, change this back to `V* ups[N]` and
|
||||
// initialize using `if constexpr` below.
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "lib/jxl/base/common.h"
|
||||
#include "lib/jxl/base/status.h"
|
||||
#include "lib/jxl/dec_cache.h"
|
||||
#include "lib/jxl/dec_xyb.h"
|
||||
#include "lib/jxl/image.h"
|
||||
#include "lib/jxl/image_bundle.h"
|
||||
#include "lib/jxl/sanitizers.h"
|
||||
|
@ -556,11 +557,11 @@ HWY_EXPORT(GetWriteToOutputStage);
|
|||
namespace {
|
||||
class WriteToImageBundleStage : public RenderPipelineStage {
|
||||
public:
|
||||
explicit WriteToImageBundleStage(ImageBundle* image_bundle,
|
||||
ColorEncoding color_encoding)
|
||||
explicit WriteToImageBundleStage(
|
||||
ImageBundle* image_bundle, const OutputEncodingInfo& output_encoding_info)
|
||||
: RenderPipelineStage(RenderPipelineStage::Settings()),
|
||||
image_bundle_(image_bundle),
|
||||
color_encoding_(std::move(color_encoding)) {}
|
||||
color_encoding_(output_encoding_info.color_encoding) {}
|
||||
|
||||
Status SetInputSizes(
|
||||
const std::vector<std::pair<size_t, size_t>>& input_sizes) override {
|
||||
|
@ -658,9 +659,9 @@ class WriteToImage3FStage : public RenderPipelineStage {
|
|||
} // namespace
|
||||
|
||||
std::unique_ptr<RenderPipelineStage> GetWriteToImageBundleStage(
|
||||
ImageBundle* image_bundle, ColorEncoding color_encoding) {
|
||||
ImageBundle* image_bundle, const OutputEncodingInfo& output_encoding_info) {
|
||||
return jxl::make_unique<WriteToImageBundleStage>(image_bundle,
|
||||
std::move(color_encoding));
|
||||
output_encoding_info);
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPipelineStage> GetWriteToImage3FStage(Image3F* image) {
|
||||
|
|
|
@ -9,13 +9,14 @@
|
|||
#include <functional>
|
||||
|
||||
#include "lib/jxl/dec_cache.h"
|
||||
#include "lib/jxl/dec_xyb.h"
|
||||
#include "lib/jxl/image_bundle.h"
|
||||
#include "lib/jxl/render_pipeline/render_pipeline_stage.h"
|
||||
|
||||
namespace jxl {
|
||||
|
||||
std::unique_ptr<RenderPipelineStage> GetWriteToImageBundleStage(
|
||||
ImageBundle* image_bundle, ColorEncoding color_encoding);
|
||||
ImageBundle* image_bundle, const OutputEncodingInfo& output_encoding_info);
|
||||
|
||||
// Gets a stage to write color channels to an Image3F.
|
||||
std::unique_ptr<RenderPipelineStage> GetWriteToImage3FStage(Image3F* image);
|
||||
|
|
|
@ -941,7 +941,7 @@ TEST(RoundtripTest, TestICCProfile) {
|
|||
JxlDecoderDestroy(dec);
|
||||
}
|
||||
|
||||
TEST(RoundtripTest, JXL_TRANSCODE_JPEG_TEST(TestJPEGReconstruction)) {
|
||||
JXL_TRANSCODE_JPEG_TEST(RoundtripTest, TestJPEGReconstruction) {
|
||||
TEST_LIBJPEG_SUPPORT();
|
||||
const std::string jpeg_path = "jxl/flower/flower.png.im_q85_420.jpg";
|
||||
const std::vector<uint8_t> orig = jxl::test::ReadTestData(jpeg_path);
|
||||
|
|
|
@ -82,7 +82,6 @@ JXL_GTEST_INSTANTIATE_TEST_SUITE_P(
|
|||
|
||||
TEST_P(SpeedTierTest, Roundtrip) {
|
||||
const SpeedTierTestParams& params = GetParam();
|
||||
test::ThreadPoolForTests pool(8);
|
||||
const std::vector<uint8_t> orig = jxl::test::ReadTestData(
|
||||
"external/wesaturate/500px/u76c0g_bliznaca_srgb8.png");
|
||||
test::TestImage t;
|
||||
|
|
|
@ -94,11 +94,11 @@ void DrawSegment(DF df, const SplineSegment& segment, const bool add,
|
|||
|
||||
void DrawSegment(const SplineSegment& segment, const bool add, const size_t y,
|
||||
const ssize_t x0, ssize_t x1, float* JXL_RESTRICT rows[3]) {
|
||||
ssize_t x =
|
||||
std::max<ssize_t>(x0, segment.center_x - segment.maximum_distance + 0.5f);
|
||||
ssize_t x = std::max<ssize_t>(
|
||||
x0, std::llround(segment.center_x - segment.maximum_distance));
|
||||
// one-past-the-end
|
||||
x1 =
|
||||
std::min<ssize_t>(x1, segment.center_x + segment.maximum_distance + 1.5f);
|
||||
x1 = std::min<ssize_t>(
|
||||
x1, std::llround(segment.center_x + segment.maximum_distance) + 1);
|
||||
HWY_FULL(float) df;
|
||||
for (; x + static_cast<ssize_t>(Lanes(df)) <= x1; x += Lanes(df)) {
|
||||
DrawSegment(df, segment, add, y, x, rows);
|
||||
|
@ -550,8 +550,8 @@ Status QuantizedSpline::Decode(const std::vector<uint8_t>& context_map,
|
|||
}
|
||||
return true;
|
||||
};
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
JXL_RETURN_IF_ERROR(decode_dct(color_dct_[c]));
|
||||
for (auto& dct : color_dct_) {
|
||||
JXL_RETURN_IF_ERROR(decode_dct(dct));
|
||||
}
|
||||
JXL_RETURN_IF_ERROR(decode_dct(sigma_dct_));
|
||||
return true;
|
||||
|
|
|
@ -288,8 +288,7 @@ TestImage& TestImage::SetAllBitDepths(uint32_t bits_per_sample,
|
|||
ppf_.info.alpha_bits = bits_per_sample;
|
||||
ppf_.info.alpha_exponent_bits = exponent_bits_per_sample;
|
||||
}
|
||||
for (size_t i = 0; i < ppf_.extra_channels_info.size(); ++i) {
|
||||
extras::PackedExtraChannel& ec = ppf_.extra_channels_info[i];
|
||||
for (auto& ec : ppf_.extra_channels_info) {
|
||||
ec.ec_info.bits_per_sample = bits_per_sample;
|
||||
ec.ec_info.exponent_bits_per_sample = exponent_bits_per_sample;
|
||||
}
|
||||
|
|
|
@ -180,8 +180,7 @@ class ThreadPoolForTests {
|
|||
}
|
||||
ThreadPoolForTests(const ThreadPoolForTests&) = delete;
|
||||
ThreadPoolForTests& operator&(const ThreadPoolForTests&) = delete;
|
||||
// TODO(eustas): avoid unary `&` overload?
|
||||
ThreadPool* operator&() { return pool_.get(); }
|
||||
ThreadPool* get() { return pool_.get(); }
|
||||
|
||||
private:
|
||||
JxlThreadParallelRunnerPtr runner_;
|
||||
|
|
|
@ -13,33 +13,37 @@
|
|||
#include "lib/jxl/common.h"
|
||||
|
||||
#ifdef JXL_DISABLE_SLOW_TESTS
|
||||
#define JXL_SLOW_TEST(X) DISABLED_##X
|
||||
#define JXL_SLOW_TEST(T, C) TEST(T, DISABLED_##C)
|
||||
#else
|
||||
#define JXL_SLOW_TEST(X) X
|
||||
#define JXL_SLOW_TEST(T, C) TEST(T, C)
|
||||
#endif // JXL_DISABLE_SLOW_TESTS
|
||||
|
||||
#if JPEGXL_ENABLE_TRANSCODE_JPEG
|
||||
#define JXL_TRANSCODE_JPEG_TEST(X) X
|
||||
#define JXL_TRANSCODE_JPEG_TEST(T, C) TEST(T, C)
|
||||
#else
|
||||
#define JXL_TRANSCODE_JPEG_TEST(X) DISABLED_##X
|
||||
#define JXL_TRANSCODE_JPEG_TEST(T, C) TEST(T, DISABLED_##C)
|
||||
#endif // JPEGXL_ENABLE_TRANSCODE_JPEG
|
||||
|
||||
#if JPEGXL_ENABLE_BOXES
|
||||
#define JXL_BOXES_TEST(X) X
|
||||
#define JXL_BOXES_TEST(T, C) TEST(T, C)
|
||||
#define JXL_BOXES_TEST_P(T, C) TEST_P(T, C)
|
||||
#else
|
||||
#define JXL_BOXES_TEST(X) DISABLED_##X
|
||||
#define JXL_BOXES_TEST(T, C) TEST(T, DISABLED_##C)
|
||||
#define JXL_BOXES_TEST_P(T, C) TEST_P(T, DISABLED_##C)
|
||||
#endif // JPEGXL_ENABLE_BOXES
|
||||
|
||||
#ifdef THREAD_SANITIZER
|
||||
#define JXL_TSAN_SLOW_TEST(X) DISABLED_##X
|
||||
#define JXL_TSAN_SLOW_TEST(T, C) TEST(T, DISABLED_##C)
|
||||
#else
|
||||
#define JXL_TSAN_SLOW_TEST(X) X
|
||||
#define JXL_TSAN_SLOW_TEST(T, C) TEST(T, C)
|
||||
#endif // THREAD_SANITIZER
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define JXL_X86_64_TEST(X) X
|
||||
#define JXL_X86_64_TEST(T, C) TEST(T, C)
|
||||
#define JXL_X86_64_TEST_P(T, C) TEST_P(T, C)
|
||||
#else
|
||||
#define JXL_X86_64_TEST(X) DISABLED_##X
|
||||
#define JXL_X86_64_TEST(T, C) TEST(T, DISABLED_##C)
|
||||
#define JXL_X86_64_TEST_P(T, C) TEST_P(T, C)
|
||||
#endif // defined(__x86_64__)
|
||||
|
||||
// googletest before 1.10 didn't define INSTANTIATE_TEST_SUITE_P() but instead
|
||||
|
|
|
@ -46,7 +46,9 @@ namespace {
|
|||
#define RUN_BENCHMARK_SCALAR(F, I) \
|
||||
constexpr size_t kNum = 1 << 12; \
|
||||
/* Three parallel runs, as this will run on R, G and B. */ \
|
||||
float sum1 = 0, sum2 = 0, sum3 = 0; \
|
||||
float sum1 = 0; \
|
||||
float sum2 = 0; \
|
||||
float sum3 = 0; \
|
||||
for (auto _ : state) { \
|
||||
float x = 1e-5; \
|
||||
float v1 = 1e-5; \
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#define JPEGXL_COMPUTE_NUMERIC_VERSION(major,minor,patch) (((major)<<24) | ((minor)<<16) | ((patch)<<8) | 0)
|
||||
|
||||
/* Numeric representation of the version */
|
||||
#define JPEGXL_NUMERIC_VERSION JPEGXL_COMPUTE_NUMERIC_VERSION(JPEGXL_MAJOR_VERSION,JPEGXL_MINOR_VERSION,JPEGXL_PATCH_VERSION)
|
||||
#define JPEGXL_NUMERIC_VERSION JPEGXL_COMPUTE_NUMERIC_VERSION(JPEGXL_MAJOR_VERSION, JPEGXL_MINOR_VERSION, JPEGXL_PATCH_VERSION)
|
||||
|
||||
#endif /* JXL_VERSION_H_ */
|
||||
|
||||
|
|
|
@ -294,7 +294,7 @@ void TestFloat() {
|
|||
const uint32_t kMaxSeed = 4096;
|
||||
#endif // JXL_DISABLE_SLOW_TESTS
|
||||
EXPECT_TRUE(RunOnPool(
|
||||
&pool, 0, kMaxSeed, ThreadPool::NoInit,
|
||||
pool.get(), 0, kMaxSeed, ThreadPool::NoInit,
|
||||
[](const uint32_t seed, size_t /*thread*/) {
|
||||
HWY_ALIGN Xorshift128Plus rng(seed);
|
||||
|
||||
|
@ -340,7 +340,7 @@ void TestNotZero() {
|
|||
const uint32_t kMaxSeed = 2000;
|
||||
#endif // JXL_DISABLE_SLOW_TESTS
|
||||
EXPECT_TRUE(RunOnPool(
|
||||
&pool, 0, kMaxSeed, ThreadPool::NoInit,
|
||||
pool.get(), 0, kMaxSeed, ThreadPool::NoInit,
|
||||
[](const uint32_t task, size_t /*thread*/) {
|
||||
HWY_ALIGN uint64_t lanes[Xorshift128Plus::N];
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче