How to save an HTML5 canvas to a png [duplicate] - javascript

This question already has answers here:
How to save a png from javascript variable
(10 answers)
Closed 8 years ago.
I am trying to have a canvas be saved as an image so it can be put somewhere else on the website as an tag.
I have seen approaches like this:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var strDataURI = canvas.toDataURL("image/png;base64");
document.write('<img src="'+strDataURI+'"/>');
But I am not sure how to implement it. I also would like a copy of the image to be saved as an actual file on the server as well but I am not sure where to start.
When I implement the above code, I put it at the bottom of my canvas script like such:
var finish = document.getElementID('finish');
finish.onclick = function() {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var strDataURI = canvas.toDataURL("image/png;base64");
};
But I don't know how to actually reference the image.
A little help for noob is all I need.

For the frontside here's a full working example only showing a red background.
http://jsfiddle.net/gramhwkg/
// create a canvas
// If the canvas is already a dom element
//var canvas = document.getElementById("canvas");
// otherwise you'd rather do
var canvas = document.createElement('canvas');
// Then set a width/height grab its context.
canvas.width = 900;
canvas.height = 400;
var ctx = canvas.getContext("2d");
// ... And do plenty of nice stuff with it.
// I'll just draw it Red.
ctx.fillStyle = "#FF0000";
ctx.fillRect(0,0,900,400);
// When you want it to appear elsewhere.
var data = canvas.toDataURL();
var picture = document.getElementById("my-picture");
picture.innerHTML = '<img src="' + data + '"/>' ;
The backend part is not much harder. Just POST to php the same image data variable and handle it that way :
$canvas = base64_decode(str_replace('data:image/png;base64,', '' , $value['picture']));
file_put_contents('my_custom_path/my_custom_filename.png', $canvas);
Hope this helps !

Related

How to get an image of a div using html2canvas

I'm trying to use html2canvas to get an image of a div to the clipboard so that a user is able to then paste the image in an email or message chat. I've looked up multiple different ways of trying to do this but none of them are working for me.
The code I am using is below.
$(document).on("click", ".canvas-button", function (){
var div = document.getElementById($(this).data("div"));
var rect = div.getBoundingClientRect();
var canvas = document.createElement("canvas");
canvas.width = rect.width;
canvas.height = rect.height;
var ctx = canvas.getContext("2d");
ctx.translate(-rect.left,-rect.top);
html2canvas(div, {
canvas:canvas,
height:rect.height,
width:rect.width,
onrendered: function(canvas) {
var image = canvas.toDataURL("impage/png");
window.open(image);
var pHtml = "<img src="+image+" />";
$("#parent").append(pHtml);
}
});
});
This code is able to find the div but it doesn't give me the image of it. I'm not sure what to do from here. Any help is appreciated.

Compare two images and see the difference using pixelmatch - refreshing canvas fails

In my codepen i want to use pixelmatch to show the difference of two images in the browser. The function is used like this
// img1, img2 — ImageData.data of the images to compare
// output — ImageData to write the diff to, or null if don't need a diff image.
// width, height of the images - all 3 images need to have the same dimensions.
// calling pixelmatch looks like this
var numDiffPixels = pixelmatch(img1.data, img2.data
, imageDataOutput, wdth, hght, {threshold: 0.1});
I got this to work
create an ImageData-Object from an <img>-tag and retrieve the data as Uint8Array from the image
pass the Uint8Array for each image using imageData.data to the function pixelmatch
fill imageDataOutput and get a number of different pixels in numDiffixels
the HTML
<p>
<img id="imgBefore" src="./img/T1_Before.jpg">
<img id="imgAfter" src="./img/T1_After.jpg" >
</p>
<p>
<button id="diff" class="js-compareImages">compare images</button>
<canvas id="cnvDiff"></canvas>
</p>
<p id="result"> </p>
Helper Function
First a helper function to get a 'canvas' from an image
// Converts image to canvas; returns new canvas element
function convertImageToCanvas(imageID) {
var image = document.getElementById(imageID);
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);
// image.style = "width: 400px";
return canvas;
}
The main function
The the main function to compare the images
function compareImages()
{
var cnvBefore = convertImageToCanvas("imgBefore");
var cnvAfter = convertImageToCanvas("imgAfter");
var ctxBefore = cnvBefore.getContext("2d");
var ctxAfter = cnvAfter.getContext("2d");
let imgDataBefore = ctxBefore.getImageData(0,0,cnvBefore.width, cnvBefore.height);
let imgDataAfter = ctxAfter.getImageData(0,0, cnvAfter.width, cnvAfter.height);
const hght = imgDataBefore.height;
const wdth = imgDataBefore.width;
var imgDataOutput = new ImageData(wdth, hght);
var numDiffPixels = pixelmatch(imgDataBefore.data, imgDataAfter.data,
imgDataOutput, wdth, hght, {threshold: 0.1});
// this line does not work
writeResultToPage(imgDataOutput)
}
What does not work
using the values from imgDataOutput to show the differences of the two images in a third image or on a canvas
What is not working: either a black image is created or the output-canvas is empty
This is the code that does not produce the desired result
function writeResultToPage(imgDataOutput)
{
var canvas = document.createElement("canvas"); // new HTMLCanvasElement();
var ctx = canvas.getContext("2d");
ctx.putImageData(imgDataOutput, 0, 0);
var result = document.getElementById("result");
result.appendChild(ctx.canvas);
}
Question
Why is the output-canvas from writeResultToPage(imgDataOutput) empty?
What do i have to change to put imgDataOutput on the page as either an <img> or as a <canvas>?
Here is my matching codepen
The problem is that you need to add ".data" to imgDataOutput here:
var numDiffPixels = pixelmatch(imgDataBefore.data, imgDataAfter.data,
imgDataOutput.data, wdth, hght, {threshold: 0.1});
I also added:
canvas.width = imgDataOutput.width;
canvas.height = imgDataOutput.height;
to writeResultToPage so that the canvas is the right size for the image.
Updated codepen: https://codepen.io/anon/pen/dEVNmv

