Created
January 22, 2026 02:22
-
-
Save nkrebs13/a410a025603d1d950a196613ccee9032 to your computer and use it in GitHub Desktop.
ADB Screenshot Comparison Tool
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
| #!/bin/bash | |
| # ADB Screenshot Comparison Tool | |
| # Dependencies: adb, imagemagick | |
| # Usage: adb-compare | |
| set -e | |
| # ============================================================================ | |
| # Configuration | |
| # ============================================================================ | |
| OUTPUT_DIR="$HOME/Downloads" | |
| TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") | |
| TEMP_DIR=$(mktemp -d) | |
| GAP_WIDTH=12 | |
| LABEL_FONT="Helvetica-Bold" | |
| LABEL_SIZE=96 | |
| LABEL_COLOR="#ff00ff" | |
| LABEL_OFFSET=28 | |
| GRID_COLOR="red" | |
| GRID_STROKE=3 | |
| GRID_DASH=10 | |
| # ============================================================================ | |
| # Cleanup | |
| # ============================================================================ | |
| cleanup() { | |
| rm -rf "$TEMP_DIR" | |
| } | |
| trap cleanup EXIT | |
| # ============================================================================ | |
| # Dependency Check | |
| # ============================================================================ | |
| check_dependencies() { | |
| local missing=() | |
| if ! command -v adb &> /dev/null; then | |
| missing+=("adb") | |
| fi | |
| if ! command -v magick &> /dev/null; then | |
| missing+=("imagemagick (magick command)") | |
| fi | |
| if [ ${#missing[@]} -gt 0 ]; then | |
| echo "Error: Missing required dependencies:" | |
| for dep in "${missing[@]}"; do | |
| echo " - $dep" | |
| done | |
| echo "" | |
| echo "Install with:" | |
| echo " brew install android-platform-tools # for adb" | |
| echo " brew install imagemagick # for magick" | |
| exit 1 | |
| fi | |
| } | |
| # ============================================================================ | |
| # Device Selection | |
| # ============================================================================ | |
| get_device() { | |
| local devices | |
| devices=$(adb devices | grep -v "^List" | grep -v "^$" | awk '{print $1}') | |
| if [ -z "$devices" ]; then | |
| echo "Error: No Android devices found." | |
| echo "" | |
| echo "Troubleshooting:" | |
| echo " 1. Ensure USB debugging is enabled on your device" | |
| echo " 2. Check the USB connection" | |
| echo " 3. Run 'adb devices' to verify connection" | |
| echo " 4. Accept the USB debugging prompt on your device" | |
| exit 1 | |
| fi | |
| local device_count | |
| device_count=$(echo "$devices" | wc -l | tr -d ' ') | |
| if [ "$device_count" -eq 1 ]; then | |
| DEVICE=$(echo "$devices" | head -1) | |
| echo "Using device: $DEVICE" | |
| else | |
| echo "Multiple devices found:" | |
| local i=1 | |
| local device_array=() | |
| while IFS= read -r device; do | |
| device_array+=("$device") | |
| echo " $i) $device" | |
| ((i++)) | |
| done <<< "$devices" | |
| echo "" | |
| read -rp "Select device [1-$device_count]: " choice | |
| if ! [[ "$choice" =~ ^[0-9]+$ ]] || [ "$choice" -lt 1 ] || [ "$choice" -gt "$device_count" ]; then | |
| echo "Error: Invalid selection" | |
| exit 1 | |
| fi | |
| DEVICE="${device_array[$((choice-1))]}" | |
| echo "Using device: $DEVICE" | |
| fi | |
| } | |
| # ============================================================================ | |
| # Screenshot Capture | |
| # ============================================================================ | |
| capture_screenshot() { | |
| local output_file="$1" | |
| local screenshot_num="$2" | |
| echo "" | |
| read -rp "Press Enter to capture screenshot $screenshot_num..." | |
| echo "Capturing..." | |
| adb -s "$DEVICE" exec-out screencap -p > "$output_file" | |
| if [ ! -s "$output_file" ]; then | |
| echo "Error: Failed to capture screenshot" | |
| exit 1 | |
| fi | |
| echo "Screenshot $screenshot_num captured." | |
| } | |
| # ============================================================================ | |
| # Image Processing | |
| # ============================================================================ | |
| add_label() { | |
| local input="$1" | |
| local output="$2" | |
| local label="$3" | |
| local dimensions | |
| dimensions=$(magick identify -format "%wx%h" "$input") | |
| local height=${dimensions#*x} | |
| magick "$input" \ | |
| -font "$LABEL_FONT" \ | |
| -pointsize "$LABEL_SIZE" \ | |
| -fill "$LABEL_COLOR" \ | |
| -gravity South \ | |
| -annotate +0+"$LABEL_OFFSET" "$label" \ | |
| "$output" | |
| } | |
| create_grid_overlay() { | |
| local input="$1" | |
| local output="$2" | |
| local dimensions | |
| dimensions=$(magick identify -format "%wx%h" "$input") | |
| local width=${dimensions%x*} | |
| local height=${dimensions#*x} | |
| # Calculate grid positions | |
| # 3 vertical lines (4 columns) | |
| local v1=$((width / 4)) | |
| local v2=$((width / 2)) | |
| local v3=$((width * 3 / 4)) | |
| # 7 horizontal lines (8 rows) | |
| local h1=$((height / 8)) | |
| local h2=$((height * 2 / 8)) | |
| local h3=$((height * 3 / 8)) | |
| local h4=$((height * 4 / 8)) | |
| local h5=$((height * 5 / 8)) | |
| local h6=$((height * 6 / 8)) | |
| local h7=$((height * 7 / 8)) | |
| # Build draw commands with MVG dash array syntax | |
| local draw_cmds="" | |
| draw_cmds+="stroke-dasharray $GRID_DASH $GRID_DASH " | |
| draw_cmds+="line $v1,0 $v1,$height " | |
| draw_cmds+="line $v2,0 $v2,$height " | |
| draw_cmds+="line $v3,0 $v3,$height " | |
| draw_cmds+="line 0,$h1 $width,$h1 " | |
| draw_cmds+="line 0,$h2 $width,$h2 " | |
| draw_cmds+="line 0,$h3 $width,$h3 " | |
| draw_cmds+="line 0,$h4 $width,$h4 " | |
| draw_cmds+="line 0,$h5 $width,$h5 " | |
| draw_cmds+="line 0,$h6 $width,$h6 " | |
| draw_cmds+="line 0,$h7 $width,$h7 " | |
| magick "$input" \ | |
| -stroke "$GRID_COLOR" \ | |
| -strokewidth "$GRID_STROKE" \ | |
| -draw "$draw_cmds" \ | |
| "$output" | |
| } | |
| stitch_images() { | |
| local img1="$1" | |
| local img2="$2" | |
| local output="$3" | |
| # Create transparent gap | |
| local dimensions | |
| dimensions=$(magick identify -format "%h" "$img1") | |
| local height=$dimensions | |
| magick -size "${GAP_WIDTH}x${height}" xc:transparent "$TEMP_DIR/gap.png" | |
| # Stitch side by side | |
| magick "$img1" "$TEMP_DIR/gap.png" "$img2" +append "$output" | |
| } | |
| # ============================================================================ | |
| # Main | |
| # ============================================================================ | |
| main() { | |
| echo "=== ADB Screenshot Comparison Tool ===" | |
| echo "" | |
| # Check dependencies | |
| check_dependencies | |
| # Get device | |
| get_device | |
| # Configuration prompts | |
| echo "" | |
| read -rp "Label for image 1 (or press Enter for none): " label1 | |
| read -rp "Label for image 2 (or press Enter for none): " label2 | |
| # Capture screenshots | |
| local raw1="$TEMP_DIR/raw1.png" | |
| local raw2="$TEMP_DIR/raw2.png" | |
| capture_screenshot "$raw1" "1" | |
| capture_screenshot "$raw2" "2" | |
| # Check dimensions | |
| local dim1 dim2 | |
| dim1=$(magick identify -format "%wx%h" "$raw1") | |
| dim2=$(magick identify -format "%wx%h" "$raw2") | |
| if [ "$dim1" != "$dim2" ]; then | |
| echo "" | |
| echo "Warning: Image dimensions differ ($dim1 vs $dim2)" | |
| echo "Continuing anyway..." | |
| fi | |
| # Process images | |
| echo "" | |
| echo "Processing images..." | |
| local proc1="$TEMP_DIR/proc1.png" | |
| local proc2="$TEMP_DIR/proc2.png" | |
| cp "$raw1" "$proc1" | |
| cp "$raw2" "$proc2" | |
| # Add labels if non-empty (trimmed) | |
| label1_trimmed=$(echo "$label1" | xargs) | |
| label2_trimmed=$(echo "$label2" | xargs) | |
| if [ -n "$label1_trimmed" ]; then | |
| add_label "$proc1" "$TEMP_DIR/labeled1.png" "$label1_trimmed" | |
| proc1="$TEMP_DIR/labeled1.png" | |
| fi | |
| if [ -n "$label2_trimmed" ]; then | |
| add_label "$proc2" "$TEMP_DIR/labeled2.png" "$label2_trimmed" | |
| proc2="$TEMP_DIR/labeled2.png" | |
| fi | |
| # Generate outputs | |
| local output_base="$OUTPUT_DIR/comparison_$TIMESTAMP" | |
| local output_plain="${output_base}.png" | |
| local output_grid="${output_base}_grid.png" | |
| echo "Generating comparison images..." | |
| # Plain comparison | |
| stitch_images "$proc1" "$proc2" "$output_plain" | |
| # Grid comparison | |
| local grid1="$TEMP_DIR/grid1.png" | |
| local grid2="$TEMP_DIR/grid2.png" | |
| create_grid_overlay "$proc1" "$grid1" | |
| create_grid_overlay "$proc2" "$grid2" | |
| stitch_images "$grid1" "$grid2" "$output_grid" | |
| echo "" | |
| echo "Created:" | |
| echo " $output_plain" | |
| echo " $output_grid" | |
| # Keep originals prompt | |
| echo "" | |
| read -rp "Keep original screenshots? [y/N]: " keep_originals | |
| if [[ "$keep_originals" =~ ^[Yy]$ ]]; then | |
| cp "$raw1" "${output_base}_1.png" | |
| cp "$raw2" "${output_base}_2.png" | |
| echo "Saved:" | |
| echo " ${output_base}_1.png" | |
| echo " ${output_base}_2.png" | |
| fi | |
| # Open results | |
| echo "" | |
| echo "Opening comparison images..." | |
| open "$output_plain" | |
| open "$output_grid" | |
| echo "" | |
| echo "Done!" | |
| } | |
| main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment