How do you save an image from a Three.js canvas?

Javascriptthree.js

Javascript Problem Overview


How do you save an image from a Three.js canvas?

I'm attempting to use Canvas2Image but it doesn't like to play with Threejs. Since the canvas isn't defined until it has a div to attach the canvas object to.

http://ajaxian.com/archives/canvas2image-save-out-your-canvas-data-to-images

Javascript Solutions


Solution 1 - Javascript

Since the toDataURL is a method of canvas html element, that will work for 3d context too. But you have to take care of couple of things.

  1. Make sure when the 3D context is initialized you set preserveDrawingBuffer flag to true, like so:

    var context = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});
    
  2. Then user canvas.toDataURL() to get the image

In threejs you would have to do the following when the renderer is instantiated:

new THREE.WebGLRenderer({
    preserveDrawingBuffer: true 
});

Also, keep in mind this can have performance implications. (Read: https://github.com/mrdoob/three.js/pull/421#issuecomment-1792008)

This is only for webgl renderer, in case of threejs canvasRenderer though, you can simply do renderer.domElement.toDataURL(); directly, no initialization parameter needed.

My webgl experiment: http://jsfiddle.net/TxcTr/3/ press 'p' to screenshot.

Props to gaitat, I just followed the link in his comment to get to this answer.

Solution 2 - Javascript

I read the conversation posted by Dinesh (https://github.com/mrdoob/three.js/pull/421#issuecomment-1792008) and came up with a solution that won't slow down your application.

	function render() { 
		requestAnimationFrame(render);
		renderer.render(scene, camera);
		if(getImageData == true){
			imgData = renderer.domElement.toDataURL();
			getImageData = false;
		}
	} 

With this you can leave the preserveDrawingBuffer-Flag at false and still get the image from THREE.js. Simply set getImageData to true and call render() and you are good to go.

getImageData = true;
render();
console.debug(imgData);

Hope this helps people like me who need the high fps :)

Solution 3 - Javascript

use canvas to create the url, and then the same can be downloaded

function createImage(saveAsFileName) {

	var canvas = document.getElementById("canvas");

	var url = canvas.toDataURL();

	var link = document.createElement('a');

	link.setAttribute('href', url);
	link.setAttribute('target', '_blank');
	link.setAttribute('download', saveAsFileName);

	link.click();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrjdView Question on Stackoverflow
Solution 1 - JavascriptDinesh SaravananView Answer on Stackoverflow
Solution 2 - JavascriptCapsEView Answer on Stackoverflow
Solution 3 - JavascriptPranav AsthanaView Answer on Stackoverflow