# ImageMagick Batch Processing Complete guide to batch operations, mogrify command, parallel processing, and automation. ## Mogrify Command ### Basic Mogrify Modify files in-place (overwrites originals). ```bash # Resize all JPEGs mogrify -resize 800x600 *.jpg # Convert format (creates new files) mogrify -format png *.jpg # Apply effect to all images mogrify -quality 85 -strip *.jpg ``` **Warning:** mogrify modifies files in-place. Always backup originals or use `-path` to output to different directory. ### Output to Different Directory Preserve originals. ```bash # Create output directory first mkdir output # Process to output directory mogrify -path ./output -resize 800x600 *.jpg # With format conversion mogrify -path ./optimized -format webp -quality 80 *.png ``` ## Common Batch Operations ### Resize All Images ```bash # Resize to width 800 mogrify -resize 800x *.jpg # Resize to height 600 mogrify -resize x600 *.jpg # Fit within 800×600 mogrify -resize 800x600 *.jpg # Resize to exact dimensions mogrify -resize 800x600! *.jpg # Only shrink, never enlarge mogrify -resize 800x600\> *.jpg ``` ### Format Conversion ```bash # PNG to JPEG mogrify -path ./jpg -format jpg -quality 85 *.png # JPEG to WebP mogrify -path ./webp -format webp -quality 80 *.jpg # Any format to PNG mogrify -path ./png -format png *.{jpg,gif,bmp} ``` ### Optimize Images ```bash # Strip metadata from all JPEGs mogrify -strip *.jpg # Optimize JPEGs for web mogrify -quality 85 -strip -interlace Plane *.jpg # Compress PNGs mogrify -quality 95 *.png # Combined optimization mogrify -quality 85 -strip -interlace Plane -sampling-factor 4:2:0 *.jpg ``` ### Apply Effects ```bash # Add watermark to all images mogrify -gravity southeast -draw "image over 10,10 0,0 'watermark.png'" *.jpg # Convert all to grayscale mogrify -colorspace Gray *.jpg # Apply sepia tone mogrify -sepia-tone 80% *.jpg # Sharpen all images mogrify -sharpen 0x1 *.jpg ``` ### Thumbnail Generation ```bash # Create square thumbnails mogrify -path ./thumbnails -resize 200x200^ -gravity center -extent 200x200 *.jpg # Create thumbnails with max dimension mogrify -path ./thumbs -thumbnail 300x300 *.jpg # Thumbnails with quality control mogrify -path ./thumbs -thumbnail 200x200 -quality 80 -strip *.jpg ``` ## Shell Loops ### Basic For Loop More control than mogrify. ```bash # Resize with custom naming for img in *.jpg; do magick "$img" -resize 800x600 "resized_$img" done # Process to subdirectory mkdir processed for img in *.jpg; do magick "$img" -resize 1920x1080 "processed/$img" done ``` ### Multiple Operations ```bash # Complex processing pipeline for img in *.jpg; do magick "$img" \ -resize 1920x1080^ \ -gravity center \ -crop 1920x1080+0+0 +repage \ -unsharp 0x1 \ -quality 85 -strip \ "processed_$img" done ``` ### Format Conversion with Rename ```bash # Convert PNG to JPEG with new names for img in *.png; do magick "$img" -quality 90 "${img%.png}.jpg" done # Add prefix during conversion for img in *.jpg; do magick "$img" -resize 800x "web_${img}" done ``` ### Conditional Processing ```bash # Only process large images for img in *.jpg; do width=$(identify -format "%w" "$img") if [ $width -gt 2000 ]; then magick "$img" -resize 2000x "resized_$img" fi done # Skip existing output files for img in *.jpg; do output="output_$img" if [ ! -f "$output" ]; then magick "$img" -resize 800x "$output" fi done ``` ## Parallel Processing ### GNU Parallel Process multiple images simultaneously. ```bash # Install GNU Parallel # Ubuntu/Debian: sudo apt-get install parallel # macOS: brew install parallel # Basic parallel resize parallel magick {} -resize 800x600 resized_{} ::: *.jpg # Parallel with function resize_image() { magick "$1" -resize 1920x1080 -quality 85 "processed_$1" } export -f resize_image parallel resize_image ::: *.jpg # Limit concurrent jobs parallel -j 4 magick {} -resize 800x {} ::: *.jpg # Progress indicator parallel --progress magick {} -resize 800x {} ::: *.jpg ``` ### Xargs Parallel ```bash # Using xargs for parallel processing ls *.jpg | xargs -I {} -P 4 magick {} -resize 800x processed_{} # With find find . -name "*.jpg" -print0 | \ xargs -0 -I {} -P 4 magick {} -resize 800x {} ``` ## Advanced Batch Patterns ### Recursive Processing ```bash # Process all JPEGs in subdirectories find . -name "*.jpg" -exec magick {} -resize 800x {} \; # With output directory structure find . -name "*.jpg" -type f | while read img; do outdir="output/$(dirname "$img")" mkdir -p "$outdir" magick "$img" -resize 800x "$outdir/$(basename "$img")" done ``` ### Batch with Different Sizes ```bash # Generate multiple sizes for size in 320 640 1024 1920; do mkdir -p "output/${size}w" for img in *.jpg; do magick "$img" -resize ${size}x -quality 85 "output/${size}w/$img" done done # Parallel version for size in 320 640 1024 1920; do mkdir -p "output/${size}w" parallel magick {} -resize ${size}x -quality 85 "output/${size}w/{}" ::: *.jpg done ``` ### Responsive Image Set ```bash # Create responsive image set with srcset mkdir -p responsive for img in *.jpg; do base="${img%.jpg}" for width in 320 640 1024 1920; do magick "$img" -resize ${width}x -quality 85 \ "responsive/${base}-${width}w.jpg" done done ``` ### Watermark Batch ```bash # Add watermark to all images for img in *.jpg; do magick "$img" watermark.png \ -gravity southeast -geometry +10+10 \ -composite "watermarked_$img" done # Different watermark positions for portrait vs landscape for img in *.jpg; do width=$(identify -format "%w" "$img") height=$(identify -format "%h" "$img") if [ $width -gt $height ]; then # Landscape magick "$img" watermark.png -gravity southeast -composite "marked_$img" else # Portrait magick "$img" watermark.png -gravity south -composite "marked_$img" fi done ``` ## Error Handling ### Check Before Processing ```bash # Verify image before processing for img in *.jpg; do if identify "$img" > /dev/null 2>&1; then magick "$img" -resize 800x "processed_$img" else echo "Skipping corrupt image: $img" fi done ``` ### Log Processing ```bash # Log successful and failed operations log_file="batch_process.log" error_log="errors.log" for img in *.jpg; do if magick "$img" -resize 800x "output/$img" 2>> "$error_log"; then echo "$(date): Processed $img" >> "$log_file" else echo "$(date): Failed $img" >> "$error_log" fi done ``` ### Dry Run Mode ```bash # Test without modifying files dry_run=true for img in *.jpg; do cmd="magick $img -resize 800x processed_$img" if [ "$dry_run" = true ]; then echo "Would run: $cmd" else eval $cmd fi done ``` ## Optimization Workflows ### Web Publishing Pipeline ```bash # Complete web optimization workflow mkdir -p web/{original,optimized,thumbnails} # Copy originals cp *.jpg web/original/ # Create optimized versions mogrify -path web/optimized \ -resize 1920x1080\> \ -quality 85 \ -strip \ -interlace Plane \ web/original/*.jpg # Create thumbnails mogrify -path web/thumbnails \ -thumbnail 300x300 \ -quality 80 \ -strip \ web/original/*.jpg ``` ### Archive to Web Conversion ```bash # Convert high-res archives to web formats for img in archives/*.jpg; do base=$(basename "$img" .jpg) # Full size web version magick "$img" -resize 2048x2048\> -quality 90 -strip "web/${base}.jpg" # Thumbnail magick "$img" -thumbnail 400x400 -quality 85 "web/${base}_thumb.jpg" # WebP version magick "$img" -resize 2048x2048\> -quality 85 "web/${base}.webp" done ``` ### Print to Web Workflow ```bash # Convert print-ready images to web for img in print/*.tif; do base=$(basename "$img" .tif) # Convert colorspace and optimize magick "$img" \ -colorspace sRGB \ -resize 2000x2000\> \ -quality 90 \ -strip \ -interlace Plane \ "web/${base}.jpg" done ``` ## Batch Reporting ### Generate Report ```bash # Create processing report report="batch_report.txt" echo "Batch Processing Report - $(date)" > "$report" echo "================================" >> "$report" total=0 success=0 failed=0 for img in *.jpg; do ((total++)) if magick "$img" -resize 800x "output/$img" 2>/dev/null; then ((success++)) echo "✓ $img" >> "$report" else ((failed++)) echo "✗ $img" >> "$report" fi done echo "" >> "$report" echo "Total: $total, Success: $success, Failed: $failed" >> "$report" ``` ### Image Inventory ```bash # Create inventory of images inventory="image_inventory.csv" echo "Filename,Width,Height,Format,Size,ColorSpace" > "$inventory" for img in *.{jpg,png,gif}; do [ -f "$img" ] || continue info=$(identify -format "%f,%w,%h,%m,%b,%[colorspace]" "$img") echo "$info" >> "$inventory" done ``` ## Performance Tips ### Optimize Loop Performance ```bash # Bad: Launch mogrify for each file for img in *.jpg; do mogrify -resize 800x "$img" done # Good: Process all files in one mogrify call mogrify -resize 800x *.jpg # Best: Use parallel processing for complex operations parallel magick {} -resize 800x -quality 85 processed_{} ::: *.jpg ``` ### Memory Management ```bash # Limit memory for batch processing for img in *.jpg; do magick -limit memory 2GB -limit map 4GB \ "$img" -resize 50% "output/$img" done ``` ### Progress Tracking ```bash # Show progress for long batch operations total=$(ls *.jpg | wc -l) current=0 for img in *.jpg; do ((current++)) echo "Processing $current/$total: $img" magick "$img" -resize 800x "output/$img" done ``` ## Automation Scripts ### Complete Bash Script ```bash #!/bin/bash # Configuration INPUT_DIR="./input" OUTPUT_DIR="./output" QUALITY=85 MAX_WIDTH=1920 THUMBNAIL_SIZE=300 # Create output directories mkdir -p "$OUTPUT_DIR"/{full,thumbnails} # Process images echo "Processing images..." for img in "$INPUT_DIR"/*.{jpg,jpeg,png}; do [ -f "$img" ] || continue filename=$(basename "$img") base="${filename%.*}" # Full size magick "$img" \ -resize ${MAX_WIDTH}x\> \ -quality $QUALITY \ -strip \ "$OUTPUT_DIR/full/${base}.jpg" # Thumbnail magick "$img" \ -thumbnail ${THUMBNAIL_SIZE}x${THUMBNAIL_SIZE} \ -quality 80 \ -strip \ "$OUTPUT_DIR/thumbnails/${base}_thumb.jpg" echo "✓ $filename" done echo "Done!" ``` ### Python Batch Script ```python #!/usr/bin/env python3 import os import subprocess from pathlib import Path INPUT_DIR = Path("./input") OUTPUT_DIR = Path("./output") SIZES = [320, 640, 1024, 1920] # Create output directories for size in SIZES: (OUTPUT_DIR / f"{size}w").mkdir(parents=True, exist_ok=True) # Process images for img in INPUT_DIR.glob("*.jpg"): for size in SIZES: output = OUTPUT_DIR / f"{size}w" / img.name subprocess.run([ "magick", str(img), "-resize", f"{size}x", "-quality", "85", "-strip", str(output) ]) print(f"✓ {img.name} -> {size}w") ``` ## Common Batch Recipes ### Social Media Sizes ```bash # Generate social media image sizes for img in *.jpg; do base="${img%.jpg}" # Instagram square (1080×1080) magick "$img" -resize 1080x1080^ -gravity center -extent 1080x1080 "${base}_ig_square.jpg" # Instagram portrait (1080×1350) magick "$img" -resize 1080x1350^ -gravity center -extent 1080x1350 "${base}_ig_portrait.jpg" # Facebook post (1200×630) magick "$img" -resize 1200x630^ -gravity center -extent 1200x630 "${base}_fb_post.jpg" # Twitter post (1200×675) magick "$img" -resize 1200x675^ -gravity center -extent 1200x675 "${base}_tw_post.jpg" done ``` ### Email Newsletter Images ```bash # Optimize images for email mogrify -path ./email \ -resize 600x\> \ -quality 75 \ -strip \ -interlace Plane \ *.jpg ``` ### Backup and Archive ```bash # Create web versions and keep originals mkdir -p {originals,web} # Move originals mv *.jpg originals/ # Create optimized copies for img in originals/*.jpg; do base=$(basename "$img") magick "$img" -resize 2000x2000\> -quality 85 -strip "web/$base" done ```