Skip to content

Instantly share code, notes, and snippets.

@selbyk
Last active December 5, 2015 20:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save selbyk/ba289a393a88bcf8142d to your computer and use it in GitHub Desktop.
Save selbyk/ba289a393a88bcf8142d to your computer and use it in GitHub Desktop.
#!/bin/bash
# Set to number of cores your computer has or you want to use
export MAGICK_THREAD_LIMIT=8
# Deleted old files
rm *.jpg
rm *.png
rm *.gif
rm *.mp4
# Copy image files newer than 60 days from parent dir to current dir
find ../ -mindepth 1 -maxdepth 1 -mtime -60 -name "*.jpg" -exec cp -t . {} +
# Rename files so ffmpeg likes them
i=0
for f in ./*.jpg
do
new_name=$(printf "0img%05d0.jpg" $i)
if [[ "$f" =~ ^0img[0-9]{5}0\.jpg$ ]];
then
echo "$f already renamed appropriately";
else
printf "Renaming $f to $new_name\n"
mv $f $new_name
fi
i=$((i+1))
done
# Create transition images using imagemagick
i=1
for f in ./0img*0.jpg
do
input1=$(printf "0img%05d0.jpg" $((i-1)))
input2=$(printf "0img%05d0.jpg" $i)
newfiles=$(printf "0img%05d" $((i-1)))
# Gotta make a mask file
convert -size 1920x1080 plasma:fractal -virtual-pixel tile -fx intensity maskfile.jpg
echo $input1
echo $input2
# Someone else's script
./transitions.sh -m dissolve -f 10 -d 10 -p 10 -e ./$input1 ./$input2 ./maskfile.jpg ./tmp.gif
convert -coalesce ./tmp.gif $newfiles%01d.jpg
i=$((i+1))
done
# Create mp4 output
ffmpeg -framerate 4 -i 0img%06d.jpg -s:v 1280x720 -pix_fmt yuv420p -r 30 \
-c:v libx264 -preset ultrafast -qp 0 noshave.mp4
#!/bin/bash
#
# Developed by Fred Weinhaus 5/29/2008 .......... revised 5/3/2015
#
# ------------------------------------------------------------------------------
#
# Licensing:
#
# Copyright © Fred Weinhaus
#
# My scripts are available free of charge for non-commercial use, ONLY.
#
# For use of my scripts in commercial (for-profit) environments or
# non-free applications, please contact me (Fred Weinhaus) for
# licensing arrangements. My email address is fmw at alink dot net.
#
# If you: 1) redistribute, 2) incorporate any of these scripts into other
# free applications or 3) reprogram them in another scripting language,
# then you must contact me for permission, especially if the result might
# be used in a commercial or for-profit environment.
#
# My scripts are also subject, in a subordinate manner, to the ImageMagick
# license, which can be found at: http://www.imagemagick.org/script/license.php
#
# ------------------------------------------------------------------------------
#
####
#
# USAGE: transitions [-m mode] [-f frames] [-d delay] [-p pause] [-r] [-e] infile1 infile2 maskfile [outfile]
# USAGE: transitions [-h or -help]
#
# OPTIONS:
#
# -m mode mode of transition; wipe or dissolve; default=wipe
# -f frames number of frames in animation; frames>1; default=20
# -d delay delay between frames; delay>0; default=20
# -p pause pause delay for two undistorted input images;
# pause>0; default=50
# -r reverse the animation sequence and append it to the end
# -e exponentiate maskfile to make the animation
# start more gradually. Mostly useful for mode=dissolve
#
# The two input files and mask file must be the same size.
#
# The output file must be of type that supports multi-frames, such as gif.
#
# If no output file is specified, the animation will be displayed automatically
# but not saved to a file
#
###
#
# NAME: TRANSITIONS
#
# PURPOSE: To apply an animated transition between two images.
#
# DESCRIPTION: TRANSITIONS applies an animated transition between two images
# using a mask image to control the transition. The first image will show
# where the mask is black and the second image will show where the mask is
# white. The mask will be made gradually more an more white as each frame
# is composited. NOTE that this is not a true warping morph. It is simply
# an animated masked composite.
#
# OPTIONS:
#
# -m mode ... MODE of transition. Values are wipe or dissolve. The default is wipe.
# Note that dissolve is generally only useful for very gradual graylevel changes
# in the mask image, such as a linear or radial gradient.
#
# -f frames ... FRAMES is the total number of frames in the animation (including
# infile1 and infile2 as the start and end frames. Values are integers > 1. The
# default is 20.
#
# -d delay ... DELAY between frames. Values are integers>0. The default=20
#
# -p pause ... PAUSE is the delay to use for the first and last frame of the
# animation, i.e. the delay for each of the input images. The default=50
#
# -r ... If supplied, then reverse the animation sequence, remove the first and
# last frames of the reversed sequence and append these reversed frames to
# the end of the animation.
#
# -e ... If supplied, then the maskfile will be exponentiated to make the
# animation start more gradually. This is useful for most dissolve mode
# transitions.
#
# CAVEAT: No guarantee that this script will work on all platforms,
# nor that trapping of inconsistent parameters is complete and
# foolproof. Use At Your Own Risk.
#
######
#
# set default values
mode="wipe" #wipe or dissolve
frames=20
delay=20
pause=50
mask="linear" #linear or exponential
reverse="no"
view="no"
# set directory for temporary files
dir="." # suggestions are dir="." or dir="/tmp"
# set up functions to report Usage and Usage with Description
PROGNAME=`type $0 | awk '{print $3}'` # search for executable on path
PROGDIR=`dirname $PROGNAME` # extract directory of program
PROGNAME=`basename $PROGNAME` # base name of program
usage1()
{
echo >&2 ""
echo >&2 "$PROGNAME:" "$@"
sed >&2 -e '1,/^####/d; /^###/g; /^#/!q; s/^#//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME"
}
usage2()
{
echo >&2 ""
echo >&2 "$PROGNAME:" "$@"
sed >&2 -e '1,/^####/d; /^######/g; /^#/!q; s/^#*//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME"
}
# function to report error messages
errMsg()
{
echo ""
echo $1
echo ""
usage1
exit 1
}
# function to test for minus at start of value of second part of option 1 or 2
checkMinus()
{
test=`echo "$1" | grep -c '^-.*$'` # returns 1 if match; 0 otherwise
[ $test -eq 1 ] && errMsg "$errorMsg"
}
# test for correct number of arguments and get values
if [ $# -eq 0 ]
then
# help information
echo ""
usage2
exit 0
elif [ $# -gt 14 ]
then
errMsg "--- TOO MANY ARGUMENTS WERE PROVIDED ---"
else
while [ $# -gt 0 ]
do
# get parameter values
case "$1" in
-h|-help) # help information
echo ""
usage2
exit 0
;;
-m) # get mode
shift # to get the next parameter - mode
# test if parameter starts with minus sign
errorMsg="--- INVALID MODE SPECIFICATION ---"
checkMinus "$1"
mode="$1"
[ "$mode" != "wipe" -a "$mode" != "dissolve" ] && errMsg "MODE=$mode MUST BE EITHER WIPE OR DISSOLVE ---"
;;
-f) # get frames
shift # to get the next parameter - frames
# test if parameter starts with minus sign
errorMsg="--- INVALID FRAMES SPECIFICATION ---"
checkMinus "$1"
frames=`expr "$1" : '\([0-9]*\)'`
[ "$frames" = "" ] && errMsg "FRAMES=$frames MUST BE AN INTEGER"
framestest=`echo "$frames <= 1" | bc`
[ $framestest -eq 1 ] && errMsg "--- FRAMES=$frames MUST BE AN INTEGER GREATER THAN 1 ---"
;;
-d) # get delay
shift # to get the next parameter - delay
# test if parameter starts with minus sign
errorMsg="--- INVALID DELAY SPECIFICATION ---"
checkMinus "$1"
delay=`expr "$1" : '\([0-9]*\)'`
[ "$delay" = "" ] && errMsg "DELAY=$delay MUST BE AN INTEGER"
delaytest=`echo "$delay < 1" | bc`
[ $delaytest -eq 1 ] && errMsg "--- DELAY=$delay MUST BE A POSITIVE INTEGER ---"
;;
-p) # get pause
shift # to get the next parameter - pause
# test if parameter starts with minus sign
errorMsg="--- INVALID PAUSE SPECIFICATION ---"
checkMinus "$1"
pause=`expr "$1" : '\([0-9]*\)'`
[ "$pause" = "" ] && errMsg "PAUSE=$pause MUST BE A NON-NEGATIVE INTEGER"
;;
-r) # set frame reversal append
reverse="yes"
;;
-e) # set exponentiation
mask="exponential"
;;
-) # STDIN and end of arguments
break
;;
-*) # any other - argument
errMsg "--- UNKNOWN OPTION ---"
;;
*) # end of arguments
break
;;
esac
shift # next option
done
#
# get infile and outfile
infile1="$1"
infile2="$2"
maskfile="$3"
outfile="$4"
fi
# test that infile1 provided
[ "$infile1" = "" ] && errMsg "NO INPUT FILE 1 SPECIFIED"
# test that infile2 provided
[ "$infile2" = "" ] && errMsg "NO INPUT FILE 2 SPECIFIED"
# test that maskfile provided
[ "$maskfile" = "" ] && errMsg "NO MASKFILE SPECIFIED"
# set temporary files
tmpA="$dir/transitions_1_$$.mpc"
tmpB="$dir/transitions_1_$$.cache"
tmpC="$dir/transitions_2_$$.mpc"
tmpD="$dir/transitions_2_$$.cache"
tmpE="$dir/transitions_3_$$.mpc"
tmpF="$dir/transitions_3_$$.cache"
tmp0="$dir/transitions_0_$$.gif"
trap "rm -f $tmpA $tmpB $tmpC $tmpD $tmpE $tmpF $tmp0;" 0
trap "rm -f $tmpA $tmpB $tmpC $tmpD $tmpE $tmpF $tmp0; exit 1" 1 2 3 15
trap "rm -f $tmpA $tmpB $tmpC $tmpD $tmpE $tmpF $tmp0; exit 1" ERR
# get im_version
im_version=`convert -list configure | \
sed '/^LIB_VERSION_NUMBER /!d; s//,/; s/,/,0/g; s/,0*\([0-9][0-9]\)/\1/g' | head -n 1`
# colorspace RGB and sRGB swapped between 6.7.5.5 and 6.7.6.7
# though probably not resolved until the latter
# then -colorspace gray changed to linear between 6.7.6.7 and 6.7.8.2
# then -separate converted to linear gray channels between 6.7.6.7 and 6.7.8.2,
# though probably not resolved until the latter
# so -colorspace HSL/HSB -separate and -colorspace gray became linear
# but we need to use -set colorspace RGB before using them at appropriate times
# so that results stay as in original script
# The following was determined from various version tests using transitions
# with IM 6.7.4.10, 6.7.6.10, 6.7.9.0
if [ "$im_version" -lt "06070607" -o "$im_version" -gt "06070707" ]; then
setcspace="-set colorspace RGB"
else
setcspace=""
fi
# no need for setcspace for grayscale or channels after 6.8.5.4
if [ "$im_version" -gt "06080504" ]; then
setcspace=""
fi
if convert -quiet "$infile1" +repage "$tmpA"
then
: ' Do Nothing '
else
errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
fi
if convert -quiet "$infile2" +repage "$tmpC"
then
: ' Do Nothing '
else
errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
fi
if [ "$mask" = "exponential" ]
then
# exponentiate mask so that transition does not show much of second image too early
if convert -quiet "$maskfile" -fx "(10^(u)-1)/9" +repage "$tmpE"
then
: ' Do Nothing '
else
errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
fi
elif [ "$mask" = "linear" ]
then
if convert -quiet "$maskfile" +repage "$tmpE"
then
: ' Do Nothing '
else
errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
fi
fi
# check image sizes
w1=`convert $tmpA -format "%w" info:`
h1=`convert $tmpA -format "%h" info:`
w2=`convert $tmpC -format "%w" info:`
h2=`convert $tmpC -format "%h" info:`
w3=`convert $tmpE -format "%w" info:`
h3=`convert $tmpE -format "%h" info:`
[ $w1 -ne $w2 -a $h1 -ne $h2 -a $w1 -ne $w3 -a $h1 -ne $h3 ] && errMsg "--- IMAGE SIZES DO NOT MATCH ---"
# test if hdri and if so limit addition to 100% (white)
is_hdri=`convert -list configure | \
sed -n 's/^.*--enable-hdri.*$/1/p'`
if [ "$is_hdri" != "" ]
then
min="-evaluate min 100%"
else
min=""
fi
echo "min=$min"
echo ""
echo "Generating $frames Frames:"
echo ""
frames=`expr $frames - 1`
echo "0"
i=1
convert $tmpA $tmp0
if [ "$mode" = "dissolve" ]
then
while [ $i -le $frames ]
do
echo $i
aa=`convert xc: -format "%[fx:100*$i/$frames]" info:`
convert $tmpA $tmpC \( $tmpE -evaluate add $aa% $min \) $setcspace -composite miff:- |\
convert -delay $delay $tmp0 -page +0+0 - -page +0+0 $tmp0
i=`expr $i + 1`
done
elif [ "$mode" = "wipe" ]
then
while [ $i -le $frames ]
do
echo $i
tt=`convert xc: -format "%[fx:100($frames-$i)/$frames]" info:`
convert $tmpA $tmpC \( $tmpE -threshold $tt% \) $setcspace -composite miff:- |\
convert -delay $delay $tmp0 -page +0+0 - -page +0+0 $tmp0
i=`expr $i + 1`
done
fi
# change delay of first and last image
if [ $pause -ne $delay ]
then
convert $tmp0 -coalesce \
\( -clone 0 -set delay $pause \) -swap 0,-1 +delete \
\( +clone -set delay $pause \) -swap -1,-2 +delete \
-quiet -layers Optimize $tmp0
fi
if [ "$reverse" = "yes" ]
then
echo ""
echo "Reversing Animation - Please Wait"
convert $tmp0 -coalesce \( -clone -2-1 \) \
-quiet -layers Optimize $tmp0
fi
if [ "$outfile" != "" ]
then
convert $tmp0 -loop 0 "$outfile"
else
animate $tmp0
fi
exit 0
#!/usr/bin/python
#
# Copyright 2013 Gerwin Sturm, FoldedSoft e.U.
# www.foldedsoft.at / google.com/+GerwinSturm
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Some parts adapted from sample code of the
# Google APIs Client Library for Python
# Copyright (C) 2013 Google Inc.
# Licensed under the Apache License, Version 2.0
"""Simple command-line tool to autoenhance photos via Google+.
To run this sample you will need the Google APIs Client Library for Python
Installation instructions here:
https://developers.google.com/api-client-library/python/start/installation
You will also need to set up a project in the APIs Console (or Cloud console)
https://code.google.com/apis/console or https://cloud.google.com/console
and create credentials for an "Installed applications".
You can then download a client_secrets.json and place it in the same folder
as this script.
"""
import httplib2
import json
import os
import sys
from argparse import ArgumentParser
from oauth2client import client
from oauth2client import file
from oauth2client import tools
UPLOAD_URL = ("https://picasaweb.google.com/data/feed/api" +
"/user/default/albumid/default?alt=json")
def main(argv):
# tools.argparser from the Google APIs Client Library for Python
# includes additional parameters to handle the authentication flow
arg_parser = ArgumentParser(parents=[tools.argparser])
arg_parser.add_argument("-o", "--output", default="output",
help="Output folder to place autoenhanced photos")
arg_parser.add_argument("input", metavar="DIR",
help="Folder with JPG images to autoenhance")
args = arg_parser.parse_args()
if not os.path.exists(args.output):
try:
os.makedirs(args.output)
except:
arg_parser.error("Couldn't create/find output directory.")
sys.exit(1)
# Name of a file containing the OAuth 2.0 information for this
# application, including client_id and client_secret, which are found
# on the API Access tab on the Google APIs Console.
client_secrets = os.path.join(os.path.dirname(__file__),
"client_secrets.json")
# Set up a Flow object to be used if we need to authenticate.
flow = client.flow_from_clientsecrets(client_secrets,
scope="https://picasaweb.google.com/data/",
message=tools.message_if_missing(client_secrets))
# Prepare credentials, and authorize HTTP object with them.
# If the credentials don't exist or are invalid run through the native client
# flow. The Storage object will ensure that if successful the good
# credentials will get written back to a file.
storage = file.Storage("autoenhance.dat")
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = tools.run_flow(flow, storage, args)
http = credentials.authorize(http=httplib2.Http())
files = os.listdir(args.input)
for filename in files:
# We only handle JPG files
if filename.upper().endswith(".JPG") or filename.upper().endswith(".JPEG"):
# Try to image data from file
image_data = None
try:
with open(os.path.join(args.input, filename), mode='rb') as image:
image_data = image.read()
except:
print("%s skipped, couldn't open file" % filename)
if image_data is not None:
# Upload photo to Picasa/Google+ in the private Dropbox/Default album
headers = {}
headers["Content-Type"] = "image/jpeg"
headers["Slug"] = filename
response, content = http.request(UPLOAD_URL, method="POST",
body=image_data, headers=headers)
result_data = json.loads(content)
if "entry" in result_data:
# Upload successful, download the photo again
thumbnail = result_data["entry"]["media$group"]["media$thumbnail"][0]
url = thumbnail["url"].replace("/s72/", "/s5000/")
response, content = http.request(url)
# save the photo data to the output folder
# (might want to check response for errors first)
with open(os.path.join(args.output, filename), 'wb') as output_file:
output_file.write(content)
print("%s autoenhanced successfully." % filename)
# Delete photo from Picasa again
headers = {}
headers["If-Match"] = "*"
http.request(result_data["entry"]["id"]["$t"],
method="DELETE", headers=headers)
sys.exit(0);
if __name__ == '__main__':
main(sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment