libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

jpegli_tools_test.sh (10333B)


      1 #!/bin/bash
      2 # Copyright (c) the JPEG XL Project Authors. All rights reserved.
      3 #
      4 # Use of this source code is governed by a BSD-style
      5 # license that can be found in the LICENSE file.
      6 
      7 # End-to-end roundtrip tests for cjpegli and djpegli tools, and other linux
      8 # tools linked with the jpegli library.
      9 
     10 set -eux
     11 
     12 MYDIR=$(dirname $(realpath "$0"))
     13 JPEGXL_TEST_DATA_PATH="${MYDIR}/../../testdata"
     14 
     15 # Temporary files cleanup hooks.
     16 CLEANUP_FILES=()
     17 cleanup() {
     18   if [[ ${#CLEANUP_FILES[@]} -ne 0 ]]; then
     19     rm -rf "${CLEANUP_FILES[@]}"
     20   fi
     21 }
     22 trap 'retcode=$?; { set +x; } 2>/dev/null; cleanup' INT TERM EXIT
     23 
     24 verify_ssimulacra2() {
     25   local score="$("${ssimulacra2}" "${1}" "${2}")"
     26   python3 -c "import sys; sys.exit(not ${score} >= ${3})"
     27 }
     28 
     29 verify_max_bpp() {
     30   local infn="$1"
     31   local jpgfn="$2"
     32   local maxbpp="$3"
     33   local size="$(wc -c "${jpgfn}" | cut -d' ' -f1)"
     34   local pixels=$(( "$(identify "${infn}" | cut -d' ' -f3 | tr 'x' '*')" ))
     35   python3 -c "import sys; sys.exit(not ${size} * 8 <= ${maxbpp} * ${pixels})"
     36 }
     37 
     38 # Test that jpeg files created with cjpegli can be decoded with normal djpeg.
     39 cjpegli_test() {
     40   local infn="${JPEGXL_TEST_DATA_PATH}/$1"
     41   local encargs="$2"
     42   local minscore="$3"
     43   local maxbpp="$4"
     44   local jpgfn="$(mktemp -p "${tmpdir}")"
     45   local outfn="$(mktemp -p "${tmpdir}").ppm"
     46 
     47   "${cjpegli}" "${infn}" "${jpgfn}" $encargs
     48   djpeg -outfile "${outfn}" "${jpgfn}"
     49 
     50   verify_ssimulacra2 "${infn}" "${outfn}" "${minscore}"
     51   verify_max_bpp "${infn}" "${jpgfn}" "${maxbpp}"
     52 }
     53 
     54 # Test full cjpegli/djpegli roundtrip.
     55 cjpegli_djpegli_test() {
     56   local infn="${JPEGXL_TEST_DATA_PATH}/$1"
     57   local encargs="$2"
     58   local minscore="$3"
     59   local maxbpp="$4"
     60   local jpgfn="$(mktemp -p "${tmpdir}")"
     61   local outfn="$(mktemp -p "${tmpdir}").png"
     62 
     63   "${cjpegli}" "${infn}" "${jpgfn}" $encargs
     64   "${djpegli}" "${jpgfn}" "${outfn}"
     65 
     66   verify_ssimulacra2 "${infn}" "${outfn}" "${minscore}"
     67   verify_max_bpp "${infn}" "${jpgfn}" "${maxbpp}"
     68 }
     69 
     70 # Test the --target_size command line argument of cjpegli.
     71 cjpegli_test_target_size() {
     72   local infn="${JPEGXL_TEST_DATA_PATH}/$1"
     73   local encargs="$2"
     74   local target_size="$3"
     75   local jpgfn="$(mktemp -p "$tmpdir")"
     76 
     77   "${cjpegli}" "${infn}" "${jpgfn}" $encargs --target_size "${target_size}"
     78   local size="$(wc -c "${jpgfn}" | cut -d' ' -f1)"
     79   python3 -c "import sys; sys.exit(not ${target_size} * 0.996 <= ${size})"
     80   python3 -c "import sys; sys.exit(not ${target_size} * 1.004 >= ${size})"
     81 }
     82 
     83 # Test that jpeg files created with cjpeg binary + jpegli library can be decoded
     84 # with normal libjpeg.
     85 cjpeg_test() {
     86   local infn="${JPEGXL_TEST_DATA_PATH}/$1"
     87   local encargs="$2"
     88   local minscore="$3"
     89   local maxbpp="$4"
     90   local jpgfn="$(mktemp -p "$tmpdir")"
     91   local outfn="$(mktemp -p "${tmpdir}").png"
     92 
     93   LD_LIBRARY_PATH="${build_dir}/lib/jpegli:${LD_LIBRARY_PATH:-}" \
     94     cjpeg $encargs -outfile "${jpgfn}" "${infn}"
     95   djpeg -outfile "${outfn}" "${jpgfn}"
     96 
     97   verify_ssimulacra2 "${infn}" "${outfn}" "${minscore}"
     98   verify_max_bpp "${infn}" "${jpgfn}" "${maxbpp}"
     99 }
    100 
    101 # Test decoding of jpeg files with the djpegli binary.
    102 djpegli_test() {
    103   local infn="${JPEGXL_TEST_DATA_PATH}/$1"
    104   local encargs="$2"
    105   local minscore="$3"
    106   local jpgfn="$(mktemp -p "$tmpdir")"
    107 
    108   cjpeg $encargs -outfile "${jpgfn}" "${infn}"
    109 
    110   # Test that disabling output works.
    111   "${djpegli}" "${jpgfn}" --disable_output
    112   for ext in png pgm ppm pfm pnm baz; do
    113     "${djpegli}" "${jpgfn}" /foo/bar.$ext --disable_output
    114   done
    115 
    116   # Test decoding to PNG, PPM, PNM, PFM
    117   for ext in png ppm pnm pfm; do
    118     local outfn="$(mktemp -p "${tmpdir}").${ext}"
    119     "${djpegli}" "${jpgfn}" "${outfn}" --num_reps 2
    120     verify_ssimulacra2 "${infn}" "${outfn}" "${minscore}"
    121   done
    122 
    123   # Test decoding to PGM (for grayscale input)
    124   if [[ "${infn: -6}" == ".g.png" ]]; then
    125     local outfn="$(mktemp -p "${tmpdir}").pgm"
    126     "${djpegli}" "${jpgfn}" "${outfn}" --quiet
    127     verify_ssimulacra2 "${infn}" "${outfn}" "${minscore}"
    128   fi
    129 
    130   # Test decoding to 16 bit
    131   for ext in png pnm; do
    132     local outfn8="$(mktemp -p "${tmpdir}").8.${ext}"
    133     local outfn16="$(mktemp -p "${tmpdir}").16.${ext}"
    134     "${djpegli}" "${jpgfn}" "${outfn8}"
    135     "${djpegli}" "${jpgfn}" "${outfn16}" --bitdepth 16
    136     local score8="$("${ssimulacra2}" "${infn}" "${outfn8}")"
    137     local score16="$("${ssimulacra2}" "${infn}" "${outfn16}")"
    138     python3 -c "import sys; sys.exit(not ${score16} > ${score8})"
    139   done
    140 }
    141 
    142 # Test decoding of jpeg files with the djpeg binary + jpegli library.
    143 djpeg_test() {
    144   local infn="${JPEGXL_TEST_DATA_PATH}/$1"
    145   local encargs="$2"
    146   local minscore="$3"
    147   local jpgfn="$(mktemp -p "$tmpdir")"
    148 
    149   cjpeg $encargs -outfile "${jpgfn}" "${infn}"
    150 
    151   # Test default behaviour.
    152   local outfn="$(mktemp -p "${tmpdir}").pnm"
    153   LD_LIBRARY_PATH="${build_dir}/lib/jpegli:${LD_LIBRARY_PATH:-}" \
    154     djpeg -outfile "${outfn}" "${jpgfn}"
    155   verify_ssimulacra2 "${infn}" "${outfn}" "${minscore}"
    156 
    157   # Test color quantization.
    158   local outfn="$(mktemp -p "${tmpdir}").pnm"
    159   LD_LIBRARY_PATH="${build_dir}/lib/jpegli:${LD_LIBRARY_PATH:-}" \
    160     djpeg -outfile "${outfn}" -colors 128 "${jpgfn}"
    161   verify_ssimulacra2 "${infn}" "${outfn}" 48
    162 
    163   local outfn="$(mktemp -p "${tmpdir}").pnm"
    164   LD_LIBRARY_PATH="${build_dir}/lib/jpegli:${LD_LIBRARY_PATH:-}" \
    165     djpeg -outfile "${outfn}" -colors 128 -onepass -dither fs "${jpgfn}"
    166   verify_ssimulacra2 "${infn}" "${outfn}" 30
    167 
    168   local outfn="$(mktemp -p "${tmpdir}").pnm"
    169   LD_LIBRARY_PATH="${build_dir}/lib/jpegli:${LD_LIBRARY_PATH:-}" \
    170     djpeg -outfile "${outfn}" -colors 128 -onepass -dither ordered "${jpgfn}"
    171   verify_ssimulacra2 "${infn}" "${outfn}" 30
    172 
    173   # Test -grayscale flag.
    174   local outfn="$(mktemp -p "${tmpdir}").pgm"
    175   LD_LIBRARY_PATH="${build_dir}/lib/jpegli:${LD_LIBRARY_PATH:-}" \
    176     djpeg -outfile "${outfn}" -grayscale "${jpgfn}"
    177   local outfn2="$(mktemp -p "${tmpdir}").pgm"
    178   convert "${infn}" -set colorspace Gray "${outfn2}"
    179   # JPEG color conversion is in gamma-compressed space, so it will not match
    180   # the correct grayscale version very well.
    181   verify_ssimulacra2 "${outfn2}" "${outfn}" 60
    182 
    183   # Test -rgb flag.
    184   local outfn="$(mktemp -p "${tmpdir}").ppm"
    185   LD_LIBRARY_PATH="${build_dir}/lib/jpegli:${LD_LIBRARY_PATH:-}" \
    186     djpeg -outfile "${outfn}" -rgb "${jpgfn}"
    187   verify_ssimulacra2 "${infn}" "${outfn}" "${minscore}"
    188 
    189   # Test -crop flag.
    190   for geometry in 256x256+128+128 256x127+128+117; do
    191     local outfn="$(mktemp -p "${tmpdir}").pnm"
    192     LD_LIBRARY_PATH="${build_dir}/lib/jpegli:${LD_LIBRARY_PATH:-}" \
    193       djpeg -outfile "${outfn}" -crop "${geometry}" "${jpgfn}"
    194     local outfn2="$(mktemp -p "${tmpdir}").pnm"
    195     convert "${infn}" -crop "${geometry}" "${outfn2}"
    196     verify_ssimulacra2 "${outfn2}" "${outfn}" "${minscore}"
    197   done
    198 
    199   # Test output scaling.
    200   for scale in 1/4 3/8 1/2 5/8 9/8; do
    201     local scalepct="$(python3 -c "print(100.0*${scale})")%"
    202     local geometry=96x128+0+0
    203     local outfn="$(mktemp -p "${tmpdir}").pnm"
    204     LD_LIBRARY_PATH="${build_dir}/lib/jpegli:${LD_LIBRARY_PATH:-}" \
    205       djpeg -outfile "${outfn}" -scale "${scale}" -crop "${geometry}" "${jpgfn}"
    206     local outfn2="$(mktemp -p "${tmpdir}").pnm"
    207     convert "${infn}" -scale "${scalepct}" -crop "${geometry}" "${outfn2}"
    208     verify_ssimulacra2 "${outfn2}" "${outfn}" 80
    209   done
    210 }
    211 
    212 main() {
    213   local tmpdir=$(mktemp -d)
    214   CLEANUP_FILES+=("${tmpdir}")
    215 
    216   local build_dir="${1:-}"
    217   if [[ -z "${build_dir}" ]]; then
    218     build_dir=$(realpath "${MYDIR}/../../build")
    219   fi
    220 
    221   local cjpegli="${build_dir}/tools/cjpegli"
    222   local djpegli="${build_dir}/tools/djpegli"
    223   local ssimulacra2="${build_dir}/tools/ssimulacra2"
    224   local rgb_in="jxl/flower/flower_small.rgb.png"
    225   local gray_in="jxl/flower/flower_small.g.png"
    226   local ppm_rgb="jxl/flower/flower_small.rgb.depth8.ppm"
    227   local ppm_gray="jxl/flower/flower_small.g.depth8.pgm"
    228 
    229   cjpegli_test "${rgb_in}" "" 88.5 1.7
    230   cjpegli_test "${rgb_in}" "-q 80" 84 1.2
    231   cjpegli_test "${rgb_in}" "-q 95" 91.5 2.4
    232   cjpegli_test "${rgb_in}" "-d 0.5" 92 2.6
    233   cjpegli_test "${rgb_in}" "--chroma_subsampling 420" 87 1.5
    234   cjpegli_test "${rgb_in}" "--chroma_subsampling 440" 87 1.6
    235   cjpegli_test "${rgb_in}" "--chroma_subsampling 422" 87 1.6
    236   cjpegli_test "${rgb_in}" "--std_quant" 91 2.2
    237   cjpegli_test "${rgb_in}" "--noadaptive_quantization" 88.5 1.85
    238   cjpegli_test "${rgb_in}" "-p 1" 88.5 1.72
    239   cjpegli_test "${rgb_in}" "-p 0" 88.5 1.75
    240   cjpegli_test "${rgb_in}" "-p 0 --fixed_code" 88.5 1.8
    241   cjpegli_test "${gray_in}" "" 92 1.4
    242 
    243   cjpegli_test_target_size "${rgb_in}" "" 10000
    244   cjpegli_test_target_size "${rgb_in}" "" 50000
    245   cjpegli_test_target_size "${rgb_in}" "" 100000
    246   cjpegli_test_target_size "${rgb_in}" "--chroma_subsampling 420" 20000
    247   cjpegli_test_target_size "${rgb_in}" "--xyb" 20000
    248   cjpegli_test_target_size "${rgb_in}" "-p 0 --fixed_code" 20000
    249 
    250   cjpegli_test "jxl/flower/flower_small.rgb.depth8.ppm" "" 88.5 1.7
    251   cjpegli_test "jxl/flower/flower_small.rgb.depth16.ppm" "" 89 1.7
    252   cjpegli_test "jxl/flower/flower_small.g.depth8.pgm" "" 89 1.7
    253   cjpegli_test "jxl/flower/flower_small.g.depth16.pgm" "" 89 1.7
    254 
    255   cjpegli_djpegli_test "${rgb_in}" "" 89 1.7
    256   cjpegli_djpegli_test "${rgb_in}" "--xyb" 87 1.5
    257 
    258   djpegli_test "${ppm_rgb}" "-q 95" 92
    259   djpegli_test "${ppm_rgb}" "-q 95 -sample 1x1" 93
    260   djpegli_test "${ppm_gray}" "-q 95 -gray" 94
    261 
    262   cjpeg_test "${ppm_rgb}" "" 89 1.9
    263   cjpeg_test "${ppm_rgb}" "-optimize" 89 1.85
    264   cjpeg_test "${ppm_rgb}" "-optimize -progressive" 89 1.8
    265   cjpeg_test "${ppm_rgb}" "-sample 2x2" 87 1.65
    266   cjpeg_test "${ppm_rgb}" "-sample 1x2" 88 1.75
    267   cjpeg_test "${ppm_rgb}" "-sample 2x1" 88 1.75
    268   cjpeg_test "${ppm_rgb}" "-grayscale" -50 1.45
    269   cjpeg_test "${ppm_rgb}" "-rgb" 92 4.5
    270   cjpeg_test "${ppm_rgb}" "-restart 1" 89 1.9
    271   cjpeg_test "${ppm_rgb}" "-restart 1024B" 89 1.9
    272   cjpeg_test "${ppm_rgb}" "-smooth 30" 88 1.75
    273   cjpeg_test "${ppm_gray}" "-grayscale" 92 1.45
    274   # The -q option works differently on v62 vs. v8 cjpeg binaries, so we have to
    275   # have looser bounds than would be necessary if we sticked to a particular
    276   # cjpeg version.
    277   cjpeg_test "${ppm_rgb}" "-q 50" 76 0.95
    278   cjpeg_test "${ppm_rgb}" "-q 80" 84 1.6
    279   cjpeg_test "${ppm_rgb}" "-q 90" 89 2.35
    280   cjpeg_test "${ppm_rgb}" "-q 100" 95 7.45
    281 
    282   djpeg_test "${ppm_rgb}" "-q 95" 92
    283   djpeg_test "${ppm_rgb}" "-q 95 -sample 1x1" 93
    284   djpeg_test "${ppm_gray}" "-q 95 -gray" 94
    285 }
    286 
    287 main "$@"