Storing HTML5 canvas containing images - html

How do you store a canvas that contains images using the toDataURL method? Everything works fine for text and drawing, but I don't know how to handle images. Any help would be appreciated. Thanks
I have modified my question as follows:
This works when the image is pulled directly from a .png. However, when I call the Google Charts API, toDataURL doesn't work even though the image renders correctly on the canvas. Google Charts is returning a .png. Anyone have any ideas? Thanks.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" charset="utf-8">
function test() {
var c = document.getElementById("drawing-canvas");
var cxt = c.getContext("2d");
// This doesn't work.
//var imgsrc = 'http://chart.apis.google.com/chart?cht=tx&chf=bg,s,ffffff&chco=000000&
chl=a';
// This works
var imgsrc = 'chart.png';
var img = new Image();
img.src = imgsrc;
cxt.drawImage(img,0,0);
}
function wr() {
var cc = document.getElementById("drawing-canvas");
var url = cc.toDataURL();
var newImg = document.createElement("img");
newImg.src = url;
document.body.appendChild(newImg);
}
</script>
</head>
<body onload = "test();">
<canvas id="drawing-canvas" width = "500px" height = "500px" style="background-color:
#ffffff; border: 2px solid #000000;">
Your browser does not support the canvas element.
</canvas>
<input type = "button" value = "go" onclick = "wr();">
</body>
</html>

First of all, your chart didn't even render on the canvas when I tested it. You need to wait for the image to load. Your chart.png image probably loads instantaneously since it's cached, but the one generated by Google Charts API isn't. This is what you should do:
var img = new Image();
img.onload = function()
{
cxt.drawImage(img,0,0);
}
img.src = imgsrc;
Aside from that, you must be getting a SECURITY_ERR in your browser's console. This is because the Canvas security model doesn't allow you to export images coming from an external URL. You should use a server-side language to save the Google Charts image to your server, then load it from there.

The HTML canvas element has a method called toDataURL, that will return a data URL image representing the canvas. You can check the documentation API on the MDN.
Specifically, it says about toDataURL:
toDataURL(in optional DOMString type, in any ...args)
returns DOMString
Returns a data: URL containing a representation of the image in the format specified by type (defaults to PNG).
If the height or width of the canvas is 0, "data:," representing the empty string, is returned.
If the type requested is not image/png, and the returned value starts with data:image/png, then the requested type is not supported.
Chrome supports the image/webp type.
If the requested type is image/jpeg or image/webp, then the second argument, if it is between 0.0 and 1.0, is treated as indicating image quality; if the second argument is anything else, the default value for image quality is used. Other arguments are ignored.
And provides and example on how to use it:
function test() {
var canvas = document.getElementById("canvas");
var url = canvas.toDataURL();
var newImg = document.createElement("img");
newImg.src = url;
document.body.appendChild(newImg);
}
In this example, we use the dataURL as the source attribute of an img element, but you can do whatever you want you it (like storing it somewhere, or sending it to the server with an ajax call).
Note that most of the methods involved in drawing on canvas are methods of drawing context (obtained by a call to getContext), while this method is one of the canvas element.

Related

converting image and video data uri to base 64

I was trying to encrypt image and video src by converting into base 64 encoded value. I had taken reference from https://www.iandevlin.com/blog/2012/09/html5/html5-media-and-data-uri
Following is my html code:
<!DOCTYPE html>
<html>
<body>
<video style="width: 640px; height: 360px;" onloadstart="" id="mediaplayer" oncontextmenu="return false;" controls preload src="" poster=""/>
</body>
<script src="https://code.jquery.com/jquery-3.1.1.js"></script>
<script>
// To access player after its creation through jQuery use:
var videoSrc = 'http://clips.vorwaerts-gmbh.de/VfE_html5.mp4';
var imageSrc = 'http://www.w3schools.com/images/w3html5.gif';
var playerObj = $('#mediaplayer')[0];
var encodedSrc = btoa(playerObj.src);
var decodedSrc = atob(encodedSrc);
var playerObjPoster = playerObj.poster;
console.log(decodedSrc);
playerObj.src = "data:video/mp4;base64,"+btoa(videoSrc);
//playerObj.src = videoSrc;
playerObj.poster = 'data:image/gif;base64,'+btoa(imageSrc);
//playerObj.poster = imageSrc;
</script>
</html>
On runtime image and video src is showing as encoded value but neither image and neither video is displayed on the web page.
Any suggesstions ?
It does not work like this. You must base64 encode the actual contents of the file, not the path to the file. The link you used actually shows this in the example:
function getEncodedVideoString($type, $file) {
return 'data:video/' . $type . ';base64,' . base64_encode(file_get_contents($file));
}
Currently what is happening is that the browser is trying to use the decoded value (whis is a URI) as the actual image or video data and of course it fails.

Detect browser support for image type in canvas.toDataURL

