Wardenclyffe
Wardenclyffe

Reputation: 2541

How To Save Canvas As An Image With canvas.toDataURL()?

I'm currently building a HTML5 web app/Phonegap native app and I can't seem to figure out how to save my canvas as an image with canvas.toDataURL(). Can somebody help me out?

Here's the code, what's wrong with it?

//My canvas was named "canvasSignature"

JavaScript:


function putImage()
{
  var canvas1 = document.getElementById("canvasSignature");        
  if (canvas1.getContext) {
     var ctx = canvas1.getContext("2d");                
     var myImage = canvas1.toDataURL("image/png");      
  }
  var imageElement = document.getElementById("MyPix");  
  imageElement.src = myImage;                           

}  

HTML5:


<div id="createPNGButton">
    <button onclick="putImage()">Save as Image</button>        
</div>

Upvotes: 217

Views: 563203

Answers (14)

Thomas Wagenaar
Thomas Wagenaar

Reputation: 6779

This solution allows you to change the name of the downloaded file:

HTML

<a id="link"></a>

JavaScript

var link = document.getElementById('link');
link.setAttribute('download', 'MintyPaper.png');
link.setAttribute('href', canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"));
link.click();

Upvotes: 85

Riya Singh
Riya Singh

Reputation: 314

try the following line after ctx

var img = new Image();
img.crossOrigin = 'anonymous';

I can show you a small example

You can create 2 functions

  1. To draw an image on the canvas from a url (could be local/remote).

         function loadCanvas(){
         var c = document.getElementById("mycanvas");
         var ctx = c.getContext("2d");
         var img = new Image();
         img.crossOrigin = 'anonymous';
         img.addEventListener("load",()=>{
              ctx.drawImage(img, 0, 0, 300, 450);
           });
          //i have chosen a random image from the internet to display
         img.src = 'https://images.squarespace-cdn.com/content/v1/592df00e3a0411d38a6c0e88/1508276785945-S2PHOFE36SU6NN6K8F3Y/70db5-sunsetideahousesunsetideahouse.jpg';
    
          }
    
  2. To save/publish that image or display in img tag

        function copyimage(){
            var c = document.getElementById("mycanvas");
            var datanew = c.toDataURL("image/jpeg");
            $(".imagecopy").html('<img src="'+datanew+'" width="300px" height="450px" />');
          }
    

Click here to see the complete code

Upvotes: 1

You need to create an Image object that will store the base 64 image of the canvas. That way your image imageElement can then take its src attribute value.

function putImage(){
   var canvas1 = document.getElementById("canvasSignature");        
   
   var imageObject = new Image();
   imageObject.src = canvas1.toDataURL("image/png");      

   var imageElement = document.getElementById("MyPix");  
   imageElement.src = imageObject.src;                           
} 

Automatically saving the image

You can automatically save the image by creating a link and attaching the src value as the href of the link. Then simulate a click using the click() method in JavaScript.

function putImage(){
       var canvas1 = document.getElementById("canvasSignature");        
       
       var imageObject = new Image();
       imageObject.src = canvas1.toDataURL("image/png");      

       var imageElement = document.getElementById("MyPix");  
       imageElement.src = imageObject.src;    
       

       // Saving it locally automatically
       let link = document.createElement("a");
       link.setAttribute('download', "download")
       link.href= imageElement.src
       link.click()               
    } 
 

Upvotes: 1

V&#237;t Zadina
V&#237;t Zadina

Reputation: 562

I create simple typescript function for this purpose, just delete types to use with javascript.

 //ImagePath == canvas.toDataUrl()
private saveImage(imagePath: string, imageName: string ){
    const link = document.createElement('a');
    link.style.display = 'none';
    document.body.appendChild(link)
    link.setAttribute('download', imageName + '.png');
    link.setAttribute('href', imagePath.replace("image/png", "image/octet-stream"));
    link.click();
}

 //function call
 saveImage(canvas.toDataURL(), "myName")

Upvotes: 2

Yogesh Yadav
Yogesh Yadav

Reputation: 863

One can also use element reference to downloaded image:

HTML:

<a download style="display:none" ref="imageDownloadRef"></a>

JAVASCRIPT:

  this.$refs['imageDownloadRef'].href = this.canvas.toDataURL({
  format: 'jpeg',
  quality: 1.0,
  })
  const imageDownloadLink = this.$refs.imageDownloadRef as HTMLElement
  imageDownloadLink.click()

Upvotes: 0

Sjeiti
Sjeiti

Reputation: 2648

Similar to 1000Bugy's answer but simpler because you don't have to make an anchor on the fly and dispatch a click event manually (plus an IE fix).

If you make your download button an anchor you can highjack it right before the default anchor functionality is run. So onAnchorClick you can set the anchor href to the canvas base64 image and the anchor download attribute to whatever you want to name your image.

This does not work in (the current) IE because it doesn't implement the download attribute and prevents download of data uris. But this can be fixed by using window.navigator.msSaveBlob instead.

So your anchor click event handler would be as followed (where anchor, canvas and fileName are scope lookups):

function onClickAnchor(e) {
  if (window.navigator.msSaveBlob) {
    window.navigator.msSaveBlob(canvas.msToBlob(), fileName);
    e.preventDefault();
  } else {
    anchor.setAttribute('download', fileName);
    anchor.setAttribute('href', canvas.toDataURL());
  }
}

Here's a fiddle

Upvotes: 8

BigBalli
BigBalli

Reputation: 817

You cannot use the methods previously mentioned to download an image when running in Cordova. You will need to use the Cordova File Plugin. This will allow you to pick where to save it and leverage different persistence settings. Details here: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/

Alternatively, you can convert the image to base64 then store the string in localStorage but this will fill your quota pretty quickly if you have many images or high-res.

Upvotes: 0

bmatovu
bmatovu

Reputation: 4074

You can try this; create a dummy HTML anchor, and download the image from there like...

// Convert canvas to image
document.getElementById('btn-download').addEventListener("click", function(e) {
    var canvas = document.querySelector('#my-canvas');

    var dataURL = canvas.toDataURL("image/jpeg", 1.0);

    downloadImage(dataURL, 'my-canvas.jpeg');
});

// Save | Download image
function downloadImage(data, filename = 'untitled.jpeg') {
    var a = document.createElement('a');
    a.href = data;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
}

Upvotes: 45

Vinay Chandra
Vinay Chandra

Reputation: 103

@Wardenclyffe and @SColvin, you both are trying to save image using the canvas, not by using canvas's context. both you should try to ctx.toDataURL(); Try This:

var canvas1 = document.getElementById("yourCanvasId");  <br>
var ctx = canvas1.getContext("2d");<br>
var img = new Image();<br>
img.src = ctx.toDataURL('image/png');<br>
ctx.drawImage(img,200,150);<br>

Also you may refer to following links:

http://tutorials.jenkov.com/html5-canvas/todataurl.html

http://www.w3.org/TR/2012/WD-html5-author-20120329/the-canvas-element.html#the-canvas-element

Upvotes: -9

Samuel Colvin
Samuel Colvin

Reputation: 13349

You can use canvas2image to prompt for download.

I had the same issue, here's a simple example that both adds the image to the page and forces the browser to download it:

<html>
    <head>
        <script src="http://hongru.github.io/proj/canvas2image/canvas2image.js"></script>
        <script>
            function draw(){
                var canvas = document.getElementById("thecanvas");
                var ctx = canvas.getContext("2d");
                ctx.fillStyle = "rgba(125, 46, 138, 0.5)";
                ctx.fillRect(25,25,100,100); 
                ctx.fillStyle = "rgba( 0, 146, 38, 0.5)";
                ctx.fillRect(58, 74, 125, 100);
            }

            function to_image(){
                var canvas = document.getElementById("thecanvas");
                document.getElementById("theimage").src = canvas.toDataURL();
                Canvas2Image.saveAsPNG(canvas);
            }
        </script>
    </head>
    <body onload="draw()">
        <canvas width=200 height=200 id="thecanvas"></canvas>
        <div><button onclick="to_image()">Draw to Image</button></div>
        <image id="theimage"></image>
    </body>
</html>

Upvotes: 25

1000Bugy
1000Bugy

Reputation: 105

This work for me: (Only google chrome)

<html>
<head>
    <script>
            function draw(){
                var canvas = document.getElementById("thecanvas");
                var ctx = canvas.getContext("2d");
                ctx.fillStyle = "rgba(125, 46, 138, 0.5)";
                ctx.fillRect(25,25,100,100);
                ctx.fillStyle = "rgba( 0, 146, 38, 0.5)";
                ctx.fillRect(58, 74, 125, 100);
            }

            function downloadImage()
            {
                var canvas = document.getElementById("thecanvas");
                var image = canvas.toDataURL();

                var aLink = document.createElement('a');
                var evt = document.createEvent("HTMLEvents");
                evt.initEvent("click");
                aLink.download = 'image.png';
                aLink.href = image;
                aLink.dispatchEvent(evt);
            }
    </script>
</head>
<body onload="draw()">
    <canvas width=200 height=200 id="thecanvas"></canvas>
    <div><button onclick="downloadImage()">Download</button></div>
    <image id="theimage"></image>
</body>
</html>

Upvotes: 7

gillyb
gillyb

Reputation: 8910

I created a small library that does this (along with some other handy conversions). It's called reimg, and it's really simple to use.

ReImg.fromCanvas(yourCanvasElement).toPng()

Upvotes: 10

user1874941
user1874941

Reputation: 3163

Here is some code. without any error.

var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");  // here is the most important part because if you dont replace you will get a DOM 18 exception.


window.location.href=image; // it will save locally

Upvotes: 208

Hakan Serce
Hakan Serce

Reputation: 11256

Instead of imageElement.src = myImage; you should use window.location = myImage;

And even after that the browser will display the image itself. You can right click and use "Save Link" for downloading the image.

Check this link for more information.

Upvotes: 1

Related Questions