Ticket #7298: trac-7298-ogv.patch

File trac-7298-ogv.patch, 8.8 KB (added by whuss, 9 years ago)

only apply this patch

  • sage/misc/html.py

    # HG changeset patch
    # User Wilfried Huss <huss@finanz.math.tugraz.at>
    # Date 1255722005 -7200
    # Node ID c714be4e402bb2544f3614beca7fe88dffc79d26
    # Parent  6b36a63b1833fc784289041a598c98094ce82534
    Ogg Theora video support for animations
    
    diff -r 6b36a63b1833 -r c714be4e402b sage/misc/html.py
    a b  
    267267            column_tag = "<th>%s</th>"
    268268
    269269        from sage.plot.plot import Graphics
     270        from sage.plot.animate import Animation
    270271        import types
    271272        if isinstance(row, types.GeneratorType):
    272273            row = list(row)
     
    274275            row = [row]
    275276
    276277        for column in xrange(len(row)):
    277             if isinstance(row[column], Graphics):
     278            if isinstance(row[column], (Graphics, Animation)):
    278279                print column_tag % row[column].show(linkmode = True)
    279280            elif isinstance(row[column], str):
    280281                print column_tag % math_parse(row[column])
  • sage/plot/animate.py

    diff -r 6b36a63b1833 -r c714be4e402b 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 libtheora
     384            sage: a.ogv(delay=35, iterations=3)                      # optional -- requires libtheora
     385            sage: a.ogv(savefile='my_animation.ogv')                 # optional -- requires libtheora
     386            sage: a.ogv(savefile='my_animation.ogv', show_path=True) # optional -- requires libtheora
     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              Error: libtheora does not appear to be installed. Saving an
     395              animation to a Ogg Theora file or displaying an animation
     396              requires the libtheora spkg, so please install it and try again.
     397        """
     398        if not savefile:
     399            savefile = sage.misc.misc.graphics_filename(ext='ogv')
     400        if not savefile.endswith('.ogv'):
     401            savefile += '.ogv'
     402        savefile = os.path.abspath(savefile)
     403        d = self.png()
     404        #cmd = 'cd "%s"; sage-native-execute ffmpeg2theora %%08d.png --inputfps %s -o "%s" 2> /dev/null'%(d, 100/delay, savefile)
     405        cmd = 'cd "%s"; sage-native-execute png2theora -o "%s" -f %s  %%08d.png 2> /dev/null'%(d, savefile, int(100/delay))
     406        from subprocess import check_call, CalledProcessError
     407        try:
     408            check_call(cmd, shell=True)
     409            if show_path:
     410                print "Animation saved to file %s." % savefile
     411        except (CalledProcessError, OSError):
     412            print ""
     413            print "Error: libtheora does not appear to be installed. Saving an"
     414            print "animation to a Ogg Theora file or displaying an animation requires the"
     415            print "libtheora spkg, so please install it and try again."
     416
     417
     418    def show(self, delay=20, iterations=0, format='gif', linkmode = False):
    354419        r"""
    355420        Show this animation.
    356421       
     
    363428        -  ``iterations`` - integer (default: 0); number of
    364429           iterations of animation. If 0, loop forever.
    365430       
     431        - ``format`` - (default: 'gif') the output format.
     432          Either 'gif' or 'ogv'.
    366433       
    367434        .. note::
    368435
     
    376443            sage: a = animate([sin(x + float(k)) for k in srange(0,2*pi,0.7)],
    377444            ...                xmin=0, xmax=2*pi, figsize=[2,1])
    378445            sage: a.show()       # optional -- requires convert command
     446
     447            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)
     448            sage: b.show(format = 'ogv')  # optional -- requires libtheora
    379449       
    380450        The preceding will loop the animation forever. If you want to show
    381451        only three iterations instead::
     
    401471            See www.imagemagick.org, for example.
    402472        """
    403473        if plot.DOCTEST_MODE:
    404             self.gif(delay = delay, iterations = iterations)
     474            if format == 'ogv':
     475                self.ogv(delay = delay, iterations = iterations)
     476            else:
     477                self.gif(delay = delay, iterations = iterations)
     478           
    405479            return
    406480       
    407481        if plot.EMBEDDED_MODE:
    408             self.gif(delay = delay, iterations = iterations)
     482            if format == 'ogv':
     483                filename = sage.misc.misc.graphics_filename(ext='ogv')
     484                self.ogv(delay = delay, savefile=filename, iterations = iterations)
     485                video_tag = """<video autoplay controls>
     486                <source src="cell://%s" type="video/ogg" />
     487                <a target="_new" href="cell://%s" class="file_link">ogv</a>
     488                </video>""" % (filename, filename)
     489                if linkmode == True:
     490                    return video_tag
     491                else:
     492                    from sage.misc.html import html
     493                    html(video_tag)
     494            else:
     495                filename = sage.misc.misc.graphics_filename(ext='gif')
     496                self.gif(delay = delay, savefile=filename, iterations = iterations)
     497                gif_tag = """<img src="cell://%s"/>""" % filename
     498                if linkmode == True:
     499                    return gif_tag
     500                else:
     501                    from sage.misc.html import html
     502                    html(gif_tag)
    409503        else:
    410             filename = sage.misc.misc.tmp_filename() + '.gif'
    411             self.gif(delay=delay, savefile=filename, iterations=iterations)
     504            if format == 'ogv':
     505                filename = sage.misc.misc.tmp_filename() + '.ogv'
     506                self.ogv(delay=delay, savefile=filename, iterations=iterations)
     507            else:
     508                filename = sage.misc.misc.tmp_filename() + '.gif'
     509                self.gif(delay=delay, savefile=filename, iterations=iterations)
    412510            os.system('%s %s 2>/dev/null 1>/dev/null &'%(
    413511                sage.misc.viewer.browser(), filename))
    414512
    415513    def save(self, filename=None, show_path=False):
    416514        """
    417         Save this animation into a gif or sobj file.
     515        Save this animation into a gif, ogv (Ogg Theora video) or sobj file.
    418516       
    419517        INPUT:
    420518       
     
    428526        If filename is None, then in notebook mode, display the animation;
    429527        otherwise, save the animation to a gif file. If filename ends in
    430528        '.gif', save to a gif file. If filename ends in '.sobj', save to an
    431         sobj file.
     529        sobj file, and if it ends with '.ogv', save it to an Ogg Theora
     530        video file.
    432531       
    433532        In all other cases, print an error.
    434533       
     
    440539            sage: a.save('wave.gif')   # optional
    441540            sage: a.save('wave.gif', show_path=True)   # optional
    442541            Animation saved to file .../wave.gif.
     542            sage: a.save('wave.ogv', show_path=True)   # optional -- requires libtheora
     543            Animation saved to file .../wave.ogv.
    443544            sage: a.save('wave0.sobj')  # optional
    444545            sage: a.save('wave1.sobj', show_path=True)  # optional
    445546            Animation saved to file wave1.sobj.
     
    447548        if filename is None or filename.endswith('.gif'):
    448549            self.gif(savefile=filename, show_path=show_path)
    449550            return
     551        elif filename.endswith('.ogv'):
     552            self.ogv(savefile=filename, show_path=show_path)
     553            return
    450554        elif filename.endswith('.sobj'):
    451555            SageObject.save(self, filename)
    452556            if show_path: