[javascript] how to save canvas as png image?

I have a canvas element with a drawing in it, and I want to create a button that when clicked on, it will save the image as a png file. So it should open up the save, open, close dialog box...

I do it using this code

var canvas = document.getElementById("myCanvas");
window.open(canvas.toDataURL("image/png"));

But when I test it out in IE9, a new window opens up saying "the web page cannot be displayed" and the url of it is:

data:image/png;base64,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

Anyone know how to fix this?

This question is related to javascript html canvas

The answer is


I had this problem and this is the best solution without any external or additional script libraries: In Javascript tags or file create this function: We assume here that canvas is your canvas:

function download(){
        var download = document.getElementById("download");
        var image = document.getElementById("canvas").toDataURL("image/png")
                    .replace("image/png", "image/octet-stream");
        download.setAttribute("href", image);

    }

In the body part of your HTML specify the button:

<a id="download" download="image.png"><button type="button" onClick="download()">Download</button></a>

This is working and download link looks like a button. Tested in Firefox and Chrome.


To accomodate all three points:

  • button
  • save the image as a png file
  • open up the save, open, close dialog box

The file dialog is a setting in the browser.

For the button/save part assign the following function, boiled down from other answers, to your buttons onclick:

function DownloadCanvasAsImage(){
    let downloadLink = document.createElement('a');
    downloadLink.setAttribute('download', 'CanvasAsImage.png');
    let canvas = document.getElementById('myCanvas');
    let dataURL = canvas.toDataURL('image/png');
    let url = dataURL.replace(/^data:image\/png/,'data:application/octet-stream');
    downloadLink.setAttribute('href', url);
    downloadLink.click();
}

Example on Codepen

Another, somewhat cleaner, approach is using Canvas.toBlob():

function DownloadCanvasAsImage(){
    let downloadLink = document.createElement('a');
    downloadLink.setAttribute('download', 'CanvasAsImage.png');
    let canvas = document.getElementById('myCanvas');
    canvas.toBlob(function(blob) {
      let url = URL.createObjectURL(blob);
      downloadLink.setAttribute('href', url);
      downloadLink.click();
    });
}

Example on Codepen

Neither solution is 100% cross browser compatible, so check the client


try this:

var c=document.getElementById("alpha");
var d=c.toDataURL("image/png");
var w=window.open('about:blank','image from canvas');
w.document.write("<img src='"+d+"' alt='from canvas'/>");

This shows image from canvas on new page, but if you have open popup in new tab setting it shows about:blank in address bar.

EDIT:- though window.open("<img src='"+ c.toDataURL('image/png') +"'/>") does not work in FF or Chrome, following works though rendering is somewhat different from what is shown on canvas, I think transparency is the issue:

window.open(c.toDataURL('image/png'));

FileSaver.js should be able to help you here.

var canvas = document.getElementById("my-canvas");
// draw to canvas...
canvas.toBlob(function(blob) {
    saveAs(blob, "pretty image.png");
});

I used this solution to set the file name:

HTML:

<a href="#" id="downloader" onclick="download()" download="image.png">Download!</a>
<canvas id="canvas"></canvas>

JavaScript:

function download(){
    document.getElementById("downloader").download = "image.png";
    document.getElementById("downloader").href = document.getElementById("canvas").toDataURL("image/png").replace(/^data:image\/[^;]/, 'data:application/octet-stream');
}

I maybe discovered a better way for not forcing the user to right click and "save image as". Live draw the canvas base64 code into the href of the link and modify it so the download will start automatically. I don't know if it's universally browser compatible, but it should work with the main/new browsers.

var canvas = document.getElementById('your-canvas');
    if (canvas.getContext) {
        var C = canvas.getContext('2d');
    }

$('#your-canvas').mousedown(function(event) {
    // feel free to choose your event ;) 

    // just for example
    // var OFFSET = $(this).offset();
    // var x = event.pageX - OFFSET.left;
    // var y = event.pageY - OFFSET.top;

    // standard data to url
    var imgdata = canvas.toDataURL('image/png');
    // modify the dataUrl so the browser starts downloading it instead of just showing it
    var newdata = imgdata.replace(/^data:image\/png/,'data:application/octet-stream');
    // give the link the values it needs
    $('a.linkwithnewattr').attr('download','your_pic_name.png').attr('href',newdata);

});

You can wrap the <a> around anything you want.


Try this:

jQuery('body').after('<a id="Download" target="_blank">Click Here</a>');

var canvas = document.getElementById('canvasID');
var ctx = canvas.getContext('2d');

document.getElementById('Download').addEventListener('click', function() {
    downloadCanvas(this, 'canvas', 'test.png');
}, false);

function downloadCanvas(link, canvasId, filename) {
    link.href = document.getElementById(canvasId).toDataURL();
    link.Download = filename;
}

You can just put this code in console in firefox or chrom and after changed your canvas tag ID in this above script and run this script in console.

After the execute this code you will see the link as text "click here" at bottom of the html page. click on this link and open the canvas drawing as a PNG image in new window save the image.


var canvasId = chart.id + '-canvas';
var canvasDownloadId = chart.id + '-download-canvas';
var canvasHtml = Ext.String.format('<canvas id="{0}" width="{1}" height="{2}"></canvas><a id="{3}"/>',
canvasId,
chart.getWidth(),
chart.getHeight(),
canvasDownloadId);
var canvasElement = reportBuilder.add({ html: canvasHtml });

var canvas = document.getElementById(canvasId);

