Subversion Repositories pub

Compare Revisions

Ignore whitespace Rev 299 → Rev 300

/video-contact-sheet/branches/1.0.7a/vcs
52,7 → 52,10
# any sane system though).
# * FEATURE: Funky modes (more to come...)
# * FEATURE: Polaroid funky mode (-kp)
# * FEATURE: Reel funky mode (-kr) (rough initial version)
# * INTERNAL: Use /dev/shm as base tempdir if possible
# * BUGFIX: Fixed safe_rename(): Don't assume current dir, added '--' to mv
# * Added workaround for ffmpeg arguments order
#
 
set -e
219,6 → 222,16
EX_NOINPUT=66 EX_SOFTWARE=70 EX_CANTCREAT=73 \
EX_INTERRUPTED=79 # This one is not on sysexits.h
 
# Workaounds:
# Argument order in FFmpeg is important -ss before or after -i will make
# the capture work or not depending on the file. XXX: I've yet to find why :P
# Anyway, this is used to change the order. See -Wo.
# Admittedly the workaraound is abit obscure: those variables will be added to
# the ffmpeg arguments, before and after -i, replacing spaces by the timestamp.
# e.g.: for second 50 '-ss ' will become '-ss 50' while '' will stay empty
# By default -ss goes before -i.
declare wa_ss_af="" wa_ss_be="-ss "
 
# Experimental in 1.0.7b: transformations/filters
# Operations are decomposed into independent optional steps, this will allow
# to add some intermediate steps (e.g. polaroid mode)
232,7 → 245,7
# Individual filters take the form:
# filt_name( vidcapfile, timestamp in seconds.milliseconds, width, height )
# They're executed in order by filter_vidcap()
declare -a FILTERS_IND=( filt_apply_stamp )
declare -a FILTERS_IND=( 'filt_resize' 'filt_apply_stamp' )
# Global filters take the form
# filtall_name( vidcapfile1, vidcapfile2, ... )
# They're executed in order by filter_all_vidcaps
515,14 → 528,17
# And print the output name to stdout
# See $safe_rename_pattern
# safe_rename($1 = original file, $2 = target file)
# XXX: Note it fails if target has no extension
safe_rename() {
local from="$1"
local to="$2"
 
# Extension
local ext=$(sed -r 's/.*\.(.*)/\1/g' <<<"$to")
# Basename without extension
local b=$(basename "$2" ".$ext")
# Output extension
local ext=$(sed -r 's/.*\.(.*)/\1/' <<<$to)
# Input extension
local iext=$(sed -r 's/.*\.(.*)/\1/' <<<$to)
# Input filename without extension
local b=${to%.$iext}
 
# safe_rename_pattern is override-able, ensure it has a valid value:
if ! grep -q '%e' <<<"$safe_rename_pattern" ||
533,14 → 549,14
 
local n=1
while [ -f "$to" ]; do # Only executes if $2 exists
to=$(sed "s/%b/$b/g" <<<"$safe_rename_pattern")
to=$(sed "s/%N/$n/g" <<<"$to")
to=$(sed "s/%e/$ext/g" <<<"$to")
to=$(sed "s#%b#$b#g" <<<"$safe_rename_pattern")
to=$(sed "s#%N#$n#g" <<<"$to")
to=$(sed "s#%e#$ext#g" <<<"$to")
 
let 'n++';
done
 
mv "$from" "$to"
mv -- "$from" "$to"
echo "$to"
}
 
727,8 → 743,6
unset -f randcolour randfound randccomp
}
 
randomize_look
 
# Add to $TIMECODES the timecodes at which a capture should be taken
# from the current video
# compute_timecodes($1 = timecode_from, $2 = interval, $3 = numcaps)
811,10 → 825,13
mplayer -sws 9 -ao null -benchmark -vo "png:z=0" -quiet \
-frames 1 -ss $stamp $shoehorned "$f" >/dev/null 2>&1
elif [ $decoder -eq $DEC_FFMPEG ]; then
# XXX: For some reason -ss before -i failed on my mkv sample
# while after -i it failed on my wmv9 sample ¿?
ffmpeg -y -ss $stamp -i "$f" -an -dframes 1 -vframes 1 -vcodec png \
-f rawvideo $shoehorned $VIDCAPFILE >/dev/null 2>&1
# XXX: It would be nice to show a message if it takes too long
{ # Used to redirect output
# See wa_ss_* declarations at the start of the file for details
ffmpeg -y ${wa_ss_be/ / $stamp} -i "$f" ${wa_ss_af/ / $stamp} -an \
-dframes 1 -vframes 1 -vcodec png \
-f rawvideo $shoehorned $VIDCAPFILE
} >/dev/null 2>&1
else
error "Internal error!"
return $EX_SOFTWARE
834,9 → 851,14
# Applies all individual vidcap filters
# filter_vidcap($1 = filename, $2 = timestamp, $3 = width, $4 = height)
filter_vidcap() {
# For performance purposes each filter simply prints a set of options
# to 'convert'. That's less flexible but enough right now for the current
# filters.
local cmdopts=
for filter in ${FILTERS_IND[@]}; do
$filter "$1" "$2" "$3" "$4"
cmdopts+=" $( $filter "$1" "$2" "$3" "$4" ) "
done
eval "convert '$1' $cmdopts '$1'"
}
 
# Applies all global vidcap filters
845,25 → 867,21
true
}
 
filt_resize() {
local f="$1" t=$2 w=$3 h=$4
 
# Note the '!', required to change the aspect ratio
echo " \( -geometry ${w}x${h}! \) "
}
 