I am trying to get dataUrl from <canvas> element using canvas.toDataURL(). By default, it returns image/png, but some browsers support the image/jpeg filetype.
How can i detect if a browser supports image/jpeg?
You just specify that you want JPEG like this:
var quality = 0.8;
var dataUri = canvas.toDataURL('image/jpeg', quality); // quality is optional
If your dataUri now contains the same string JPEG is supported. Otherwise the string will be image/png.
if (dataUri.match('image/jpeg')) {
// support jpeg
}
That being said, I don't think there is any browser which do not support the jpeg format. A test like this is better suited for more uncommon formats in various degrees such as webp, bitmap etc.
For a general test you could do:
function hasSupport(mime) {
var canvas = document.createElement('canvas');
canvas.width = canvas.height = 1;
var uri = canvas.toDataURL(mime);
return (uri.match(mime) !== null);
}
Per the HTML5 spec at https://www.w3.org/TR/html5/scripting-1.html#the-canvas-element:
When trying to use types other than "image/png", authors can check if
the image was really returned in the requested format by checking to
see if the returned string starts with one of the exact strings
"data:image/png," or "data:image/png;". If it does, the image is PNG,
and thus the requested type was not supported. (The one exception to
this is if the canvas has either no height or no width, in which case
the result might simply be "data:,".)
Therefore you can check like this:
var type = 'image/jpeg';
var data = canvas.toDataUrl(type);
if ( /^data:image\/png[,;]/.test(data) ) {
type='image/png';
} else if ( /^data:,/.test(data) ) {
type = null;
}

whats the difference between html2canvas and rasterizehtml.js

Apparently there are solutions to capturing screenshot of a web page:
Snapabug works by using an applet
GrabzIt I guess this is done on the server side.
Webkit2png is a command line tool, so not really part of the browser code.
There are probably other solutions that use ActiveX.
But I am interested in a Javascript only solution. From what I understand, both html2canvas and rasterizeHTML.js allow to convert html (in a web page) to an image. So, in what way is the implementation of html2canvas vs rasterizehtml.js different ? From what I understand both of them seem to use Canvas to generate the result. So in what way are they different? Which one is better ?
The main difference is that Rasterize is a wrapper around SVG foreignObject and html2canvas is essentially a reimplementation of browser HTML rendering from scratch. There are a lot of security headaches that Rasterize has to handle, but I think that its approach is better, as suggested by its being only 950 lines of code to html2canvas's 2400.
If the HTML you're rendering isn't very complex or doesn't need to be pixel-perfect, you may be able to skip Rasterize and use foreignObject directly, as described in MDN: Drawing DOM objects into a canvas:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var data = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">' +
'<foreignObject width="100%" height="100%">' +
'<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px">' +
'<em>I</em> like <span style="color:white; text-shadow:0 0 2px blue;">cheese</span>' +
'</div>' +
'</foreignObject>' +
'</svg>';
var DOMURL = window.URL || window.webkitURL || window;
var img = new Image();
var svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
var url = DOMURL.createObjectURL(svg);
img.onload = function () {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
}
img.src = url;
I tried html2canvas.js and rasterizeHTML.js for visualisation of a piece of html. Both have some issues, though. html2canvas.js can't get through with elements which have transformation (For example, text with css scale transform). As long as, I can't make rasterizeHTML.js to draw a canvas inside the canvas which displays the html.

Canvas algorithm to plot signatures randomly like a signed yearbook?

I'm looking for the best approach to plot multiple signatures randomly on a page like a high school yearbook using Canvas or SVG. Anyone know of existing algorithms or open source code similar to this?
Did you look into the following javascript libraries? I've used both of them and they work quite well:
SignaturePad or jSignature
Both of the offer a fallback to flash if the browser doesn't support it. We have chosen jSignature since the overall performance on different tablets when drawing new signature was better, but I personally like the style & API of signaturePad better.
You can record the signatures as example on a secured admin page and then just plot them wherever you want them.
Update
Since you just want random strings and not really signatures I recommend you'll have a look at HTML5 Canvas – Arrays and Random text:
<!DOCTYPE html>
<html>
<head>
<title>Random Text</title>
<script type="text/javascript">
var canvas, ctx;
var quotes = new Array();
var img = new Image(); // Create new img element
//or you can also use:
//var quotes = [];
function setup(){
//canvas and context setup
canvas=document.getElementById("myCanvas");
ctx=canvas.getContext("2d");
//create values for the array
quotes[0]="I";
quotes[1]="think";
quotes[2]="you";
quotes[3]="always";
quotes[4]="have";
quotes[5]="regrets";
//function calls
setInterval(draw,300);
window.addEventListener("keydown",checkKeyboard);
}
function draw(){
var randomIndex = Math.floor(Math.random()*quotes.length);
var randomColor = Math.round(Math.random()*80);
var randomX = Math.random()*canvas.width;
var randomY = Math.random()*canvas.height*2-canvas.width/2;
var randomSize = Math.random()*30+10;
ctx.fillStyle="rgba(255,255,255,0.8)";
ctx.font=randomSize+"px Arial Black, Gadget, sans-serif";
ctx.fillText(quotes[randomIndex],randomX,randomY);
ctx.lineWidth=1;
//ctx.strokeText(quotes[randomIndex],randomX,randomY);
}
function checkKeyboard(myEvt){
if(myEvt.keyCode==13){
ctx.clearRect(0,0,canvas.width,canvas.height);
}
}
</script>
</head>
<body onload="setup()">
<canvas id="myCanvas" width="800" height="600" style="border:1px solid; background:url(bg-hand.jpg)"></canvas>
<p>Press "ENTER" to clear the canvas</p>
</body>
</html>

