about summary refs log tree commit diff stats
path: root/scripts/optimize_images.sh
blob: 75f04af4f478089abb6506417aa137a7eb968571 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env nix
#! nix shell nixpkgs#optipng nixpkgs#jpegoptim nixpkgs#nodePackages.svgo nixpkgs#dash --command dash

# Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# This file is part of Quotify - A simple CLI utility to shell quote the text
# inputted into it.
#
# You should have received a copy of the License along with this program.
# If not, see <https://www.gnu.org/licenses/agpl.txt>.

# shellcheck shell=dash

# source: https://github.com/stride-tasks/stride/blob/148d513297c8ae66d79fc287769adfe5e711c93c/scripts/optimize-images

PROJECT_DIR="$(git rev-parse --show-toplevel)"

cd "$PROJECT_DIR" || {
    echo "No '$PROJECT_DIR' ?!"
    exit 1
}

PNG_OPITMIZE_COMMAND='optipng --quiet -o7 -preserve'
JPG_OPITMIZE_COMMAND='jpegoptim --quiet --strip-all -m76'
SVG_OPITMIZE_COMMAND='svgo --multipass --quiet --input'

# The extension is the part after the first dot in the filename:
#
# For example:
# file.png    => png
# file.tar.gz => tar.gz
find_files_by_extension() {
    wanted_extension="$1"
    tmp="$(mktemp)"

    git ls-files --cached --modified --other --exclude-standard --deduplicate | while IFS= read -r file; do
        extension="${file#*.}"
        if [ "$extension" = "$wanted_extension" ]; then
            echo "$file"
        else
            :
            # echo "'$file' with extension: '$extension' does not match filter: '$wanted_extension'" 1>&2
        fi
    done >"$tmp"

    echo "$tmp"
}

size_of() {
    du -b "$1" | cut -f1
}

bytes_human() {
    number="$1"

    numfmt --to=iec-i --suffix=B --format="%9.2f" "$number"
}

# https://stackoverflow.com/questions/44695878/how-to-calculate-percentage-in-shell-script
# Native POSIX solution using string manipulation (assumes integer inputs).
percent() {
    DP="$1"
    SDC="$2"

    # Special case when DP is zero.
    [ "$DP" = "0" ] && echo "0.00" && return

    #                                  # e.g. round down   e.g. round up
    #                                  # DP=1 SDC=3        DP=2 SDC=3
    Percent=$((DP * 100000 / SDC + 5)) # Percent=33338     Percent=66671
    Whole=${Percent%???}               # Whole=33          Whole=66
    Percent=${Percent#"$Whole"}        # Percent=338       Percent=671
    Percent=$Whole.${Percent%?}        # Percent=33.33     Percent=66.67
    echo "$Percent"
}

TOTAL=0
TOTAL_SAVED=0

optimize_files() {
    FILTER="$1"
    PROGRAM="$2"

    printf "%s" "Processing $FILTER files:"

    FILES="$(find_files_by_extension "$FILTER")"
    COUNT=$(wc -l <"$FILES")

    if [ "$COUNT" -eq 0 ]; then
        echo " no files found!"
        return
    fi

    echo ""

    I=1

    TOTAL_INNER=0
    TOTAL_SAVED_INNER=0

    while IFS= read -r f; do
        printf "%-2s/${COUNT} $f ... " "$I"

        SIZE="$(size_of "$f")"

        $PROGRAM "$f"

        NEW_SIZE="$(size_of "$f")"
        DIFF=$((SIZE - NEW_SIZE))

        echo "saved: $(bytes_human "$DIFF") ($(percent $DIFF "$SIZE")%)"

        TOTAL_INNER=$((TOTAL_INNER + SIZE))
        TOTAL_SAVED_INNER=$((TOTAL_SAVED_INNER + DIFF))

        I=$((I + 1))
    done <"$FILES"
    rm "$FILES"

    echo "Total saved for $FILTER: $(bytes_human "$TOTAL_SAVED_INNER") ($(percent $TOTAL_SAVED_INNER $TOTAL_INNER)%)"
    echo ""

    TOTAL=$((TOTAL + TOTAL_INNER))
    TOTAL_SAVED=$((TOTAL_SAVED + TOTAL_SAVED_INNER))
}

optimize_files 'png' "$PNG_OPITMIZE_COMMAND"
optimize_files 'jpg' "$JPG_OPITMIZE_COMMAND"
optimize_files 'jpeg' "$JPG_OPITMIZE_COMMAND"
optimize_files 'svg' "$SVG_OPITMIZE_COMMAND"

echo "Total saved: $(bytes_human "$TOTAL_SAVED") ($(percent $TOTAL_SAVED $TOTAL)%)"