Files
file-manager/tools/make-store-screenshots.sh
SoftwareApp b28e9dca37 Screenshots: 10-inch tablet set; guard against blank captures
The 7-inch roots capture was pure app background (Compose had not composed its
first frame yet, though the system bars had drawn) so it measured as uniform.
made-store-screenshots.sh now measures each capture and refuses to normalise a
blank one.
2026-10-14 23:44:24 +02:00

91 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Normalises `adb exec-out screencap` captures into the files that get uploaded to Play.
#
# ./tools/make-store-screenshots.sh # phone -> 1080x2160
# FORM_FACTOR=tablet-7in ./tools/make-store-screenshots.sh # 7-inch -> 1200x1920
# FORM_FACTOR=tablet-10in ./tools/make-store-screenshots.sh # 10-inch -> 2560x1600
#
# store-assets/raw-screenshots/<form>/ the raw captures (git-ignored)
# store-assets/screenshots/<form>/ what gets uploaded (committed)
#
# Play's rule that actually bites: JPEG or 24-bit PNG **without alpha**, shorter side >= 320,
# longer side <= 3840, and **longer side <= 2x the shorter side**. A phone at its native
# 1080x2400 is 2.22:1 and is therefore REJECTED, which is why the phone path crops system
# chrome (status + navigation bars) before clamping to 2:1. A tablet frame is already inside
# the 2:1 cap on every profile the SDK ships, so its crop defaults to 0 and is opt-in.
#
# Play accepts portrait or landscape for the tablet slots; the targets below match the AVDs
# this repo is tested against (the 10-inch one is a landscape profile), and the extent step
# normalises to them either way.
set -euo pipefail
here="$(cd "$(dirname "$0")" && pwd)"
repo="$(dirname "$here")"
form="${FORM_FACTOR:-phone}"
case "$form" in
phone) target_w=1080; target_h=2160; default_status=93; default_nav=130 ;;
tablet-7in) target_w=1200; target_h=1920; default_status=0; default_nav=0 ;;
tablet-10in) target_w=2560; target_h=1600; default_status=0; default_nav=0 ;;
*) echo "Unknown FORM_FACTOR '$form' (phone|tablet-7in|tablet-10in)" >&2; exit 1 ;;
esac
status_px="${STATUS_BAR_PX:-$default_status}"
nav_px="${NAV_BAR_PX:-$default_nav}"
# A headless AVD whose display has slept, or an app whose first frame has not composed yet,
# produces a screencap of pure background. The top and bottom system bars are still drawn,
# so the file is not *obviously* empty — but the app area has no ink at all. That is
# invisible in a thumbnail and unacceptable on a listing, so each capture is measured
# before it is normalised. `sample_inset` shaves the top and bottom margin (where the
# system bars sit on every profile here) so the measurement covers app content only.
blank_threshold="${BLANK_THRESHOLD:-0.005}"
sample_inset=150
raw="$repo/store-assets/raw-screenshots/$form"
out="$repo/store-assets/screenshots/$form"
mkdir -p "$out"
shopt -s nullglob
captures=("$raw"/*.png)
if [ ${#captures[@]} -eq 0 ]; then
echo "No captures in $raw — take some with:" >&2
echo " adb exec-out screencap -p > $raw/01-roots.png" >&2
exit 1
fi
echo "Normalising ${#captures[@]} capture(s) from $raw -> $out"
blanks=0
for capture in "${captures[@]}"; do
name="$(basename "$capture")"
content_stddev="$(magick "$capture" -shave 0x"$sample_inset" \
-colorspace gray -format '%[fx:standard_deviation]' info:)"
if awk -v s="$content_stddev" -v t="$blank_threshold" 'BEGIN { exit !(s < t) }'; then
printf ' %s BLANK (content stddev %s) — not normalised\n' "$name" "$content_stddev" >&2
blanks=$((blanks + 1))
continue
fi
magick "$capture" \
-gravity North -chop 0x"$status_px" \
-gravity South -chop 0x"$nav_px" \
+repage \
-resize "${target_w}x${target_h}^" \
-gravity Center -extent "${target_w}x${target_h}" \
-alpha remove -alpha off PNG24:"$out/$name"
printf ' %s ' "$out/$name"
magick identify -format '%wx%h %[channels] %b\n' "$out/$name"
done
if [ "$blanks" -gt 0 ]; then
echo "ERROR: $blanks capture(s) were blank and are missing from $out." >&2
echo " Wake the display and wait for the app's first frame, then re-capture:" >&2
echo " adb shell svc power stayon true" >&2
echo " adb shell input keyevent KEYCODE_WAKEUP" >&2
exit 1
fi
echo "Done."