Created
August 12, 2025 09:48
-
-
Save Flower7C3/dba997eab4f945851fbfa58c3217c2d3 to your computer and use it in GitHub Desktop.
Wallpaper Crop Script - Automatic creation of wallpapers for vertical layout with aligned centers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Wallpaper Crop Script - Automatic creation of wallpapers for vertical layout with aligned centers | |
| # Usage: ./wallpaper-crop.sh <source_image> [--inches external_inches builtin_inches] [--position position] | |
| # Example: ./wallpaper-crop.sh wallpaper.jpg | |
| # Example: ./wallpaper-crop.sh wallpaper.jpg --inches 27 16 | |
| # Example: ./wallpaper-crop.sh wallpaper.jpg --inches 27 16 --position center-top | |
| # Function displays help | |
| function show_help() { | |
| echo "Usage: $0 <source_image> [options]" | |
| echo "" | |
| echo "This script creates wallpapers for vertical screens layout with aligned centers." | |
| echo "" | |
| echo "Options:" | |
| echo " --inches | -i <external_inches> <builtin_inches> Physical screen dimensions in inches (default: auto-detect)" | |
| echo " --position | -p <position> Cropping position (default: center-top)" | |
| echo " --help | -h Show this help" | |
| echo "" | |
| echo "Available cropping positions:" | |
| echo " left-top | lt Left top" | |
| echo " center-top | ct Center top" | |
| echo " right-top | rt Right top" | |
| echo " left-middle | lm Left middle" | |
| echo " center-middle | cm Center middle" | |
| echo " right-middle | rm Right middle" | |
| echo " left-bottom | lb Left bottom" | |
| echo " center-bottom | cb Center bottom" | |
| echo " right-bottom | rb Right bottom" | |
| echo "" | |
| echo "Examples:" | |
| echo " $0 wallpaper.jpg" | |
| echo " $0 wallpaper.jpg --inches 27 16" | |
| echo " $0 wallpaper.jpg --inches 27 16 --position left-top" | |
| echo "" | |
| echo "π‘ If you don't specify physical dimensions, the script will try to detect them automatically." | |
| } | |
| # Function gets screen dimensions from macOS system | |
| function get_screen_dimensions() { | |
| # Get screen information from macOS system | |
| local display_info=$(system_profiler SPDisplaysDataType 2>/dev/null) | |
| if [ -n "$display_info" ]; then | |
| # Extract all resolutions | |
| local all_resolutions=$(echo "$display_info" | grep "Resolution:" | sed 's/.*Resolution: \([0-9]*\) x \([0-9]*\).*/\1 \2/') | |
| local res_array=($all_resolutions) | |
| # Check if we have at least 2 screens (4 values: width and height for each) | |
| if [ ${#res_array[@]} -ge 4 ]; then | |
| # First screen is built-in, second is external | |
| local builtin_width=${res_array[0]} | |
| local builtin_height=${res_array[1]} | |
| local external_width=${res_array[2]} | |
| local external_height=${res_array[3]} | |
| # Return in format: external_width external_height builtin_width builtin_height | |
| echo "$external_width $external_height $builtin_width $builtin_height" | |
| return | |
| fi | |
| fi | |
| # Fallback: try to get resolutions in another way | |
| local displays=$(system_profiler SPDisplaysDataType 2>/dev/null | grep "Resolution:" | sed 's/.*Resolution: \([0-9]*\) x \([0-9]*\).*/\1 \2/') | |
| if [ -z "$displays" ]; then | |
| # Final fallback: use screeninfo command if available | |
| if command -v screeninfo &> /dev/null; then | |
| displays=$(screeninfo | grep -E '[0-9]+x[0-9]+' | head -2 | sed 's/.*\([0-9]*\)x\([0-9]*\).*/\1 \2/') | |
| fi | |
| fi | |
| echo "$displays" | |
| } | |
| # Function automatically detects physical screen dimensions | |
| function get_physical_dimensions() { | |
| local display_info=$(system_profiler SPDisplaysDataType 2>/dev/null) | |
| local external_inches="" | |
| local builtin_inches="" | |
| if [ -n "$display_info" ]; then | |
| # Try to detect external screen (DisplayPort, HDMI, Thunderbolt) | |
| local external_info=$(echo "$display_info" | grep -A 20 -B 5 "DisplayPort\|HDMI\|Thunderbolt" | grep -E "Display Size|Screen Size|Physical Size" | head -1) | |
| if [ -n "$external_info" ]; then | |
| # Extract dimensions from screen information | |
| local external_size=$(echo "$external_info" | grep -oE '[0-9]+(\.[0-9]+)?' | head -1) | |
| if [ -n "$external_size" ]; then | |
| external_inches="$external_size" | |
| echo "π Detected external screen: ${external_inches}\"" >&2 | |
| fi | |
| fi | |
| # Try to detect built-in screen (Built-in) | |
| local builtin_info=$(echo "$display_info" | grep -A 20 -B 5 "Built-in\|Internal" | grep -E "Display Size|Screen Size|Physical Size" | head -1) | |
| if [ -n "$builtin_info" ]; then | |
| local builtin_size=$(echo "$builtin_info" | grep -oE '[0-9]+(\.[0-9]+)?' | head -1) | |
| if [ -n "$builtin_size" ]; then | |
| builtin_inches="$builtin_size" | |
| echo "π Detected built-in screen: ${builtin_inches}\"" >&2 | |
| fi | |
| fi | |
| # If detection failed, try alternative methods | |
| if [ -z "$external_inches" ]; then | |
| # Check if this might be a Retina display (typical dimensions) | |
| local external_res=$(echo "$display_info" | grep "Resolution:" | grep -v "Built-in" | head -1) | |
| if echo "$external_res" | grep -q "1920x1080\|2560x1440\|3840x2160"; then | |
| external_inches="27" | |
| echo "π Detected external screen (based on resolution): ${external_inches}\"" >&2 | |
| fi | |
| fi | |
| if [ -z "$builtin_inches" ]; then | |
| # Check if this might be a Retina display (typical dimensions) | |
| local builtin_res=$(echo "$display_info" | grep "Resolution:" | grep "Built-in" | head -1) | |
| if echo "$builtin_res" | grep -q "2056x1329\|2560x1600\|3024x1964"; then | |
| builtin_inches="16" | |
| echo "π Detected built-in screen (based on resolution): ${builtin_inches}\"" >&2 | |
| fi | |
| fi | |
| fi | |
| # Return dimensions in format: external_inches builtin_inches | |
| echo "$external_inches $builtin_inches" | |
| } | |
| function map_crop_position() { | |
| local position="$1" | |
| case "$position" in | |
| "left-top" | "lt") | |
| echo "left_top" | |
| ;; | |
| "center-top" | "ct") | |
| echo "center_top" | |
| ;; | |
| "right-top" | "rt") | |
| echo "right_top" | |
| ;; | |
| "left-middle" | "lm") | |
| echo "left_middle" | |
| ;; | |
| "center-middle" | "cm") | |
| echo "center_middle" | |
| ;; | |
| "right-middle" | "rm") | |
| echo "right_middle" | |
| ;; | |
| "left-bottom" | "lb") | |
| echo "left_bottom" | |
| ;; | |
| "center-bottom" | "cb") | |
| echo "center_bottom" | |
| ;; | |
| "right-bottom" | "rb") | |
| echo "right_bottom" | |
| ;; | |
| "all") | |
| echo "all" | |
| ;; | |
| esac | |
| } | |
| # Function calculates cropping position based on selected position | |
| function calculate_crop_position() { | |
| local position="$1" | |
| local src_width="$2" | |
| local src_height="$3" | |
| local crop_width="$4" | |
| local crop_height="$5" | |
| local x="-1" | |
| local y="-1" | |
| # round up to nearest integer | |
| if [[ "$position" == left_* ]]; then | |
| x=0 | |
| fi | |
| if [[ "$position" == center_* ]]; then | |
| x=$(echo "scale=1; ($src_width - $crop_width) / 2 + 0.5" | bc -l | cut -d. -f1) | |
| fi | |
| if [[ "$position" == right_* ]]; then | |
| x=$(echo "scale=1; $src_width - $crop_width + 0.5" | bc -l | cut -d. -f1) | |
| fi | |
| if [[ "$position" == *_top ]]; then | |
| y=0 | |
| fi | |
| if [[ "$position" == *_middle ]]; then | |
| y=$(echo "scale=1; ($src_height - $crop_height) / 2 + 0.5" | bc -l | cut -d. -f1) | |
| fi | |
| if [[ "$position" == *_bottom ]]; then | |
| y=$(echo "scale=1; $src_height - $crop_height + 0.5" | bc -l | cut -d. -f1) | |
| fi | |
| echo "$x $y" | |
| } | |
| # Function crops images based on given parameters | |
| function cropper() { | |
| local source_image="$1" # Source image path | |
| local display_name="$2" # Screen name (external/builtin) | |
| local width="$3" # Target width | |
| local height="$4" # Target height | |
| local x_start="$5" # Initial X position | |
| local y_start="$6" # Initial Y position | |
| local position="$7" # Cropping position | |
| # Remove resolution from filename if present | |
| local base_name=$(echo "$source_image" | sed 's/-[0-9]*x[0-9]*\.jpg$//') | |
| # Create output filename | |
| local output_filename="${base_name}-${position}-${display_name}-${width}x${height}.jpg" | |
| printf "π¨ Creating %s [%s] " "$display_name" "$output_filename" | |
| # Crop image using ImageMagick | |
| magick "$source_image" -crop "${width}x${height}+${x_start}+${y_start}" "$output_filename" | |
| # Check if operation succeeded | |
| if [ $? -eq 0 ]; then | |
| # Verify output file was created and has content | |
| if [[ -f "$output_filename" ]] && [[ -s "$output_filename" ]]; then | |
| # Check file size is reasonable (not too small) | |
| local file_size=$(stat -f%z "$output_filename" 2>/dev/null || stat -c%s "$output_filename" 2>/dev/null || echo "0") | |
| if (( file_size < 1000 )); then | |
| echo "β οΈ (file created but very small: ${file_size} bytes)" | |
| else | |
| echo "β " | |
| fi | |
| else | |
| echo "β (file not created or empty)" | |
| return 1 | |
| fi | |
| else | |
| echo "β" | |
| return 1 | |
| fi | |
| } | |
| # Function to validate command line arguments | |
| validate_arguments() { | |
| local external="$1" | |
| local builtin="$2" | |
| local position="$3" | |
| local file_path="$4" | |
| # Validate external screen dimensions | |
| if ! [[ "$external" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then | |
| echo "β Error: External screen dimension must be a positive number (e.g. 27 or 27.5)" | |
| return 1 | |
| fi | |
| # Check if external screen dimension is reasonable (1-100 inches) | |
| if (( $(echo "$external < 1" | bc -l) )) || (( $(echo "$external > 100" | bc -l) )); then | |
| echo "β Error: External screen dimension must be between 1 and 100 inches" | |
| return 1 | |
| fi | |
| # Validate built-in screen dimensions | |
| if ! [[ "$builtin" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then | |
| echo "β Error: Built-in screen dimension must be a positive number (e.g. 16 or 13.3)" | |
| return 1 | |
| fi | |
| # Check if built-in screen dimension is reasonable (1-50 inches) | |
| if (( $(echo "$builtin < 1" | bc -l) )) || (( $(echo "$builtin > 50" | bc -l) )); then | |
| echo "β Error: Built-in screen dimension must be between 1 and 50 inches" | |
| return 1 | |
| fi | |
| # Check if external screen is larger than built-in (reasonable assumption) | |
| if (( $(echo "$external <= $builtin" | bc -l) )); then | |
| echo "β οΈ Warning: External screen ($external\") is not larger than built-in screen ($builtin\")" | |
| echo " This might not be the intended configuration. Continue anyway? (y/N)" | |
| read -r response | |
| if [[ ! "$response" =~ ^[Yy]$ ]]; then | |
| echo "β Operation cancelled by user" | |
| return 1 | |
| fi | |
| fi | |
| # Validate cropping position | |
| local valid_positions=("left-top" "center-top" "right-top" "left-middle" "center-middle" "right-middle" "left-bottom" "center-bottom" "right-bottom" "all") | |
| local is_valid=false | |
| for valid_pos in "${valid_positions[@]}"; do | |
| if [[ "$position" == "$valid_pos" ]]; then | |
| is_valid=true | |
| break | |
| fi | |
| done | |
| if [[ "$is_valid" == false ]]; then | |
| echo "β Error: Invalid cropping position '$position'" | |
| echo " Valid positions: ${valid_positions[*]}" | |
| return 1 | |
| fi | |
| # Check if source image was provided | |
| if [[ -z "$file_path" ]]; then | |
| echo "β Error: You must provide a source image" | |
| show_help | |
| exit 1 | |
| fi | |
| # Check if file exists | |
| if [[ ! -f "$file_path" ]]; then | |
| echo "β Error: File '$file_path' does not exist" | |
| return 1 | |
| fi | |
| # Check if file is readable | |
| if [[ ! -r "$file_path" ]]; then | |
| echo "β Error: File '$file_path' is not readable" | |
| return 1 | |
| fi | |
| # Check file size (must be > 0 bytes) | |
| if [[ ! -s "$file_path" ]]; then | |
| echo "β Error: File '$file_path' is empty" | |
| return 1 | |
| fi | |
| # Check if ImageMagick can identify the file | |
| if ! magick identify -ping -format '%w' "$file_path" >/dev/null 2>&1; then | |
| echo "β Error: File '$file_path' is not a valid image format supported by ImageMagick" | |
| echo " Supported formats: JPG, PNG, GIF, BMP, TIFF, etc." | |
| return 1 | |
| fi | |
| return 0 | |
| } | |
| # Function to validate system requirements | |
| validate_system_requirements() { | |
| # Check if output directory is writable | |
| if [[ ! -w "." ]]; then | |
| echo "β Error: Current directory is not writable" | |
| return 1 | |
| fi | |
| # Check available disk space (at least 100MB free) | |
| available_space=$(df . | awk 'NR==2 {print $4}') | |
| if (( available_space < 102400 )); then | |
| echo "β οΈ Warning: Low disk space available (${available_space}KB)" | |
| echo " This might cause wallpaper creation to fail" | |
| fi | |
| # Check if ImageMagick is available | |
| if ! command -v magick &> /dev/null; then | |
| echo "β Error: ImageMagick (magick) is not installed or not in PATH" | |
| echo " Please install ImageMagick to use this script" | |
| return 1 | |
| fi | |
| # Check if bc calculator is available | |
| if ! command -v bc &> /dev/null; then | |
| echo "β Error: bc calculator is not installed or not in PATH" | |
| echo " Please install bc to use this script" | |
| return 1 | |
| fi | |
| # Check if system_profiler is available (macOS specific) | |
| if ! command -v system_profiler &> /dev/null; then | |
| echo "β οΈ Warning: system_profiler not found, automatic screen detection may fail" | |
| fi | |
| # Check if we're running on macOS | |
| if [[ "$OSTYPE" != "darwin"* ]]; then | |
| echo "β οΈ Warning: This script is designed for macOS" | |
| echo " Some features may not work correctly on other systems" | |
| fi | |
| # Check script permissions | |
| if [[ ! -x "$0" ]]; then | |
| echo "β οΈ Warning: Script is not executable" | |
| echo " Run: chmod +x $0" | |
| fi | |
| # Check if we have enough memory (at least 100MB free) | |
| if command -v vm_stat &> /dev/null; then | |
| memory_info=$(vm_stat | grep "Pages free:" | awk '{print $3}' | sed 's/\.//') | |
| if [[ -n "$memory_info" ]]; then | |
| free_memory_mb=$((memory_info * 4096 / 1024 / 1024)) | |
| if (( free_memory_mb < 100 )); then | |
| echo "β οΈ Warning: Low memory available (${free_memory_mb}MB)" | |
| echo " This might cause wallpaper creation to fail" | |
| fi | |
| fi | |
| fi | |
| # Check if we're running as root (not recommended) | |
| if [[ $EUID -eq 0 ]]; then | |
| echo "β οΈ Warning: Running as root is not recommended" | |
| echo " Consider running as a regular user" | |
| fi | |
| return 0 | |
| } | |
| echo "=== WALLPAPER CROPPER ===" | |
| echo "" | |
| # Initialize variables | |
| source_image="" | |
| external_inches="" | |
| builtin_inches="" | |
| crop_position="center-top" | |
| # Parse arguments | |
| while [[ $# -gt 0 ]]; do | |
| case $1 in | |
| --inches|-i) | |
| if [[ $# -lt 3 ]]; then | |
| echo "β Error: --inches requires two arguments" | |
| echo " Usage: --inches <external> <builtin>" | |
| echo " Example: --inches 27 16" | |
| exit 1 | |
| fi | |
| external_inches="$2" | |
| builtin_inches="$3" | |
| shift 3 | |
| ;; | |
| --position|-p) | |
| if [[ $# -lt 2 ]]; then | |
| echo "β Error: --position requires one argument" | |
| echo " Usage: --position <position>" | |
| echo " Valid positions: left-top, center-top, right-top, left-middle, center-middle, right-middle, left-bottom, center-bottom, right-bottom, all" | |
| exit 1 | |
| fi | |
| crop_position="$2" | |
| shift 2 | |
| ;; | |
| -h|--help) | |
| show_help | |
| exit 0 | |
| ;; | |
| -*) | |
| echo "β Error: Unknown option $1" | |
| echo "Use --help to show help" | |
| exit 1 | |
| ;; | |
| *) | |
| if [[ -z "$source_image" ]]; then | |
| # Check if argument looks like an option | |
| if [[ "$1" == -* ]]; then | |
| echo "β Error: '$1' looks like an option but is not recognized" | |
| echo " Use --help to see available options" | |
| exit 1 | |
| fi | |
| source_image="$1" | |
| else | |
| echo "β Error: Too many arguments" | |
| echo " Expected: <source_image>" | |
| echo " Got: $source_image and $1" | |
| exit 1 | |
| fi | |
| shift | |
| ;; | |
| esac | |
| done | |
| # Validate system requirements | |
| if ! validate_system_requirements; then | |
| exit 1 | |
| fi | |
| ######### SCREEN DIMENSIONS ######### | |
| if [ -n "$external_inches" ] && [ -n "$builtin_inches" ]; then | |
| # User provided dimensions via --inches | |
| echo "π Using user-provided dimensions!" | |
| else | |
| # Automatic screen detection | |
| echo "π Automatic screen detection..." | |
| # Detect physical screen dimensions | |
| physical_dimensions=$(get_physical_dimensions) | |
| detected_external=$(echo "$physical_dimensions" | cut -d' ' -f1) | |
| detected_builtin=$(echo "$physical_dimensions" | cut -d' ' -f2) | |
| # Check if dimensions were detected successfully | |
| if [ -n "$detected_external" ] && [ -n "$detected_builtin" ]; then | |
| echo "π Physical dimensions detected automatically!" | |
| external_inches="$detected_external" | |
| builtin_inches="$detected_builtin" | |
| else | |
| # Could not detect and user did not provide | |
| echo "β Could not automatically detect physical dimensions." | |
| echo "π Please provide physical screen dimensions in inches:" | |
| echo -n "π₯οΈ External screen: " | |
| read -r external_inches | |
| echo -n "π» Built-in screen: " | |
| read -r builtin_inches | |
| fi | |
| fi | |
| # Validate all arguments together | |
| if ! validate_arguments "$external_inches" "$builtin_inches" "$crop_position" "$source_image"; then | |
| exit 1 | |
| fi | |
| if [[ $crop_position == "all" ]]; then | |
| echo "π Generating wallpapers for all cropping positions..." | |
| $0 --inches $external_inches $builtin_inches --position "left-top" "$source_image" | |
| $0 --inches $external_inches $builtin_inches --position "center-top" "$source_image" | |
| $0 --inches $external_inches $builtin_inches --position "right-top" "$source_image" | |
| $0 --inches $external_inches $builtin_inches --position "left-middle" "$source_image" | |
| $0 --inches $external_inches $builtin_inches --position "center-middle" "$source_image" | |
| $0 --inches $external_inches $builtin_inches --position "right-middle" "$source_image" | |
| $0 --inches $external_inches $builtin_inches --position "left-bottom" "$source_image" | |
| $0 --inches $external_inches $builtin_inches --position "center-bottom" "$source_image" | |
| $0 --inches $external_inches $builtin_inches --position "right-bottom" "$source_image" | |
| echo "β All wallpapers generated successfully!" | |
| exit 0 | |
| fi | |
| ######### SCREEN DIMENSIONS ######### | |
| # Detect screen dimensions from macOS system | |
| screen_dimensions=$(get_screen_dimensions) | |
| # Get screen dimensions from array | |
| external_width=$(echo "$screen_dimensions" | cut -d' ' -f1) | |
| external_height=$(echo "$screen_dimensions" | cut -d' ' -f2) | |
| builtin_width=$(echo "$screen_dimensions" | cut -d' ' -f3) | |
| builtin_height=$(echo "$screen_dimensions" | cut -d' ' -f4) | |
| # Validate screen dimensions | |
| if [[ -z "$external_width" ]] || [[ -z "$external_height" ]] || [[ -z "$builtin_width" ]] || [[ -z "$builtin_height" ]]; then | |
| echo "β Error: Failed to detect screen dimensions" | |
| echo " External: ${external_width}x${external_height}" | |
| echo " Built-in: ${builtin_width}x${builtin_height}" | |
| exit 1 | |
| fi | |
| # Check if dimensions are reasonable (must be positive and not too large) | |
| if (( external_width <= 0 )) || (( external_height <= 0 )) || (( builtin_width <= 0 )) || (( builtin_height <= 0 )); then | |
| echo "β Error: Invalid screen dimensions detected" | |
| echo " External: ${external_width}x${external_height}" | |
| echo " Built-in: ${builtin_width}x${builtin_height}" | |
| exit 1 | |
| fi | |
| if (( external_width > 10000 )) || (( external_height > 10000 )) || (( builtin_width > 10000 )) || (( builtin_height > 10000 )); then | |
| echo "β Error: Screen dimensions seem unreasonably large" | |
| echo " External: ${external_width}x${external_height}" | |
| echo " Built-in: ${builtin_width}x${builtin_height}" | |
| exit 1 | |
| fi | |
| ######### SCREEN ASPECT RATIO ######### | |
| # Check aspect ratio sanity (should be between 0.5 and 3.0) | |
| external_ratio=$(echo "scale=4; $external_width / $external_height" | bc -l) | |
| builtin_ratio=$(echo "scale=4; $builtin_width / $builtin_height" | bc -l) | |
| if (( $(echo "$external_ratio < 0.5" | bc -l) )) || (( $(echo "$external_ratio > 3.0" | bc -l) )); then | |
| echo "β οΈ Warning: External screen aspect ratio ($external_ratio) seems unusual" | |
| fi | |
| if (( $(echo "$builtin_ratio < 0.5" | bc -l) )) || (( $(echo "$builtin_ratio > 3.0" | bc -l) )); then | |
| echo "β οΈ Warning: Built-in screen aspect ratio ($builtin_ratio) seems unusual" | |
| fi | |
| # Calculate screen diagonals (needed for DPI calculation) | |
| external_diameter=$(( external_width * external_width + external_height * external_height )) | |
| builtin_diameter=$(( builtin_width * builtin_width + builtin_height * builtin_height )) | |
| # Calculate DPI for each screen (diagonal in pixels / diagonal in inches) | |
| external_dpi=$(echo "scale=2; sqrt($external_diameter) / $external_inches" | bc -l 2>/dev/null || echo "0") | |
| builtin_dpi=$(echo "scale=2; sqrt($builtin_diameter) / $builtin_inches" | bc -l 2>/dev/null || echo "0") | |
| # Validate DPI calculations | |
| if [[ "$external_dpi" == "0" ]] || [[ "$builtin_dpi" == "0" ]]; then | |
| echo "β Error: Failed to calculate DPI values" | |
| echo " External DPI: $external_dpi" | |
| echo " Built-in DPI: $builtin_dpi" | |
| exit 1 | |
| fi | |
| # Check if DPI values are reasonable (typically between 72-300) | |
| if (( $(echo "$external_dpi < 72" | bc -l) )) || (( $(echo "$external_dpi > 300" | bc -l) )); then | |
| echo "β οΈ Warning: External screen DPI ($external_dpi) seems unusual (expected 72-300)" | |
| fi | |
| if (( $(echo "$builtin_dpi < 72" | bc -l) )) || (( $(echo "$builtin_dpi > 300" | bc -l) )); then | |
| echo "β οΈ Warning: Built-in screen DPI ($builtin_dpi) seems unusual (expected 72-300)" | |
| fi | |
| echo "π₯οΈ External screen: $external_inches\" ($external_ratio ratio)" | |
| echo "π» Built-in screen: $builtin_inches\" ($builtin_ratio ratio)" | |
| echo "" | |
| ######### ADJUST WALLPAPER SIZE DIMENSIONS ######### | |
| external_info="$external_width x $external_height px ($external_dpi dpi)" | |
| builtin_info="$builtin_width x $builtin_height px ($builtin_dpi dpi)" | |
| # Physical scaling logic - adjust dimensions of screen with lower DPI to screen with higher DPI | |
| if (( $(echo "$builtin_dpi < $external_dpi" | bc -l) )); then | |
| # Scale built-in screen up to external screen DPI | |
| echo "π Scaling size of built-in screen wallpaper up to external screen DPI" | |
| builtin_width_fixed=$(echo "scale=0; $builtin_width * $external_dpi / $builtin_dpi" | bc -l 2>/dev/null || echo "0") | |
| builtin_height_fixed=$(echo "scale=0; $builtin_height * $external_dpi / $builtin_dpi" | bc -l 2>/dev/null || echo "0") | |
| builtin_dpi_fixed=$(echo "scale=2; sqrt($builtin_width_fixed * $builtin_width_fixed + $builtin_height_fixed * $builtin_height_fixed) / $builtin_inches" | bc -l 2>/dev/null || echo "0") | |
| builtin_ratio_fixed=$(echo "scale=4; $builtin_width_fixed / $builtin_height_fixed" | bc -l) | |
| changes_builtin="$builtin_width_fixed x $builtin_height_fixed px ($builtin_dpi_fixed dpi)" | |
| builtin_width=$builtin_width_fixed | |
| builtin_height=$builtin_height_fixed | |
| builtin_dpi=$builtin_dpi_fixed | |
| else | |
| # Scale external screen up to built-in screen DPI | |
| echo "π Scaling size of external screen wallpaper up to built-in screen DPI" | |
| external_width_fixed=$(echo "scale=0; $external_width * $builtin_dpi / $external_dpi" | bc -l 2>/dev/null || echo "0") | |
| external_height_fixed=$(echo "scale=0; $external_height * $builtin_dpi / $external_dpi" | bc -l 2>/dev/null || echo "0") | |
| external_dpi_fixed=$(echo "scale=2; sqrt($external_width_fixed * $external_width_fixed + $external_height_fixed * $external_height_fixed) / $external_inches" | bc -l 2>/dev/null || echo "0") | |
| external_ratio_fixed=$(echo "scale=4; $external_width_fixed / $external_height_fixed" | bc -l) | |
| changes_external=" β $external_width_fixed x $external_height_fixed px ($external_dpi_fixed dpi)" | |
| external_width=$external_width_fixed | |
| external_height=$external_height_fixed | |
| external_dpi=$external_dpi_fixed | |
| fi | |
| echo "π₯οΈ External screen wallpaper: $external_info$changes_external" | |
| echo "π» Built-in screen wallpaper: $builtin_info$changes_builtin" | |
| # Calculate total wallpapers height and max wallpapers width | |
| total_height=$(echo "scale=0; $external_height + $builtin_height" | bc -l) | |
| max_width=$((external_width > builtin_width ? external_width : builtin_width)) | |
| echo "π Total wallpapers height: $total_height px" | |
| echo "π Max wallpapers width: $max_width px" | |
| echo "" | |
| ######### SOURCE IMAGE DIMENSIONS ######### | |
| # Get source image dimensions | |
| src_width=$(magick identify -ping -format '%w' "$source_image") | |
| src_height=$(magick identify -ping -format '%h' "$source_image") | |
| # Validate source image dimensions | |
| if [[ -z "$src_width" ]] || [[ -z "$src_height" ]]; then | |
| echo "β Error: Failed to get source image dimensions" | |
| exit 1 | |
| fi | |
| if (( src_width <= 0 )) || (( src_height <= 0 )); then | |
| echo "β Error: Invalid source image dimensions: ${src_width}x${src_height}" | |
| exit 1 | |
| fi | |
| echo "πΌοΈ Source image dimensions: ${src_width} x ${src_height} px" | |
| # Check if image dimensions are reasonable (not too small or too large) | |
| if (( src_width < 100 )) || (( src_height < 100 )); then | |
| echo "β οΈ Warning: Source image dimensions seem very small: ${src_width}x${src_height}" | |
| echo " This might result in poor quality wallpapers" | |
| fi | |
| if (( src_width > 10000 )) || (( src_height > 10000 )); then | |
| echo "β οΈ Warning: Source image dimensions seem very large: ${src_width}x${src_height}" | |
| echo " Processing might take longer than expected" | |
| fi | |
| echo "" | |
| ######### SCALE FACTORS ######### | |
| # Check if screen dimensions don't exceed source image dimensions | |
| scale_factor_height=1 | |
| scale_factor_width=1 | |
| # Check height | |
| if (( $(echo "$src_height < $total_height" | bc -l) )); then | |
| echo "β οΈ Warning: Total wallpapers height exceeds source image height" | |
| # Calculate scaling factor (image height / total screen height) | |
| scale_factor_height=$(echo "scale=4; $src_height / $total_height" | bc -l) | |
| echo "π’ Height scaling factor: $scale_factor_height" | |
| fi | |
| # Check width | |
| if (( $(echo "$src_width < $max_width" | bc -l) )); then | |
| echo "β οΈ Warning: Maximum wallpapers width exceeds source image width" | |
| # Calculate scaling factor (image width / maximum screen width) | |
| scale_factor_width=$(echo "scale=4; $src_width / $max_width" | bc -l) | |
| echo "π’ Width scaling factor: $scale_factor_width" | |
| fi | |
| # Apply scaling only if needed | |
| if (( $(echo "$scale_factor_height < 1" | bc -l) || $(echo "$scale_factor_width < 1" | bc -l) )); then | |
| # Validate scaling factors | |
| if (( $(echo "$scale_factor_height <= 0" | bc -l) )) || (( $(echo "$scale_factor_width <= 0" | bc -l) )); then | |
| echo "β Error: Invalid scaling factors calculated" | |
| echo " Height factor: $scale_factor_height" | |
| echo " Width factor: $scale_factor_width" | |
| exit 1 | |
| fi | |
| # Check if scaling factors are reasonable (not too small) | |
| if (( $(echo "$scale_factor_height < 0.1" | bc -l) )) || (( $(echo "$scale_factor_width < 0.1" | bc -l) )); then | |
| echo "β οΈ Warning: Scaling factors are very small, this might result in poor quality" | |
| echo " Height factor: $scale_factor_height" | |
| echo " Width factor: $scale_factor_width" | |
| fi | |
| if (( $(echo "$scale_factor_height < $scale_factor_width" | bc -l) )); then | |
| scale_factor=$scale_factor_height | |
| echo "π Using height scaling factor (more restrictive): $scale_factor" | |
| else | |
| scale_factor=$scale_factor_width | |
| echo "π Using width scaling factor (more restrictive): $scale_factor" | |
| fi | |
| # Scale screen dimensions proportionally | |
| external_width_scaled=$(echo "scale=0; $external_width * $scale_factor / 1" | bc -l) | |
| external_height_scaled=$(echo "scale=0; $external_height * $scale_factor / 1" | bc -l) | |
| builtin_width_scaled=$(echo "scale=0; $builtin_width * $scale_factor / 1" | bc -l) | |
| builtin_height_scaled=$(echo "scale=0; $builtin_height * $scale_factor / 1" | bc -l) | |
| # Update screen dimensions | |
| external_width=$external_width_scaled | |
| external_height=$external_height_scaled | |
| builtin_width=$builtin_width_scaled | |
| builtin_height=$builtin_height_scaled | |
| echo "" | |
| fi | |
| ######### CROPPING POSITION ######### | |
| crop_position="$(map_crop_position "$crop_position")" | |
| echo "π Cropping position: ${crop_position/_/ }" | |
| # Calculate cropping position for external screen | |
| external_pos=$(calculate_crop_position "$crop_position" "$src_width" "$src_height" "$external_width" "$(echo "scale=0; $external_height + $builtin_height" | bc -l)") | |
| external_x_start=$(echo "$external_pos" | cut -d' ' -f1) | |
| external_y_start=$(echo "$external_pos" | cut -d' ' -f2) | |
| # Calculate cropping position for built-in screen | |
| builtin_x_start=$(echo "scale=1; $external_x_start + $external_width/2 - $builtin_width/2" | bc -l | cut -d. -f1) | |
| builtin_y_start=$(echo "scale=1; $external_y_start + $external_height" | bc -l | cut -d. -f1) | |
| # Validate cropping coordinates | |
| if [[ -z "$external_x_start" ]] || [[ -z "$external_y_start" ]] || [[ -z "$builtin_x_start" ]] || [[ -z "$builtin_y_start" ]]; then | |
| echo "β Error: Failed to calculate cropping coordinates" | |
| echo " External: x=$external_x_start, y=$external_y_start" | |
| echo " Built-in: x=$builtin_x_start, y=$builtin_y_start" | |
| exit 1 | |
| fi | |
| # Check if coordinates are valid numbers | |
| if ! [[ "$external_x_start" =~ ^-?[0-9]+$ ]] || ! [[ "$external_y_start" =~ ^-?[0-9]+$ ]] || ! [[ "$builtin_x_start" =~ ^-?[0-9]+$ ]] || ! [[ "$builtin_y_start" =~ ^-?[0-9]+$ ]]; then | |
| echo "β Error: Invalid cropping coordinates (not integers)" | |
| echo " External: x=$external_x_start, y=$external_y_start" | |
| echo " Built-in: x=$builtin_x_start, y=$builtin_y_start" | |
| exit 1 | |
| fi | |
| # Check if coordinates are within image bounds | |
| if (( external_x_start < 0 )) || (( external_y_start < 0 )) || (( builtin_x_start < 0 )) || (( builtin_y_start < 0 )); then | |
| echo "β Error: Cropping coordinates cannot be negative" | |
| echo " External: x=$external_x_start, y=$external_y_start" | |
| echo " Built-in: x=$builtin_x_start, y=$builtin_y_start" | |
| exit 1 | |
| fi | |
| if (( external_x_start + external_width > src_width )) || (( external_y_start + external_height > src_height )); then | |
| echo "β Error: External screen crop area exceeds image boundaries" | |
| echo " Crop area: ${external_width}x${external_height} at ($external_x_start, $external_y_start)" | |
| echo " Image size: ${src_width}x${src_height}" | |
| exit 1 | |
| fi | |
| if (( builtin_x_start + builtin_width > src_width )) || (( builtin_y_start + builtin_height > src_height )); then | |
| echo "β Error: Built-in screen crop area exceeds image boundaries" | |
| echo " Crop area: ${builtin_width}x${builtin_height} at ($builtin_x_start, $builtin_y_start)" | |
| echo " Image size: ${src_width}x${src_height}" | |
| exit 1 | |
| fi | |
| # Final validation before creating wallpapers | |
| if (( external_width <= 0 )) || (( external_height <= 0 )) || (( builtin_width <= 0 )) || (( builtin_height <= 0 )); then | |
| echo "β Error: Invalid final dimensions for cropping" | |
| echo " External: ${external_width}x${external_height}" | |
| echo " Built-in: ${builtin_width}x${builtin_height}" | |
| exit 1 | |
| fi | |
| echo "π₯οΈ External screen wallpaper cropped to: ${src_width}x${src_height}+${external_x_start}+${external_y_start} β ${external_width}x${external_height}" | |
| echo "π» Built-in screen wallpaper cropped to: ${src_width}x${src_height}+${builtin_x_start}+${builtin_y_start} β ${builtin_width}x${builtin_height}" | |
| echo "" | |
| ######### CREATE WALLPAPERS ######### | |
| echo "π¨ Creating wallpapers..." | |
| if ! cropper "$source_image" "1_external" "$external_width" "$external_height" "$external_x_start" "$external_y_start" "$crop_position"; then | |
| echo "β Error: Failed to create external screen wallpaper" | |
| exit 1 | |
| fi | |
| if ! cropper "$source_image" "2_builtin" "$builtin_width" "$builtin_height" "$builtin_x_start" "$builtin_y_start" "$crop_position"; then | |
| echo "β Error: Failed to create built-in screen wallpaper" | |
| exit 1 | |
| fi | |
| echo "" | |
| echo "π― Done! Created wallpapers for $external_inches\" external screen and $builtin_inches\" built-in screen in vertical layout with '${crop_position/_/ }' as cropping position." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment