Subversion Repositories pub

Compare Revisions

Ignore whitespace Rev 295 → Rev 296

/video-contact-sheet/branches/1.0.7a/vcs
46,6 → 46,12
# * BUGFIX: Corrected test of accepted characters for intervals
# * Allow floating point intervals (e.g.: 3m.3 is 3 minutes and 0.3 seconds)
# * INTERNAL: New parsing code
# * FEATURE: Replaced hard by soft shadows
# * BUGFIX: Corrected colour usage: Print the colours to the correct channel
# * Made tput (coloured console output) optional (AFAIK should be present in
# any sane system though).
# * FEATURE: Funky modes (more to come...)
# * FEATURE: Polaroid funky mode (-kp)
#
 
set -e
238,6 → 244,8
declare CSHEET_DELEGATE=csheet_montage
declare -ri CTX_HL=1 CTX_STD=2 CTX_EXT=3
 
# Gravity of the timestamp (will be override-able in the future)
declare grav_timestamp=SouthEast
 
# These are the variables allowed to be overriden in the config file,
# please.
340,6 → 348,13
egrep -q '^[0-9]+/[0-9]+$'<<<"$1"
}
 
# Makes a string lowercase
# tolower($1 = string)
tolower() {
tr '[A-Z]' '[a-z]' <<<"$1"
}
 
 
# Rounded product
# multiplies parameters and prints the result, rounded to the closest int
# parameters can be separated by commas or spaces
354,6 → 369,13
bc -q <<<"( $f + 0.5 ) / 1"
}
 
# Like rmultiply() but always rounded upwards
ceilmultiply() {
local exp=$(sed 's/[ ,]/*/g'<<<"$@") # bc expression
local f=$(bc -lq<<<"$exp") # exact float value
bc -q <<<"( $f + 0.999999999 ) / 1"
}
 
# Prints the width correspoding to the input height and the variable
# aspect ratio
# compute_width($1 = height) (=AR*height) (rounded)
372,7 → 394,7
get_interval() {
if is_number "$1" ; then echo $1 ; return 0 ; fi
 
local s=$(tr '[A-Z]' '[a-z]' <<<"$1") t r
local s=$(tolower "$1") t r
 
# Only allowed characters
if ! egrep -qi '^[0-9smh.]+$' <<<"$s"; then
415,6 → 437,18
echo $str
}
 
# Get Image Width
# imw($1 = file)
imw() {
identify "$1" | cut -d' ' -f3 | cut -d'x' -f1
}
 
# Get Image Height
# imh($1 = file)
imh() {
identify "$1" | cut -d' ' -f3 | cut -d'x' -f2
}
 
# Prints a number of seconds in a more human readable form
# e.g.: 3600 becomes 1:00:00
# pretty_stamp($1 = seconds)
504,7 → 538,8
# test_programs()
test_programs() {
local retval=0 last=0
for prog in getopt mplayer convert montage identify bc ffmpeg mktemp sed grep egrep ; do
for prog in getopt mplayer convert montage identify bc \
ffmpeg mktemp sed grep egrep cut; do
type -pf "$prog" >/dev/null
if [ $? -ne 0 ] ; then
error "Required program $prog not found!"
547,8 → 582,10
# sgr0 is always used, this way if
# a) something prints inbetween messages it isn't affected
# b) if plain_messages is overridden colour stops after the override
echo "$1" >&2 ; tput sgr0
fi
echo "$1" ; tput sgr0
fi >&2
# It is important to redirect both tput and echo to stderr. Otherwise
# n=$(something) wouldn't be coloured
}
#
# Print a non-fatal error or warning
558,8 → 595,8
if [ $plain_messages -eq 0 ]; then
tput bold ; tput setaf 3;
fi
echo "$1" >&2 ; tput sgr0
fi
echo "$1" ; tput sgr0
fi >&2
}
#
# Print an informational message
569,8 → 606,8
if [ $plain_messages -eq 0 ]; then
tput bold ; tput setaf 2;
fi
echo "$1" >&2 ; tput sgr0
fi
echo "$1" ; tput sgr0
fi >&2
}
#
# Same as info but with no colour ever.
739,7 → 776,7
# than with the next montage command
# Note the '!', it is necessary to apply aspect ratio change
convert -box '#000000aa' -geometry ${width}x${height}! \
-fill "$fg_tstamps" -pointsize "$pts_tstamps" -gravity SouthEast \
-fill "$fg_tstamps" -pointsize "$pts_tstamps" -gravity "$grav_timestamp" \
-stroke none -strokewidth 3 -annotate +5+5 " "$(pretty_stamp $stamp)" " \
"$temp" "$filename"
if [ ! -f "$filename" ]; then
749,6 → 786,25
fi
}
 
