javascript - 将 HTML Canvas 导出为图像序列

标签 javascript python html three.js

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

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

我目前的流程如下:

Javascript:

  • 创建 WebGL 场景并设置渲染周期
  • 将 Canvas 宽度/高度设置为所需尺寸
  • 使用 requestAnimationFrame 渲染场景
  • 暂停场景的渲染/更新周期
  • 调用toDataURL()在 Canvas 元素上并检索 base64 字符串
  • 向 python 脚本发出 POST 请求,传递 base64 字符串(以及其他内容,例如要保存到的目标目录以及是否正在捕获单个图像或序列)

python :

  • 去除 MIME 头内容类型并解码 base64 字符串
  • 将字符串写入图像文件
  • 如果文件已写入,则打印/返回表示成功状态的字符串,否则打印出有问题的错误消息

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:

  • 接收来自 Python 脚本的响应并显示返回的消息
  • 恢复/更新渲染周期
  • (根据需要对尽可能多的帧重复该过程)

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

我已经做了一些快速测试,它似乎在大多数情况下都能正常工作,尽管有点慢。


  • 我是否遗漏了一些非常明显的事情?如何改进? (特别是在 python 方面..)
  • 对每张图片进行单独的 ajax 调用是否效率低下?一个优点是我可以随时停止/关闭选项卡,它会保存到那时为止的所有图像。存储所有这些 base64 字符串并在最后发送它们有什么好处吗?
  • 作为requestAnimationFrame将更新周期限制为 60fps,是否可以轻松设置较低的帧速率?可以说出于某种风格原因我想以 15fps 的速度更新所有内容,唯一的选择是使用 setTimeout(callback, 1000 / targetFPS)据了解它将drift over time
  • 根据上面的内容,这个动画有一个 var frame这是递增 1每个更新周期。然后,此变量用于控制动画的不同部分(例如,旋转立方体,并传递给顶点/片段着色器以操纵颜色和纹理 UV 坐标)。

    如果我想模拟 15 fps 之类的东西,我需要递增 frame 是否正确?通过 (60 / 15)反而?是否有更优雅的方式能够在上限帧速率之间轻松切换?

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

我真的希望这是有道理的,任何见解或建议都将不胜感激。

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

最佳答案

在 EaselJS 中你可以设置 FPS

EaselJS Ticker

关于javascript - 将 HTML Canvas 导出为图像序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8900498/

相关文章:

javascript - 为什么不会 react 类打印 json 除非 props

python - 如何将列表项的值计数归因于新列 - pandas

python - 将 html 表转换为字典而不丢失结构

python - Python 脚本是如何执行的?

html - 如何根据 div 缩略图调整图像大小并保持比例?

jQuery : Scroll To - Change the div ID

javascript - 解析 js - 无法接收用户字段

javascript - Firebase 函数仅设置 Firebase 实时数据库中的第一个值

javascript - 总是从 FileReader 收到 NotReadableError

html - 带有 Angular 组件的 Flexbox 布局