add truck post

This commit is contained in:
2026-03-08 00:08:39 -07:00
parent 809bb3c081
commit d3efb33db8
28 changed files with 238 additions and 25 deletions
+173 -25
View File
@@ -116,6 +116,52 @@ human_size() {
fi
}
# ---------------------------------------------------------------------------
# Manifest: track which images have been optimized (skip re-processing)
# ---------------------------------------------------------------------------
MANIFEST_FILE=".image-manifest"
manifest_hash() {
sha256sum "$1" | cut -d' ' -f1
}
# Look up a file's stored hash; prints it or empty string if not found
manifest_lookup() {
local file="$1"
if [[ -f "$MANIFEST_FILE" ]]; then
grep -F " $file" "$MANIFEST_FILE" 2>/dev/null | head -1 | awk '{print $1}' || true
fi
}
# Update or add a file's hash in the manifest
manifest_update() {
local file="$1"
local hash
hash=$(manifest_hash "$file")
if [[ ! -f "$MANIFEST_FILE" ]]; then
echo "# fosscat.com image optimization manifest — do not edit manually" > "$MANIFEST_FILE"
fi
# Remove existing entry for this file (if any)
if grep -qF " $file" "$MANIFEST_FILE" 2>/dev/null; then
grep -vF " $file" "$MANIFEST_FILE" > "${MANIFEST_FILE}.tmp"
mv "${MANIFEST_FILE}.tmp" "$MANIFEST_FILE"
fi
# Append new entry
echo "$hash $file" >> "$MANIFEST_FILE"
}
# Remove a file's entry from the manifest
manifest_remove() {
local file="$1"
if [[ -f "$MANIFEST_FILE" ]] && grep -qF " $file" "$MANIFEST_FILE" 2>/dev/null; then
grep -vF " $file" "$MANIFEST_FILE" > "${MANIFEST_FILE}.tmp"
mv "${MANIFEST_FILE}.tmp" "$MANIFEST_FILE"
fi
}
# ---------------------------------------------------------------------------
# Utility: confirm prompt (respects --yes and --dry-run)
# ---------------------------------------------------------------------------
@@ -394,6 +440,9 @@ phase_strip_metadata() {
exiftool -all= -overwrite_original "$img" 2>/dev/null
stripped=$((stripped + 1))
echo -e " ${GREEN}$fname${NC} — metadata stripped"
# Update manifest since file content changed
manifest_update "$img"
done
echo ""
@@ -423,6 +472,7 @@ phase_convert() {
echo -e " ${DIM}(dry-run) Would delete: $(basename "$img") ($(human_size "$fsize"))${NC}"
else
rm -f "$img"
manifest_remove "$img"
echo -e " ${RED}Deleted:${NC} $(basename "$img") ($(human_size "$fsize"))"
fi
done
@@ -430,12 +480,14 @@ phase_convert() {
fi
echo -e "${BOLD}Converting images to WebP (quality $WEBP_QUALITY, max ${MAX_WIDTH}x${MAX_HEIGHT})${NC}"
printf " %-40s %-12s %-12s %s\n" "FILENAME" "BEFORE" "AFTER" "SAVINGS"
printf " %-40s %-12s %-12s %s\n" "--------" "------" "-----" "-------"
printf " %-40s %-12s %-12s %s\n" "FILENAME" "BEFORE" "AFTER" "STATUS"
printf " %-40s %-12s %-12s %s\n" "--------" "------" "-----" "------"
local total_before=0
local total_after=0
local converted=0
local skipped=0
local resized_only=0
for img in "${image_files[@]}"; do
[[ -z "$img" ]] && continue
@@ -446,6 +498,7 @@ phase_convert() {
fname=$(basename "$img")
local ext="${fname##*.}"
local base="${fname%.*}"
local ext_lower
ext_lower=$(echo "$ext" | tr '[:upper:]' '[:lower:]')
local webp_path="$IMAGES_DIR/${base}.webp"
@@ -453,14 +506,33 @@ phase_convert() {
before_size=$(stat -c%s "$img" 2>/dev/null || stat -f%z "$img" 2>/dev/null)
total_before=$((total_before + before_size))
# --- Manifest-based skip logic ---
local current_hash stored_hash
current_hash=$(manifest_hash "$img")
stored_hash=$(manifest_lookup "$img")
if [[ "$ext_lower" == "webp" ]] && [[ "$current_hash" == "$stored_hash" ]] && [[ -n "$stored_hash" ]]; then
# Already optimized, hash unchanged — skip entirely
total_after=$((total_after + before_size))
skipped=$((skipped + 1))
printf " %-40s %-12s %-12s ${DIM}%s${NC}\n" \
"$fname" "$(human_size "$before_size")" "—" "already optimized"
continue
fi
if $DRY_RUN; then
echo -e " ${DIM}(dry-run) Would convert: $fname -> ${base}.webp${NC}"
# Estimate: assume 80% reduction for JPEGs, 70% for PNGs, 10% for existing WebP
if [[ "$ext_lower" == "webp" ]] && [[ -n "$stored_hash" ]] && [[ "$current_hash" != "$stored_hash" ]]; then
echo -e " ${DIM}(dry-run) $fname — edited, would check dimensions only${NC}"
elif [[ "$ext_lower" == "webp" ]] && [[ -z "$stored_hash" ]]; then
echo -e " ${DIM}(dry-run) $fname — new webp, would record in manifest${NC}"
else
echo -e " ${DIM}(dry-run) Would convert: $fname -> ${base}.webp${NC}"
fi
local est_after=$before_size
case "$ext_lower" in
jpg|jpeg) est_after=$((before_size / 5)) ;;
png) est_after=$((before_size / 3)) ;;
webp) est_after=$((before_size * 9 / 10)) ;;
webp) est_after=$before_size ;;
esac
total_after=$((total_after + est_after))
converted=$((converted + 1))
@@ -476,7 +548,47 @@ phase_convert() {
needs_resize=true
fi
# Determine the input for cwebp
# --- Already WebP (edited or new): skip lossy re-compression ---
if [[ "$ext_lower" == "webp" ]]; then
if $needs_resize; then
# Resize oversized WebP via ImageMagick (lossless resize, no re-encoding)
local tmp_resized
tmp_resized=$(mktemp /tmp/optimg_XXXXXX.webp)
magick "$img" -resize "${MAX_WIDTH}x${MAX_HEIGHT}>" "$tmp_resized"
local new_dims
new_dims=$(magick identify -format '%wx%h' "$tmp_resized")
mv "$tmp_resized" "$img"
info " Resized $fname: ${cur_width}x${cur_height} -> $new_dims"
resized_only=$((resized_only + 1))
fi
# Record in manifest (whether resized or just newly tracked)
manifest_update "$img"
local after_size
after_size=$(stat -c%s "$img" 2>/dev/null || stat -f%z "$img" 2>/dev/null)
total_after=$((total_after + after_size))
if $needs_resize; then
local savings=0
if (( before_size > 0 )); then
savings=$(( (before_size - after_size) * 100 / before_size ))
fi
printf " %-40s %-12s %-12s ${CYAN}%s${NC}\n" \
"$fname" "$(human_size "$before_size")" "$(human_size "$after_size")" "resized (${savings}%)"
elif [[ -z "$stored_hash" ]]; then
printf " %-40s %-12s %-12s ${GREEN}%s${NC}\n" \
"$fname" "$(human_size "$before_size")" "—" "recorded"
else
printf " %-40s %-12s %-12s ${CYAN}%s${NC}\n" \
"$fname" "$(human_size "$before_size")" "—" "updated (edited)"
fi
converted=$((converted + 1))
continue
fi
# --- Non-WebP image: full convert + compress pipeline ---
local cwebp_input="$img"
local tmp_resized=""
@@ -488,24 +600,17 @@ phase_convert() {
cwebp_input="$tmp_resized"
fi
# Convert to WebP via cwebp (handles JPEG/PNG/WebP input natively)
if [[ "$ext_lower" == "webp" ]] && [[ "$img" == "$webp_path" ]]; then
# Same input and output: use temp output
local tmp_webp
tmp_webp=$(mktemp /tmp/optimg_XXXXXX.webp)
cwebp -q "$WEBP_QUALITY" "$cwebp_input" -o "$tmp_webp" 2>/dev/null
mv "$tmp_webp" "$webp_path"
else
cwebp -q "$WEBP_QUALITY" "$cwebp_input" -o "$webp_path" 2>/dev/null
fi
# Convert to WebP via cwebp
cwebp -q "$WEBP_QUALITY" "$cwebp_input" -o "$webp_path" 2>/dev/null
# Cleanup temp file if we resized
[[ -n "$tmp_resized" ]] && rm -f "$tmp_resized"
# Step 3: Delete original if it's not already .webp
if [[ "$ext_lower" != "webp" ]]; then
rm -f "$img"
fi
# Delete original non-WebP source
rm -f "$img"
# Record the new WebP in the manifest
manifest_update "$webp_path"
local after_size
after_size=$(stat -c%s "$webp_path" 2>/dev/null || stat -f%z "$webp_path" 2>/dev/null)
@@ -529,16 +634,27 @@ phase_convert() {
echo ""
local total_savings=0
if (( total_before > 0 )); then
if (( total_before > 0 )) && (( total_after > 0 )); then
total_savings=$(( (total_before - total_after) * 100 / total_before ))
fi
info "Converted $converted image(s)"
info "Total: $(human_size $total_before) -> $(human_size $total_after) (${total_savings}% reduction)"
if (( skipped > 0 )); then
info "Skipped $skipped already-optimized image(s)"
fi
if (( resized_only > 0 )); then
info "Resized $resized_only edited image(s) (no re-compression)"
fi
info "Processed $converted image(s)"
if (( total_before > total_after )); then
info "Total: $(human_size $total_before) -> $(human_size $total_after) (${total_savings}% reduction)"
else
info "Total size: $(human_size $total_after)"
fi
# Save totals for summary
echo "$total_before" > /tmp/optimg_total_before.txt
echo "$total_after" > /tmp/optimg_total_after.txt
echo "$converted" > /tmp/optimg_converted.txt
echo "$skipped" > /tmp/optimg_skipped.txt
}
# ---------------------------------------------------------------------------
@@ -656,10 +772,11 @@ phase_summary() {
echo ""
fi
local total_before total_after converted
local total_before total_after converted skipped
total_before=$(cat /tmp/optimg_total_before.txt 2>/dev/null || cat /tmp/optimg_total_size.txt 2>/dev/null || echo 0)
total_after=$(cat /tmp/optimg_total_after.txt 2>/dev/null || echo 0)
converted=$(cat /tmp/optimg_converted.txt 2>/dev/null || echo 0)
skipped=$(cat /tmp/optimg_skipped.txt 2>/dev/null || echo 0)
local savings=0
if (( total_before > 0 )) && (( total_after > 0 )); then
@@ -667,10 +784,41 @@ phase_summary() {
fi
echo -e " Images processed: ${BOLD}$converted${NC}"
if (( total_after > 0 )); then
if (( skipped > 0 )); then
echo -e " Images skipped: ${BOLD}$skipped${NC} (already optimized)"
fi
if (( total_after > 0 )) && (( total_before > total_after )); then
echo -e " Size before: ${BOLD}$(human_size "$total_before")${NC}"
echo -e " Size after: ${BOLD}$(human_size "$total_after")${NC}"
echo -e " Total reduction: ${BOLD}${GREEN}${savings}%${NC}"
elif (( total_after > 0 )); then
echo -e " Total size: ${BOLD}$(human_size "$total_after")${NC}"
fi
# Clean up stale manifest entries (files that no longer exist)
if [[ -f "$MANIFEST_FILE" ]] && ! $DRY_RUN; then
local stale=0
local manifest_tmp
manifest_tmp=$(mktemp /tmp/optimg_manifest_XXXXXX.txt)
while IFS= read -r line; do
# Keep comment lines
if [[ "$line" == \#* ]]; then
echo "$line" >> "$manifest_tmp"
continue
fi
# Extract filename (second field, after hash + two spaces)
local entry_file
entry_file=$(echo "$line" | awk '{print $2}')
if [[ -z "$entry_file" ]] || [[ -f "$entry_file" ]]; then
echo "$line" >> "$manifest_tmp"
else
stale=$((stale + 1))
fi
done < "$MANIFEST_FILE"
mv "$manifest_tmp" "$MANIFEST_FILE"
if (( stale > 0 )); then
info "Removed $stale stale manifest entry/entries"
fi
fi
echo ""