将HTML画布导出为图像序列 [英] Exporting HTML canvas as an image sequence

查看:105
本文介绍了将HTML画布导出为图像序列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个非常天真的页面,它将采用Three.js场景(尽管这可能是任何非WebGL < canvas> 动画),然后导出单个图像(或图像序列),然后转换为视频。



我这样做部分是为了学习Python,而且还能够在Three.js中快速创建原型,然后导出大量高分辨率丝般流畅视频的想法对我来说非常有吸引力。在过去,我使用屏幕捕捉软件来抓取视频,尽管它总是感觉有点笨拙,实时的FPS下降也会在最终的视频中体现出来。



我现在拥有的过程如下:

Javascript




  • 创建WebGL场景并设置渲染周期
  • 将画布宽度/高度设置为所需的尺寸

  • 使用 requestAnimationFrame

  • 渲染场景暂停场景的渲染/更新周期

  • 在canvas元素上调用 toDataURL(),并检索一个base64字符串

  • POST请求到python脚本,传递base64字符串(以及其他内容,例如要保存的目标目录以及是否捕获单个图像或序列)。


Python:


  • 删除MIME头的content-type并解码base64字符串
  • 将字符串写入图像文件

  • 打印/返回表示成功状态的字符串(如果文件已写入),否则打印出错的错误消息



  • $

     
    导入base64,cgi,cgitb,datetime,glob,re,os

    cgitb.enable()
    #cgitb.enable(display = 0,logdir ='/ tmp')

    printContent-type: ():
    form = cgi.FieldStorage()

    saveLocation =../httpdocs/export /

    #POST变量
    dataURL = form ['dataURL']。value
    captureSequence = form ['captureSequence']。value
    folderName = saveLocation + form ['folderName']。值

    saveImage(dataURL,captureSequence,saveLocation,folderName)
    $ b $ def saveImage(dataURL,captureSequence,saveLocation,folderName):
    #去除MIME内容类型(例如, data:image / png; base64)
    dataURL = dataURL [dataURL.index(','):]

    decodeString = base64.decodestring(dataURL)

    if captureSequence =='true':
    #基于http://www.akeric.com/blog/?p=632
    currentImages = glob.glob(folderName +/ *。 jpg)

    #TODO:也许文件名不应该从%08d + 1开始,而应该是%08d + 0?
    numList = [0]

    如果不是os.path.exists(文件夹名称):
    os.makedirs(文件夹名称)

    img in currentImages :
    i = os.path.splitext(img)[0]
    try:
    num = re.findall('[0-9] + $',i)[0]
    numList.append(int(num))
    除了IndexError:
    传递

    numList = sorted(numList)
    newNum = numList [-1] + 1
    saveName = folderName +'/%08d.jpg'newNum
    else:
    如果不是os.path.exists(saveLocation):
    os.makedirs(saveLocation)

    saveName = saveLocation + datetime.datetime.now()。isoformat()。replace(':','。')+'.jpg'

    #TODO;而不是返回一个简单的字符串,请考虑返回一个对象?
    try:
    output = open(saveName,'w')
    output.write(decodedString)
    output.close()
    print'true'
    除了例外,e:
    print e

    if __name__ =='__main__':
    main()

    $ b

    Javascript


    • 并显示返回的消息
    • 恢复/更新呈现周期

    • / ul>

      这是我总是在本地运行的东西,所以不会有冲突的写入或类型的任何风险。



      我做了一些快速测试,似乎大部分工作,如果有点慢。





      • 我在做这件事的时候错过了一些完全明显的东西吗?如何改进? (尤其是在python方面的东西..)

      • 每个图像执行单独的ajax调用效率低吗?一个好处是,我可以随时停止/关闭标签,它将保存所有图像直到那一刻。将存储所有这些base64字符串并将它们全部发送到最后会有什么好处吗?

      • 由于 requestAnimationFrame 将限制更新循环到60fps,是否可以轻松设置较低的帧速率?让我们说一些文体上的原因,我想要以15fps更新所有内容,唯一的选择是使用 setTimeout(callback,1000 / targetFPS) 随着时间的推移而漂移

      • 继上文所述之后,动画有一个var frame ,每增加一个更新周期,它就会增加 1 。这个var然后用来控制动画的不同部分(例如旋转立方体,并传递给顶点/片段着色器来操纵颜色和纹理UV坐标)。

        如果我想模拟15 fps的东西,我是否需要通过(60/15)增加 frame 而不是?有没有更好的方法可以轻松切换限制帧速率?

      • ,是否有任何技术可以采用提高正在渲染的图像的质量? (大声思考,以双倍大小储蓄,然后减少它们?)





      I真的希望这是有道理的,任何洞察力或建议将大规模赞赏。



      源文件: http://cl.ly/3V46120C2d3B0A1o3o25 (在Mac / Chrome稳定版上测试,需要WebGL)

      解决方案

      在EaselJS中,您可以设置FPS



      EaselJS代码


      I've created a very naive page that will take a Three.js scene (though this could be any non WebGL <canvas> animation) and exports individual images (or sequences of images) to then be converted into video.

      I'm doing this partially as a way to learn Python, but also the idea of being able to rapidly prototype something in Three.js and then export a massive high res silky smooth video is super attractive to me. In the past I've used screen capture software to grab video, though it's always felt a bit clunky and real time drops in FPS would show through in the final video too.

      The process I currently have is as follows:

      Javascript:

      • Create the WebGL scene and set up a render cycle
      • Set canvas width/height to desired dimensions
      • Render the scene using requestAnimationFrame
      • Pause the scene's render/update cycle
      • Call toDataURL() on the canvas element and retrieve a base64 string
      • POST request to a python script, passing the base64 string (and other things, like target directory to save to and whether a single image or sequence is being captured)

      Python:

      • Strip the MIME header content-type and decode the base64 string
      • Write the string to an image file
      • Print / return out a string that signifies successful state if the file was written, otherwise print out the offending error message

      import base64, cgi, cgitb, datetime, glob, re, os

      cgitb.enable() #cgitb.enable(display=0, logdir='/tmp') print "Content-type: text/html" print def main(): form = cgi.FieldStorage() saveLocation = "../httpdocs/export/" # POST variables dataURL = form['dataURL'].value captureSequence = form['captureSequence'].value folderName = saveLocation + form['folderName'].value saveImage(dataURL, captureSequence, saveLocation, folderName) def saveImage(dataURL, captureSequence, saveLocation, folderName): # strip out MIME content-type (e.g. "data:image/png;base64,") dataURL = dataURL[dataURL.index(','):] decodedString = base64.decodestring(dataURL) if captureSequence == 'true': # based off http://www.akeric.com/blog/?p=632 currentImages = glob.glob(folderName + "/*.jpg") # TODO: perhaps filenames shouldnt start at %08d+1 but rather %08d+0? numList = [0] if not os.path.exists(folderName): os.makedirs(folderName) for img in currentImages: i = os.path.splitext(img)[0] try: num = re.findall('[0-9]+$', i)[0] numList.append(int(num)) except IndexError: pass numList = sorted(numList) newNum = numList[-1] + 1 saveName = folderName + '/%08d.jpg' % newNum else: if not os.path.exists(saveLocation): os.makedirs(saveLocation) saveName = saveLocation + datetime.datetime.now().isoformat().replace(':', '.') + '.jpg' # TODO; rather than returning a simple string, consider returning an object? try: output = open(saveName, 'w') output.write(decodedString) output.close() print 'true' except Exception, e: print e if __name__ == '__main__': main()

      Javascript:

      • Receive response from Python script and display returned message
      • Resume/update render cycle
      • (Repeat process for as many frames as desired)

      This is something that I would always run locally so there would be no risk of conflicting writes or anything of the sort.

      I've done a few quick tests and it seems to work for the most part, if a little slow.


      • Am I missing something completely obvious in the way this is being done? How could it be improved? (Especially on the python side of things..)
      • Is it inefficient to do an individual ajax call per image? One advantage is that I can just stop / close the tab at any time and it'll have saved all images up until that point. Would there be any benefit to storing all those base64 strings and sending them all at the very end?
      • As requestAnimationFrame will cap the update cycle to 60fps, is it possible to easily set a lower frame rate? Lets say for some stylistic reason I'd want to update everything at 15fps, would the only option be to use setTimeout(callback, 1000 / targetFPS) with the understanding that it will drift over time?
      • Following on from the above, this animation has a var frame which is being incremented by 1 every update cycle. This var is then used to control varied parts of the animation (e.g, rotating the cube, and being passed to vertex/fragment shaders to manipulate colors and texture UV coordinates).

        If I wanted to simulate something like 15 fps, would I be correct in needing to increment frame by (60 / 15) instead? Is there a more elegant way to be able to easily switch between capped frame rates?

      • Finally, are there any techniques that could be adopted to improve the quality of images being rendered? (Thinking out aloud, saving out at double size then reducing them?)

      I really hope that makes sense, any insight or advice would be massively appreciated.

      Source files: http://cl.ly/3V46120C2d3B0A1o3o25 (Tested on Mac / Chrome stable, WebGL required)

      解决方案

      In EaselJS you can set FPS

      EaselJS Ticker

      这篇关于将HTML画布导出为图像序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