192 lines
4.5 KiB
Bash
Executable file
192 lines
4.5 KiB
Bash
Executable file
#!/usr/bin/env nix-shell
|
|
#! nix-shell -i bash --pure
|
|
#! nix-shell -p bash coreutils imagemagick libjpeg optipng ffmpeg diffutils
|
|
# vim: filetype=sh
|
|
|
|
set -euo pipefail
|
|
|
|
# Optimizes everything the script can find in a folder,
|
|
# meaning it will compress files as much as possible,
|
|
# without losing any data (verification will be done
|
|
# in order to verify that no data has been done)
|
|
# (executable)
|
|
|
|
# TODO Run in parallel
|
|
# TODO Lots of dupplicated code there
|
|
# TODO Maybe replace part with https://github.com/toy/image_optim?
|
|
|
|
dir=${1:-$PWD}
|
|
total=$(mktemp)
|
|
echo -n 0 > "$total"
|
|
|
|
function showtotal {
|
|
echo "Total saved: $(cat "$total") bytes"
|
|
rm "$total"
|
|
exit
|
|
}
|
|
|
|
trap showtotal SIGTERM SIGINT SIGFPE
|
|
|
|
function doReplace { # candidate original
|
|
mv "$c" "$o"
|
|
saved=$((os - cs))
|
|
perc=$((100 * saved / os))
|
|
echo "→ $os ⇒ $cs (saved $saved bytes, or ${perc}%)"
|
|
newtotal=$(($(cat "$total") + saved))
|
|
echo -n $newtotal > "$total"
|
|
}
|
|
|
|
function replace { # candidate original
|
|
c="$1"
|
|
o="$2"
|
|
|
|
# File verifications
|
|
if [ ! -f "$o" ]; then
|
|
echo "→ Original is inexistant, skipping!"
|
|
return
|
|
fi
|
|
if [ ! -f "$c" ]; then
|
|
echo "→ Candidate is inexistant, skipping!"
|
|
return
|
|
fi
|
|
|
|
# Size verifications
|
|
cs=$(wc -c "$c" | cut -d' ' -f1)
|
|
os=$(wc -c "$o" | cut -d' ' -f1)
|
|
if [ "$cs" -le 0 ]; then
|
|
echo "→ Candidate is empty, skipping!"
|
|
rm "$c"
|
|
return
|
|
fi
|
|
if [ "$cs" -eq "$os" ]; then
|
|
echo "→ Candidate weight the same, skipping."
|
|
rm "$c"
|
|
return
|
|
fi
|
|
if [ "$cs" -gt "$os" ]; then
|
|
echo "→ Candidate is larger, skipping."
|
|
rm "$c"
|
|
return
|
|
fi
|
|
|
|
doReplace "$c" "$o"
|
|
}
|
|
|
|
# function replaceImg { # candidate original
|
|
# # With bitmap verification
|
|
#
|
|
# c="$1"
|
|
# o="$2"
|
|
#
|
|
# # File verifications
|
|
# if [ ! -f "$o" ]; then
|
|
# echo "→ Original is inexistant, skipping!"
|
|
# return
|
|
# fi
|
|
# if [ ! -f "$c" ]; then
|
|
# echo "→ Candidate is inexistant, skipping!"
|
|
# return
|
|
# fi
|
|
#
|
|
# # Size verifications
|
|
# cs=$(wc -c "$c" | cut -d' ' -f1)
|
|
# os=$(wc -c "$o" | cut -d' ' -f1)
|
|
# if [ $cs -le 0 ]; then
|
|
# echo "→ Candidate is empty, skipping!"
|
|
# rm "$c"
|
|
# return
|
|
# fi
|
|
# if [ $cs -eq $os ]; then
|
|
# echo "→ Candidate weight the same, skipping."
|
|
# rm "$c"
|
|
# return
|
|
# fi
|
|
# if [ $cs -gt $os ]; then
|
|
# echo "→ Candidate is larger, skipping."
|
|
# rm "$c"
|
|
# return
|
|
# fi
|
|
#
|
|
# # Bitmap verification
|
|
# ppmc="$(mktemp --suffix .ppm)"
|
|
# ppmo="$(mktemp --suffix .ppm)"
|
|
# convert "$c" "$ppmc"
|
|
# convert "$o" "$ppmo"
|
|
#
|
|
# if cmp --silent "$ppmo" "$ppmc"; then
|
|
# doReplace "$c" "$o"
|
|
# else
|
|
# echo "→ Candidate don't have the same bit map as original, skipping!"
|
|
# fi
|
|
# rm -f "$ppmc" "$ppmo" "$c"
|
|
#
|
|
# }
|
|
|
|
# JPEG (requires jpegtran)
|
|
while read -r image
|
|
do
|
|
if [ -z "$image" ]; then continue; fi
|
|
echo Processing "$image"
|
|
|
|
prog=$(mktemp --suffix .jpg)
|
|
jpegtran -copy all -progressive "$image" > "$prog"
|
|
echo "→ Progressive done"
|
|
replace "$prog" "$image"
|
|
|
|
|
|
done <<< "$(find "$dir/" -type f -iregex ".+.jpe?g$")"
|
|
|
|
# PNG (requires optipng)
|
|
while read -r image
|
|
do
|
|
if [ -z "$image" ]; then continue; fi
|
|
echo Processing "$image"
|
|
|
|
temp=$(mktemp --suffix .png)
|
|
cp "$image" "$temp"
|
|
optipng -quiet "$temp"
|
|
echo "→ Optimize done"
|
|
|
|
replace "$temp" "$image"
|
|
|
|
done <<< "$(find "$dir/" -type f -iname "*.png")"
|
|
|
|
# FLAC (requires ffmpeg)
|
|
while read -r music
|
|
do
|
|
if [ -z "$music" ]; then continue; fi
|
|
echo "Processing $music"
|
|
|
|
temp=$(mktemp --suffix .flac)
|
|
ffmpeg -nostdin -y -i "$music" -compression_level 8 "$temp"
|
|
echo "→ Optimize done"
|
|
|
|
replace "$temp" "$music"
|
|
|
|
done <<< "$(find "$dir/" -type f -iname "*.flac")"
|
|
|
|
# # SVG (requires scour)
|
|
# while read image
|
|
# do
|
|
# if [ -z "$image" ]; then continue; fi
|
|
# echo Processing $image
|
|
#
|
|
# temp=$(mktemp --suffix .svg)
|
|
# scour --quiet "$image" "$temp" --no-line-breaks
|
|
# echo "→ Optimize done"
|
|
#
|
|
# replaceImg "$temp" "$image"
|
|
#
|
|
# done <<< "$(find "$dir/" -type f -iname "*.svg")"
|
|
|
|
# NOTE Explicitely disabled since:
|
|
# - I only have ~50 MiB of SVG in TOTAL
|
|
# - Most conversions are not image losseless
|
|
# - Even when they are losseless, they are mostly worthless
|
|
# - I might want to keep editor data and/or ids for some of them
|
|
# So rather use scour explicitely when needed
|
|
|
|
cleandev
|
|
|
|
showtotal
|