Source code for imaging.images2avi

#   Copyright (C) 2012, Almar Klein
#   All rights reserved.
#
#   This code is subject to the (new) BSD license:
#
#   Redistribution and use in source and binary forms, with or without
#   modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the <organization> nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#
# changes of this file GRASS (PNG instead of JPG) by Anna Petrasova 2013

""" Module images2avi

Uses ffmpeg to read and write AVI files. Requires PIL

I found these sites useful:
http://www.catswhocode.com/blog/19-ffmpeg-commands-for-all-needs
http://linux.die.net/man/1/ffmpeg

"""

import os
import time
import subprocess
import shutil

from grass.imaging import images2ims
import grass.script as gscript


def _cleanDir(tempDir):
    for i in range(3):
        try:
            shutil.rmtree(tempDir)
        except Exception:
            time.sleep(0.2)  # Give OS time to free sources
        else:
            break
    else:
        print("Oops, could not fully clean up temporary files.")


[docs]def writeAvi(filename, images, duration=0.1, encoding='mpeg4', inputOptions='', outputOptions='', bg_task=False): """Export movie to a AVI file, which is encoded with the given encoding. Hint for Windows users: the 'msmpeg4v2' codec is natively supported on Windows. Images should be a list consisting of PIL images or numpy arrays. The latter should be between 0 and 255 for integer types, and between 0 and 1 for float types. Requires the "ffmpeg" application: * Most linux users can install using their package manager * There is a windows installer on the visvis website :param str filename: output filename :param images: :param float duration: :param str encoding: the encoding type :param inputOptions: :param outputOptions: :param bool bg_task: if thread background task, not raise but return error message :return str: error message """ # Get fps try: fps = float(1.0 / duration) except Exception: raise ValueError(_('Invalid duration parameter for writeAvi.')) # Determine temp dir and create images tempDir = os.path.join(os.path.expanduser('~'), '.tempIms') images2ims.writeIms(os.path.join(tempDir, 'im*.png'), images) # Determine formatter N = len(images) formatter = '%04d' if N < 10: formatter = '%d' elif N < 100: formatter = '%02d' elif N < 1000: formatter = '%03d' # Compile command to create avi command = "ffmpeg -r %i %s " % (int(fps), inputOptions) command += "-i im%s.png " % (formatter,) command += "-g 1 -vcodec %s %s " % (encoding, outputOptions) command += "output.avi" # Run ffmpeg S = subprocess.Popen(command, shell=True, cwd=tempDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Show what ffmpeg has to say outPut = S.stdout.read() if S.wait(): # Clean up _cleanDir(tempDir) if bg_task: return gscript.decode(outPut) + '\n' + gscript.decode( S.stderr.read()) + '\n' + _('Could not write avi.') else: # An error occurred, show print(gscript.decode(outPut)) print(gscript.decode(S.stderr.read())) raise RuntimeError(_('Could not write avi.')) else: try: # Copy avi shutil.copy(os.path.join(tempDir, 'output.avi'), filename) except Exception as err: # Clean up _cleanDir(tempDir) if bg_task: return str(err) else: raise # Clean up _cleanDir(tempDir)
[docs]def readAvi(filename, asNumpy=True): """Read images from an AVI (or MPG) movie. Requires the "ffmpeg" application: * Most linux users can install using their package manager * There is a windows installer on the visvis website :param str filename: name of input movie file :param bool asNumpy: """ # Check whether it exists if not os.path.isfile(filename): raise IOError('File not found: '+str(filename)) # Determine temp dir, make sure it exists tempDir = os.path.join(os.path.expanduser('~'), '.tempIms') if not os.path.isdir(tempDir): os.makedirs(tempDir) # Copy movie there shutil.copy(filename, os.path.join(tempDir, 'input.avi')) # Run ffmpeg command = "ffmpeg -i input.avi im%d.jpg" S = subprocess.Popen(command, shell=True, cwd=tempDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Show what mencodec has to say outPut = S.stdout.read() if S.wait(): # An error occurred, show print(outPut) print(S.stderr.read()) # Clean up _cleanDir(tempDir) raise RuntimeError("Could not read avi.") else: # Read images images = images2ims.readIms(os.path.join(tempDir, 'im*.jpg'), asNumpy) # Clean up _cleanDir(tempDir) # Done return images