Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## v0.6.7

- Support images of dimensions below 8 pixels despite some distortion metrics.

## v0.6.6

- Fix path to libaom binary object for libheif in deps.sh.
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ cmake_minimum_required(VERSION 3.20)
project(
codec-compare-gen
LANGUAGES CXX
VERSION 0.6.6)
VERSION 0.6.7)
set(CMAKE_CXX_STANDARD 17)

option(BUILD_SHARED_LIBS "Build the shared codec-compare-gen library" ON)
Expand Down
11 changes: 10 additions & 1 deletion src/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ struct StatusOr {
};

// Can be used as follows:
// OK_OR_RETURN(FuncThatReturnsStatusOrType());
// OK_OR_RETURN(FuncThatReturnsStatus());
#define OK_OR_RETURN(STATUS) \
do { \
const Status checked_status = (STATUS); \
Expand Down Expand Up @@ -140,6 +140,15 @@ struct LogError {
if (!(CONDITION)) \
return LogError(QUIET) << "(" << (__FILE__) << ":" << (__LINE__) << ") "

// Can be used as follows:
// OK_WP2_OR_RETURN(FuncThatReturnsWP2Status(), quiet);
#if defined(HAS_WEBP2)
#define OK_WP2_OR_RETURN(STATUS, QUIET) \
const WP2Status CONCAT(checked_status, __LINE__) = (STATUS); \
CHECK_OR_RETURN(CONCAT(checked_status, __LINE__) == WP2_STATUS_OK, QUIET) \
<< WP2GetStatusMessage(CONCAT(checked_status, __LINE__)) << " "
#endif // HAS_WEBP2

//------------------------------------------------------------------------------

} // namespace codec_compare_gen
Expand Down
2 changes: 1 addition & 1 deletion src/codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ std::string CodecExtension(Codec codec) {
case Codec::kAvifAvm:
return "avmf";
case Codec::kAvifLibheif:
return "avif";
return "libheif.avif";
case Codec::kCombination:
return "comb";
case Codec::kJpegturbo:
Expand Down
67 changes: 49 additions & 18 deletions src/distortion.cc
Original file line number Diff line number Diff line change
Expand Up @@ -141,23 +141,38 @@ Status SaveImage(const WP2::ArgbBuffer& image, const std::string& file_path,
image.format() != WP2_Argb_32 && image.format() != WP2_ARGB_32) {
WP2::ArgbBuffer image4(WP2IsPremultiplied(image.format()) ? WP2_Argb_32
: WP2_ARGB_32);
CHECK_OR_RETURN(image4.ConvertFrom(image) == WP2_STATUS_OK, quiet);
OK_WP2_OR_RETURN(image4.ConvertFrom(image), quiet);
return ::codec_compare_gen::SaveImage(image4, file_path, quiet);
}
OK_WP2_OR_RETURN(status, quiet) << "SaveImage(" << file_path << ") failed";
return Status::kOk;
}

CHECK_OR_RETURN(status == WP2_STATUS_OK, quiet)
<< "SaveImage(" << file_path
<< ") failed: " << WP2GetStatusMessage(status);
Status ScaleTill8x8(const WP2::ArgbBuffer& from, WP2::ArgbBuffer& to,
bool quiet) {
OK_WP2_OR_RETURN(to.SetFormat(from.format()), quiet);
OK_WP2_OR_RETURN(
to.Resize(std::max(from.width(), 8u), std::max(from.height(), 8u)),
quiet);
for (uint8_t to_y = 0; to_y < to.height(); ++to_y) {
const uint32_t from_y = to_y * (from.height() - 1) / (to.height() - 1);
for (uint8_t to_x = 0; to_x < to.width(); ++to_x) {
const uint32_t from_x = to_x * (from.width() - 1) / (to.width() - 1);
if (WP2Formatbpc(to.format()) == 8) {
to.GetRow8(to_y)[to_x] = from.GetRow8(from_y)[from_x];
} else {
to.GetRow16(to_y)[to_x] = from.GetRow16(from_y)[from_x];
}
}
}
return Status::kOk;
}

StatusOr<std::string> GetBinaryDistortion(const std::string& reference_path,
const WP2::ArgbBuffer& reference,
const std::string& image_path,
const WP2::ArgbBuffer& image,
const TaskInput& task,
const std::string& metric_binary_path,
size_t thread_id, bool quiet) {
StatusOr<std::string> GetBinaryDistortion(
const std::string& reference_path, const WP2::ArgbBuffer& reference,
const std::string& image_path, const WP2::ArgbBuffer& image,
const TaskInput& task, const std::string& metric_binary_path,
bool metric_supports_tiny_dimensions, size_t thread_id, bool quiet) {
CHECK_OR_RETURN(!reference_path.empty(), quiet);
CHECK_OR_RETURN(!metric_binary_path.empty(), quiet);
const bool maybeAnimated = !EndsWith(reference_path, ".png");
Expand All @@ -175,24 +190,33 @@ StatusOr<std::string> GetBinaryDistortion(const std::string& reference_path,
path_prefix += std::to_string(thread_id);
}

WP2::ArgbBuffer final_reference(reference.format());
WP2::ArgbBuffer final_image(image.format());
if (metric_supports_tiny_dimensions) {
OK_WP2_OR_RETURN(final_reference.SetView(reference), quiet);
OK_WP2_OR_RETURN(final_image.SetView(image), quiet);
} else {
OK_OR_RETURN(ScaleTill8x8(reference, final_reference, quiet));
OK_OR_RETURN(ScaleTill8x8(image, final_image, quiet));
}

// Create a PNG file containing the original pixels of the current frame if
// not PNG (could be a GIF with multiple frames for example).
std::string temp_reference_path;
std::string_view final_reference_path = reference_path;
if (maybeAnimated) {
// Thread-safe file name.
if (!metric_supports_tiny_dimensions || maybeAnimated) {
temp_reference_path = path_prefix + "_reference.png";
OK_OR_RETURN(SaveImage(reference, temp_reference_path, quiet));
OK_OR_RETURN(SaveImage(final_reference, temp_reference_path, quiet));
final_reference_path = temp_reference_path;
}
const FileDeleter temp_reference_path_deleter(temp_reference_path);

// Create a PNG file containing the decoded pixels if not done or if animated.
std::string temp_image_path;
std::string_view final_image_path = image_path;
if (image_path.empty() || maybeAnimated) {
if (!metric_supports_tiny_dimensions || image_path.empty() || maybeAnimated) {
temp_image_path = path_prefix + "_image.png";
OK_OR_RETURN(SaveImage(image, temp_image_path, quiet));
OK_OR_RETURN(SaveImage(final_image, temp_image_path, quiet));
final_image_path = temp_image_path;
}
const FileDeleter temp_image_path_deleter(temp_image_path);
Expand All @@ -212,22 +236,27 @@ StatusOr<float> GetLibjxlDistortion(
if (metric_binary_folder_path.empty()) return -1;

const char* metric_binary_name;
bool metric_supports_tiny_dimensions;
if (metric == DistortionMetric::kLibjxlButteraugli ||
metric == DistortionMetric::kLibjxlP3norm) {
metric_binary_name = "butteraugli_main";
metric_supports_tiny_dimensions = true;
} else if (metric == DistortionMetric::kLibjxlSsimulacra) {
metric_binary_name = "ssimulacra_main";
metric_supports_tiny_dimensions = false;
} else {
CHECK_OR_RETURN(metric == DistortionMetric::kLibjxlSsimulacra2, quiet);
metric_binary_name = "ssimulacra2";
metric_supports_tiny_dimensions = false;
}
const std::string metric_binary_path =
std::filesystem::path(metric_binary_folder_path) / "libjxl" / "build" /
"tools" / metric_binary_name;
ASSIGN_OR_RETURN(
std::string standard_output,
GetBinaryDistortion(reference_path, reference, image_path, image, task,
metric_binary_path, thread_id, quiet));
metric_binary_path, metric_supports_tiny_dimensions,
thread_id, quiet));

if (metric == DistortionMetric::kLibjxlButteraugli ||
metric == DistortionMetric::kLibjxlP3norm) {
Expand Down Expand Up @@ -257,10 +286,12 @@ StatusOr<float> GetDssimDistortion(const std::string& reference_path,
const std::string metric_binary_path =
std::filesystem::path(metric_binary_folder_path) / "dssim" / "target" /
"release" / "dssim";
const bool metric_supports_tiny_dimensions = true;
ASSIGN_OR_RETURN(
const std::string standard_output,
GetBinaryDistortion(reference_path, reference, image_path, image, task,
metric_binary_path, thread_id, quiet));
metric_binary_path, metric_supports_tiny_dimensions,
thread_id, quiet));
return std::stof(Trim(Split(standard_output, '\t').front()));
}

Expand Down
2 changes: 1 addition & 1 deletion src/result_json.cc
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ Status TasksToJson(const std::string& batch_pretty_name, CodecSettings settings,
/*prefix=*/encoded_common_parent.parent_path(), encoded_common_parent));

const std::string build_cmd =
"git clone -b v0.6.6 --depth 1"
"git clone -b v0.6.7 --depth 1"
" https://github.com/webmproject/codec-compare-gen.git"
" && cd codec-compare-gen && ./deps.sh"
" && cmake -S . -B build -DCMAKE_CXX_COMPILER=clang++"
Expand Down