1#!/usr/bin/env python3 2# SPDX-License-Identifier: Apache-2.0 3# ----------------------------------------------------------------------------- 4# Copyright 2021-2022 Arm Limited 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); you may not 7# use this file except in compliance with the License. You may obtain a copy 8# of the License at: 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15# License for the specific language governing permissions and limitations 16# under the License. 17# ----------------------------------------------------------------------------- 18""" 19The ``astc_quality_test`` utility provides a tool to sweep quality settings. 20""" 21 22import numpy as np 23import re 24import subprocess as sp 25import sys 26 27 28def get_psnr_pattern(): 29 return r"\s*PSNR \(LDR-RGB\):\s*([0-9.]*) dB" 30 31 32def get_coding_rate_pattern(): 33 return r"\s*Coding rate:\s*([0-9.]*) MT/s" 34 35 36def parse_output(output): 37 # Regex pattern for image quality 38 patternPSNR = re.compile(get_psnr_pattern()) 39 patternCRate = re.compile(get_coding_rate_pattern()) 40 41 # Extract results from the log 42 runPSNR = None 43 runCRate = None 44 45 for line in output: 46 match = patternPSNR.match(line) 47 if match: 48 runPSNR = float(match.group(1)) 49 50 match = patternCRate.match(line) 51 if match: 52 runCRate = float(match.group(1)) 53 54 assert runPSNR is not None, "No coding PSNR found" 55 assert runCRate is not None, "No coding rate found" 56 return (runPSNR, runCRate) 57 58def execute(command): 59 """ 60 Run a subprocess with the specified command. 61 62 Args: 63 command (list(str)): The list of command line arguments. 64 65 Returns: 66 list(str): The output log (stdout) split into lines. 67 """ 68 try: 69 result = sp.run(command, stdout=sp.PIPE, stderr=sp.PIPE, 70 check=True, universal_newlines=True) 71 except (OSError, sp.CalledProcessError): 72 print("ERROR: Test run failed") 73 print(" + %s" % " ".join(command)) 74 qcommand = ["\"%s\"" % x for x in command] 75 print(" + %s" % ", ".join(qcommand)) 76 sys.exit(1) 77 78 return result.stdout.splitlines() 79 80def main(): 81 """ 82 The main function. 83 84 Returns: 85 int: The process return code. 86 """ 87 for block in ("4x4", "5x5", "6x6", "8x8", "10x10"): 88 89 for quality in range (0, 101, 2): 90 91 resultsQ = [] 92 resultsS = [] 93 94 if (quality < 40): 95 repeats = 20 96 elif (quality < 75): 97 repeats = 10 98 else: 99 repeats = 5 100 101 for _ in range(0, repeats): 102 command = [ 103 "./bin/astcenc-avx2", 104 "-tl", 105 "./Test/Images/Kodak/LDR-RGB/ldr-rgb-kodak23.png", 106 "/dev/null", 107 block, 108 "%s" % quality, 109 "-silent" 110 ] 111 112 stdout = execute(command) 113 psnr, mts = parse_output(stdout) 114 resultsQ.append(psnr) 115 resultsS.append(mts) 116 117 print("%s, %u, %0.3f, %0.3f" % (block, quality, np.mean(resultsS), np.mean(resultsQ))) 118 119 120 return 0 121 122 123if __name__ == "__main__": 124 sys.exit(main()) 125