Guest User

mozjpeg-optimizer-v1.sh

a guest
Jun 11th, 2021
1,499
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 7.95 KB | None | 0 0
  1. #!/bin/bash
  2. #This script recursively simulates compression of jpg and png files to jpg files without significant loss in visual quality with "mozjpeg" (https://github.com/mozilla/mozjpeg) with 21 sets of parameters that were tested to produce the smallest files most of the time. Parameter set with the best results is then used to produce the smallest possible jpg files. This script asks whether the original files should be preserved or replaced with the compressed files. To make processing faster, rest of the compression simulations are skipped if the first simulation produces files that are larger than the original files. Thus, files compressed with this script are also always smaller than the original files.
  3.  
  4. #8 june 2021 v1
  5. #mozjpeg-optimizer-v1.sh was written in 8 june 2021 and tested to be functional with mozjpeg v 4.0.4 on Debian 10. This script works with files/folders containing at least %, $, *, white spaces horizontal tabs or newlines. Parameters in this script include "-nojfif". This prevents JFIF write to the compressed jpg files and reduces their size by 18 bytes, but this breaks standards and may cause problems e.g. in some file viewers. "mozjpeg" command denoted in this script in mozjpeg v 4.0.4 is actually "cjpeg" unless a symbolic link after mozjpeg installation is created like so:
  6. #sudo ln -s /opt/mozjpeg/bin/cjpeg /usr/bin/mozjpeg
  7. #If no symbolic link is created, replace all instances of "mozjpeg" in this script to "cjpeg" to be able to use this script.
  8.  
  9. #COPYRIGHT: this script is made available under the Creative Commons CC0 1.0 Universal Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/deed.en). The original creator of this script has no affiliation with "mozjpeg" or "Mozilla".
  10.  
  11. printf "START:\t`date`\n"
  12. printf "Size in bytes:\norig.\tnow\t%% of orig.\tname and path (seconds spent processing) parameters used\n"
  13.  
  14. #Temp files to RAM as variables.
  15. R0="$(mktemp -p /dev/shm/)"
  16. R1="$(mktemp -p /dev/shm/)"
  17. R2="$(mktemp -p /dev/shm/)"
  18.  
  19. while IFS= read -r -d '' i; do
  20.     S=`date +%s`
  21.     #Filename and size saved. If the name has newlines or tabs, they are converted to spaces so the names display well on terminal.
  22.     name="$(stat --printf="%n" "$i" | tr '\n' ' ' | tr '\t' ' ')"
  23.     size="$(stat --printf="%s" "$i")"
  24.  
  25.     #Compression is simulated once. Compressed size in bytes are extracted and saved to a variable along with the used parameters.
  26.     mozjpeg -memdst -dct float -quant-table 1 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  27.     n=$(grep -oE "[0-9]+" "$R0"); printf "$n\t-dct float -quant-table 1 -nojfif -dc-scan-opt 2" > "$R1"
  28.  
  29.     #If compressed size is smaller than original size, then other parameters are skipped. Else: other parameters are tested.
  30.     if(($size < $n)); then
  31.         printf '%s\n' "$size    ----    skipped     $name"
  32.  
  33.     else
  34.         mozjpeg -memdst -dct float -quant-table 2 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  35.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-dct float -quant-table 2 -nojfif -dc-scan-opt 2" >> "$R1"
  36.         mozjpeg -memdst -dct float -quant-table 3 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  37.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-dct float -quant-table 3 -nojfif -dc-scan-opt 2" >> "$R1"
  38.         mozjpeg -memdst -dct float -tune-ms-ssim -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  39.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-dct float -tune-ms-ssim -nojfif -dc-scan-opt 2" >> "$R1"
  40.         mozjpeg -memdst -dct float -tune-ms-ssim -quant-table 3 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  41.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-dct float -tune-ms-ssim -quant-table 3 -nojfif -dc-scan-opt 2" >> "$R1"
  42.         mozjpeg -memdst -dct float -tune-ssim -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  43.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-dct float -tune-ssim -nojfif -dc-scan-opt 2" >> "$R1"
  44.         mozjpeg -memdst -dct float -tune-ssim -quant-table 0 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  45.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-dct float -tune-ssim -quant-table 0 -nojfif -dc-scan-opt 2" >> "$R1"
  46.         mozjpeg -memdst -dct float -tune-ssim -quant-table 1 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  47.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-dct float -tune-ssim -quant-table 1 -nojfif -dc-scan-opt 2" >> "$R1"
  48.         mozjpeg -memdst -dct float -tune-ssim -quant-table 2 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  49.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-dct float -tune-ssim -quant-table 2 -nojfif -dc-scan-opt 2" >> "$R1"
  50.         mozjpeg -memdst -dct float -tune-ssim -quant-table 3 -nojfif -dc-scan-opt 1 "$i" > "$R0" 2>&1
  51.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-dct float -tune-ssim -quant-table 3 -nojfif -dc-scan-opt 1" >> "$R1"
  52.         mozjpeg -memdst -dct float -tune-ssim -quant-table 3 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  53.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-dct float -tune-ssim -quant-table 3 -nojfif -dc-scan-opt 2" >> "$R1"
  54.         mozjpeg -memdst -dct float -tune-ssim -quant-table 4 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  55.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-dct float -tune-ssim -quant-table 4 -nojfif -dc-scan-opt 2" >> "$R1"
  56.         mozjpeg -memdst -quant-table 2 -nojfif -dc-scan-opt 1 "$i" > "$R0" 2>&1
  57.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-quant-table 2 -nojfif -dc-scan-opt 1" >> "$R1"
  58.         mozjpeg -memdst -quant-table 2 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  59.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-quant-table 2 -nojfif -dc-scan-opt 2" >> "$R1"
  60.         mozjpeg -memdst -tune-ssim -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  61.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-tune-ssim -nojfif -dc-scan-opt 2" >> "$R1"
  62.         mozjpeg -memdst -tune-ssim -quant-table 1 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  63.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-tune-ssim -quant-table 1 -nojfif -dc-scan-opt 2" >> "$R1"
  64.         mozjpeg -memdst -tune-ssim -quant-table 2 -nojfif "$i" > "$R0" 2>&1
  65.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-tune-ssim -quant-table 2 -nojfif" >> "$R1"
  66.         mozjpeg -memdst -tune-ssim -quant-table 2 -nojfif -dc-scan-opt 0 "$i" > "$R0" 2>&1
  67.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-tune-ssim -quant-table 2 -nojfif -dc-scan-opt 0" >> "$R1"
  68.         mozjpeg -memdst -tune-ssim -quant-table 2 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  69.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-tune-ssim -quant-table 2 -nojfif -dc-scan-opt 2" >> "$R1"
  70.         mozjpeg -memdst -tune-ssim -quant-table 3 -nojfif -dc-scan-opt 1 "$i" > "$R0" 2>&1
  71.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-tune-ssim -quant-table 3 -nojfif -dc-scan-opt 1" >> "$R1"
  72.         mozjpeg -memdst -tune-ssim -quant-table 3 -nojfif -dc-scan-opt 2 "$i" > "$R0" 2>&1
  73.         n=$(grep -oE "[0-9]+" "$R0"); printf "\n$n\t-tune-ssim -quant-table 3 -nojfif -dc-scan-opt 2" >> "$R1"
  74.  
  75.         #Smallest bytesize is found via sort from simulation info. Parameters used to obtain this size are extracted and used in mozjpeg to produce an actual compressed file.
  76.         sort -n "$R1" > "$R2"
  77.         par=$(head -n1 "$R2" | cut -f2)
  78.         mozjpeg $par "$i" > "$i.opti.jpg"
  79.  
  80.         #Time spent on processing and compressed vs original size in percentage are calculated and diplayed.
  81.         size2=$(head -n1 "$R2" | cut -f1)
  82.         percent=$((200*$size2/$size % 2 + 100*$size2/$size))
  83.         E=`date +%s`
  84.         T=$(("$E"-"$S"))
  85.         printf '%s\n' "$size    $size2  $percent        $name ($T) $par"
  86.     fi
  87. #Finds recursively files with variable extensions. Add "-maxdepth 1" after "find" to search non-recursively. To compress e.g. png files only, remove "-iname '*.jpg' -o -iname '*.jpeg' -o".
  88. done < <(find . -type f \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \) -print0)
  89.  
  90. #Temp files are removed from RAM.
  91. rm -f "$R0" "$R1" "$R2"
  92.  
  93. printf "END:\t`date`\n"
  94.  
  95. read -r -p "Replace original jpg or png files with compressed .opti.jpg backups? Press Y for YES or N for NO and press ENTER. Note: compressed files are always smaller." response
  96. if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]
  97. then
  98.     find . -type f -name '*.opti.jpg' -exec bash -c 'mv "$1" "${1/%.opti.jpg/}"' -- {} \;
  99.     printf "Done. Original files were replaced.\n"
  100. else
  101.     printf "Done. Original and compressed files were preserved. Compressed files have .opti.jpg suffix.\n"
  102. fi
  103.  
Advertisement
Add Comment
Please, Sign In to add comment