var canvasDownload = document.getElementById(canvasDownloadId);
canvasDownload.href = chart.getImage().data;
canvasDownload.download = 'chart';

canvasDownload.click();

Submit a form that contains an input with value of canvas toDataURL('image/png') e.g

//JAVASCRIPT

    var canvas = document.getElementById("canvas");
    var url = canvas.toDataUrl('image/png');

Insert the value of the url to your hidden input on form element.

//PHP

    $data = $_POST['photo'];
    $data = str_replace('data:image/png;base64,', '', $data);
    $data = base64_decode($data);
    file_put_contents("i".  rand(0, 50).".png", $data);

Full Working HTML Code. Cut+Paste into new .HTML file:

Contains Two Examples:

  1. Canvas in HTML file.
  2. Canvas dynamically created with Javascript.

Tested In:

  1. Chrome
  2. Internet Explorer
  3. *Edge (title name does not show up)
  4. Firefox
  5. Opera

<!DOCTYPE HTML >
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> #SAVE_CANVAS_TEST# </title>
    <meta 
        name   ="author" 
        content="John Mark Isaac Madison"
    >
    <!-- EMAIL: J4M4I5M7 -[AT]- Hotmail.com -->
</head>
<body>

<div id="about_the_code">
    Illustrates:
    <ol>
    <li>How to save a canvas from HTML page.     </li>
    <li>How to save a dynamically created canvas.</li>
    </ol>
</div>

<canvas id="DOM_CANVAS" 
        width ="300" 
        height="300"
></canvas>

<div id="controls">
    <button type="button" style="width:300px;"
            onclick="obj.SAVE_CANVAS()">
        SAVE_CANVAS ( Dynamically Made Canvas )
    </button>

    <button type="button" style="width:300px;"
            onclick="obj.SAVE_CANVAS('DOM_CANVAS')">
        SAVE_CANVAS ( Canvas In HTML Code )
    </button>
</div>

<script>
var obj = new MyTestCodeClass();
function MyTestCodeClass(){

    //Publically exposed functions:
    this.SAVE_CANVAS = SAVE_CANVAS;

    //:Private:
    var _canvas;
    var _canvas_id = "ID_OF_DYNAMIC_CANVAS";
    var _name_hash_counter = 0;

    //:Create Canvas:
    (function _constructor(){
        var D   = document;
        var CE  = D.createElement.bind(D);
        _canvas = CE("canvas");
        _canvas.width = 300;
        _canvas.height= 300;
        _canvas.id    = _canvas_id;
    })();

    //:Before saving the canvas, fill it so
    //:we can see it. For demonstration of code.
    function _fillCanvas(input_canvas, r,g,b){
        var ctx = input_canvas.getContext("2d");
        var c   = input_canvas;

        ctx.fillStyle = "rgb("+r+","+g+","+b+")";
        ctx.fillRect(0, 0, c.width, c.height);
    }

    //:Saves canvas. If optional_id supplied,
    //:will save canvas off the DOM. If not,
    //:will save the dynamically created canvas.
    function SAVE_CANVAS(optional_id){

        var c = _getCanvas( optional_id );

        //:Debug Code: Color canvas from DOM
        //:green, internal canvas red.
        if( optional_id ){
            _fillCanvas(c,0,255,0);
        }else{
            _fillCanvas(c,255,0,0);
        }

        _saveCanvas( c );
    }

    //:If optional_id supplied, get canvas
    //:from DOM. Else, get internal dynamically
    //:created canvas.
    function _getCanvas( optional_id ){
        var c = null; //:canvas.
        if( typeof optional_id == "string"){
            var id = optional_id;
            var  d = document;
            var c  = d.getElementById( id );
        }else{
            c = _canvas; 
        }
        return c;
    }

    function _saveCanvas( canvas ){
        if(!window){ alert("[WINDOW_IS_NULL]"); }

        //:We want to give the window a unique
        //:name so that we can save multiple times
        //:without having to close previous
        //:windows.
        _name_hash_counter++              ; 
        var NHC = _name_hash_counter      ;
        var URL = 'about:blank'           ;
        var name= 'UNIQUE_WINDOW_ID' + NHC;
        var w=window.open( URL, name )    ;

        if(!w){ alert("[W_IS_NULL]");}

        //:Create the page contents,
        //:THEN set the tile. Order Matters.
        var DW = ""                        ;
        DW += "<img src='"                 ;
        DW += canvas.toDataURL("image/png");
        DW += "' alt='from canvas'/>"      ;
        w.document.write(DW)               ;
        w.document.title = "NHC"+NHC       ;

    }

}//:end class

</script>

</body>
<!-- In IE: Script cannot be outside of body.  -->
</html>

I really like Tovask's answer but it doesn't work due to the function having the name download (this answer explains why). I also don't see the point in replacing "data:image/..." with "data:application/...".

The following code has been tested in Chrome and Firefox and seems to work fine in both.

JavaScript:

function prepDownload(a, canvas, name) {
    a.download = name
    a.href = canvas.toDataURL()
}

HTML:

<a href="#" onclick="prepDownload(this, document.getElementById('canvasId'), 'imgName.png')">Download</a>
<canvas id="canvasId"></canvas>

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to canvas

How to make canvas responsive How to fill the whole canvas with specific color? Use HTML5 to resize an image before upload Convert canvas to PDF Scaling an image to fit on canvas Split string in JavaScript and detect line break Get distance between two points in canvas canvas.toDataURL() SecurityError Converting Chart.js canvas chart to image using .toDataUrl() results in blank image Chart.js canvas resize