From 2f9e47a551f705dbb0ae14f77a134927e9967fd5 Mon Sep 17 00:00:00 2001 From: akirschbaum Date: Sat, 12 Jan 2008 07:14:57 +0000 Subject: [PATCH] Add PNG compression script. git-svn-id: svn+ssh://svn.code.sf.net/p/crossfire/code/arch/trunk@8172 282e977c-c81d-0410-88c4-b93c2d0d6712 --- dev/png_recompress.sh | 284 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100755 dev/png_recompress.sh diff --git a/dev/png_recompress.sh b/dev/png_recompress.sh new file mode 100755 index 000000000..761c798b0 --- /dev/null +++ b/dev/png_recompress.sh @@ -0,0 +1,284 @@ +#!/usr/bin/env bash +# $Id: png_recompress.sh 5270 2008-01-08 21:23:59Z anmaster $ + +# Copyright (C) 2007-2008 Arvid Norlander +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# This script recompressess .png files using optipng and +# advpng to get the smallest images. All recompression is +# looseless. +# +# This script needs at least bash 3.1, bash 3.x or 2.x will not work. +# (Note that it was only tested on bash 3.2.17 or later though.) +# Also this need the programs mentioned above (optipng and advpng). +# +# TODO: +# * Better docs +# * Check that input really are *.png +# * If advpng doesn't make a file smaller, don't run the second +# optipng pass on that file (if the first optipng pass was enabled). + +# Check for new enough bash version +fail_old_bash() { + echo "Sorry your bash version is too old!" + echo "You need at least version 3.1 of bash." + echo "Please install a newer version:" + echo " * Either use your distro's packages." + echo " * Or see http://www.gnu.org/software/bash/" + exit 2 +} + +# Check bash version. We need at least 3.1 +# Lets not use anything like =~ here because +# that may not work on old bash versions. +if [[ "${BASH_VERSINFO[0]}${BASH_VERSINFO[1]}" -lt 31 ]]; then + fail_old_bash +fi + +# Version +declare -r png_recompress_version='0.0.1' + +# Useful for debugging +export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]} : ' + +print_cmd_help() { + echo 'png_recompress is a script to automate compressing of png images.' + echo '' + echo 'Usage: png_recompress [OPTION] files...' + echo '' + echo 'Options:' + echo ' -h, --help Display this help and exit.' + echo ' -V, --version Output version information and exit.' + echo ' -r, --recursive Run recursively on directories specified on command line. Will not follow symlinks.' + echo ' --skip pass Make png_recompress skip this pass (1, 2 or 3).' + echo '' + echo "Note that png_recompress can't handle short versions of options being written together like" + echo "-vv currently." + echo '' + echo 'Exit status is 0 if OK, 1 if minor problems, 2 if serious trouble.' + echo '' + echo 'Examples:' + echo ' png_recompress *.png Runs png_recompress on all *.png files in the current directory.' + exit $1 +} + +print_version() { + echo "png_recompress $png_recompress_version - Script to automate compressing of png images." + echo '' + echo 'Copyright (C) 2007-2008 Arvid Norlander' + echo 'This is free software; see the source for copying conditions. There is NO' + echo 'warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.' + echo '' + echo 'Written by Arvid Norlander.' + envbot_quit 0 +} + +#--------------------------------------------------------------------- +## Checks if a space separated list contains a value. +## @param List to check. +## @param Value to check for. +## @return 0 If found. +## @return 1 If not found. +#--------------------------------------------------------------------- +list_contains() { + [[ " ${!1} " = *" $2 "* ]] +} + +die() { + if [[ $2 ]]; then + echo -e "\e[1mERROR\e[0m: $2" + fi + exit $1 +} + +# Array of paths (images or directories) to process +PATHS=() +# Option: Skip passes +SKIP="" +# Recursive? +RECURSIVE='' +if [[ $# -gt 0 ]]; then + while [[ $# -gt 0 ]]; do + case "$1" in + '--help'|'-help'|'--usage'|'-usage'|'-h') + print_cmd_help 0 + ;; + '--version'|'-V') + print_version + ;; + '--recursive'|'-r') + RECURSIVE=1 + shift 1 + ;; + '--skip') + if [[ -z "$2" ]]; then + die 1 "Missing parameter to --skip. Maybe try --help" + else + case $2 in + 1|2|3) + SKIP+=" $2" + shift 2 + ;; + *) + die 1 "Parameter to skip must be 1, 2 or 3 (see --help)" + ;; + esac + fi + ;; + '-'*) + die 1 "Unknown option, try --help" + ;; + *) + PATHS+=( "$1" ) + shift 1 + ;; + esac + done +else + print_cmd_help 1 +fi + +if ! hash optipng > /dev/null 2>&1; then + echo "Can't find optipng!" + echo "This script depends on the optipng tool to be in PATH." + echo "Please install it or, if it is already installed add the" + echo "directory it is in to PATH and try again." + echo "Homepage of this tool is: http://optipng.sourceforge.net/" + die 2 +fi + +if ! hash advpng > /dev/null 2>&1; then + echo "Can't find advpng!" + echo "This script depends on the advpng tool to be in PATH." + echo "Please install it or, if it is already installed add the" + echo "directory it is in to PATH and try again." + echo "Homepage of this tool is: http://advancemame.sourceforge.net/comp-readme.html" + echo "Hint: For package name in your distro, try looking for \"advancecomp\" if" + echo "there is no \"advpng\"." + die 2 +fi + +echo -e "Please wait, this can take a \e[1mlong\e[0m time." + +# Array of image files +IMAGES=() + + +# ${PATHS[@]} paths to process +# Sets IMAGES +collect_images_recursive() { + local image directory results + local images=() + for directory in "${PATHS[@]}"; do + if ! [[ -d $directory && -r "$directory" && -w "$directory" ]]; then + echo "$directory skipped: directory not found, not readable and/or writable, or not a directory." + continue + fi + export IFS=$'\n' + results=( $(find "$directory" -iname '*.png' -type f -print ) ) + unset IFS + images+=( "${results[@]}" ) + done + PATHS=( "${images[@]}" ) +} + +# This will check that the images in question is a png, otherwise remove it from the list +checkimages() { + local image + local failcount=0 + for image in "${PATHS[@]}"; do + # First check it is a file that exists: + if ! [[ -f "$image" && -r "$image" && -w "$image" ]]; then + echo "$image skipped: file not found, not readable and/or writable, or not a normal file" + (( failcount++ )) + continue + elif ! [[ $(file -i "$image" ) == *image/png* ]]; then + echo "$image skipped: not a valid png (according to file)" + (( failcount++ )) + continue + else + IMAGES+=( "$image" ) + fi + done + if [[ $failcount -ne 0 ]]; then + echo "Of the images given as parameters $failcount could not be processed (see above for reasons)" + else + echo "All images ok" + fi + return 0 +} + +# Run optipng +dooptipng() { + optipng -i 0 -o 7 "$@" | \ + awk ' + /^\*\* Processing:/ { print "File: " $3 } + /^Input file size/ { print "Input: " $5,$6 } + /^Output file size/ { print "Output: " $5,$6,$7,$8,$9,$10,$11,"\n" } + /is already optimized/ { print "Output: No change\n" } + ' +} + +# Run advpng +doadvpng() { + # I hope this matches up with the columns in all cases... + echo " In Out % Filename" + advpng -z -4 "$@" +} + +# Check if pass should run, if yes print out the string as description and +# returns true. If no: returns false. +# $1 = pass number +# $2 = string to print +pass_check() { + if ! list_contains SKIP "$1"; then + echo -e "\n\e[1mPass $1: $2\e[0m\n" + return 0 + else + return 1 + fi +} + +if [[ $RECURSIVE ]]; then + echo "Collecting images from directories" + collect_images_recursive +fi + +pass_check 0 "verifying images (can not be skipped, checks that all images exists and are png)" && { + checkimages || die 2 "Pass 0 (check images) failed with return code $?" +} + +# Hacks around issue with one more newline on optipng +echo + +pass_check 1 "optipng" && { + dooptipng "${IMAGES[@]}" || die 2 "Pass 1 (optipng) failed with return code $?" +} + +pass_check 2 "advpng" && { + doadvpng "${IMAGES[@]}" || die 2 "Pass 2 (advpng) failed with return code $?" +} + +# Hacks around issue with one more newline on optipng +echo + +pass_check 3 "optipng again (as advpng often makes optipng more effective)" && { + dooptipng "${IMAGES[@]}" || die 2 "Pass 3 (optipng) failed with return code $?" +} + +# Hacks around issue with one more newline on optipng +echo + +exit 0