Wrong base64 from canvas - javascript

Try a couple of days to solve one problem, but I can not understand why it is impossible. In canvas pictures drawn but the derivation gives wrong base64. I did not understand why. I just started, and didn't have great experience javascript. Help a newbie who can.
HTML:
<canvas id="canvas" width="400" height="300"></canvas>
<textarea id="base64" rows="10" cols="80"></textarea>
<img id="image">
JAVASCRIPT
function loadImages(sources, callback) { var images = {}; var loadedImages = 0; var numImages = 0; for(var src in sources) { numImages++; } for(var src in sources) { images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
} };
images[src].src = sources[src];}} var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); var sources = { a: 'http://www.prairiedogmag.com/wp-content/uploads/2012/08/Cute-Animals-office-bat-4-200x300.jpg', b: 'http://worldnewspress.net/wp-content/uploads/2014/03/happiest-animals-all-time-18-200x300.jpg' }; loadImages(sources, function(images) { context.fillStyle = "red"; context.fillRect(0, 0, 400, 300); context.drawImage(images.a, 0, 0, 200, 300); context.drawImage(images.b, 201, 0, 200, 300); }); var url = document.getElementById('base64').value =document.getElementById('canvas').toDataURL(); document.getElementById('image').src = url;

To execute the context.toDataURL method any images drawn on the canvas must originate from the same domain as the web page code.
If not, you fail cross-domain security and the browser will refuse to do .toDataURL.
It looks like you are pulling cross-domain images and therefore failing this security concern.
Check out CORS security:
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
Here's example working code and a Demo: http://jsfiddle.net/m1erickson/76xF3/
This example fetches images from a server that's configured to deliver images in a cross-domain compliant way. There are multiple configuration adjustments that must be done on the server. Also notice the code: crossOrigin="anonymous". That's the code on the client side that allows cross-origin images (the server must be configured properly first).
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var imageURLs=[]; // put the paths to your images here
var imagesOK=0;
var imgs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/character1.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/character3.png");
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
img.crossOrigin="anonymous";
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK>=imageURLs.length ) {
callback();
}
};
img.onerror=function(){alert("image load failed");}
img.src = imageURLs[i];
}
}
function start(){
// the imgs[] array now holds fully loaded images
// the imgs[] are in the same order as imageURLs[]
context.fillStyle = "red";
context.fillRect(0,0,120,110);
context.drawImage(imgs[0], 0, 0, 60, 110);
context.drawImage(imgs[1], 60, 0, 60, 110);
var url = document.getElementById('base64').value =canvas.toDataURL();
document.getElementById('image').src = canvas.toDataURL();
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>The canvas</h4>
<canvas id="canvas" width=120 height=110></canvas>
<h4>The image created from the canvas .toDataURL</h4>
<img id="image">
<h4>The base64 encoded image data</h4>
<textarea id="base64" rows="10" cols="80"></textarea>
</body>
</html>

Related

How to add a dynamic id into a loader in canvas

I decided to load the images first then, draw it unto the canvas.
I want to add a button to allow the image to be moved around. For that I need the ID of the image. Does the image have an ID or can I give the image an id?
I want to be able to change the ID of the image with a loop. For example, everything in a certain area of the canvas becomes pit1marble1, pit1marble2.
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div>
<canvas id="myCanvas" width="1024" height="479" usemap="Canvas"></canvas>
<script>
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var sources = {
background: 'MANCALA-game_bg_combined3.png',
};
loadImages(sources, function(images) {
context.drawImage(images.background, 0, 0, 1024, 479);
});
</script>
</body>
</html>

Display image in canvas with Javascript?

I want to be able to click on a button on my page and load an image into a canvas at some X,Y coordinates?
The following code is what I have below. I would like the image to be in either image/photo.jpg or in the same directory but preferably in a subdirectory of the main page.
**Question: How to make a JPG show up in a canvas with the click of a button on the web page?
Code:
<!DOCTYPE html>
<html>
<script>
function draw(){
var ctx = document.getElementById("myCanvas").getContext("2d");
var img = new Image():
// img.src = "2c.jpg";
img.src = "/images/2c.jpg";
ctx.drawImage(img,0,0);
}
</script>
<body background="Black">
<div align="center">
<button type="button" onclick="draw()">Show Image on Canvas</button>
<canvas id="myCanvas" width="900" height="400" style="border:2px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
</div>
<script>
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.font="20px Arial";
ctx.fillText("Royal Flush $",500,50);
ctx.fillText("Striaght Flush $",500,80);
ctx.fillText("Flush $",500,110);
ctx.fillText("Four of a Kind $",500,140);
ctx.fillText("Full House $",500,170);
ctx.fillText("Three of a Kind $",500,200);
ctx.fillText("Two Pair $",500,230);
ctx.fillText("Pair of ACES $",500,260);
ctx.rect(495,10,270,350);
ctx.stroke();
</script>
</body>
</html>
March 6th, 2014 Code:
How is the following code not working. Do you have to have an ID tag on Canvas. The page will display but for some reason the image will not when the button is clicked. The image is in the same directory that my index.html file is in.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<style type="text/css">
canvas{
border: 5px solid black;
}
</style>
</html>
<button id="galaxy">Add image #1</button>
<button id="circles">Add image #2</button><span></span>
<canvas width="500" height="500"></canvas>
<script>
var Images = {};
function loadImages(list){
var total = 0;
document.querySelector("span").innerText = "...Loading...";
for(var i = 0; i < list.length; i++){
var img = new Image();
Images[list[i].name] = img;
img.onload = function(){
total++;
if(total == list.length){
document.querySelector("span").innerText = "...Loaded.";
}
};
img.src = list[i].url;
}
}
function drawImage(img){
var ctx = document.querySelector("canvas").getContext("2d");
ctx.drawImage(Images[img], 0, 0, 50, 50);
}
loadImages([{
name: "2c.jpg",
url: "mp.jpg"
},{
name: "mp.jpg",
url: "mp.jpg"
}]);
document.querySelector("#galaxy").addEventListener("click", function(){
drawImage("galaxy");
});
document.querySelector("#circles").addEventListener("click", function(){
drawImage("weirdCircles");
});
</script>
</html>
Wait till the image is loaded before drawing:
var img = new Image();
img.onload = function(){ /*or*/ img.addEventListener("load", function(){
ctx.drawImage(img,0,0); ctx.drawImage(img,0,0);
}; };
img.src = "/images/2c.jpg";
Demo: http://jsfiddle.net/DerekL/YcLgw/
If you have more than one image in your game,
It is better to preload all images before it starts.
Preload images: http://jsfiddle.net/DerekL/uCQAH/ (Without jQuery: http://jsfiddle.net/DerekL/Lr9Gb/)
If you are more familiar with OOP: http://jsfiddle.net/DerekL/2F2gu/
function ImageCollection(list, callback){
var total = 0, images = {}; //private :)
for(var i = 0; i < list.length; i++){
var img = new Image();
images[list[i].name] = img;
img.onload = function(){
total++;
if(total == list.length){
callback && callback();
}
};
img.src = list[i].url;
}
this.get = function(name){
return images[name] || (function(){throw "Not exist"})();
};
}
//Create an ImageCollection to load and store my images
var images = new ImageCollection([{
name: "MyImage", url: "//example.com/example.jpg"
}]);
//To pick and draw an image from the collection:
var ctx = document.querySelector("canvas").getContext("2d");
ctx.drawImage(images.get("MyImage"), 0, 0);

Fading a loaded image into Canvas with drawImage

This question about crossfading images already gave an answer to the crossfading solution in Canvas. I am trying to do the same thing, only difference is that i am trying to fade images that are loaded on runtime.
The images are loaded propperly but no fade is visible. Is this not working because of the loaded images? Thanks.
HTML
<div id="wrapper">
<canvas id="bg1"></canvas>
<canvas id="bg2"></canvas>
</div>
JS
var toggle = true;
var canvas = document.getElementById('bg1');
canvas.width = $(document).width();
canvas.height = $(document).height();
var ctx = canvas.getContext('2d');
var canvas2 = document.getElementById('bg2');
canvas2.width = $(document).width();
canvas2.height = $(document).height();
var ctx2 = canvas2.getContext('2d');
var image = new Image();
image.src = 'download1.jpg';
var image2 = new Image();
image2.src = 'download2.jpg';
image.onload = function() {
ctx.drawImage(image, 0, 0, 200, 100);
ctx2.drawImage(image2, 0, 0, 200, 100);
};
$('#wrapper').click(function () {
if (toggle)
{
$('#bg2').fadeIn();
$('#bg1').fadeOut();
}
else
{
$('#bg1').fadeIn();
$('#bg2').fadeOut();
}
toggle = !toggle;
});
Yep, you need to give your images time to load.
But also, jQuery cannot do fadeIn/fadeout on a canvas element so you will have to do that manually.
Demo: http://jsfiddle.net/m1erickson/zw9S4/
Code:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
$("#fade").hide();
var imageURLs=[]; // put the paths to your images here
var imagesOK=0;
var imgs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-1.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-2.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-3.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-4.jpg");
loadAllImages();
//
function loadAllImages(){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK>=imageURLs.length ) {
$("#fade").show();
ctx.drawImage(imgs[0],0,0);
}
};
img.onerror=function(){alert("image load failed");}
img.crossOrigin="anonymous";
img.src = imageURLs[i];
}
}
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var fadeOutIndex=imgs.length-1;
var fadeInIndex=0;
var fadePct=0;
function animateFade(){
if(fadePct>100){return;}
requestAnimationFrame(animateFade);
ctx.clearRect(0,0,canvas.width,canvas.height);
draw(imgs[fadeInIndex],fadePct/100);
draw(imgs[fadeOutIndex],(1-fadePct/100));
fadePct++;
}
function draw(img,opacity){
ctx.save();
ctx.globalAlpha=opacity;
ctx.drawImage(img,0,0);
ctx.restore();
}
$("#fade").click(function(){
fadePct=0;
if(++fadeOutIndex == imgs.length){fadeOutIndex=0;}
if(++fadeInIndex == imgs.length){fadeInIndex=0;}
animateFade();
});
}); // end $(function(){});
</script>
</head>
<body>
<button id="fade">Fade to next Image</button><br>
<canvas id="canvas" width=204 height=204></canvas><br>
</body>
</html>
Try to fade in/out the images directly on the canvas instead of fading in and out the canvas elements (or there is not really any point using the canvas as you could use image elements instead).
First, of course, wait for the images to load:
var isBusy = false, /// for fade loop
count = 2; /// number of images to load
image = new Image();
image2 = new Image();
/// setup load handler
image.onload = image2.onload = handleLoad;
image.src = 'download1.jpg';
image2.src = 'download2.jpg';
function handleLoad() {
count--;
if (count === 0) {
/// when loaded draw a single image onto canvas
ctx.drawImage(image, 0, 0, ctx.canvas.width, ctx.canvas.height);
}
};
Now we can change the click handler a little bit around and use canvas only to do the fade in of the next image:
$('#wrapper').click(function () {
var img, /// current image to fade in
opacity = 0; /// current globalAlpha of canvas
/// if we're in a fade exit until done
if (isBusy) return;
isBusy = true;
/// what image to use
img = toggle ? image2 : image;
/// fade in
(function fadeIn() {
/// set alpha
ctx.globalAlpha = opacity;
/// draw image with current alpha
ctx.drawImage(img, 0, 0, ctx.canvas.width, ctx.canvas.height);
/// increase alpha to 1, then exit resetting isBusy flag
opacity += 0.02;
if (opacity < 1)
requestAnimationFrame(fadeIn);
else
isBusy = false;
})();
toggle = !toggle;
});
Online demo
Hope this helps.

