-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoptimize-images.sh
More file actions
executable file
·342 lines (307 loc) · 10.4 KB
/
Copy pathoptimize-images.sh
File metadata and controls
executable file
·342 lines (307 loc) · 10.4 KB
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
#!/bin/bash
# ============================================================================
# Image Optimization Script
# ============================================================================
#
# Purpose:
# Optimizes image files to reduce size while maintaining quality.
# - Resizes images larger than 3840px (width or height) to fit within 3840x3840
# - Optimizes all images to 85% JPEG quality
# - Strips metadata by default (for privacy and file size)
#
# Usage:
# ./optimize-images.sh [options] [directory]
#
# Options:
# --auto Process all images without asking for confirmation
# --interactive Ask for confirmation for each image (default)
# --keep-metadata Preserve image metadata (default: strip metadata)
# --quality N Set JPEG quality (1-100, default: 85)
# --max-size N Set maximum image dimension (default: 3840)
# --git-only Only process staged images in git repositories
# --help Show this help message
#
# Directory:
# Path to directory containing images (default: current directory)
#
# Examples:
# ./optimize-images.sh # Interactive mode, all images
# ./optimize-images.sh --auto # Auto mode, all images
# git add . && ./optimize-images.sh --git-only # Process only staged git images
# ./optimize-images.sh --quality 90 # Custom quality, all images
# ./optimize-images.sh --max-size 2048 --auto # Custom settings, all images
#
# Requirements:
# - ImageMagick (install with: sudo apt-get install imagemagick)
# - Git (optional, only needed for --git-only mode)
#
# IMPORTANT: For --git-only mode, run 'git add .' first to stage files.
# This allows the script to detect new/modified images while respecting .gitignore.
#
# ============================================================================
# Default settings
INTERACTIVE=true
STRIP_METADATA=true
QUALITY=85
MAX_SIZE=3840
GIT_ONLY=false
DIRECTORY="."
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
--auto)
INTERACTIVE=false
shift
;;
--interactive)
INTERACTIVE=true
shift
;;
--keep-metadata)
STRIP_METADATA=false
shift
;;
--quality)
if [[ $2 =~ ^[0-9]+$ ]] && [ $2 -ge 1 ] && [ $2 -le 100 ]; then
QUALITY=$2
shift 2
else
echo "Error: Quality must be a number between 1 and 100"
exit 1
fi
;;
--max-size)
if [[ $2 =~ ^[0-9]+$ ]] && [ $2 -ge 100 ]; then
MAX_SIZE=$2
shift 2
else
echo "Error: Max size must be a number >= 100"
exit 1
fi
;;
--git-only)
GIT_ONLY=true
shift
;;
--help)
head -n 40 "$0" | grep "^#" | sed 's/^# \?//'
exit 0
;;
-*)
echo "Unknown option: $1"
echo "Use --help for usage information"
exit 1
;;
*)
DIRECTORY="$1"
shift
;;
esac
done
# Check requirements
if ! command -v mogrify &> /dev/null; then
echo "Error: ImageMagick is not installed."
echo ""
echo "Please install ImageMagick:"
echo " Ubuntu/Debian: sudo apt-get install imagemagick"
echo " macOS: brew install imagemagick"
echo " Windows WSL: sudo apt-get install imagemagick"
exit 1
fi
if ! command -v identify &> /dev/null; then
echo "Error: ImageMagick 'identify' command not found."
echo "Please ensure ImageMagick is properly installed."
exit 1
fi
if [ "$GIT_ONLY" = true ]; then
if ! command -v git &> /dev/null; then
echo "Error: Git is not installed (required for --git-only mode)."
exit 1
fi
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo "Error: Not in a git repository (required for --git-only mode)."
echo "Please run this script from within your project directory or remove --git-only."
exit 1
fi
fi
# Check if directory exists
if [ ! -d "$DIRECTORY" ]; then
echo "Error: Directory '$DIRECTORY' does not exist."
exit 1
fi
# Change to target directory
cd "$DIRECTORY" || exit 1
# Find images based on mode
if [ "$GIT_ONLY" = true ]; then
# Git mode: Find staged and modified images in git repository
# This requires running 'git add .' first to stage files
images=$(git status --porcelain | grep -E '^A |^M ' | grep -E '\.(jpg|jpeg|png)$' | awk '{print $2}')
# If no staged images found, suggest running git add
if [ -z "$images" ]; then
echo "No staged images found."
echo ""
echo "IMPORTANT: You need to stage files first with 'git add .' to detect images."
echo "This allows the script to find new and modified images while respecting .gitignore."
echo ""
echo "Run: git add . && ./optimize-images.sh --git-only [options]"
echo "Or use: ./optimize-images.sh (to process all images regardless of git status)"
exit 0
fi
else
# Default: Find all images in directory
images=$(find . -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" | sed 's|^\./||')
fi
if [ -z "$images" ]; then
if [ "$GIT_ONLY" = true ]; then
echo "No staged images found."
else
echo "No images found in directory: $DIRECTORY"
fi
exit 0
fi
# Count images
image_count=$(echo "$images" | wc -l)
# Show what the script will do
echo "============================================"
echo "Image Optimization Script"
echo "============================================"
echo ""
echo "Directory: $(pwd)"
echo "Found $image_count image(s)"
echo ""
echo "This script will:"
echo " • Resize images larger than ${MAX_SIZE}px to fit within ${MAX_SIZE}x${MAX_SIZE}"
echo " • Optimize all images to ${QUALITY}% quality"
if [ "$STRIP_METADATA" = true ]; then
echo " • Strip metadata (EXIF, GPS, etc.)"
else
echo " • Keep metadata"
fi
echo ""
if [ "$INTERACTIVE" = true ]; then
echo "Mode: Interactive (will ask for each image)"
else
echo "Mode: Automatic (will process all images)"
fi
echo ""
# Process statistics
total_before=0
total_after=0
processed_count=0
skipped_count=0
# Process each image
for img in $images; do
# Check if file exists (in case it was deleted after finding)
if [ ! -f "$img" ]; then
echo "Warning: $img no longer exists, skipping."
((skipped_count++))
continue
fi
# Get file info
size_before=$(stat -f%z "$img" 2>/dev/null || stat -c%s "$img" 2>/dev/null || echo "0")
size_kb=$(( size_before / 1024 ))
# Get image dimensions
dimensions=$(identify -format "%wx%h" "$img" 2>/dev/null || echo "unknown")
width=$(echo "$dimensions" | cut -d'x' -f1)
height=$(echo "$dimensions" | cut -d'x' -f2)
# Determine if resize is needed
needs_resize=false
new_dimensions=""
if [[ "$width" =~ ^[0-9]+$ ]] && [[ "$height" =~ ^[0-9]+$ ]]; then
if [ "$width" -gt "$MAX_SIZE" ] || [ "$height" -gt "$MAX_SIZE" ]; then
needs_resize=true
# Calculate new dimensions maintaining aspect ratio
if [ "$width" -gt "$height" ]; then
new_width=$MAX_SIZE
new_height=$(( (height * MAX_SIZE) / width ))
else
new_height=$MAX_SIZE
new_width=$(( (width * MAX_SIZE) / height ))
fi
new_dimensions="${new_width}x${new_height}"
fi
fi
# Show image info
echo "----------------------------------------"
echo "Image: $img"
echo "Current: ${size_kb}KB, ${dimensions}"
# Show what will be done
echo "Actions:"
if [ "$needs_resize" = true ]; then
echo " • Resize to approximately $new_dimensions"
else
echo " • No resize needed (within ${MAX_SIZE}x${MAX_SIZE})"
fi
echo " • Optimize to ${QUALITY}% quality"
if [ "$STRIP_METADATA" = true ]; then
echo " • Strip metadata"
else
echo " • Keep metadata"
fi
# Ask for confirmation if in interactive mode
if [ "$INTERACTIVE" = true ]; then
echo -n "Process this image? [Y/n/q] "
read -r answer
case "$answer" in
[nN])
echo "Skipped."
((skipped_count++))
continue
;;
[qQ])
echo ""
echo "Quitting. Processed $processed_count image(s), skipped $skipped_count."
exit 0
;;
esac
fi
# Build mogrify command arguments
mogrify_args=()
# Add resize if needed
if [ "$needs_resize" = true ]; then
mogrify_args+=("-resize" "${MAX_SIZE}x${MAX_SIZE}>")
fi
# Add quality setting
mogrify_args+=("-quality" "$QUALITY")
# Add strip metadata if requested
if [ "$STRIP_METADATA" = true ]; then
mogrify_args+=("-strip")
fi
# Execute the command with proper argument handling
mogrify "${mogrify_args[@]}" "$img"
if [ $? -eq 0 ]; then
# Get new size
size_after=$(stat -f%z "$img" 2>/dev/null || stat -c%s "$img" 2>/dev/null || echo "0")
# Calculate reduction
if [ "$size_before" -gt 0 ]; then
reduction=$(( ((size_before - size_after) * 100) / size_before ))
else
reduction=0
fi
# Update totals
total_before=$((total_before + size_before))
total_after=$((total_after + size_after))
((processed_count++))
echo "✓ Optimized: $(( size_before / 1024 ))KB → $(( size_after / 1024 ))KB (-${reduction}%)"
else
echo "✗ Error processing image"
((skipped_count++))
fi
done
# Show summary
echo ""
echo "============================================"
echo "Summary:"
echo " • Processed: $processed_count image(s)"
echo " • Skipped: $skipped_count image(s)"
if [ "$processed_count" -gt 0 ] && [ "$total_before" -gt 0 ]; then
total_reduction=$(( ((total_before - total_after) * 100) / total_before ))
echo " • Total size: $(( total_before / 1024 ))KB → $(( total_after / 1024 ))KB (-${total_reduction}%)"
fi
echo ""
if [ "$GIT_ONLY" = true ]; then
echo "Use 'git status' to see the changes."
echo "Use 'git add' to stage the optimized images."
else
echo "All images in directory processed."
fi