# Apply a Polaroid-like effect
# Taken from <http://www.imagemagick.org/Usage/thumbnails/#polaroid>
# filt_polaroid($1 = filename, $2 = timestamp, $3 = width, $4 = height)
filt_polaroid() {
local file="$1" ts=$2 w=$3 h=$4
# Rotation angle [-9..18]
local angle=$(( ($RANDOM % 19) - 9 ))
# Tweaking the size gives a nice effect too
# w=$(( $w - ( $RANDOM % ( $w / 3 ) ) ))
# -geometry ${w}x \
convert "$file" \
-bordercolor white -border 6 \
-bordercolor grey60 -border 1 \
-background none -rotate $angle \
-background black \( +clone -shadow 60x4+4+4 \) +swap \
-background none -flatten \
"$file"
}
 
# Creates a contact sheet by calling the delegate
# create_contact_sheet($1 = columns, $2... = vidcaps) : output
create_contact_sheet() {
775,6 → 831,104
echo $output
}
 
# Polaroid contact sheet creator: it overlaps vidcaps with some randomness
# csheet_polaroid($1 = columns, $2 = context, $3... = $vidcaps) : output
csheet_polaroid() {
local cols=$1 ctx=$2
# globals: $VID
shift ; shift
 
# TBD: Handle context
 
# Explanation of how this works:
# On the first loop we do what the "montage" command would do (arrange the
# images in a grid) but overlapping each image to the one on their left,
# creating the output row by row, each row in a file.
# On the second loop we append the rows, again overlapping each one to the
# one before (above) it.
# XXX: Compositing over huge images is quite slow, there's probably a
# better way to do it
 
# Offset bounds, this controls how much of each snap will be over the
# previous one
local maxoffset=$(( ${VID[$W]} / 3 )) # ~ Vid width / 3
local minoffset=$(( $maxoffset / 2 )) # ~ Vid Width / 6
 
# Holds the files that will form the full contact sheet
# each file is a row on the final composition
local -a rowfiles=( )
 
# Dimensions of the canvas for each row, this should be enough
# to hold all snaps (not the snaps are rotated so width and height
# aren't necessarily the same as the video)
local canvasw=$(( ${VID[$W]} * ( $cols + 1 ) ))
local canvash=$(( ${VID[$H]} * 2 ))
 
# The number of rows required to hold all the snaps
local numrows=$(ceilmultiply ${#@},1/$cols) # rounded division
 
# Variables inside the loop
local col # Current column
local rowfile # Holds the row we're working on
local offset # Random offset of the current snap [$minoffset..$maxoffset]
local accoffset # The absolute (horizontal) offset used on the next iteration
local cmdopts # Holds the arguments passed to convert to compose the sheet
local w # Width of the current snap
for row in $(seq 1 $numrows) ; do
col=0
rowfile=$(new_temp_file .png)
rowfiles+=( "$rowfile" )
accoffset=0
cmdopts= # This command is pretty time-consuming, let's make it in a row
 
# Base canvas
info "Creating polaroid base canvas $row/$numrows..."
convert -size ${canvasw}x${canvash} xc:transparent "$rowfile"
 
# Step through vidcaps (col=[0..cols-1])
for col in $(seq 0 $(( $cols - 1 ))); do
w=$(imw "$1")
 
# Stick the vicap in the canvas
#convert -geometry +${accoffset}+0 "$rowfile" "$1" -composite "$rowfile"
cmdopts+=" -geometry +${accoffset}+0 '$1' -composite "
 
offset=$(( $minoffset + ( $RANDOM % $maxoffset ) ))
let 'accoffset=accoffset + w - offset'
shift
done
info "Composing polaroid row $row/$numrows..."
eval convert "'$rowfile'" "$cmdopts" -trim +repage "'$rowfile'" >&2
done
 
info "Merging polaroid rows..."
output=$(new_temp_file .png)
# Standard composition
#convert -background Transparent "${rowfiles[@]}" -append polaroid.png
# Overlapped composition
convert -size ${canvasw}x$(( $canvash * $cols )) xc:transparent "$output"
cmdopts=
accoffset=0
local h
for row in "${rowfiles[@]}" ; do
w=$(imw "$row")
h=$(imh "$row")
minoffset=$(( $h / 8 ))
maxoffset=$(( $h / 4 ))
offset=$(( $minoffset + ( $RANDOM % $maxoffset ) ))
# The row is also offset horizontally
cmdopts+=" -geometry +$(( $RANDOM % $maxoffset ))+$accoffset '$row' -composite "
let 'accoffset=accoffset + h - offset'
done
# After the trim the top corners are too near the heading, we add some space
# with -splce
eval convert -background transparent "$output" $cmdopts -trim +repage \
-bordercolor Transparent -splice 0x10 "$output" >&2
 
# FIXME: Error handling
echo $output
}
 
# Sorts timestamps and removes duplicates
# clean_timestamps($1 = space separated timestamps)
clean_timestamps() {
968,7 → 1122,7
# Another software with a list of fourccs -> name mappings:
# <http://webcvs.freedesktop.org/clipart/experimental/rejon/getid3/getid3/module.audio-video.riff.php?view=markup>
local vcodec= acodec=
case $( tr '[A-Z]' '[a-z]' <<<${VID[$VCODEC]}) in
case $(tolower ${VID[$VCODEC]}) in
xvid) vcodec=Xvid ;;
dx50) vcodec="DivX 5" ;;
0x10000001) vcodec="MPEG-1" ;;
1010,7 → 1164,7
vcodec+=" (h.264)"
fi
 
