dotfiles/hm/scripts/optimize

192 lines
4.5 KiB
Plaintext
Raw Permalink Normal View History

#!/usr/bin/env nix-shell
#! nix-shell -i bash --pure
#! nix-shell -p bash coreutils imagemagick libjpeg optipng ffmpeg diffutils
2024-11-07 14:47:39 +01:00
# vim: filetype=sh
2016-12-31 01:11:31 +01:00
2024-11-07 14:47:39 +01:00
set -euo pipefail
2023-11-19 22:41:09 +01:00
2016-12-31 01:11:31 +01:00
# 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
2018-01-08 12:26:49 +01:00
# TODO Lots of dupplicated code there
2023-11-19 22:41:09 +01:00
# TODO Maybe replace part with https://github.com/toy/image_optim?
2016-12-31 01:11:31 +01:00
dir=${1:-$PWD}
total=$(mktemp)
2024-11-07 14:47:39 +01:00
echo -n 0 > "$total"
2016-12-31 01:11:31 +01:00
function showtotal {
echo "Total saved: $(cat "$total") bytes"
2024-11-07 14:47:39 +01:00
rm "$total"
2016-12-31 01:11:31 +01:00
exit
}
trap showtotal SIGTERM SIGINT SIGFPE
2018-01-08 12:26:49 +01:00
function doReplace { # candidate original
mv "$c" "$o"
2024-11-07 14:47:39 +01:00
saved=$((os - cs))
perc=$((100 * saved / os))
2018-01-08 12:26:49 +01:00
echo "→ $os ⇒ $cs (saved $saved bytes, or ${perc}%)"
2024-11-07 14:47:39 +01:00
newtotal=$(($(cat "$total") + saved))
echo -n $newtotal > "$total"
2018-01-08 12:26:49 +01:00
}
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)
2024-11-07 14:47:39 +01:00
if [ "$cs" -le 0 ]; then
2018-01-08 12:26:49 +01:00
echo "→ Candidate is empty, skipping!"
rm "$c"
return
fi
2024-11-07 14:47:39 +01:00
if [ "$cs" -eq "$os" ]; then
2018-01-08 12:26:49 +01:00
echo "→ Candidate weight the same, skipping."
rm "$c"
return
fi
2024-11-07 14:47:39 +01:00
if [ "$cs" -gt "$os" ]; then
2018-01-08 12:26:49 +01:00
echo "→ Candidate is larger, skipping."
rm "$c"
return
fi
doReplace "$c" "$o"
}
2024-11-07 14:47:39 +01:00
# 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"
#
# }
2016-12-31 01:11:31 +01:00
# JPEG (requires jpegtran)
2024-11-07 14:47:39 +01:00
while read -r image
2016-12-31 01:11:31 +01:00
do
2017-07-02 22:06:24 +02:00
if [ -z "$image" ]; then continue; fi
2024-11-07 14:47:39 +01:00
echo Processing "$image"
2016-12-31 01:11:31 +01:00
prog=$(mktemp --suffix .jpg)
jpegtran -copy all -progressive "$image" > "$prog"
echo "→ Progressive done"
2018-01-08 12:26:49 +01:00
replace "$prog" "$image"
2016-12-31 01:11:31 +01:00
2019-10-17 12:44:30 +02:00
done <<< "$(find "$dir/" -type f -iregex ".+.jpe?g$")"
2016-12-31 01:11:31 +01:00
# PNG (requires optipng)
2024-11-07 14:47:39 +01:00
while read -r image
2016-12-31 01:11:31 +01:00
do
2017-07-02 22:06:24 +02:00
if [ -z "$image" ]; then continue; fi
2024-11-07 14:47:39 +01:00
echo Processing "$image"
2016-12-31 01:11:31 +01:00
temp=$(mktemp --suffix .png)
cp "$image" "$temp"
2018-01-08 12:26:49 +01:00
optipng -quiet "$temp"
2016-12-31 01:11:31 +01:00
echo "→ Optimize done"
2018-01-08 12:26:49 +01:00
replace "$temp" "$image"
2016-12-31 01:11:31 +01:00
2019-10-17 12:44:30 +02:00
done <<< "$(find "$dir/" -type f -iname "*.png")"
2016-12-31 01:11:31 +01:00
# FLAC (requires ffmpeg)
2024-11-07 14:47:39 +01:00
while read -r music
2019-11-01 18:34:45 +01:00
do
if [ -z "$music" ]; then continue; fi
2024-11-07 14:47:39 +01:00
echo "Processing $music"
2019-11-01 18:34:45 +01:00
temp=$(mktemp --suffix .flac)
2024-11-07 14:47:39 +01:00
ffmpeg -nostdin -y -i "$music" -compression_level 8 "$temp"
2019-11-01 18:34:45 +01:00
echo "→ Optimize done"
replace "$temp" "$music"
done <<< "$(find "$dir/" -type f -iname "*.flac")"
2018-08-13 12:20:09 +02:00
# # 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"
#
2019-10-17 12:44:30 +02:00
# done <<< "$(find "$dir/" -type f -iname "*.svg")"
2018-08-13 12:20:09 +02:00
# 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
2016-12-31 01:11:31 +01:00
2024-11-07 14:47:39 +01:00
cleandev
2016-12-31 01:11:31 +01:00
showtotal