diff --git a/.gitignore b/.gitignore index cb4acb8f8..72adb7c5c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,12 +9,6 @@ # The downloaded corpora files for benchmark. /third_party/corpora -# hdrvdp source code -third_party/hdrvdp-2.2.2 -third_party/hdrvdp-2.2.2.zip -third_party/hdrvdp-2.2.2.zip.tmp - # Output plots tools/benchmark/metrics/plots tools/benchmark/metrics/results.csv -tools/conformance/__pycache__ diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 5b0858968..b815d8077 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -12,7 +12,6 @@ set(FUZZER_CORPUS_BINARIES) add_library(jxl_tool STATIC EXCLUDE_FROM_ALL cmdline.cc - codec_config.cc speed_stats.cc tool_version.cc ${JXL_CMS_OBJECTS} diff --git a/tools/benchmark/benchmark_xl.cc b/tools/benchmark/benchmark_xl.cc index 5960ffc63..99dca68a2 100644 --- a/tools/benchmark/benchmark_xl.cc +++ b/tools/benchmark/benchmark_xl.cc @@ -44,7 +44,6 @@ #include "tools/benchmark/benchmark_file_io.h" #include "tools/benchmark/benchmark_stats.h" #include "tools/benchmark/benchmark_utils.h" -#include "tools/codec_config.h" #include "tools/file_io.h" #include "tools/speed_stats.h" #include "tools/ssimulacra2.h" diff --git a/tools/benchmark/hm/README.md b/tools/benchmark/hm/README.md deleted file mode 100644 index e54904eff..000000000 --- a/tools/benchmark/hm/README.md +++ /dev/null @@ -1,12 +0,0 @@ -This directory contains encoding and decoding scripts for HEVC, for use with -the benchmark custom codec. They use the HEVC reference encoder at https://hevc.hhi.fraunhofer.de/svn/svn_HEVCSoftware/ -and require the `TAppEncoderHighBitDepthStatic` and -`TAppDecoderHighBitDepthStatic` binaries to be placed in this directory. - -Example usage, for encoding at QP = 30: - -``` -tools/benchmark_xl --input=image.png --codec='custom:bin:.../tools/benchmark/hm/encode.sh:.../tools/benchmark/hm/decode.sh:-q:30' -``` - -The paths to the encode and decode scripts should be adjusted as necessary. diff --git a/tools/benchmark/hm/decode.sh b/tools/benchmark/hm/decode.sh deleted file mode 100755 index 582faab77..000000000 --- a/tools/benchmark/hm/decode.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -set -euo pipefail - -decoder="$(dirname "$0")"/TAppDecoderHighBitDepthStatic - -usage() { - echo "$0 [-v] " >&2 - exit 1 -} - -verbose=0 - -while getopts ':hv' arg; do - case "$arg" in - h) - usage - ;; - - v) - verbose=1 - ;; - - \?) - echo "Unrecognized option -$OPTARG" >&2 - exit 1 - ;; - esac -done -shift $((OPTIND-1)) - -if [ $# -lt 2 ]; then - usage -fi - -run() { - if [ "$verbose" -eq 1 ]; then - "$@" - else - "$@" > /dev/null 2>&1 - fi -} - -input="$1" -output="$2" - -bin="$(mktemp)" -yuv="$(mktemp)" -width_file="$(mktemp)" -height_file="$(mktemp)" -icc_file="$(mktemp --suffix=.icc)" - -cleanup() { - rm -- "$bin" "$yuv" "$width_file" "$height_file" "$icc_file" -} -trap cleanup EXIT - -unpack_program="$(cat <<'END' - use File::Copy; - my ($input, $bin, $width_file, $height_file, $icc_file) = @ARGV; - open my $input_fh, '<:raw', $input; - sysread($input_fh, my $size, 8) == 8 or die; - my ($width, $height) = unpack 'NN', $size; - open my $width_fh, '>', $width_file; - print {$width_fh} "$width\n"; - open my $height_fh, '>', $height_file; - print {$height_fh} "$height\n"; - sysread($input_fh, my $icc_size, 4) == 4 or die; - $icc_size = unpack 'N', $icc_size; - sysread($input_fh, my $icc_data, $icc_size) == $icc_size or die; - open my $icc_fh, '>', $icc_file; - print {$icc_fh} $icc_data; - copy $input_fh, $bin; -END -)" -run perl -Mstrict -Mwarnings -Mautodie -e "$unpack_program" -- "$input" "$bin" "$width_file" "$height_file" "$icc_file" - -width="$(cat "$width_file")" -height="$(cat "$height_file")" - -start="$EPOCHREALTIME" -run "$decoder" --OutputBitDepth=10 -b "$bin" -o "$yuv" -end="$EPOCHREALTIME" - -elapsed="$(echo "$end - $start" | bc)" -run echo "Completed in $elapsed seconds" - -echo "$elapsed" > "${output%.png}".time - -run ffmpeg -hide_banner -f rawvideo -vcodec rawvideo -s "${width}x$height" -r 25 -pix_fmt yuv444p10le -i "$yuv" -pix_fmt rgb24 -vf scale=in_color_matrix=bt709 -y "$output" -if [ -s "$icc_file" ]; then - mogrify -profile "$icc_file" "$output" -fi diff --git a/tools/benchmark/hm/encode.sh b/tools/benchmark/hm/encode.sh deleted file mode 100755 index 210d83eeb..000000000 --- a/tools/benchmark/hm/encode.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -set -euo pipefail - -encoder="$(dirname "$0")"/TAppEncoderHighBitDepthStatic -cfg_dir="$(dirname "$0")"/../../../third_party/HEVCSoftware/cfg - -usage() { - echo "$0 [-v] [-q ] " >&2 - exit 1 -} - -q=27 -verbose=0 - -while getopts ':hq:v' arg; do - case "$arg" in - h) - usage - ;; - - q) - q="$OPTARG" - ;; - - v) - verbose=1 - ;; - - \?) - echo "Unrecognized option -$OPTARG" >&2 - exit 1 - ;; - esac -done -shift $((OPTIND-1)) - -if [ $# -lt 2 ]; then - usage -fi - -run() { - if [ "$verbose" -eq 1 ]; then - "$@" - else - "$@" > /dev/null 2>&1 - fi -} - -input="$1" -output="$2" - -yuv="$(mktemp)" -bin="$(mktemp)" - -to_clean=("$yuv" "$bin") -cleanup() { - rm -- "${to_clean[@]}" -} -trap cleanup EXIT - -run ffmpeg -hide_banner -i "$input" -pix_fmt yuv444p10le -vf scale=out_color_matrix=bt709 -color_primaries bt709 -color_trc bt709 -colorspace bt709 -f rawvideo -y "$yuv" - -width="$(identify -format '%w' "$input")" -height="$(identify -format '%h' "$input")" - -start="$EPOCHREALTIME" -run "$encoder" -c "$cfg_dir"/encoder_intra_main_scc_10.cfg -f 1 -fr 1 -wdt "$width" -hgt "$height" --InputChromaFormat=444 --InputBitDepth=10 --ConformanceWindowMode=1 -i "$yuv" -b "$bin" -q "$q" -end="$EPOCHREALTIME" - -elapsed="$(echo "$end - $start" | bc)" -run echo "Completed in $elapsed seconds" - -echo "$elapsed" > "${output%.bin}".time - -icc="${output%.*}.icc" -if run convert "$input" "$icc"; then - to_clean+=("$icc") -fi - -pack_program="$(cat <<'END' - use File::Copy; - use IO::Handle; - my ($width, $height, $bin, $icc, $output) = @ARGV; - open my $output_fh, '>:raw', $output; - syswrite $output_fh, pack 'NN', $width, $height; - syswrite $output_fh, pack 'N', -s $icc; - copy $icc, $output_fh; - copy $bin, $output_fh; -END -)" -run perl -Mstrict -Mwarnings -Mautodie -e "$pack_program" -- "$width" "$height" "$bin" "$icc" "$output" diff --git a/tools/benchmark/metrics/compute-hdrvdp.m b/tools/benchmark/metrics/compute-hdrvdp.m deleted file mode 100644 index 56d17440c..000000000 --- a/tools/benchmark/metrics/compute-hdrvdp.m +++ /dev/null @@ -1,18 +0,0 @@ -% Copyright (c) the JPEG XL Project Authors. -% -% Use of this source code is governed by a BSD-style -% license that can be found in the LICENSE file or at -% https://developers.google.com/open-source/licenses/bsd - -pkg load image; - -args = argv(); - -original_filename = args{1}; -decoded_filename = args{2}; - -original = pfs_read_luminance(original_filename); -decoded = pfs_read_luminance(decoded_filename); - -res = hdrvdp(decoded, original, 'luminance', 30, {}); -printf("%f\n", res.Q); diff --git a/tools/benchmark/metrics/compute-pumetrics.m b/tools/benchmark/metrics/compute-pumetrics.m deleted file mode 100644 index d5bc258d6..000000000 --- a/tools/benchmark/metrics/compute-pumetrics.m +++ /dev/null @@ -1,27 +0,0 @@ -% Copyright (c) the JPEG XL Project Authors. -% -% Use of this source code is governed by a BSD-style -% license that can be found in the LICENSE file or at -% https://developers.google.com/open-source/licenses/bsd - -pkg load image; - -args = argv(); - -metric = args{1}; -original_filename = args{2}; -decoded_filename = args{3}; - -original = pfs_read_luminance(original_filename); -decoded = pfs_read_luminance(decoded_filename); - -switch (metric) - case "psnr" - res = qm_pu2_psnr(original, decoded); - case "ssim" - res = qm_pu2_ssim(original, decoded); - otherwise - error(sprintf("unrecognized metric %s", metric)); -end - -printf("%f\n", res); diff --git a/tools/benchmark/metrics/compute_octave_metric.sh b/tools/benchmark/metrics/compute_octave_metric.sh deleted file mode 100755 index fc6fa3ae3..000000000 --- a/tools/benchmark/metrics/compute_octave_metric.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -# Usage: ./compute-octave-metric.sh [octave args...] -# Where octave args do not need to contain -qf or the path to the original and decoded images. - -set -euo pipefail - -original="$1" -decoded="$2" -output="$3" -intensity_target="$4" -shift 4 - -tmpdir="$(mktemp --directory)" - -linearized_original="$(mktemp --tmpdir="$tmpdir" --suffix='.pfm')" -linearized_decoded="$(mktemp --tmpdir="$tmpdir" --suffix='.pfm')" - -cleanup() { - rm -- "$linearized_original" "$linearized_decoded" - rmdir --ignore-fail-on-non-empty -- "$tmpdir" -} -trap cleanup EXIT - -linearize() { - local input="$1" - local output="$2" - convert "$input" -set colorspace sRGB -colorspace RGB -evaluate multiply "$intensity_target" "$output" -} - -linearize "$original" "$linearized_original" -linearize "$decoded" "$linearized_decoded" - -octave -qf "$@" \ - "$linearized_original" "$linearized_decoded" \ - 2> /dev/null \ - > "$output" diff --git a/tools/benchmark/metrics/dists-rgb.sh b/tools/benchmark/metrics/dists-rgb.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/dists-rgb.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/benchmark/metrics/fsim-rgb.sh b/tools/benchmark/metrics/fsim-rgb.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/fsim-rgb.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/benchmark/metrics/fsim-y.sh b/tools/benchmark/metrics/fsim-y.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/fsim-y.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/benchmark/metrics/gmsd-rgb.sh b/tools/benchmark/metrics/gmsd-rgb.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/gmsd-rgb.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/benchmark/metrics/hdr_plots.sh b/tools/benchmark/metrics/hdr_plots.sh deleted file mode 100755 index df47c941f..000000000 --- a/tools/benchmark/metrics/hdr_plots.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -"$(dirname "$0")/run_all_hdr_metrics.sh" "$@" | sed -n '/```/q;p' > hdr_results.csv -mkdir -p hdr_plots/ -rm -rf hdr_plots/* -python3 "$(dirname "$0")/plots.py" hdr_results.csv hdr_plots diff --git a/tools/benchmark/metrics/hdrvdp-fixes.patch b/tools/benchmark/metrics/hdrvdp-fixes.patch deleted file mode 100644 index 23f3f17b6..000000000 --- a/tools/benchmark/metrics/hdrvdp-fixes.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 44a21be2c4de409f80d90cbcc2c20cb3f42e859e Mon Sep 17 00:00:00 2001 -From: Sami Boukortt -Date: Fri, 16 Oct 2020 20:01:02 +0200 -Subject: [PATCH] Fixes for Octave -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Copyright (c) the JPEG XL Project Authors. All rights reserved. - -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file. - ----- - -ifft2: https://savannah.gnu.org/bugs/?43742 - -Removing #include : https://octave.org/doc/v5.2.0/Getting-Started-with-Mex_002dFiles.html -“One important difference between Octave and MATLAB is that the header -"matrix.h" is implicitly included through the inclusion of "mex.h".” - -Length checks: it appears that functions(…).file for MEX files in Octave -is empty. ---- - fast_conv_fft.m | 2 +- - matlabPyrTools_1.4_fixed/MEX/corrDn.c | 1 - - matlabPyrTools_1.4_fixed/MEX/pointOp.c | 1 - - matlabPyrTools_1.4_fixed/MEX/upConv.c | 1 - - matlabPyrTools_1.4_fixed/reconSpyr.m | 2 +- - matlabPyrTools_1.4_fixed/reconSpyrLevs.m | 2 +- - 6 files changed, 3 insertions(+), 6 deletions(-) - -diff --git a/fast_conv_fft.m b/fast_conv_fft.m -index 65ceef8..b89e54b 100644 ---- a/fast_conv_fft.m -+++ b/fast_conv_fft.m -@@ -16,7 +16,7 @@ pad_size = (size(fH)-size(X)); - - fX = fft2( padarray( X, pad_size, pad_value, 'post' ) ); - --Yl = real(ifft2( fX.*fH, size(fX,1), size(fX,2), 'symmetric' )); -+Yl = real(ifft2( fX.*fH, size(fX,1), size(fX,2))); - - Y = Yl(1:size(X,1),1:size(X,2)); - -diff --git a/matlabPyrTools_1.4_fixed/MEX/corrDn.c b/matlabPyrTools_1.4_fixed/MEX/corrDn.c -index d02e272..17e739e 100755 ---- a/matlabPyrTools_1.4_fixed/MEX/corrDn.c -+++ b/matlabPyrTools_1.4_fixed/MEX/corrDn.c -@@ -6,7 +6,6 @@ RES = corrDn(IM, FILT, EDGES, STEP, START, STOP); - */ - - #define V4_COMPAT --#include /* Matlab matrices */ - #include - - #include "convolve.h" -diff --git a/matlabPyrTools_1.4_fixed/MEX/pointOp.c b/matlabPyrTools_1.4_fixed/MEX/pointOp.c -index 3623a02..e553adf 100755 ---- a/matlabPyrTools_1.4_fixed/MEX/pointOp.c -+++ b/matlabPyrTools_1.4_fixed/MEX/pointOp.c -@@ -5,7 +5,6 @@ RES = pointOp(IM, LUT, ORIGIN, INCREMENT, WARNINGS) - */ - - #define V4_COMPAT --#include /* Matlab matrices */ - #include - - #include /* NULL */ -diff --git a/matlabPyrTools_1.4_fixed/MEX/upConv.c b/matlabPyrTools_1.4_fixed/MEX/upConv.c -index 98a2bec..08fdf75 100755 ---- a/matlabPyrTools_1.4_fixed/MEX/upConv.c -+++ b/matlabPyrTools_1.4_fixed/MEX/upConv.c -@@ -6,7 +6,6 @@ RES = upConv(IM, FILT, EDGES, STEP, START, STOP, RES); - */ - - #define V4_COMPAT --#include /* Matlab matrices */ - #include - - #include "convolve.h" -diff --git a/matlabPyrTools_1.4_fixed/reconSpyr.m b/matlabPyrTools_1.4_fixed/reconSpyr.m -index 05eeafb..1440d8a 100644 ---- a/matlabPyrTools_1.4_fixed/reconSpyr.m -+++ b/matlabPyrTools_1.4_fixed/reconSpyr.m -@@ -31,7 +31,7 @@ function res = reconSpyr(pyr, pind, filtfile, edges, levs, bands) - % Deterimine whether a MEX version of upConv is available - is_mex = true; - finfo = functions( @upConv ); --if( strcmp( finfo.file((end-2):end), '.m') ) -+if( length(finfo.file) > 2 && strcmp( finfo.file((end-2):end), '.m') ) - is_mex = false; - end - -diff --git a/matlabPyrTools_1.4_fixed/reconSpyrLevs.m b/matlabPyrTools_1.4_fixed/reconSpyrLevs.m -index ac5e2b1..d3b91d5 100644 ---- a/matlabPyrTools_1.4_fixed/reconSpyrLevs.m -+++ b/matlabPyrTools_1.4_fixed/reconSpyrLevs.m -@@ -11,7 +11,7 @@ function res = reconSpyrLevs(pyr,pind,lofilt,bfilts,edges,levs,bands) - % Deterimine whether MEX version of upConv is available - is_mex = true; - finfo = functions( @upConv ); --if( strcmp( finfo.file((end-2):end), '.m') ) -+if( length(finfo.file) > 2 && strcmp( finfo.file((end-2):end), '.m') ) - is_mex = false; - end - --- -2.28.0 - diff --git a/tools/benchmark/metrics/hdrvdp.sh b/tools/benchmark/metrics/hdrvdp.sh deleted file mode 100755 index e9b6d5bfd..000000000 --- a/tools/benchmark/metrics/hdrvdp.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -"$(dirname "$0")"/compute_octave_metric.sh "$@" \ - --path "$(dirname "$0")"/../../../third_party/hdrvdp-2.2.2/ \ - "$(dirname "$0")"/compute-hdrvdp.m diff --git a/tools/benchmark/metrics/iqa.py b/tools/benchmark/metrics/iqa.py deleted file mode 100644 index 284dd5c21..000000000 --- a/tools/benchmark/metrics/iqa.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -import os -import sys -import pathlib -import torch -from torchvision import transforms -import numpy as np - -path = pathlib.Path(__file__).parent.absolute( -) / '..' / '..' / '..' / 'third_party' / 'IQA-optimization' -sys.path.append(str(path)) - -from IQA_pytorch import SSIM, MS_SSIM, CW_SSIM, GMSD, LPIPSvgg, DISTS, NLPD, FSIM, VSI, VIFs, VIF, MAD - - -# only really works with the output from JXL, but we don't need more than that. -def read_pfm(fname): - with open(fname, 'rb') as f: - header_width_height = [] - while len(header_width_height) < 3: - header_width_height += f.readline().rstrip().split() - header, width, height = header_width_height - assert header == b'PF' or header == b'Pf' - width, height = int(width), int(height) - scale = float(f.readline().rstrip()) - fmt = 'f' - data = np.fromfile(f, fmt) - if header == b'PF': - out = np.reshape(data, (height, width, 3))[::-1, :, :] - else: - out = np.reshape(data, (height, width))[::-1, :] - return out.astype(np.float) - - -D_dict = { - 'cwssim': CW_SSIM, - 'dists': DISTS, - 'fsim': FSIM, - 'gmsd': GMSD, - 'lpips': LPIPSvgg, - 'mad': MAD, - 'msssim': MS_SSIM, - 'nlpd': NLPD, - 'ssim': SSIM, - 'vif': VIF, - 'vsi': VSI, -} - -algo = os.path.basename(sys.argv[1]).split('.')[0] -algo, color = algo.split('-') - -channels = 3 - -if color == 'y': - channels = 1 - - -def Load(path): - device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') - transform = transforms.Compose([ - transforms.ToTensor(), - ]) - img = read_pfm(path) - if len(img.shape) == 3 and channels == 1: # rgb -> Y - assert img.shape[2] == 3 - tmp = np.zeros((img.shape[0], img.shape[1], 1), dtype=float) - tmp[:, :, 0] = (0.2126 * img[:, :, 0] + 0.7152 * img[:, :, 1] + - 0.0722 * img[:, :, 2]) - img = tmp - if len(img.shape) == 2 and channels == 3: # Y -> rgb - gray = img - img = np.zeros((img.shape[0], img.shape[1], 3), dtype=float) - img[:, :, 0] = img[:, :, 1] = img[:, :, 2] = gray - if len(img.shape) == 3: - img = np.transpose(img, axes=(2, 0, 1)).copy() - return torch.FloatTensor(img).unsqueeze(0).to(device) - - -ref_img = Load(sys.argv[2]) -enc_img = Load(sys.argv[3]) -D = D_dict[algo](channels=channels) -score = D(ref_img, enc_img, as_loss=False) - -with open(sys.argv[4], 'w') as f: - print(score.item(), file=f) diff --git a/tools/benchmark/metrics/iqa_wrapper.sh b/tools/benchmark/metrics/iqa_wrapper.sh deleted file mode 100755 index 68662a8aa..000000000 --- a/tools/benchmark/metrics/iqa_wrapper.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -python3 "$(dirname "$0")/iqa.py" "$0" "$@" diff --git a/tools/benchmark/metrics/lpips-rgb.sh b/tools/benchmark/metrics/lpips-rgb.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/lpips-rgb.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/benchmark/metrics/mrse.sh b/tools/benchmark/metrics/mrse.sh deleted file mode 100755 index c493b4661..000000000 --- a/tools/benchmark/metrics/mrse.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -set -euo pipefail - -original="$1" -decoded="$2" -output="$3" -intensity_target="$4" - -tmpdir="$(mktemp --directory)" - -linearized_original="$(mktemp --tmpdir="$tmpdir" --suffix='.pfm')" -linearized_decoded="$(mktemp --tmpdir="$tmpdir" --suffix='.pfm')" - -cleanup() { - rm -- "$linearized_original" "$linearized_decoded" - rmdir --ignore-fail-on-non-empty -- "$tmpdir" -} -trap cleanup EXIT - -linearize() { - local input="$1" - local output="$2" - convert "$input" -set colorspace sRGB -colorspace RGB -evaluate multiply "$intensity_target" "$output" -} - -linearize "$original" "$linearized_original" -linearize "$decoded" "$linearized_decoded" - -"$(dirname "$0")"/../../../third_party/difftest_ng/difftest_ng --mrse "$linearized_original" "$linearized_decoded" \ - | sed -e 's/^MRSE:\s*//' \ - > "$output" diff --git a/tools/benchmark/metrics/msssim-rgb.sh b/tools/benchmark/metrics/msssim-rgb.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/msssim-rgb.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/benchmark/metrics/msssim-y.sh b/tools/benchmark/metrics/msssim-y.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/msssim-y.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/benchmark/metrics/nlpd-y.sh b/tools/benchmark/metrics/nlpd-y.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/nlpd-y.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/benchmark/metrics/plots.py b/tools/benchmark/metrics/plots.py deleted file mode 100755 index b139a0f0e..000000000 --- a/tools/benchmark/metrics/plots.py +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -import csv -import sys -import math -import plotly.graph_objects as go - -_, results, output_dir, *rest = sys.argv -OUTPUT = rest[0] if rest else 'svg' -# valid values: html, svg, png, webp, jpeg, pdf - -with open(results, 'r') as f: - reader = csv.DictReader(f) - all_results = list(reader) - -nonmetric_columns = set([ - "method", "image", "error", "size", "pixels", "enc_speed", "dec_speed", - "bpp", "bppp", "qabpp" -]) - -metrics = set(all_results[0].keys()) - nonmetric_columns - - -def codec(method): - sm = method.split(':') - ssm = set(sm) - speeds = set([ - 'kitten', 'falcon', 'wombat', 'cheetah', 'tortoise', 'squirrel', - 'hare', 'fast' - ]) - s = speeds.intersection(ssm) - if sm[0] == 'custom': - return sm[1] - if sm[0] == 'jxl' and s: - return 'jxl-' + list(s)[0] - return sm[0] - - -data = {(m, img): {c: [] - for c in {codec(x['method']) - for x in all_results}} - for m in metrics for img in {x['image'] - for x in all_results}} - -for r in all_results: - c = codec(r['method']) - img = r['image'] - bpp = r['bpp'] - for m in metrics: - data[(m, img)][c].append((float(bpp), float(r[m]))) - - -def pos(codec): - if 'jxl-dis' in codec: - return 6, codec - elif 'jxl' in codec: - return 7, codec - elif 'avif' in codec: - return 5, codec - elif 'kdu' in codec: - return 4, codec - elif 'heif' in codec: - return 3, codec - elif 'fuif' in codec or 'pik' in codec: - return 2, codec - elif 'jpg' in codec or 'jpeg' in codec or 'web' in codec: - return 1, codec - else: - return 0, codec - - -def style(codec): - configs = { - 'jxl-cheetah': { - 'color': '#e41a1c', - 'dash': '1px, 1px', - 'width': 2 - }, - 'jxl-wombat': { - 'color': '#e41a1c', - 'dash': '2px, 2px', - 'width': 2 - }, - 'jxl-squirrel': { - 'color': '#e41a1c', - 'dash': '5px, 5px', - 'width': 2 - }, - 'jxl-kitten': { - 'color': '#e41a1c', - 'width': 2 - }, - 'jxl-dis-cheetah': { - 'color': '#377eb8', - 'dash': '1px, 1px', - 'width': 2 - }, - 'jxl-dis-wombat': { - 'color': '#377eb8', - 'dash': '2px, 2px', - 'width': 2 - }, - 'jxl-dis-squirrel': { - 'color': '#377eb8', - 'dash': '5px, 5px', - 'width': 2 - }, - 'jxl-dis-kitten': { - 'color': '#377eb8', - 'width': 2 - }, - 'rav1e.avif': { - 'color': '#4daf4a', - 'dash': '3px, 3px', - 'width': 2 - }, - '420.rav1e.avif': { - 'color': '#4daf4a', - 'dash': '1px, 1px', - 'width': 2 - }, - '444.rav1e.avif': { - 'color': '#4daf4a', - 'dash': '3px, 3px', - 'width': 2 - }, - 'psnr.420.aom.avif': { - 'color': '#4daf4a', - 'dash': '5px, 5px', - 'width': 2 - }, - 'psnr.444.aom.avif': { - 'color': '#4daf4a', - 'dash': '7px, 7px', - 'width': 2 - }, - 'ssim.420.aom.avif': { - 'color': '#4daf4a', - 'dash': '9px, 9px', - 'width': 2 - }, - 'ssim.444.aom.avif': { - 'color': '#4daf4a', - 'width': 2 - }, - 'heif': { - 'color': '#984ea3', - 'width': 2 - }, - 'fuif': { - 'color': '#ff7f00', - 'dash': '2px, 2px', - 'width': 2 - }, - 'pik-cfp': { - 'color': '#ff7f00', - 'width': 2 - }, - 'pik-cfp-fast': { - 'color': '#ff7f00', - 'dash': '4px, 4px', - 'width': 2 - }, - 'webp': { - 'color': '#000000', - 'width': 2 - }, - 'jpeg': { - 'color': '#a65628', - 'width': 2 - }, - 'xt.jpg': { - 'color': '#a65628', - 'width': 2 - }, - 'perc1.kdu.j2k': { - 'color': '#f781bf', - 'dash': '1px, 1px', - 'width': 2 - }, - 'perc2.kdu.j2k': { - 'color': '#f781bf', - 'dash': '3px, 3px', - 'width': 2 - }, - 'perc3.kdu.j2k': { - 'color': '#f781bf', - 'dash': '5px, 5px', - 'width': 2 - }, - 'perc4.kdu.j2k': { - 'color': '#f781bf', - 'dash': '7px, 7px', - 'width': 2 - }, - 'default.kdu.j2k': { - 'color': '#f781bf', - 'width': 2 - }, - } - return configs.get(codec, dict()) - - -visible_by_default = set([ - 'jxl-kitten', 'ssim.444.aom.avif', 'heif', 'webp', 'jpeg', 'xt.jpg', - 'default.kdu.j2k' -]) - -column_remap = { - 'p': '6-Butteraugli', - 'dist': 'Max-Butteraugli', - 'psnr': "PSNR-YUV 6/8 Y", - 'MS-SSIM-Y': '-log10(1 - MS-SSIM-Y)', - 'puSSIM': '-log10(1 - puSSIM)', - 'FSIM-Y': '-log10(1 - FSIM-Y)', - 'FSIM-RGB': '-log10(1 - FSIM-RGB)', - 'VMAF': '-log10(1 - VMAF / 100)', -} - - -def remap(metric): - funs = { - 'MS-SSIM-Y': lambda x: -math.log10(1 - x), - 'puSSIM': lambda x: -math.log10(1 - x), - 'FSIM-Y': lambda x: -math.log10(1 - x), - 'FSIM-RGB': lambda x: -math.log10(1 - x), - 'VMAF': lambda x: -math.log10(1 + 1e-8 - x / 100), - } - return funs.get(metric, lambda x: x) - - -for (m, img) in data: - fname = "%s/%s_%s" % (output_dir, m, img) - fig = go.Figure() - for method in sorted(data[(m, img)].keys(), key=pos): - vals = data[(m, img)][method] - zvals = list(zip(*sorted(vals))) - if not zvals: - continue - fig.add_trace( - go.Scatter(x=zvals[0], - y=[remap(m)(x) for x in zvals[1]], - mode='lines', - name=method, - line=style(method), - visible=True - if method in visible_by_default else 'legendonly')) - fig.update_layout(title=img, - xaxis_title='bpp', - yaxis_title=column_remap.get(m, m)) - fig.update_xaxes(type='log') - if OUTPUT == 'html': - fig.write_html(fname + '.html', include_plotlyjs='directory') - else: - fig.write_image(fname + '.' + OUTPUT, scale=4) diff --git a/tools/benchmark/metrics/prepare_metrics.sh b/tools/benchmark/metrics/prepare_metrics.sh deleted file mode 100755 index 57601d618..000000000 --- a/tools/benchmark/metrics/prepare_metrics.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -set -eu - -MYDIR=$(dirname $(realpath "$0")) - - -main() { - cd "${MYDIR}/../../../third_party" - local zipurl - local repourl - for repourl in \ - 'https://github.com/veluca93/IQA-optimization.git' \ - 'https://github.com/Netflix/vmaf.git' \ - 'https://github.com/thorfdbg/difftest_ng.git' - do - local reponame=$(basename "${repourl%.git}") - local dirname=$(basename "${reponame}") - if [[ ! -e "${dirname}" ]]; then - git clone "${repourl}" - fi - done - for zipurl in \ - 'https://sourceforge.net/projects/hdrvdp/files/hdrvdp/2.2.2/hdrvdp-2.2.2.zip' \ - 'https://sourceforge.net/projects/hdrvdp/files/simple_metrics/1.0/hdr_metrics.zip' - do - local zipfile="$(basename "${zipurl}")" - local dirname="$(basename "${zipfile}" '.zip')" - rm -fr "${dirname}" - if [[ ! -e "${zipfile}" ]]; then - wget -O "${zipfile}.tmp" "${zipurl}" - mv "${zipfile}.tmp" "${zipfile}" - fi - unzip "${zipfile}" "${dirname}"/'*' - done - - pushd hdrvdp-2.2.2 - patch -p1 < ../../tools/benchmark/metrics/hdrvdp-fixes.patch - pushd matlabPyrTools_1.4_fixed - mkoctfile --mex MEX/corrDn.c MEX/convolve.c MEX/wrap.c MEX/edges.c - mkoctfile --mex MEX/pointOp.c - mkoctfile --mex MEX/upConv.c - popd - popd - - - pushd difftest_ng - ./configure - make - popd - - - pushd vmaf/libvmaf - rm -rf build - meson build --buildtype release - ninja -vC build - popd -} -main "$@" - diff --git a/tools/benchmark/metrics/pupsnr.sh b/tools/benchmark/metrics/pupsnr.sh deleted file mode 100755 index 238fb5811..000000000 --- a/tools/benchmark/metrics/pupsnr.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -./compute_octave_metric.sh "$@" \ - --path "$(dirname "$0")"/../../../third_party/hdr_metrics/ \ - "$(dirname "$0")"/compute-pumetrics.m 'psnr' diff --git a/tools/benchmark/metrics/pussim.sh b/tools/benchmark/metrics/pussim.sh deleted file mode 100755 index a86f07fcd..000000000 --- a/tools/benchmark/metrics/pussim.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -./compute_octave_metric.sh "$@" \ - --path "$(dirname "$0")"/../../../third_party/hdr_metrics/ \ - "$(dirname "$0")"/compute-pumetrics.m 'ssim' diff --git a/tools/benchmark/metrics/run_all_hdr_metrics.sh b/tools/benchmark/metrics/run_all_hdr_metrics.sh deleted file mode 100755 index c443b220d..000000000 --- a/tools/benchmark/metrics/run_all_hdr_metrics.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -set -eu -dir="$(dirname "$0")" - -main() { - local metrics=( - HDR-VDP:"${dir}"/hdrvdp.sh - MRSE:"${dir}"/mrse.sh - puPSNR:"${dir}"/pupsnr.sh - puSSIM:"${dir}"/pussim.sh - ) - - local metrics_args=$(printf '%s' "${metrics[@]/#/,}") - metrics_args=${metrics_args:1} - - - "${dir}/../../../build/tools/benchmark_xl" \ - --print_details_csv \ - --num_threads=32 \ - --error_pnorm=6 \ - --extra_metrics ${metrics_args} \ - "$@" -} - -main "$@" diff --git a/tools/benchmark/metrics/run_all_sdr_metrics.sh b/tools/benchmark/metrics/run_all_sdr_metrics.sh deleted file mode 100755 index 8a811f579..000000000 --- a/tools/benchmark/metrics/run_all_sdr_metrics.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -set -eu -dir="$(dirname "$0")" - -main() { - local metrics=( - FSIM-Y:"${dir}"/fsim-y.sh - FSIM-RGB:"${dir}"/fsim-rgb.sh - LPIPS:"${dir}"/lpips-rgb.sh - MS-SSIM-Y:"${dir}"/msssim-y.sh - NLPD:"${dir}"/nlpd-y.sh - SSIMULACRA:"${dir}"/ssimulacra.sh - VIF:"${dir}"/vif-rgb.sh - VMAF:"${dir}"/vmaf.sh - ) - # other metrics, not in core experiments: -# VSI:"${dir}"/vsi-rgb.sh -# SSIM-RGB:"${dir}"/ssim-rgb.sh -# SSIM-Y:"${dir}"/ssim-y.sh -# GMSD:"${dir}"/gmsd.sh -# DISTS:"${dir}"/dists-rgb.sh -# MS-SSIM-RGB:"${dir}"/msssim-rgb.sh - - local metrics_args=$(printf '%s' "${metrics[@]/#/,}") - metrics_args=${metrics_args:1} - - - "${dir}/../../../build/tools/benchmark_xl" \ - --print_details_csv \ - --num_threads=1 \ - --error_pnorm=6 \ - --extra_metrics ${metrics_args} \ - "$@" -} - -main "$@" diff --git a/tools/benchmark/metrics/sdr_plots.sh b/tools/benchmark/metrics/sdr_plots.sh deleted file mode 100755 index 93f01cca3..000000000 --- a/tools/benchmark/metrics/sdr_plots.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -"$(dirname "$0")/run_all_sdr_metrics.sh" "$@" | sed -n '/```/q;p' > sdr_results.csv -mkdir -p sdr_plots/ -rm -rf sdr_plots/* -python3 "$(dirname "$0")/plots.py" sdr_results.csv sdr_plots diff --git a/tools/benchmark/metrics/ssim-rgb.sh b/tools/benchmark/metrics/ssim-rgb.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/ssim-rgb.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/benchmark/metrics/ssim-y.sh b/tools/benchmark/metrics/ssim-y.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/ssim-y.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/benchmark/metrics/ssimulacra.sh b/tools/benchmark/metrics/ssimulacra.sh deleted file mode 100755 index c1a737498..000000000 --- a/tools/benchmark/metrics/ssimulacra.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -"$(dirname "$0")"/../../../build/tools/ssimulacra_main "$1" "$2" > "$3" 2>/dev/null diff --git a/tools/benchmark/metrics/vif-rgb.sh b/tools/benchmark/metrics/vif-rgb.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/vif-rgb.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/benchmark/metrics/vmaf.sh b/tools/benchmark/metrics/vmaf.sh deleted file mode 100755 index ecb78b0b7..000000000 --- a/tools/benchmark/metrics/vmaf.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -set -euo pipefail - -original="$1" -decoded="$2" -output="$3" - -tmpdir="$(mktemp --directory)" - -exr_original="$(mktemp --tmpdir="$tmpdir" --suffix='.exr')" -exr_decoded="$(mktemp --tmpdir="$tmpdir" --suffix='.exr')" - -yuv_original="$(mktemp --tmpdir="$tmpdir" --suffix='.yuv')" -yuv_decoded="$(mktemp --tmpdir="$tmpdir" --suffix='.yuv')" - -vmaf_csv="$(mktemp --tmpdir="$tmpdir" --suffix='.csv')" - -cleanup() { - rm -- "$exr_original" "$exr_decoded" "$yuv_original" "$yuv_decoded" "$vmaf_csv" - rmdir --ignore-fail-on-non-empty -- "$tmpdir" -} -trap cleanup EXIT - -convert "$original" "$exr_original" -convert "$decoded" "$exr_decoded" - -srgb=(-colorspace bt709 -color_primaries bt709 -color_trc iec61966-2-1) -ffmpeg "${srgb[@]}" -i "$exr_original" -pix_fmt yuv444p10le "${srgb[@]}" -y "$yuv_original" &>/dev/null -ffmpeg "${srgb[@]}" -i "$exr_decoded" -pix_fmt yuv444p10le "${srgb[@]}" -y "$yuv_decoded" &>/dev/null - -"$(dirname "$0")"/../../../third_party/vmaf/libvmaf/build/tools/vmafossexec \ - yuv444p10le \ - "$(identify -format '%w' "$original")" "$(identify -format '%h' "$original")" \ - "$yuv_original" "$yuv_decoded" \ - "$(dirname "$0")/../../../third_party/vmaf/model/vmaf_v0.6.1.pkl" \ - --log-fmt csv --log "$vmaf_csv" &>/dev/null - -read_csv="$(cat <<'END' -import csv -import sys -reader = csv.DictReader(sys.stdin) -for row in reader: - print(row['vmaf']) -END -)" - -python -c "$read_csv" < "$vmaf_csv" > "$output" diff --git a/tools/benchmark/metrics/vsi-rgb.sh b/tools/benchmark/metrics/vsi-rgb.sh deleted file mode 120000 index 9e57c8f66..000000000 --- a/tools/benchmark/metrics/vsi-rgb.sh +++ /dev/null @@ -1 +0,0 @@ -iqa_wrapper.sh \ No newline at end of file diff --git a/tools/codec_config.cc b/tools/codec_config.cc deleted file mode 100644 index c1d9ea5a6..000000000 --- a/tools/codec_config.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) the JPEG XL Project Authors. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd - -#include "tools/codec_config.h" - -#include - -#include "tools/tool_version.h" - -namespace jpegxl { -namespace tools { - -std::string CodecConfigString(uint32_t lib_version) { - std::string config; - - if (lib_version != 0) { - char version_str[20]; - snprintf(version_str, sizeof(version_str), "v%d.%d.%d ", - lib_version / 1000000, (lib_version / 1000) % 1000, - lib_version % 1000); - config += version_str; - } - - std::string version = kJpegxlVersion; - if (version != "(unknown)") { - config += version + ' '; - } - -#if defined(ADDRESS_SANITIZER) - config += " asan "; -#elif defined(MEMORY_SANITIZER) - config += " msan "; -#elif defined(THREAD_SANITIZER) - config += " tsan "; -#else -#endif - - bool saw_target = false; - config += "["; - for (const uint32_t target : hwy::SupportedAndGeneratedTargets()) { - config += hwy::TargetName(target); - config += ','; - saw_target = true; - } - if (!saw_target) { - config += "no targets found,"; - } - config.resize(config.size() - 1); // remove trailing comma - config += "]"; - - return config; -} - -} // namespace tools -} // namespace jpegxl diff --git a/tools/codec_config.h b/tools/codec_config.h deleted file mode 100644 index fcbe3ce82..000000000 --- a/tools/codec_config.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) the JPEG XL Project Authors. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd - -#ifndef TOOLS_CODEC_CONFIG_H_ -#define TOOLS_CODEC_CONFIG_H_ - -#include - -#include - -namespace jpegxl { -namespace tools { - -// Returns a short string describing the codec version (if known) and build -// settings such as sanitizers and SIMD targets. Used in the benchmark and -// command-line tools. -std::string CodecConfigString(uint32_t lib_version); - -} // namespace tools -} // namespace jpegxl - -#endif // TOOLS_CODEC_CONFIG_H_ diff --git a/tools/demo_vardct_select.sh b/tools/demo_vardct_select.sh deleted file mode 100755 index 2ffe73dad..000000000 --- a/tools/demo_vardct_select.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/bash -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -# Produces a demo video showing VarDCT block type selection -# from very high quality to very low quality. - -# Assumes ImageMagick convert, ffmpeg, bc are available. - -set -eu - -MYDIR=$(dirname $(realpath "$0")) - -CLEANUP_FILES=() -cleanup() { - if [[ ${#CLEANUP_FILES[@]} -ne 0 ]]; then - rm -fr "${CLEANUP_FILES[@]}" - fi -} -trap "{ set +x; } 2>/dev/null; cleanup" INT TERM EXIT - - - -main() { - local infile="${1:-}" - if [[ -z "${infile}" ]]; then - cat >&2 </dev/null 2>&1; then - PATH=$PATH:$MYDIR/../build/tools - if ! command -v benchmark_xl &>/dev/null 2>&1; then - echo "Could not find benchmark_xl, try building first" - exit - fi - fi - local b=benchmark_xl - - if ! command -v ffmpeg &>/dev/null 2>&1; then - echo "Could not find ffmpeg" - exit - fi - - if ! command -v convert &>/dev/null 2>&1; then - echo "Could not find ImageMagick (convert)" - exit - fi - - local tmp=$(mktemp -d --suffix=vardctdemo) - CLEANUP_FILES+=("${tmp}") - - cp $infile $tmp/orig - - local n=0 - local pixels="$(identify -format "(%w * %h)" $tmp/orig)" - for i in $(seq 0.2 0.2 2) $(seq 2.5 0.5 5) $(seq 6 1 10) $(seq 12 2 40); do - $b --input=$tmp/orig --codec=jxl:d$i --save_decompressed --save_compressed \ - --debug_image_dir=$tmp --output_dir=$tmp - convert $tmp/orig \( $tmp/orig.jxl:d$i.dbg/ac_strategy.png \ - -alpha set -channel A -evaluate set 66% \) \ - -composite $tmp/t.ppm - bytes=$(stat -c "%s" $tmp/orig.jxl_d$i) - bpp=$( echo "$bytes * 8 / $pixels " | bc -l | cut -b 1-6 ) - label="cjxl -d $i ($((bytes / 1000)) kb, bpp: $bpp)" - convert +append $tmp/t.ppm $tmp/orig.jxl_d$i.png $tmp/t2.ppm - convert $tmp/t2.ppm \ - -gravity north \ - -pointsize 32 \ - -stroke '#000C' -strokewidth 5 -annotate +0+12 "$label" \ - -stroke none -fill white -annotate +0+12 "$label" $tmp/frame-$n.png - - n=$((n+1)) - done - - ffmpeg -framerate 1 -i $tmp/frame-%d.png $outfile -} - -main "$@" diff --git a/tools/example_tree.txt b/tools/example_tree.txt deleted file mode 100644 index c4df6d408..000000000 --- a/tools/example_tree.txt +++ /dev/null @@ -1,50 +0,0 @@ -RCT 1 /* YCoCg */ -GroupShift 3 /* Group size is 128 << 3 == 1024 */ -Width 1024 -Height 1024 -Bitdepth 8 -/* FloatExpBits 3 */ -/* Alpha */ -/* Squeeze */ -/* XYB */ -/* CbYCr */ - - -if c > 0 - /* Co, Cg: diagonal stripes */ - if W > 50 - - Set -50 - - W + 5 - /* Y: elementary cellular automaton */ - if y > 0 - if N > 0 - if NW-N > -1 - if N-NE > 0 - - Set 0 - - Set 255 - if N-NE > 0 - - Set 255 - - Set 0 - if NW-N > 0 - if N-NE > -1 - - Set 255 - - Set 0 - if N-NE > -1 - - Set 0 - - Set 255 - /* First row initialization */ - if x > 511 - - Set 255 - - Set 0 - -Everything after the end of the tree is ignored. - -The tree above represents a cellular automaton on a subtly striped background. - - - -List of properties: c, g, y, x, |N|, |W|, N, W, W-WW-NW+NWW, W+N-NW, W-NW, NW-N, N-NE, N-NN, W-WW, WGH, - PrevAbs, Prev, PrevAbsErr, PrevErr, PPrevAbs, PPrev, PPrevAbsErr, PPrevErr - -List of predictors: Set, W, N, AvgW+N, Select, Gradient, Weighted, NE, NW, WW, AvgW+NW, AvgN+NW, AvgN+NE, AvgAll - diff --git a/tools/scripts/bisector b/tools/scripts/bisector deleted file mode 100755 index b6a82d0b4..000000000 --- a/tools/scripts/bisector +++ /dev/null @@ -1,287 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) the JPEG XL Project Authors. All rights reserved. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -r"""General-purpose bisector - -Prints a space-separated list of values to stdout: -1_if_success_0_otherwise left_x left_f(x) right_x right_f(x) - -Usage examples: - -# Finding the square root of 200 via bisection: -bisector --var=BB --range=0.0,100.0 --target=200 --maxiter=100 \ - --atol_val=1e-12 --rtol_val=0 --cmd='echo "$BB * $BB" | bc' -# => 1 14.142135623730923 199.99999999999923 14.142135623731633 200.0000000000193 - -# Finding an integer approximation to sqrt(200) via bisection: -bisector --var=BB --range=0,100 --target=200 --maxiter=100 \ - --atol_arg=1 --cmd='echo "$BB * $BB" | bc' -# => 1 14 196.0 15 225.0 - -# Finding a change-id that broke something via bisection: -bisector --var=BB --range=0,1000000 --target=0.5 --maxiter=100 \ - --atol_arg=1 \ - --cmd='test $BB -gt 123456 && echo 1 || echo 0' --verbosity=3 -# => 1 123456 0.0 123457 1.0 - -# Finding settings that compress /usr/share/dict/words to a given target size: -bisector --var=BB --range=1,9 --target=250000 --atol_arg=1 \ - --cmd='gzip -$BB /tmp/w_$BB.gz; wc -c /tmp/w_$BB.gz' \ - --final='mv /tmp/w_$BB.gz /tmp/words.gz; rm /tmp/w_*.gz' \ - --verbosity=1 -# => 1 3 263170.0 4 240043.0 - -# JXL-encoding with bisection-for-size (tolerance 0.5%): -bisector --var=BB --range=0.1,3.0 --target=3500 --rtol_val=0.005 \ - --cmd='(build/tools/cjxl --distance=$BB /tmp/baseball.png /tmp/baseball_$BB.jxl && wc -c /tmp/baseball_$BB.jxl)' \ - --final='mv /tmp/baseball_$BB.jxl /tmp/baseball.jxl; rm -f /tmp/baseball_*.jxl' \ - --verbosity=1 -# => 1 1.1875 3573.0 1.278125 3481.0 - -# JXL-encoding with bisection-for-bits-per-pixel (tolerance 0.5%), using helper: -bisector --var=BB --range=0.1,3.0 --target=1.2 --rtol_val=0.005 \ - --cmd='(build/tools/cjxl --distance=$BB /tmp/baseball.png /tmp/baseball_$BB.jxl && get_bpp /tmp/baseball_$BB.jxl)' \ - --final='mv /tmp/baseball_$BB.jxl /tmp/baseball.jxl; rm -f /tmp/baseball_*.jxl' \ - --verbosity=1 -# => ... -""" - -import argparse -import os -import re -import subprocess -import sys - - -def _expandvars(vardef, env, - max_recursion=100, - max_length=10**6, - verbosity=0): - """os.path.expandvars() variant using parameter env rather than os.environ.""" - current_expanded = vardef - for num_recursions in range(max_recursion): - if verbosity >= 3: - print(f'_expandvars(): num_recursions={num_recursions}, ' - f'len={len(current_expanded)}' + - (', current: ' + current_expanded if verbosity >= 4 else '')) - if len > max_length: - break - current_expanded, num_replacements = re.subn( - r'$\{(\w+)\}|$(\w+)', - lambda m: env.get(m[1] if m[1] is not None else m[2], ''), - current_expanded) - if num_replacements == 0: - break - return current_expanded - - -def _strtod(string): - """Extracts leftmost float from string (like strtod(3)).""" - match = re.match(r'[+-]?\d*[.]?\d*(?:[eE][+-]?\d+)?', string) - return float(match[0]) if match[0] else None - - -def run_shell_command(shell_command, - bisect_var, bisect_val, - extra_env_defs, - verbosity=0): - """Runs a shell command with env modifications, fetching return value.""" - shell_env = dict(os.environ) - shell_env[bisect_var] = str(bisect_val) - for env_def in extra_env_defs: - varname, vardef = env_def.split('=', 1) - shell_env[varname] = _expandvars(vardev, shell_env, - verbosity=verbosity) - shell_ret = subprocess.run(shell_command, - # We explicitly want subshell semantics! - shell=True, - capture_output=True, - env=shell_env) - stdout = shell_ret.stdout.decode('utf-8') - score = _strtod(stdout) - if verbosity >= 2: - print(f'{bisect_var}={bisect_val} {shell_command} => ' - f'{shell_ret.returncode} # {stdout.strip()}') - return (shell_ret.returncode == 0, # Command was successful? - score) - - -def _bisect(*, - shell_command, - final_shell_command, - target, - int_args, - bisect_var, bisect_left, bisect_right, - rtol_val, atol_val, rtol_arg, atol_arg, - maxiter, - extra_env_defs, - verbosity=0 - ): - """Performs bisection.""" - def _get_val(x): - success, val = run_shell_command(shell_command, - bisect_var, x, - extra_env_defs, - verbosity=verbosity) - if not success: - raise RuntimeError(f'Bisection failed for: {bisect_var}={x}: ' - f'success={success}, val={val}, ' - f'cmd={shell_command}, var={bisect_var}') - return val - # - bisect_mid, value_mid = None, None - try: - value_left = _get_val(bisect_left) - value_right = _get_val(bisect_right) - if (value_left < target) != (target <= value_right): - raise RuntimeError( - f'Cannot bisect: target={target}, value_left={value_left}, ' - f'value_right={value_right}') - for num_iter in range(maxiter): - bisect_mid_f = 0.5 * (bisect_left + bisect_right) - bisect_mid = round(bisect_mid_f) if int_args else bisect_mid_f - value_mid = _get_val(bisect_mid) - if (value_left < target) == (value_mid < target): - # Relative to target, `value_mid` is on the same side - # as `value_left`. - bisect_left = bisect_mid - value_left = value_mid - else: - # Otherwise, this situation must hold for value_right - # ("tertium non datur"). - bisect_right = bisect_mid - value_right = value_mid - if verbosity >= 1: - print(f'bisect target={target}, ' - f'left: {value_left} at {bisect_left}, ' - f'right: {value_right} at {bisect_right}, ' - f'mid: {value_mid} at {bisect_mid}') - delta_val = target - value_mid - if abs(delta_val) <= atol_val + rtol_val * abs(target): - return 1, bisect_left, value_left, bisect_right, value_right - delta_arg = bisect_right - bisect_left - # Also check whether the argument is "within tolerance". - # Here, we have to be careful if bisect_left and bisect_right - # have different signs: Then, their absolute magnitude - # "sets the relevant scale". - if abs(delta_arg) <= atol_arg + ( - rtol_arg * 0.5 * (abs(bisect_left) + abs(bisect_right))): - return 1, bisect_left, value_left, bisect_right, value_right - return 0, bisect_left, value_left, bisect_right, value_right - finally: - # If cleanup is specified, always run it - if final_shell_command: - run_shell_command( - final_shell_command, - bisect_var, - bisect_mid if bisect_mid is not None else bisect_left, - extra_env_defs, verbosity=verbosity) - - -def main(args): - """Main entry point.""" - parser = argparse.ArgumentParser(description='mhtml_walk args') - parser.add_argument( - '--var', - help='The variable to use for bisection.', - default='BISECT') - parser.add_argument( - '--range', - help=('The argument range for bisecting, as {low},{high}. ' - 'If no argument has a decimal dot, assume integer parameters.'), - default='0.0,1.0') - parser.add_argument( - '--max', - help='The maximal value for bisecting.', - type=float, - default=0.0) - parser.add_argument( - '--target', - help='The target value to aim for.', - type=float, - default=1.0) - parser.add_argument( - '--maxiter', - help='The maximal number of iterations to perform.', - type=int, - default=40) - parser.add_argument( - '--rtol_val', - help='Relative tolerance to accept for deviations from target value.', - type=float, - default=0.0) - parser.add_argument( - '--atol_val', - help='Absolute tolerance to accept for deviations from target value.', - type=float, - default=0.0) - parser.add_argument( - '--rtol_arg', - help='Relative tolerance to accept for the argument.', - type=float, - default=0.0) - parser.add_argument( - '--atol_arg', - help=('Absolute tolerance to accept for the argument ' - '(e.g. for bisecting change-IDs).'), - type=float, - default=0.0) - parser.add_argument( - '--verbosity', - help='The verbosity level.', - type=int, - default=1) - parser.add_argument( - '--env', - help=('Comma-separated list of extra environment variables ' - 'to incrementally add before executing the shell-command.'), - default='') - parser.add_argument( - '--cmd', - help=('The shell command to execute. Must print a numerical result ' - 'to stdout.')) - parser.add_argument( - '--final', - help='The cleanup shell command to execute.') - # - parsed = parser.parse_args(args) - extra_env_defs = tuple(filter(None, parsed.env.split(','))) - try: - low_high = parsed.range.split(',') - if len(low_high) != 2: - raise ValueError('--range must be {low},{high}') - int_args = False - low_val, high_val = map(float, low_high) - low_val_int = round(low_val) - high_val_int = round(high_val) - if low_high == [str(low_val_int), str(high_val_int)]: - int_args = True - low_val = low_val_int - high_val = high_val_int - ret = _bisect( - shell_command=parsed.cmd, - final_shell_command=parsed.final, - target=parsed.target, - int_args=int_args, - bisect_var=parsed.var, - bisect_left=low_val, - bisect_right=high_val, - rtol_val=parsed.rtol_val, - atol_val=parsed.atol_val, - rtol_arg=parsed.rtol_arg, - atol_arg=parsed.atol_arg, - maxiter=parsed.maxiter, - extra_env_defs=extra_env_defs, - verbosity=parsed.verbosity, - ) - print(' '.join(map(str, ret))) - except Exception as exn: - sys.exit(f'Problem: {exn}') - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/tools/scripts/cjxl_bisect_bpp b/tools/scripts/cjxl_bisect_bpp deleted file mode 100755 index 13a908c57..000000000 --- a/tools/scripts/cjxl_bisect_bpp +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh -# -# Copyright (c) the JPEG XL Project Authors. All rights reserved. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. -# -# Bisects JPEG XL encoding quality parameter to reach a given -# target bits-per-pixel value. -# (To be used directly, or as a template for tailored processing.) -# -# Usage: cjxl_bisect_size {input_filename} {output_filename} {target_bpp} - -# -# We take the `bisector` tool from $PATH, or, if not available, -# try to locate it in the same directory as the current script. -# The `get_bpp` helper is taken from the same directory as the current script. -# - -input_filename=$1 -output_filename=$2 -target_size=$3 - -script_dir=$(dirname $(readlink -f $0)) -bisect_tool=$(which bisector) -if [ -z $bisect_tool ] ; then - bisect_tool="${script_dir}/bisector" -fi -jxl_get_bpp_helper="${script_dir}/jxl_get_bpp_helper" -# If $CJXL_BIN is set, we use this instead of looking for `cjxl` on $PATH. - -cjxl_bin=${CJXL_BIN} -if [ -z $cjxl_bin ] ; then - cjxl_bin="cjxl" -fi - -# Using `identify` from ImageMagick here. -num_pixels=$(identify -format "%w*%h\n" /tmp/baseball.png|bc) - -# Allow 0.5% tolerance in size (--rtol=0.005). -exec $bisect_tool --var=BISECT --range=0.01,15.0 --target=$target_size \ - --rtol_val=0.005 \ - --cmd="$cjxl_bin --distance=\$BISECT ${input_filename} ${output_filename}_bisect_\$BISECT.jxl ; (find ${output_filename}_bisect_\$BISECT.jxl -printf \"scale=10;%s/$num_pixels\n\" | bc -l)" \ - --final="mv ${output_filename}_bisect_\$BISECT.jxl ${output_filename}; rm -f ${output_filename}_bisect_*.jxl" \ - --verbosity=1 diff --git a/tools/scripts/cjxl_bisect_size b/tools/scripts/cjxl_bisect_size deleted file mode 100755 index c0945d92f..000000000 --- a/tools/scripts/cjxl_bisect_size +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh -# -# Copyright (c) the JPEG XL Project Authors. All rights reserved. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. -# -# Bisects JPEG XL encoding quality parameter to reach a given -# target byte-size. -# (To be used directly, or as a template for tailored processing.) -# -# Usage: cjxl_bisect_size {input_filename} {output_filename} {target_size} - -# -# We take the `bisector` tool from $PATH, or, if not available, -# try to locate it in the same directory as the current script. -# - -input_filename=$1 -output_filename=$2 -target_size=$3 - -script_dir=$(dirname $(readlink -f $0)) -bisect_tool=$(which bisector) -if [ -z $bisect_tool ] ; then - bisect_tool="${script_dir}/bisector" -fi - -# If $CJXL_BIN is set, we use this instead of looking for `cjxl` on $PATH. - -cjxl_bin=${CJXL_BIN} -if [-z $cjxl_bin ] ; then - cjxl_bin="cjxl" -fi - -# Allow 0.5% tolerance in size (--rtol=0.005). -exec $bisect_tool --var=BISECT --range=0.01,10.0 --target=$target_size \ - --rtol_val=0.005 \ - --cmd="$cjxl_bin --distance=\$BISECT ${input_filename} ${output_filename}_bisect_\$BISECT.jxl && wc -c ${output_filename}_bisect_\$BISECT.jxl" \ - --final="mv ${output_filename}_bisect_\$BISECT.jxl ${output_filename}; rm -f ${output_filename}_bisect_*.jxl" \ - --verbosity=1 diff --git a/tools/scripts/demo_progressive_saliency_encoding.py b/tools/scripts/demo_progressive_saliency_encoding.py deleted file mode 100755 index fb3e16b06..000000000 --- a/tools/scripts/demo_progressive_saliency_encoding.py +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) the JPEG XL Project Authors. -# -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file or at -# https://developers.google.com/open-source/licenses/bsd - -"""Produces demos for how progressive-saliency encoding would look like. - -As long as we do not have a progressive decoder that allows showing images -generated from partially-available data, we can resort to building -animated gifs that show how progressive loading would look like. - -Method: - -1. JPEG-XL encode the image, but stop at the pre-final (2nd) step. -2. Use separate tool to compute a heatmap which shows where differences between - the pre-final and final image are expected to be perceptually worst. -3. Use this heatmap to JPEG-XL encode the image with the final step split into - 'salient parts only' and 'non-salient parts'. Generate a sequence of images - that stop decoding after the 1st, 2nd, 3rd, 4th step. JPEG-XL decode these - truncated images back to PNG. -4. Measure byte sizes of the truncated-encoded images. -5. Build an animated GIF with variable delays by calling ImageMagick's - `convert` command. - -""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from six.moves import zip -import ast # For ast.literal_eval() only. -import os -import re -import shlex -import subprocess -import sys - -_BLOCKSIZE = 8 - -_CONF_PARSERS = dict( - keep_tempfiles=lambda s: bool(ast.literal_eval(s)), - heatmap_command=shlex.split, - simulated_progressive_loading_time_sec=float, - simulated_progressive_loading_delay_until_looparound_sec=float, - jpegxl_encoder=shlex.split, - jpegxl_decoder=shlex.split, - blurring=lambda s: s.split(), -) - - -def parse_config(config_filename): - """Parses the configuration file.""" - conf = {} - re_comment = re.compile(r'^\s*(?:#.*)?$') - re_param = re.compile(r'^(?P