--- version: '3' vars: TINYPNG_API_KEY: z4qhFBLRvNMG9rHmdkSLx1DR1FNZN5gc tasks: compress: deps: - :install:npm:tinypng - :install:software:exiftool desc: Compress JPG/PNG images via TinyPNG summary: | # Compress JPG/PNG images via TinyPNG Finding the best stack for compressing images is not easy. All the best stacks seem to only be available for macOS. This task gets around this shortcoming by using [TinyPNG](https://tinypng.org) to compress images. Although relying on a third-party service is not ideal, TinyPNG does a fantastic job compressing images. After an image is compressed, file meta is stored to the image using 'exiftool'. This helps us avoid compressing the same image twice. An API key is embedded in these Taskfiles but it is a free one and has usage limits. If you would like to use your own credits then you can [sign up for a developer account here] (https://tinypng.com/developers). After you sign up, save your key to a file at `~/.tinypng` and this task will use your API key instead. **Example of compressing all '**.*.(jpg|png)' files in a project:** `task image:compress` **Example of compressing single image:** `task image:compress -- ./path/image.png` cmds: - task: compress:{{if .CLI_ARGS}}cli{{else}}default{{end}} compress:cli: cmds: - | function compressImage() { if exiftool "$1" &> /dev/null; then if (exiftool "$1" | grep Comment | grep tinypng-compressed) > /dev/null; then .config/log info '`'"$1"'` has already been compressed by TinyPNG' else if [ -f ~/.tinypng ]; then tinypng "$1" else tinypng -k "{{.TINYPNG_API_KEY}}" "$1" fi .config/log "Adding 'tinypng-compressed' as a comment in the EXIF data" exiftool -overwrite_original -comment="tinypng-compressed" "$1" .config/log success "Successfully compressed $1" fi else .config/log error 'Failed to extract EXIF data from `$1` so the compression is being skipped' fi } compressImage '{{.CLI_ARGS}}' compress:default: cmds: - | function compressImage() { if exiftool "$1" &> /dev/null; then if (exiftool "$1" | grep Comment | grep tinypng-compressed) > /dev/null; then .config/log info '`'"$1"'` has already been compressed by TinyPNG' else if [ -f ~/.tinypng ]; then tinypng "$1" else tinypng -k "{{.TINYPNG_API_KEY}}" "$1" fi .config/log "Adding 'tinypng-compressed' as a comment in the EXIF data" exiftool -overwrite_original -comment="tinypng-compressed" "$1" .config/log success "Successfully compressed $1" fi else .config/log error 'Failed to extract EXIF data from `$1` so the compression is being skipped' fi } while read PATHH; do compressImage "$PATHH" done < <(find . -type d \( {{.IGNORE_FOLDERS}} \) -prune -o -type f \( -name '*.jpg' -o -name '*.png' \)) sources: - '**/*.(jpg|png)' convert:logo: deps: - :install:npm:sharp - :install:npm:tinypng cmds: - sharp -i {{.CLI_ARGS}} -f png -o logo.png resize 200 200 - tinypng -k "{{.TINYPNG_API_KEY}}" logo.png - .config/log info 'Generated `logo.png`' - rm -f {{.CLI_ARGS}} - .config/log info 'Ensured `{{.CLI_ARGS}}` is removed' favicons: deps: - :install:npm:real-favicon cmds: - task donothing resize: deps: - :install:npm:sharp - :install:software:exiftool desc: Resize an image summary: | # Resize images This task leverages the NPM package named `sharp` to resize images. To use this task, specify the width, followed by the height, and then the image path (or just the name if it is in the same directory). Alternatively, you can open an interactive dialog to walk you through the process. **Example opening an interactive dialog:** `task image:resize` **Example changing the width to 200px and height to 240px of an image named `image.png`:** `task image:resize -- 200 240 image.png` cmds: - task: resize:{{if .CLI_ARGS}}cli{{else}}default{{end}} resize:all: summary: | # Resize all images in a specific directory This task will scan a directory passed in via the CLI and resize the images it finds using arguments also passed in via the CLI. It will also scan subdirectories. To use this command, follow the following format: **Example for resizing to 250px width and 300px height:** `task image:resize:all -- path/to/dir ---- 250 300` cmds: - | RESIZE_ALL_ARRAY=({{index (splitList " ---- " .CLI_ARGS) 1}}) while read IMAGE_PATH; do task image:resize:cli -- "$RESIZE_ALL_ARRAY[0]" "$RESIZE_ALL_ARRAY[1]" "$IMAGE_PATH" done < <(find "{{index (splitList " ---- " .CLI_ARGS) 0}}" -type f -name "*.jpg" -or -name "*.jpeg" -or -name "*.png" -or -name "*.bmp" -or -name "*.gif" -or -name "*.tif" -or -name "*.tiff" | sed 's/^.\///') resize:cli: cmds: - | ARGS_ARRAY=({{.CLI_ARGS}}) if ! exiftool "${ARGS_ARRAY[2]}" | grep "Image Size" | grep "${ARGS_ARRAY[0]}x${ARGS_ARRAY[1]}"; then .config/log info "Resizing "'`'"${ARGS_ARRAY[2]}"'`' sharp -i "${ARGS_ARRAY[2]}" -o "${ARGS_ARRAY[2]}.resized" resize "${ARGS_ARRAY[0]}" "${ARGS_ARRAY[1]}" mv "${ARGS_ARRAY[2]}.resized" "${ARGS_ARRAY[2]}" .config/log success "Successfully resized "'`'"${ARGS_ARRAY[2]}"'`' else .config/log info '`'"${ARGS_ARRAY[2]}"'`'" appears to already be the appropriate size" fi status: - 'exiftool "${ARGS_ARRAY[2]}" | grep "Image Size" | grep "${ARGS_ARRAY[0]}x${ARGS_ARRAY[1]}"' resize:default: cmds: - | DIRS_TMP="$(mktemp)" find . -type d -not -path "*/.*" > "$DIRS_TMP" .config/log prompt 'Select the directory of the image(s) you would like to resize (hidden directories are omitted)' CHOSEN_DIR="$(.config/log filter "$DIRS_TMP")" FILES_TMP="$(mktemp)" find "$CHOSEN_DIR" -type f -name "*.jpg" -or -name "*.jpeg" -or -name "*.png" -or -name "*.bmp" -or -name "*.gif" -or -name "*.tif" -or -name "*.tiff" | sed 's/^.\///' > "$FILES_TMP" .config/log prompt 'Select the image that you would like to resize' CHOSEN_IMAGE="$(.config/log filter "$FILES_TMP")" .config/log prompt 'Enter the desired width' CHOSEN_WIDTH="$(.config/log input "Enter width..")" .config/log prompt 'Enter the desired height' CHOSEN_HEIGHT="$(.config/log input "Enter height..")" task image:resize:cli -- "$CHOSEN_WIDTH" "$CHOSEN_HEIGHT" "$CHOSEN_IMAGE"