mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 16:43:05 +02:00
- Move slow hooks (mypy, pylint, bandit, pytest, prettier) to pre-push stage - Remove redundant autoflake (ruff covers F401/F841) - Fix shellcheck OOM by batching files with xargs -n 40 - Remove tracked .o, .wav, .pyc binaries from git - Move pomodoro wav files to ../testsAndMisc_binaries/ with symlinks - Add *.o, *.so, *.a to .gitignore - Refactor hltb._pick_best_hltb_entry to fix C901/PLR0911/SIM102 - Fix SC2034 warnings in gif_to_square.sh and upgrade.sh - Add disk_cleanup_check.sh script - Various test and code improvements across screen_locker, steam_backlog_enforcer, word_frequency, moviepy_showcase
153 lines
4.5 KiB
Bash
Executable File
153 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Pad a GIF to a square with transparent background, centered.
|
|
# Useful for making Slack emojis from rectangular GIFs.
|
|
# Usage: gif_to_square.sh <input.gif> [output.gif] [background]
|
|
|
|
set -euo pipefail
|
|
|
|
# Source common library for shared functions
|
|
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
|
# shellcheck source=../lib/common.sh
|
|
source "$SCRIPT_DIR/../lib/common.sh"
|
|
|
|
# Default background color (transparent)
|
|
DEFAULT_BG="none"
|
|
|
|
# Function to display usage
|
|
usage() {
|
|
cat << EOF
|
|
Usage: $0 <input.gif> [output.gif] [background]
|
|
|
|
Arguments:
|
|
input.gif Path to the input GIF file (required)
|
|
output.gif Path to the output GIF file (default: <input>_square.gif)
|
|
background Background color for padding (default: ${DEFAULT_BG})
|
|
Use "none" for transparent, or any color name/hex
|
|
|
|
Examples:
|
|
$0 emoji.gif
|
|
$0 emoji.gif square_emoji.gif
|
|
$0 emoji.gif square_emoji.gif white
|
|
$0 emoji.gif square_emoji.gif "#FF0000"
|
|
|
|
Note: Requires ImageMagick (magick or convert command)
|
|
Slack emoji max size: 128x128 pixels, 256KB
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
# Install ImageMagick if missing
|
|
if ! command -v magick &> /dev/null && ! command -v convert &> /dev/null; then
|
|
echo "ImageMagick not found. Installing..."
|
|
if command -v pacman &> /dev/null; then
|
|
sudo pacman -S --noconfirm imagemagick
|
|
elif command -v apt-get &> /dev/null; then
|
|
sudo apt-get update && sudo apt-get install -y imagemagick
|
|
else
|
|
echo "Error: Could not detect package manager. Install ImageMagick manually."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
require_imagemagick || exit 1
|
|
|
|
# Set up identify command (IM7: magick identify, IM6: identify)
|
|
if [[ ${MAGICK_CMD} == "magick" ]]; then
|
|
IDENTIFY_CMD="magick identify"
|
|
else
|
|
IDENTIFY_CMD="identify"
|
|
fi
|
|
|
|
# Parse arguments
|
|
if [[ $# -lt 1 ]]; then
|
|
echo "Error: Missing required argument <input.gif>"
|
|
usage
|
|
fi
|
|
|
|
INPUT_GIF="$1"
|
|
OUTPUT_GIF="${2:-}"
|
|
BACKGROUND="${3:-${DEFAULT_BG}}" # Reserved for future padding mode
|
|
export BACKGROUND
|
|
|
|
# Validate input file exists
|
|
if [[ ! -f ${INPUT_GIF} ]]; then
|
|
echo "Error: Input file '${INPUT_GIF}' does not exist."
|
|
exit 1
|
|
fi
|
|
|
|
# Validate it's a GIF
|
|
MIME_TYPE=$(file --mime-type -b "${INPUT_GIF}")
|
|
if [[ ${MIME_TYPE} != "image/gif" ]]; then
|
|
echo "Error: '${INPUT_GIF}' is not a GIF file (detected: ${MIME_TYPE})"
|
|
exit 1
|
|
fi
|
|
|
|
# Generate output filename if not provided
|
|
if [[ -z ${OUTPUT_GIF} ]]; then
|
|
OUTPUT_GIF=$(generate_output_filename "${INPUT_GIF}" "_square")
|
|
fi
|
|
|
|
# Get dimensions of the first frame
|
|
DIMENSIONS=$(${IDENTIFY_CMD} -format "%wx%h" "${INPUT_GIF}[0]")
|
|
WIDTH="${DIMENSIONS%x*}"
|
|
HEIGHT="${DIMENSIONS#*x}"
|
|
|
|
echo "Input: ${INPUT_GIF}"
|
|
echo "Dimensions: ${WIDTH}x${HEIGHT}"
|
|
|
|
if [[ ${WIDTH} -eq ${HEIGHT} ]]; then
|
|
echo "Image is already square. Copying to output."
|
|
cp "${INPUT_GIF}" "${OUTPUT_GIF}"
|
|
else
|
|
# Stretch to square using the larger dimension
|
|
if [[ ${WIDTH} -gt ${HEIGHT} ]]; then
|
|
SIDE=${WIDTH}
|
|
else
|
|
SIDE=${HEIGHT}
|
|
fi
|
|
|
|
echo "Stretching to ${SIDE}x${SIDE}..."
|
|
|
|
"${MAGICK_CMD}" "${INPUT_GIF}" \
|
|
-coalesce \
|
|
-resize "${SIDE}x${SIDE}!" \
|
|
-layers Optimize \
|
|
"${OUTPUT_GIF}"
|
|
fi
|
|
|
|
if [[ -f ${OUTPUT_GIF} ]]; then
|
|
OUT_DIMENSIONS=$(${IDENTIFY_CMD} -format "%wx%h" "${OUTPUT_GIF}[0]")
|
|
INPUT_SIZE=$(du -h "${INPUT_GIF}" | cut -f1)
|
|
OUTPUT_SIZE=$(du -h "${OUTPUT_GIF}" | cut -f1)
|
|
|
|
echo "✓ Successfully created square GIF"
|
|
echo "Output: ${OUTPUT_GIF} (${OUT_DIMENSIONS})"
|
|
echo "Input size: ${INPUT_SIZE}"
|
|
echo "Output size: ${OUTPUT_SIZE}"
|
|
|
|
# Auto-shrink if over Slack's 128KB emoji limit (target 124KB for safety margin)
|
|
MAX_BYTES=126976
|
|
OUTPUT_BYTES=$(stat -c%s "${OUTPUT_GIF}" 2>/dev/null || stat -f%z "${OUTPUT_GIF}" 2>/dev/null)
|
|
if [[ ${OUTPUT_BYTES} -gt ${MAX_BYTES} ]]; then
|
|
echo ""
|
|
echo "Output is over 128KB (${OUTPUT_BYTES} bytes). Auto-shrinking for Slack..."
|
|
CURRENT_SIDE=$(${IDENTIFY_CMD} -format "%w" "${OUTPUT_GIF}[0]")
|
|
while [[ ${OUTPUT_BYTES} -gt ${MAX_BYTES} && ${CURRENT_SIDE} -gt 16 ]]; do
|
|
# Reduce by ~25% each iteration
|
|
CURRENT_SIDE=$(( CURRENT_SIDE * 75 / 100 ))
|
|
echo " Trying ${CURRENT_SIDE}x${CURRENT_SIDE}..."
|
|
"${MAGICK_CMD}" "${OUTPUT_GIF}" \
|
|
-coalesce \
|
|
-resize "${CURRENT_SIDE}x${CURRENT_SIDE}!" \
|
|
-layers Optimize \
|
|
"${OUTPUT_GIF}"
|
|
OUTPUT_BYTES=$(stat -c%s "${OUTPUT_GIF}" 2>/dev/null || stat -f%z "${OUTPUT_GIF}" 2>/dev/null)
|
|
done
|
|
OUTPUT_SIZE=$(du -h "${OUTPUT_GIF}" | cut -f1)
|
|
echo "✓ Shrunk to ${CURRENT_SIDE}x${CURRENT_SIDE} (${OUTPUT_SIZE}, ${OUTPUT_BYTES} bytes)"
|
|
fi
|
|
else
|
|
echo "✗ Error: Failed to create output file"
|
|
exit 1
|
|
fi
|