Ticket #7298: ogv.patch

File ogv.patch, 8.4 KB (added by whuss, 10 years ago)
  • sage/misc/html.py

    # HG changeset patch
    # User Wilfried Huss <huss@finanz.math.tugraz.at>
    # Date 1255722005 -7200
    # Node ID ae4ce4d65cd4b990e1feb8c8f32240e5799fc0da
    # Parent  5bf36a37cd0c2ce42b6bf42038e84a1968d3ad8b
    Ogg Theora video support for animations
    
    diff -r 5bf36a37cd0c -r ae4ce4d65cd4 sage/misc/html.py
    a b  
    264264            column_tag = "<th>%s</th>"
    265265
    266266        from sage.plot.plot import Graphics
     267        from sage.plot.animate import Animation
    267268        import types
    268269        if isinstance(row, types.GeneratorType):
    269270            row = list(row)
     
    271272            row = [row]
    272273
    273274        for column in xrange(len(row)):
    274             if isinstance(row[column], Graphics):
     275            if isinstance(row[column], (Graphics, Animation)):
    275276                print column_tag % row[column].show(linkmode = True)
    276277            elif isinstance(row[column], str):
    277278                print column_tag % row[column]
  • sage/plot/animate.py

    diff -r 5bf36a37cd0c -r ae4ce4d65cd4 sage/plot/animate.py
    a b  
    350350            print ""
    351351            print "See www.imagemagick.org, for example."
    352352
    353     def show(self, delay=20, iterations=0):
     353    def ogv(self, delay=20, savefile=None, iterations=0, show_path=False):
     354        r"""
     355        Returns an Ogg Theora video of the graphics
     356        objects in self.
     357       
     358        This function will only work if the libtheora spkg is installed.
     359       
     360        INPUT:
     361       
     362       
     363        -  ``delay`` - (default: 20) delay in hundredths of a
     364           second between frames
     365       
     366        -  ``savefile`` - file that the Ogg Theora video gets saved
     367           to
     368       
     369        -  ``iterations`` - integer (default: 0); number of
     370           iterations of animation. If 0, loop forever.
     371       
     372        -  ``show_path`` - boolean (default: False); if True,
     373           print the path to the saved file
     374       
     375       
     376        If savefile is not specified: in notebook mode, display the
     377        animation; otherwise, save it to a default file name.
     378       
     379        EXAMPLES::
     380       
     381            sage: a = animate([sin(x + float(k)) for k in srange(0,2*pi,0.7)],
     382            ...                xmin=0, xmax=2*pi, figsize=[2,1])
     383            sage: a.ogv()              # optional -- requires ffmpeg2theora command
     384            sage: a.ogv(delay=35, iterations=3)       # optional
     385            sage: a.ogv(savefile='my_animation.ogv')  # optional
     386            sage: a.ogv(savefile='my_animation.ogv', show_path=True) # optional
     387            Animation saved to .../my_animation.ogv.
     388       
     389        .. note::
     390
     391           If libtheora is not installed, you will get an error
     392           message like this::
     393        """
     394        if not savefile:
     395            savefile = sage.misc.misc.graphics_filename(ext='ogv')
     396        if not savefile.endswith('.ogv'):
     397            savefile += '.ogv'
     398        savefile = os.path.abspath(savefile)
     399        d = self.png()
     400        #cmd = 'cd "%s"; sage-native-execute ffmpeg2theora %%08d.png --inputfps %s -o "%s" 2> /dev/null'%(d, 100/delay, savefile)
     401        cmd = 'cd "%s"; sage-native-execute png2theora -o "%s" -f %s  %%08d.png 2> /dev/null'%(d, savefile, int(100/delay))
     402        from subprocess import check_call, CalledProcessError
     403        try:
     404            check_call(cmd, shell=True)
     405            if show_path:
     406                print "Animation saved to file %s." % savefile
     407        except (CalledProcessError, OSError):
     408            print ""
     409            print "Error: libtheora does not appear to be installed. Saving an"
     410            print "animation to a Ogg Theora file or displaying an animation requires the"
     411            print "libtheora spkg, so please install it and try again."
     412
     413
     414    def show(self, delay=20, iterations=0, format='gif', linkmode = False):
    354415        r"""
    355416        Show this animation.
    356417       
     
    363424        -  ``iterations`` - integer (default: 0); number of
    364425           iterations of animation. If 0, loop forever.
    365426       
     427        - ``format`` - (default: 'gif') the output format.
     428          Either 'gif' or 'ogv'.
    366429       
    367430        .. note::
    368431
     
    376439            sage: a = animate([sin(x + float(k)) for k in srange(0,2*pi,0.7)],
    377440            ...                xmin=0, xmax=2*pi, figsize=[2,1])
    378441            sage: a.show()       # optional -- requires convert command
     442
     443            sage: b = animate([sin(y*x^2)*cos(x/2) for y in srange(0,2,0.05)], xmin = -pi, xmax=pi, ymax = 1, ymin = -1)
     444            sage: b.show(format = 'ogv')  # optional -- requires libtheora
    379445       
    380446        The preceding will loop the animation forever. If you want to show
    381447        only three iterations instead::
     
    401467            See www.imagemagick.org, for example.
    402468        """
    403469        if plot.DOCTEST_MODE:
    404             self.gif(delay = delay, iterations = iterations)
     470            if format == 'ogv':
     471                self.ogv(delay = delay, iterations = iterations)
     472            else:
     473                self.gif(delay = delay, iterations = iterations)
     474           
    405475            return
    406476       
    407477        if plot.EMBEDDED_MODE:
    408             self.gif(delay = delay, iterations = iterations)
     478            if format == 'ogv':
     479                filename = sage.misc.misc.graphics_filename(ext='ogv')
     480                self.ogv(delay = delay, savefile=filename, iterations = iterations)
     481                video_tag = """<video autoplay controls>
     482                <source src="cell://%s" type="video/ogg" />
     483                <a target="_new" href="cell://%s" class="file_link">ogv</a>
     484                </video>""" % (filename, filename)
     485                if linkmode == True:
     486                    return video_tag
     487                else:
     488                    from sage.misc.html import html
     489                    html(video_tag)
     490            else:
     491                filename = sage.misc.misc.graphics_filename(ext='gif')
     492                self.gif(delay = delay, savefile=filename, iterations = iterations)
     493                gif_tag = """<img src="cell://%s"/>""" % filename
     494                if linkmode == True:
     495                    return gif_tag
     496                else:
     497                    from sage.misc.html import html
     498                    html(gif_tag)
    409499        else:
    410             filename = sage.misc.misc.tmp_filename() + '.gif'
    411             self.gif(delay=delay, savefile=filename, iterations=iterations)
     500            if format == 'ogv':
     501                filename = sage.misc.misc.tmp_filename() + '.ogv'
     502                self.ogv(delay=delay, savefile=filename, iterations=iterations)
     503            else:
     504                filename = sage.misc.misc.tmp_filename() + '.gif'
     505                self.gif(delay=delay, savefile=filename, iterations=iterations)
    412506            os.system('%s %s 2>/dev/null 1>/dev/null &'%(
    413507                sage.misc.viewer.browser(), filename))
    414508
    415509    def save(self, filename=None, show_path=False):
    416510        """
    417         Save this animation into a gif or sobj file.
     511        Save this animation into a gif, ogv (Ogg Theora video) or sobj file.
    418512       
    419513        INPUT:
    420514       
     
    428522        If filename is None, then in notebook mode, display the animation;
    429523        otherwise, save the animation to a gif file. If filename ends in
    430524        '.gif', save to a gif file. If filename ends in '.sobj', save to an
    431         sobj file.
     525        sobj file, and if it ends with '.ogv', save it to an Ogg Theora
     526        video file.
    432527       
    433528        In all other cases, print an error.
    434529       
     
    440535            sage: a.save('wave.gif')   # optional
    441536            sage: a.save('wave.gif', show_path=True)   # optional
    442537            Animation saved to file .../wave.gif.
     538            sage: a.save('wave.ogv', show_path=True)   # optional
     539            Animation saved to file .../wave.ogv.
    443540            sage: a.save('wave0.sobj')  # optional
    444541            sage: a.save('wave1.sobj', show_path=True)  # optional
    445542            Animation saved to file wave1.sobj.
     
    447544        if filename is None or filename.endswith('.gif'):
    448545            self.gif(savefile=filename, show_path=show_path)
    449546            return
     547        elif filename.endswith('.ogv'):
     548            self.ogv(savefile=filename, show_path=show_path)
     549            return
    450550        elif filename.endswith('.sobj'):
    451551            SageObject.save(self, filename)
    452552            if show_path: