Skip to content

Instantly share code, notes, and snippets.

@bect
Created October 24, 2025 15:29
Show Gist options
  • Select an option

  • Save bect/200f591a9a216cecc316614083798a07 to your computer and use it in GitHub Desktop.

Select an option

Save bect/200f591a9a216cecc316614083798a07 to your computer and use it in GitHub Desktop.
#!/bin/bash
# =========================================================
# Skrip Optimasi Gambar
# Fitur:
# ✅ Kompresi lossless JPG & PNG tanpa ubah kualitas
# ✅ Gunakan semua core CPU (GNU Parallel / xargs -P)
# ✅ Tambahkan suffix _optimized (kecuali --overwrite)
# ✅ Cache untuk melewati gambar yang sudah dioptimasi
# =========================================================
set -e
# Lokasi cache log
DIR_CACHE="$HOME/.cache/image-optimizer"
FILE_CATATAN="$DIR_CACHE/optimized-images.log"
# Buat folder cache jika belum ada
mkdir -p "$DIR_CACHE"
touch "$FILE_CATATAN"
# Default folder dan flag
FOLDER_TUJUAN_INPUT="${1:-$HOME/Pictures}"
FORCE_REOPTIMIZE=false
OVERWRITE=false
# Parsing argumen
for arg in "$@"; do
case $arg in
--force)
FORCE_REOPTIMIZE=true
;;
--overwrite)
OVERWRITE=true
;;
esac
done
# Normalisasi path (gunakan absolut)
FOLDER_TUJUAN=$(realpath "$FOLDER_TUJUAN_INPUT" 2>/dev/null || readlink -f "$FOLDER_TUJUAN_INPUT" || echo "$FOLDER_TUJUAN_INPUT")
# Fungsi hitung checksum
hitung_checksum() {
sha1sum "$1" | awk '{print $1}'
}
# Fungsi cek cache
sudah_dioptimasi() {
local gambar="$1"
local checksum
checksum=$(hitung_checksum "$gambar")
grep -qF "|$checksum|" "$FILE_CATATAN"
}
# Fungsi mencatat hasil
catat_gambar() {
local gambar="$1"
local checksum
checksum=$(hitung_checksum "$gambar")
local timestamp
timestamp=$(date +%s)
awk -F'|' -v file="$gambar" '$1 != file' "$FILE_CATATAN" > "$FILE_CATATAN.tmp" && mv "$FILE_CATATAN.tmp" "$FILE_CATATAN"
echo "$gambar|$checksum|$timestamp" >> "$FILE_CATATAN"
}
# Fungsi utama optimasi
optimasi_gambar() {
local gambar
gambar=$(realpath "$1" 2>/dev/null || readlink -f "$1" || echo "$1")
local ekstensi="${gambar##*.}"
local nama_dasar
nama_dasar="$(basename "${gambar%.*}")"
local direktori
direktori="$(dirname "$gambar")"
# Lewati file dengan _optimized
if [[ "$nama_dasar" == *_optimized ]]; then
echo "⏭ Lewati (sudah dioptimasi): $gambar"
return
fi
# Tentukan target output
local target="$direktori/${nama_dasar}_optimized.${ekstensi}"
if $OVERWRITE; then
target="$gambar"
fi
# Skip jika sudah dioptimasi (berdasar cache)
if ! $FORCE_REOPTIMIZE && sudah_dioptimasi "$gambar"; then
echo "✔ Sudah dioptimasi: $gambar"
return
fi
echo "🔧 Mengoptimasi: $gambar → $target"
case "${ekstensi,,}" in
jpg|jpeg)
if $OVERWRITE; then
jpegoptim --strip-all --all-progressive -q "$gambar"
else
jpegoptim --strip-all --all-progressive -q --stdout "$gambar" > "$target"
fi
;;
png)
if $OVERWRITE; then
optipng -o7 -quiet "$gambar"
else
optipng -o7 -quiet -out "$target" "$gambar"
fi
;;
*)
echo "⚠ Format tidak didukung: $gambar"
return
;;
esac
catat_gambar "$gambar"
}
# --- Jalankan proses ---
echo "🚀 Memulai optimasi di folder: $FOLDER_TUJUAN"
echo "💾 Log disimpan di: $FILE_CATATAN"
echo
# Temukan semua file gambar
CMD_FIND="find \"$FOLDER_TUJUAN\" -type f \\( -iname \"*.jpg\" -o -iname \"*.jpeg\" -o -iname \"*.png\" \\) ! -iname \"*_optimized.*\""
# Mode 1: GNU Parallel
if command -v parallel >/dev/null 2>&1; then
echo "⚡ Mode paralel aktif (GNU Parallel) — menggunakan $(nproc) core CPU"
export -f optimasi_gambar hitung_checksum sudah_dioptimasi catat_gambar
export FILE_CATATAN FORCE_REOPTIMIZE OVERWRITE
eval "$CMD_FIND" | parallel -j "$(nproc)" optimasi_gambar {}
# Mode 2: xargs dengan -P (multi-core basic)
elif xargs --help 2>&1 | grep -q -- "-P"; then
echo "⚙️ Mode paralel (xargs) — menggunakan $(nproc) core CPU"
export -f optimasi_gambar hitung_checksum sudah_dioptimasi catat_gambar
export FILE_CATATAN FORCE_REOPTIMIZE OVERWRITE
eval "$CMD_FIND" | xargs -I{} -P"$(nproc)" bash -c 'optimasi_gambar "$@"' _ {}
# Mode 3: Fallback loop tunggal
else
echo "💤 Mode tunggal (fallback, 1 core)"
eval "$CMD_FIND" | while read -r img; do
optimasi_gambar "$img"
done
fi
echo
echo "✅ Proses selesai!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment