#!/usr/bin/env bash # Use this Bash script to test RT processing speed. # Written by DrSlony # v1 2012-02-10 # v2 2013-02-15 # v3 2013-03-04 # v4 2013-03-07 # v5 2013-03-23 # v6 2017-07-03 # v7 2017-07-04 # www.rawtherapee.com inFile='http://rawtherapee.com/shared/test_images/colorspace_flowers.pef' rtExe="rawtherapee-cli" OPTIND=1 # Reset in case getopts has been used previously in the shell. tmpDir="/tmp/rawtherapee-benchmark" runs=5 echo die () { printf '%s\n' "Cleaning up." rm -rv "${tmpDir}" exit 1 } trap die HUP INT QUIT ABRT TERM download () { local retries=3 while [[ $retries -ne 0 ]]; do wget --progress=dot:binary --continue --trust-server-names --tries=1 --timestamping "$1" 2>&1 | sed "s/^/\t/" return=${PIPESTATUS[0]} ((retries--)) if [[ $return -eq 0 ]]; then # I don't trust wget to only exit with 0 if it downloaded the file successfully, so I check. if [[ -f "$(basename "$1")" ]]; then break fi fi printf "%s\n\n" "Failed to download \"$1\"" "Retrying: " sleep 1s done if [[ $retries -eq 0 ]]; then printf "%s\n" "Tried to download \"$1\" 3 times but failed. Exiting." exit 1 fi } howto() { cat< - Absolute path to image file. This can be a file on your hard drive or a url. The url must start with "http". The default behavior if you do not specify -i is to download a raw image from ${inFile} -s -s -s - Absolute path to sidecar file. You can specify multiple sidecar files, use -s each time. The processing profile can be a file on your hard drive or a url. The default behaviour if you do not specify -s is to use the "Neutral" profile. Examples -------- Run the default benchmark (recommended) ./benchmarkRT Run a benchmark using your own image file, a RawTherpee executable in a custom directory, and multiple processing profiles: ./benchmarkRT -i /tmp/kittens.raw -s /tmp/noise_reduction.pp3 -s /tmp/tonemapping.pp3 -s /tmp/retinex.pp3 Further Help ------------ If you need further help, discover bugs or want to request new functionality, then tell us in the forum or on IRC: https://discuss.pixls.us/t/welcome-to-the-rawtherapee-forum-read-this-first/473 http://webchat.freenode.net/?randomnick=1&channels=rawtherapee&prompt=1 END } OPTIND=1 while getopts "ae:i:s:h?" opt; do case "$opt" in a) testAllTools=1 ;; e) customExeDir="${OPTARG%/}" ;; i) inFile="$OPTARG" ;; s) sidecarCustom+=("$OPTARG") ;; h|\?|*) howto exit 0 ;; esac done shift $((OPTIND-1)) [ "$1" = "--" ] && shift inFileName="$(basename "${inFile}")" if [[ ! -e "${tmpDir}" ]]; then if [[ ! -w /tmp ]]; then printf "Error: /tmp is not writable.\n" exit 1 fi mkdir "$tmpDir" fi cd "$tmpDir" if [[ ${inFile} = http* ]]; then # if inFile is a url and if we haven't downloaded it already, then download it [[ ! -e "${tmpDir}/${inFileName}" ]] && { printf "%s\n\n" "${inFileName} not found in ${tmpDir}, downloading it." [[ ! -w /tmp ]] && { printf "Error: /tmp is not writable.\n"; exit 1; } [[ ! -e "$tmpDir" ]] && mkdir "$tmpDir" cd "$tmpDir" download "$inFile" echo } else # otherwise if inFile is not a url, check if it exists [[ ! -e "${inFile}" ]] && { # if it doesn't exist, choke printf "%s\n" "You specified" "-i ${inFile}" "but that file does not exist." exit 1 } cp "${inFile}" "${tmpDir}/${inFileName}" fi rtExeDirs=("${customExeDir}" "${HOME}/rt" "${HOME}/programs/code-rawtherapee/build/release" "${HOME}/rt_${branch}_${buildType}" "${HOME}/rawtherapee/") found="false" for rtExeDir in "${rtExeDirs[@]}"; do if [[ -x "${rtExeDir}/${rtExe}" ]]; then found="true" break fi done if [[ $found = false ]]; then printf "%s\n" "Could not find the RawTherapee executable." "Re-run this script using the -e flag." exit 0 fi if [[ $testAllTools -ne 1 ]]; then if [[ -n "${sidecarCustom}" ]]; then # if sidecarCustom was specified for sidecarFile in "${sidecarCustom[@]}"; do if [[ ${sidecarFile} = http* ]]; then # and if sidecarCustom starts with an http if [[ ! -e "${tmpDir}/$/{sidecarFile##*/}" ]]; then # and if sidecarCustom hasn't been previously downloaded, then download it printf "${sidecarCustom} not found in ${tmpDir}, downloading it.\n" download "$sidecarCustom" fi fi if [[ -e "${sidecarFile}" ]]; then # then check if it exists sidecarFinal+=("${sidecarFile}") else printf '%s\n' "You specified \"-s ${sidecarFile}\" but it does not exist. Make sure you wrote a full, absolute path, e.g.:" " -s /tmp/custom.pp3" exit 1 fi done unset sidecarFiles sidecarFiles=("${sidecarCustom[@]}") else # if sidecarCustom was not specified, use neutral. Since neutral is not a file, # we take advantage of the fact that when RawTherapee does not find a processing profile, it uses neutral values. sidecarFinal=("Neutral") fi else unset sidecarFiles avgTable sidecarDir sidecarDir="${tmpDir}/" tools=("Auto Exposure;Exposure;Auto=true" "Sharpening - Unsharp Mask;Sharpening;Enabled=true;Method=usm" "Sharpening - RL Deconvolution;Sharpening;Enabled=true;Method=rld" "Vibrance;Vibrance;Enabled=true" "Edges;SharpenEdge;Enabled=true" "Microcontrast;SharpenMicro;Enabled=true" "CIECAM02;Color appearance;Enabled=true" "Impulse Noise Reduction;Impulse Denoising;Enabled=true" "Defringe;Defringing;Enabled=true" "Noise Reduction;Directional Pyramid Denoising;Enabled=true" "Tone Mapping;EPD;Enabled=true" "Shadows/Highlights;Shadows & Highlights;Enabled=true" "Contrast by Detail Levels;Directional Pyramid Equalizer;Enabled=true" "Raw Chromatic Aberration;RAW;CA=true") for i in "${!tools[@]}"; do IFS=";" read toolNameHuman tool key1 key2 key3 <<< "${tools[$i]}" i=$(printf "%02d\n" "$i") printf "%s\n" "[${tool}]" "$key1" "$key2" "$key3" > "${sidecarDir}/${i} - ${tool}.pp3" sidecarFinal+=("${i} - ${tool}.pp3;${toolNameHuman}") done fi printf "%s\n" "$(uname -srvmpio)" "" hash cpufreq-info 2>/dev/null && { cpufreq-info -mo; printf "%s\n" ""; } printf "%s\n" "RawTherapee executable: ${rtExeDir}/${rtExe}" if [[ ! -f "${rtExeDir}/AboutThisBuild.txt" ]]; then printf "%s\n" "[Could not find ${rtExeDir}/AboutThisBuild.txt]" "" else cat "${rtExeDir}/AboutThisBuild.txt" fi printf "%s\n" "Photo: ${tmpDir}/${inFileName}" for sidecar in "${sidecarFinal[@]}"; do if [[ $testAllTools -eq 1 ]]; then IFS=";" read sidecar toolNameHuman <<< "${sidecar}" fi printf "%s\n" "Sidecar: ${sidecarDir}${sidecar}" done echo declare -A avgTable unset benchmark total sidecar sorted # Unfudge numbers to make sed/PE possible without spaghetti. export LC_ALL=C for s in "${!sidecarFinal[@]}"; do IFS=";" read sidecar toolNameHuman <<< "${sidecarFinal[s]}" unset benchmark for (( i=1; i<=${runs}; i++ )); do runTime="$( { time "${rtExeDir}/${rtExe}" -o /dev/null/ -p "${sidecarDir}${sidecar}" -t -Y -c "${tmpDir}/${inFileName}"; } 2>&1 | grep ^real; )" # runTime=real 0m4.751s runTime=${runTime#*[[:blank:]]} # runTime=0m4.751s minOnly=${runTime%m*} secOnly=${runTime#*m}; secOnly=${secOnly%s*} t="$( printf "%s\n" "scale=3; $secOnly+$minOnly*60" | bc )" # t=4.751 ## t="$(( $RANDOM %20 )).$(( $RANDOM %999 ))" # benchmark stores time array of each run, gets reset after each PP3 benchmark+=("$t") # total stores time array of each run, doesn't get reset, adds up total afterwards total+=("$t") i="$(printf "%02d\n" "$i")" if [[ $testAllTools -eq 1 ]]; then printf "%*b" "-50" "Benchmark ${i} \"${toolNameHuman}\"" "7" "${benchmark[$i - 1]}" "" "\n" | sed 's/ /../g' else printf "%*b" "-50" "Benchmark ${i} \"${sidecar##*/}\"" "7" "${benchmark[$i - 1]}" "" "\n" | sed 's/ /../g' fi done avg=$( { printf "%s" "scale=3; ("; IFS="+"; printf "%s" "${benchmark[*]}"; printf "%s\n" ") / ${#benchmark[@]}"; } | bc ); if [[ $testAllTools -eq 1 ]]; then printf "%*b" "-50" "Benchmark \"${toolNameHuman}\" average" "7" "${avg}" "" "\n\n" | sed 's/ /../g' avgTable+=(["${toolNameHuman}"]="$avg") else printf "%*b" "-50" "Benchmark \"${sidecar##*/}\" average" "7" "${avg}" "" "\n\n" | sed 's/ /../g' avgTable+=(["${sidecar}"]="$avg") fi done printf "%*b" "-50" "Benchmark total" "7" "$(IFS=+; bc -l <<< "${total[*]}")" "" "\n\n" | sed 's/ /../g' # Associative arrays don't return in alphanumerical order, must be sorted manually IFS=$'\n' sorted=($(sort <<<"${!avgTable[*]}")); printf "%s\n" "Average times for each set:" for x in "${sorted[@]}"; do printf "%*b" "-50" "${x}" "7" "${avgTable[$x]}" "" "\n" | sed 's/ /../g' done