printing just canvas element on a page

im a little stuck using the canvas element in html5, have scoured the net looking for a workable solution but to no avail!
the main issue is that I want to click a button and send just the canvas element on the page to the printer.
i have tried using toDataUrl() - but this just seems to be resulting in a blank white image which has none of the canvas content!
the other issue i am experiencing is that attempting to initiate any javascript functions using "onClick" attached to a form button seems to be being tempermental at best!
here is my current attempt - this works in the sense that it does open a new window and attempt to send it to printer and it does create a base64 string (tested this using the "dataUrl" output on the second lowest document.write line) but as previously mentioned the image appears to be completely blank! (the canvas itself is definitely filled, both with an imported image and some text)
function printCanv()
{
var dataUrl = document.getElementById('copy').toDataURL(); //attempt to save base64 string to server using this var
document.getElementById('testBox').value = dataUrl; //load data into textarea
//attempt open window and add canvas etc
win = window.open();
self.focus();
win.document.open();
win.document.write('<'+'html'+'><'+'head'+'><'+'style'+'>');
win.document.write('body, td { font-family: Verdana; font-size: 10pt;}');
win.document.write('<'+'/'+'style'+'><'+'/'+'head'+'><'+'body'+'>');
((image code is here but site will not let me post it for some reason?))
win.document.write(dataUrl);
win.document.write('<'+'/'+'body'+'><'+'/'+'html'+'>');
win.document.close();
win.print();
win.close();
}
note: the code from "win = window.open()" onwards is currently taken from a tutorial and not my own work!
it is currently being called using <body onload="printCanv";"> - for some reason I could not get this to work at all using a button (little chunk of code below is my attempt which seemed to fail)
<input type="button" id="test" value="click me" onClick="printCanv();"> </input>
apologies is this help request is all over the place! i haven't posted to a site like this before and it didn't like me posting some html/script!
thanks in advance for any help you may be able to offer :)
Edit: draw function:
function copydraw() { //function called "copydraw" (could be anything)
var testimage3 = document.getElementById('copy').getContext('2d'); //declare variable for canvas overall (inc paths)
var img3 = new Image(); //declare image variable called "img3"
var testVar = document.getElementById('userIn').value; //take value from userin box. only updating on browser refresh?
img3.onload = function(){ //when image has loaded (img.onload) run this function
testimage3.drawImage(img3,0,0); //draw "img" to testimage
testimage3.font = "30pt 'Arial'"; //font method varies font attrib (weight, size, face)
testimage3.fillStyle = "#000000"; //sets fill color
testimage3.fillText(testVar, 310, 360); //filltext method draws text (xup ydown)
}
img3.src = 'images/liecakeA4.jpg'; //source of image
}
This function works perfectly, it draws the object and adds text from the variable, but for some reason it seems to be preventing me from outputting it as an image. I'm really confused!
I'm not sure exactly what's wrong with your code, I suspect in your current version calling printCanv in the body load event will mean you're trying to print the canvas before it's drawn. Running it off the button should work better, I'm not sure why that wasn't working for you as there's no reason in principle why it shouldn't work.
To arrive at a working version I've modified your code slightly:
function printCanvas(el) {
var dataUrl = document.getElementById(el).toDataURL(); //attempt to save base64 string to server using this var
var windowContent = '<!DOCTYPE html>';
windowContent += '<html>'
windowContent += '<head><title>Print canvas</title></head>';
windowContent += '<body>'
windowContent += '<img src="' + dataUrl + '">';
windowContent += '</body>';
windowContent += '</html>';
var printWin = window.open('','','width=340,height=260');
printWin.document.open();
printWin.document.write(windowContent);
printWin.document.close();
printWin.focus();
printWin.print();
printWin.close();
}
This works for me in the Firefox 4.0 nightly.
One addition to the accepted-best-answer: It doesnt work here with Chrome 17.0.942.0 winvista, because the print-preview-dlg is shown within the website itself and printWin.close() will close the dlg too.
So printWin.close() must be delayed or initiated by the user, but those are no good solutions.
It would be best, if chrome printdlg could have a callback, sth. one knows, printing is done, and can close the window. If this is possible is another question.