case $( tr '[A-Z]' '[a-z]' <<<${VID[$ACODEC]} ) in
case $(tolower ${VID[$ACODEC]} ) in
85) acodec='MPEG Layer III (MP3)' ;;
80) acodec='MPEG Layer I/II (MP1/MP2)' ;; # Apparently they use the same tag
mp4a) acodec='MPEG-4 AAC' ;; # LC and HE, apparently
1224,6 → 1378,16
-Ij|-Ik
--mincho Use the kana/kanji/hiragana font (EXPERIMENTAL) might
also work for Hangul and Cyrillic.
-k <arg>
--funky <arg> Funky modes:
These are toy output modes in which the contact sheet
gets a more informal look. They're random in nature
so using the same funky mode twice will usually lead to
quite different results.
Currently the only "funky mode" available is
"polaroid": Use '-kp' or '--funky polaroid'
Makes output look like photographs laid over a
table.
-O|--override <arg> Use it to override a variable (see the homepage for
more details). Format accepted is 'variable=value' (can
also be quoted -variable="some value"- and can take an
1259,6 → 1423,14
 
#### Execution starts here ####
 
# If tput isn't found simply ignore tput commands
# (no colour support)
# Important to do it before any message can be thrown
if ! type -pf tput >/dev/null ; then
tput() { cat >/dev/null <<<"$1"; }
warn "tput wasn't found. Coloured feedback disabled."
fi
 
# Execute exithdlr on exit
trap exithdlr EXIT
 
1273,10 → 1445,10
 
# TODO: use no name at all with -u noarg
#eval set -- "${default_options} ${@}"
TEMP=$(getopt -s bash -o i:n:u:T:f:t:S:jhFMH:c:ma:l:De::UqAO:I:: \
TEMP=$(getopt -s bash -o i:n:u:T:f:t:S:jhFMH:c:ma:l:De::UqAO:I::k: \
--long "interval:,numcaps:,username:,title:,from:,to:,stamp:,jpeg,help,"\
"shoehorn:,mplayer,ffmpeg,height:,columns:,manual,aspect:,highlight:,"\
"extended::,fullname,quiet,autoaspect,override:,mincho" \
"extended::,fullname,quiet,autoaspect,override:,mincho,funky:" \
-n $0 -- "$@")
 
eval set -- "$TEMP"
1432,6 → 1604,22
override "$2" "command line"
shift
;;
-k|--funky) # Funky modes
case $(tolower "$2") in
p|polaroid)
info "Changed to polaroid funky mode."
FILTERS_IND+=( 'filt_polaroid' )
CSHEET_DELEGATE='csheet_polaroid'
# The timestamp must change location to be visible
grav_timestamp=NorthWest
;;
*)
error "Unknown funky mode. Got '$2'."
exit $EX_UAGE
;;
esac
shift
;;
-q|--quiet)
# -q to only show errors
# -qq to be completely quiet