Save canvas in client side

JavaScript
if (!window.Clipboard) {
var pasteCatcher = document.createElement("apDiv1");
pasteCatcher.setAttribute("contenteditable", "");
pasteCatcher.style.opacity = 0;
document.body.appendChild(pasteCatcher);
pasteCatcher.focus();
document.addEventListener("click", function() { pasteCatcher.focus(); });
}
window.addEventListener("paste", onPasteHandler);
function onPasteHandler(e)
{
if(e.clipboardData) {
var items = e.clipboardData.items;
if(!items){
alert("Image Not found");
}
for (var i = 0; i < items.length; ++i) {
if (items[i].kind === 'file' && items[i].type === 'image/png') {
var blob = items[i].getAsFile(),
source = window.webkitURL.createObjectURL(blob);
pastedImage = new Image();
pastedImage.src = source;
pasteData();
}
}
}
}
function pasteData()
{
drawCanvas = document.getElementById('drawCanvas1');
ctx = drawCanvas.getContext( '2d' );
ctx.clearRect(0, 0, 640,480);
ctx.drawImage(pastedImage, 0, 0);
}
DIV
<div id="apDiv1" contenteditable='true'>Paste Test</div>
Above javascript will capture image from clipboard and paste in the DIV. How do I save the canvas in clientside. I'm not using any server so i need to save the canvas in client side.
I found that canvas.toDataURL() will convert contents as a base64 encoded PNG file, but how do I do if i want the image save in my local. Let say, I have a folder Image in my C://. How do I do if i want the image saved in particular folder.
Just set an html img element's src to canvas.toDataURL()
Then right-click-save-as.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.fillRect(50,50,150,75);
var theImage=document.getElementById("toImage");
theImage.src=canvas.toDataURL();
Here's a complete example:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.fillRect(50,50,150,75);
var theImage=document.getElementById("toImage");
theImage.src=canvas.toDataURL();
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
<img id="toImage" width=300 height=300>
</body>
</html>