Execute Function After Canvas toDataURL() Function is Complete

I'm converting images to base64 using canvas. What i need to do is convert those images and then show the result to the user (original image and base64 version). Everything works as expected with small images, but when i try to convert large images (>3MB) and the conversion time increases, the base64 version is empty.
This might be is caused because the result is shown before the toDataURL() function is completed.
I need to show the result after all the needed processing has ended, for testing purposes.
Here's my code:
var convertToBase64 = function(url, callback)
{
var image = new Image();
image.onload = function ()
{
//create canvas and draw image...
var imageData = canvas.toDataURL('image/png');
callback(imageData);
};
image.src = url;
};
convertToBase64('img/circle.png', function(imageData)
{
window.open(imageData);
});
Even though i'm using image.onload() with a callback, i'm unable to show the result after the toDataURL() has been processed.
What am i doing wrong?
UPDATE: I tried both the solutions below and they didn't work. I'm using AngularJS and Electron in this project. Any way i can force the code to be synchronous? Or maybe some solution using Promises?
UPDATE #2: #Kaiido pointed out that toDataURL() is in fact synchronous and this issue is more likely due to maximum URI length. Since i'm using Electron and the image preview was for testing purposes only, i'm going to save the file in a folder and analise it from there.
Your code seems absolutely fine. Not sure why isn't working you. Maybe, there are some issues with your browser. Perhaps try using a different one. Also you could use a custom event, which gets triggered when the image conversion is competed.
// using jQuery for custom event
function convertToBase64(url) {
var image = new Image();
image.src = url;
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
var imageData = canvas.toDataURL();
$(document).trigger('conversionCompleted', imageData);
};
};
convertToBase64('4mb.jpg');
$(document).on('conversionCompleted', function(e, d) {
window.open(d);
});
This approach might work for you. It shows the image onscreen using the native html element, then draws it to a canvas, then converts the canvas to Base64, then clears the canvas and draws the converted image onto the canvas. You can then scroll between the top image (original) and the bottom image (converted). I tried it on large images and it takes a second or two for the second image to draw but it seems to work...
Html is here:
<img id="imageID">
<canvas id="myCanvas" style="width:400;height:400;">
</canvas>
Script is here:
var ctx;
function convertToBase64(url, callback)
{
var image = document.getElementById("imageID");
image.onload = function() {
var canvas = document.getElementById("myCanvas");
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
ctx = canvas.getContext("2d");
ctx.drawImage(image,0,0);
var imageData = canvas.toDataURL('image/png');
ctx.fillStyle ="#FFFFFF";
ctx.fillRect(0,0,canvas.width,canvas.height);
callback(imageData);
};
image.src = url;
};
var imagename = 'images/bigfiletest.jpg';
window.onload = function () {
convertToBase64(imagename, function(imageData) {
var myImage = new Image();
myImage.src = imageData;
ctx.drawImage(myImage,0,0);
});
}
Note that I also tried it without the callback and it worked fine as well...

Saving an image for offline use in a Chrome App

I have an image that is being shown in a Chrome App and is from a remote site. I want to be able to save the image locally in case network connection is unavailable.
I've been researching and found some APIs that might help me such as chrome.fileSystem, however, there aren't any simple examples like this.
Would someone be able to provide me with a simple example on how to do this?
It is preferred if the user doesn't have to press save or anything, having the downloading happen in the background. The image changes at random so I need this to be automated if possible.
what about storing it in localStorage?
var image = document.getElementById('bannerImg');
imgData = getBase64Image(image);
localStorage.setItem("imgData", imgData);
then to restore (adapted from this answer):
function getBase64Image(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL("image/png");
return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}
var dataImage = localStorage.getItem('imgData');
bannerImg = document.getElementById('tableBanner');
bannerImg.src = "data:image/png;base64," + dataImage;

How to make html5 canvas display crisp image based off chrome screencap

I am making a chrome extension that uses the chrome.tabs.captureVisibleTab method to grab a screencap of the current tab and then displays that in a popup from the chrome extension. If I use the img tag and use the data coming from the chrome function, such as data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwME…UUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAf/2Q==, the <img> displays pixel perfect, it is crisp and that's what I want. Problem is that I need to make it into a canvas, and when I do that, it becomes blurry.
This is a screencap of the <img> that uses the link data provided by Google to be used as a comparison to the canvas which is below.
This is the blurry canvas.
This is the code that I am using to try to do this, but I can't figure out how to make the canvas crisp like the image.
chrome.runtime.sendMessage({msg: "capture"}, function(response) {
console.log(response.imgSrc);
var img = document.createElement('img');
var _canvas = document.createElement("canvas");
img.src = response.imgSrc;
img.height = 436;
img.width = 800;
document.getElementById('main-canvas').appendChild(img);
draw(response);
});
function draw(response) {
var canvas = document.getElementById('imageCanvas');
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
//Get a 2d context
var ctx = canvas.getContext('2d');
//use image to paint canvas
var _image = new Image();
_image.onload = function() {
ctx.drawImage(_image, 0, 0, 800, 436);
}
_image.src = response.imgSrc;
document.getElementById('main-canvas').appendChild(canvas);
}
This is what I used to fix my problem: High Resolution Canvas from HTML5Rocks

Categories