# Draw a timestamp in the file
# filt_apply_stamp($1 = filename, $2 = timestamp, $3 = width, $4 = height)
filt_apply_stamp() {
local filename=$1 timestamp=$2 width=$3 height=$4
 
local temp=$(new_temp_file ".png")
mv "$filename" "$temp"
# Add the timestamp to each vidcap, doing it here is much powerful/simple
# 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 "$grav_timestamp" \
-stroke none -strokewidth 3 -annotate +5+5 " "$(pretty_stamp $stamp)" " \
"$temp" "$filename"
if [ ! -f "$filename" ]; then
error "Failed to add timestamp to capture"
mv "$temp" "$filename" # Leave things as before
return $EX_CANTCREAT
fi
echo -n " \( -box '#000000aa' -fill '$fg_tstamps' -pointsize '$pts_tstamps' "
echo -n " -gravity '$grav_timestamp' -stroke none -strokewidth 3 -annotate +5+5 "
echo " ' $(pretty_stamp $stamp) ' \) -flatten "
}
 
# Apply a Polaroid-like effect
875,16 → 893,53
local angle=$(( ($RANDOM % 37) - 18 ))
# 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"
 
echo -n "-bordercolor white -border 6 -bordercolor grey60 -border 1 "
echo -n "-background none -rotate $angle "
echo -n "-background black \( +clone -shadow 60x4+4+4 \) +swap "
echo "-background none -flatten -trim +repage"
}
 
# This one requires much more work, the results are pretty rough, but ok as
# a starting point / proof of concept
filt_reel() {
local file="$1" ts=$2 w=$3 h=$4
# Base reel dimensions
local rw=$(rmultiply $w,0.08) # 8% width
local rh=$(( $rw / 2 ))
# Ellipse center
local ecx=$(( $rw / 2 )) ecy=0
# Ellipse x, y radius
local erx=$(( (rw/2)*60/100 )) # 60% halt rect width
local ery=$(( $erx / 2))
 
local base_reel=$(new_temp_file .png) reel_strip=$(new_temp_file .png)
 
# Create the reel pattern...
convert -size ${rw}x${rh} 'xc:black' \
-fill white -draw "ellipse $ecx,$ecy $erx,$ery 0,360" -flatten \
\( +clone -flip \) -append \
-fuzz '40%' -transparent white \
"$base_reel"
# FIXME: Error handling
 
# Repeat it until the height is reached and crop to the exact height
local sh=$(imh "$base_reel") in=
local repeat=$( ceilmultiply $h/$sh)
while [ $repeat -gt 1 ]; do
in+=" '$base_reel' "
let 'repeat--'
done
eval convert "$base_reel" $in -append -crop $(imw "$base_reel")x${h}+0+0 \
"$reel_strip"
 
# As this options will be appended to the commandline we cannot
# order the arguments optimally (eg: reel.png image.png reel.png +append)
# A bit of trickery must be done flipping the image. Note also that the
# second strip will be appended flipped, which is intended.
echo -n "'$reel_strip' +append -flop '$reel_strip' +append -flop "
}
 
# Creates a contact sheet by calling the delegate
# create_contact_sheet($1 = columns, $2 = context, $3 = width, $4 = height,
# $5...$# = vidcaps) : output
948,7 → 1003,9
# I believe no image should ever be wider/taller than the diagonal (note the
# ceilmultiply is there to simply round the result)
local diagonal=$(ceilmultiply $(pyth_th $width $height) 1)
local canvasw=$(( $diagonal * $cols ))
# XXX: The width, though isn't guaranteed (e.g. using filt_reel it ends wider)
# adding 3% to the diagonal *should* be enough to compensate
local canvasw=$(( ( $diagonal + $(rmultiply $diagonal,0.3) ) * $cols ))
local canvash=$(( $diagonal ))
 
# The number of rows required to hold all the snaps
1464,6 → 1521,8
-j|--jpeg Output in jpeg (by default output is in png).
-q|--quiet Don't print progess messages just errors. Repeat to
mute completely even on error.
-Wo Workaround: Change ffmpeg's arguments order, might
work with some files that fail otherwise.
-Ij|-Ik
--mincho Use the kana/kanji/hiragana font (EXPERIMENTAL) might
also work for Hangul and Cyrillic.
1534,7 → 1593,7
 
# 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::k: \
TEMP=$(getopt -s bash -o i:n:u:T:f:t:S:jhFMH:c:ma:l:De::UqAO:I::k:W: \
--long "interval:,numcaps:,username:,title:,from:,to:,stamp:,jpeg,help,"\
"shoehorn:,mplayer,ffmpeg,height:,columns:,manual,aspect:,highlight:,"\
"extended::,fullname,quiet,autoaspect,override:,mincho,funky:" \
1693,6 → 1752,14
override "$2" "command line"
shift
;;
-W) # Workaround mode, see wa_ss_* declarations at the start for details
if [ "$2" != "o" ]; then
error "Wrong argument. Use -Wo instead of -W$2."
exit $EX_USAGE
fi
wa_ss_af='-ss ' wa_ss_be=''
shift
;;
-k|--funky) # Funky modes
case $(tolower "$2") in
p|polaroid)
1702,6 → 1769,10
# The timestamp must change location to be visible
grav_timestamp=NorthWest
;;
r|reel) # Undocumented for good reason!
info "Enabled reel mode."
FILTERS_IND+=( 'filt_reel' )
;;
*)
error "Unknown funky mode. Got '$2'."
exit $EX_UAGE