How can I draw an image from the HTML5 File API on Canvas?

I would like to draw an image opened with the HTML5 File API on a canvas.
In the handleFiles(e) method, I can access the File with e.target.files[0] but I can't draw that image directly using drawImage. How do I draw an image from the File API on HTML5 canvas?
Here is the code I have used:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script>
window.onload = function() {
var input = document.getElementById('input');
input.addEventListener('change', handleFiles);
}
function handleFiles(e) {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.drawImage(e.target.files[0], 20,20);
alert('the image is drawn');
}
</script>
</head>
<body>
<h1>Test</h1>
<input type="file" id="input"/>
<canvas width="400" height="300" id="canvas"/>
</body>
</html>
You have a File instance which is not an image.
To get an image, use new Image(). The src needs to be an URL referencing to the selected File. You can use URL.createObjectURL to get an URL referencing to a Blob (a File is also a Blob): http://jsfiddle.net/t7mv6/86/.
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image;
img.onload = function() {
ctx.drawImage(img, 20,20);
alert('the image is drawn');
}
img.src = URL.createObjectURL(e.target.files[0]);
Note: be sure to revoke the object url when you are done with it otherwise you'll leak memory. If you're not doing anything too crazy, you can just stick a URL.revokeObjectURL(img.src) in the img.onload function.
References:
https://developer.mozilla.org/en/DOM/File
http://html5demos.com/file-api
Live Example
function handleFiles(e) {
var ctx = document.getElementById('canvas').getContext('2d');
var url = URL.createObjectURL(e.target.files[0]);
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 20, 20);
}
img.src = url;
}
window.URL.createObjectUrldocs
You could also use the FileReader instead to create the object URL.
The FileReader has slightly better browser support.
The FileReader approach works in FF6 / Chrome. I'm not certain whether setting Img.src to a Blob is valid and cross-browser though.
Creating object urls is the correct way to do it.
Edit:
As mentioned in the commment window.URL support whilst offline seems unavailable in FF6/Chrome.
Here is a complete example (Fiddle) using FileReader (which has better browser support as mentioned by Raynos). In this example I also scale Canvas to fit the image.
In real life example you might scale the image to some maximum so that your form will not blow up ;-). Here is an example with scaling (Fiddle).
var URL = window.webkitURL || window.URL;
window.onload = function() {
var input = document.getElementById('input');
input.addEventListener('change', handleFiles, false);
// set original canvas dimensions as max
var canvas = document.getElementById('canvas');
canvas.dataMaxWidth = canvas.width;
canvas.dataMaxHeight = canvas.height;
}
function handleFiles(e) {
var ctx = document.getElementById('canvas').getContext('2d');
var reader = new FileReader();
var file = e.target.files[0];
// load to image to get it's width/height
var img = new Image();
img.onload = function() {
// setup scaled dimensions
var scaled = getScaledDim(img, ctx.canvas.dataMaxWidth, ctx.canvas.dataMaxHeight);
// scale canvas to image
ctx.canvas.width = scaled.width;
ctx.canvas.height = scaled.height;
// draw image
ctx.drawImage(img, 0, 0
, ctx.canvas.width, ctx.canvas.height
);
}
// this is to setup loading the image
reader.onloadend = function () {
img.src = reader.result;
}
// this is to read the file
reader.readAsDataURL(file);
}
// returns scaled dimensions object
function getScaledDim(img, maxWidth, maxHeight) {
var scaled = {
ratio: img.width / img.height,
width: img.width,
height: img.height
}
if (scaled.width > maxWidth) {
scaled.width = maxWidth;
scaled.height = scaled.width / scaled.ratio;
}
if (scaled.height > maxHeight) {
scaled.height = maxHeight;
scaled.width = scaled.height / scaled.ratio;
}
return scaled;
}
canvas {
border:1px solid black
}
<input type="file" id="input"/>
<div>
<canvas width="400" height="300" id="canvas"/>
</div>

Categories