libjxl

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

update_jpegli_global_scale.py (3090B)


      1 #!/usr/bin/python
      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 """Script to update jpegli global scale after a change affecting quality.
      8 
      9 start as ./update_jpegli_global_scale.py build <corpus-dir>
     10 """
     11 
     12 import os
     13 import re
     14 import subprocess
     15 import sys
     16 
     17 def SourceFileName():
     18   return "lib/jpegli/quant.cc"
     19 
     20 def ScalePattern(scale_type):
     21   return "constexpr float kGlobalScale" + scale_type + " = ";
     22 
     23 def CodecName(scale_type):
     24   if scale_type == "YCbCr":
     25     return "jpeg:enc-jpegli:q90"
     26   elif scale_type == "XYB":
     27     return "jpeg:enc-jpegli:xyb:q90"
     28   else:
     29     raise Exception("Unknown scale type %s" % scale_type)
     30   
     31 def ReadGlobalScale(scale_type):
     32   pattern = ScalePattern(scale_type)
     33   with open(SourceFileName()) as f:
     34     for line in f.read().splitlines():
     35       if line.startswith(pattern):
     36         return float(line[len(pattern):-2])
     37   raise Exception("Global scale %s not found." % scale_type)
     38   
     39     
     40 def UpdateGlobalScale(scale_type, new_val):
     41   pattern = ScalePattern(scale_type)
     42   found_pattern = False
     43   fdata = ""
     44   with open(SourceFileName()) as f:
     45     for line in f.read().splitlines():
     46       if line.startswith(pattern):
     47         fdata += pattern + "%.8ff;\n" % new_val
     48         found_pattern = True
     49       else:
     50         fdata += line + "\n"
     51   if not found_pattern:
     52     raise Exception("Global scale %s not found." % scale_type)
     53   with open(SourceFileName(), "w") as f:
     54     f.write(fdata)
     55     f.close()
     56 
     57 def EvalPnorm(build_dir, corpus_dir, codec):
     58   compile_args = ["ninja", "-C", build_dir, "tools/benchmark_xl"]
     59   try:
     60     subprocess.check_output(compile_args)
     61   except:
     62     subprocess.check_call(compile_args)
     63   process = subprocess.Popen(
     64     (os.path.join(build_dir, "tools/benchmark_xl"),
     65      "--input", os.path.join(corpus_dir, "*.png"),
     66      "--codec", codec),
     67     stdout=subprocess.PIPE,
     68     stderr=subprocess.PIPE)
     69   (out, err) = process.communicate(input=None)
     70   for line in out.splitlines():
     71     if line.startswith(codec):
     72       return float(line.split()[8])
     73   raise Exception("Unexpected benchmark output:\n%sstderr:\n%s" % (out, err))
     74 
     75 
     76 if len(sys.argv) != 3:
     77   print("usage: ", sys.argv[0], "build-dir corpus-dir")
     78   exit(1)
     79 
     80 build_dir = sys.argv[1]
     81 corpus_dir = sys.argv[2]
     82     
     83 jpeg_pnorm = EvalPnorm(build_dir, corpus_dir, "jpeg:q90")
     84 
     85 print("Libjpeg pnorm: %.8f" % jpeg_pnorm)
     86 
     87 for scale_type in ["YCbCr", "XYB"]:
     88   scale = ReadGlobalScale(scale_type)
     89   best_scale = scale
     90   best_rel_error = 100.0
     91   for i in range(10):
     92     jpegli_pnorm = EvalPnorm(build_dir, corpus_dir, CodecName(scale_type))
     93     rel_error = abs(jpegli_pnorm / jpeg_pnorm - 1)
     94     print("[%-5s] scale: %.8f  pnorm: %.8f  error: %.8f" %
     95           (scale_type, scale, jpegli_pnorm, rel_error))
     96     if rel_error < best_rel_error:
     97       best_rel_error = rel_error
     98       best_scale = scale
     99     if rel_error < 0.0001:
    100       break
    101     scale = scale * jpeg_pnorm / jpegli_pnorm
    102     UpdateGlobalScale(scale_type, scale)
    103   UpdateGlobalScale(scale_type, best_scale)