I am trying to save image in encoded64 and than get the value of image from local storage .But I am getting null value why ?
here is my fiddle:
http://jsfiddle.net/sAH8w/7/
function getBase64Image(img) {
// Create an empty canvas element
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
// Copy the image contents to the canvas
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// Get the data-URL formatted image
// Firefox supports PNG and JPEG. You could check img.src to
// guess the original format, but be aware the using "image/jpg"
// will re-encode the image.
var dataURL = canvas.toDataURL("image/png");
try {
localStorage.setItem("elephant", dataURL);
}
catch (e) {
alert('error')
console.log("Storage failed: " + e);
}
//return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}
This minor change fix the issue:
$('#save').click(function(){
var image = new Image();
image.src = "https://dl.dropboxusercontent.com/s/t2ywui846zp58ye/plus_minus_icons.png?m=";
getBase64Image(image);
})
Working fiddle: http://jsfiddle.net/robertrozas/sAH8w/15/
Update(get button): http://jsfiddle.net/robertrozas/sAH8w/17/
Related
I'm attempting to put a watermark image on an input image before saving it to a database. I'm using a canvas to do this then convert the canvas back to a blob but when I reference the watermark image in the projects local file directory to draw onto the canvas, I get a "Tainted canvases may not be exported." error in the console.
// Read input file
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
// Create canvas & calculate Stamp size and position
const canvas = document.createElement("canvas");
canvas.width = canvasSize.width;
canvas.height = canvasSize.height;
var calcW = canvasSize.width/2;
var calcH = calcW/2.16;
var calcX = (canvasSize.width - calcW)/2;
var calcY = (canvasSize.height - calcH)/2;
// Load input image into canvas
const img = document.createElement("img");
img.src = reader.result;
img.onload = () => {
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
//Load & draw the Stamp image
const mark = new Image();
mark.src = 'assets/img/compliant.png'; // <<TAINTED ASSET?
mark.onload = () => {
ctx.drawImage(mark, calcX,calcY,calcW,calcH);
// Convert to blob and get URL
canvas.toBlob((canvasBlob) => {
const newImg = document.createElement("img"),
url = URL.createObjectURL(canvasBlob);
newImg.onload = function () {
//Destroy objecturl after image loading
URL.revokeObjectURL(url);
};
// Show stamped image
newImg.src = url;
window.open(url);
});
};
};
};
});
You have to use
img.crossOrigin='anonymous';
On every image you want to manipulate (draw in a canvas, transform to an array buffer… this is to prevent you from manipulating potentially private user data)
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#attr-crossorigin
Im converting an SVG to a PNG and it's working fine except for some super bizarre behavior that setting the image src to the b64 value only works if you put it in a setTimeout of 0. If you copy the b64 value and hardcode it as the src it also works. Here's the JS:
var testSVG = {
height: 31.987199999999998,
template: '<svg width="19.2" height="31.987199999999998" viewBox="0 0 149.39 248.95" xmlns="http://www.w3.org/2000/svg"><path fill="#c599fe" stroke="#000" stroke-miterlimit="10" stroke-width="5" d="M74.89,236.14c-5.35-26.25-14.78-48.1-26.2-68.35-8.47-15-18.29-28.88-27.37-43.45-3-4.86-5.65-10-8.56-15C6.94,99.2,2.21,87.5,2.51,72.32A68.92,68.92,0,0,1,13.28,35.88,71.31,71.31,0,0,1,63.34,3.32,75.55,75.55,0,0,1,112,12.53a70.38,70.38,0,0,1,24,23.22,68.1,68.1,0,0,1,10.9,36.32A67.12,67.12,0,0,1,144,92.82c-1.8,6-4.69,11-7.26,16.34-5,10.44-11.32,20-17.64,29.57C100.29,167.24,82.62,196.3,74.89,236.14Z"/><circle cx="74.69" cy="72.16" r="25.29"/></svg>',
width: 19.2
}
// Pass in the testSVG object
var convertSVGtoBitmap = function (svgObject) {
if(!svgObject) return null;
var canvas = document.createElement("canvas");
canvas.width = Math.ceil(svgObject.width);
canvas.height = Math.ceil(svgObject.height);
var ctx = canvas.getContext("2d");
// Convert the SVG string into a base64 and append a header
var svg = btoa(svgObject.template);
var b64Start = 'data:image/svg+xml;base64,';
var image64 = b64Start + svg;
// Draw the SVG onto the canvas instance
var img = new Image();
img.src = image64;
ctx.drawImage(img, 0, 0);
// Return both svg base64 and png base64
return {svg: image64, png: canvas.toDataURL()};
};
console.warn('test')
// Get SVG base64 stuff
var svgimg = document.createElement("img");
document.getElementById('svg-render').appendChild(svgimg);
svgimg.src = convertSVGtoBitmap(testSVG).svg;
// Get converted PNG base64 stuff
var pngimg = document.createElement("img");
document.getElementById('png-render').appendChild(pngimg);
setTimeout(function () {
pngimg.src = convertSVGtoBitmap(testSVG).png;
}, 0)
Note, this works because of the setTimeout of 0. If I change it to just pngimg.src = convertSVGtoBitmap(testSVG).png; without the setTimeout it doesn't display. If I do pngimg.src = '...' where the ... is the hardcoded b64 value it also works. Here's a JSBin if you want to mess with it.
https://jsbin.com/qecedev/2/edit?html,js,output
I also tried putting it in a document.ready from jQuery as well as adding an onload to the pngimg object and adding the src in that.
I figured it out. The problem area was this
// Draw the SVG onto the canvas instance
var img = new Image();
img.src = image64;
ctx.drawImage(img, 0, 0);
// Return both svg base64 and png base64
return {svg: image64, png: canvas.toDataURL()};
The png value in the return wasnt loaded yet. I converted it to have a callback (you could use async or promises too) and it started working.
// USE CALLBACK
var convertSVGtoBitmap = function (svgObject, callback) {
if(!svgObject) return null;
var canvas = document.createElement("canvas");
canvas.width = Math.ceil(svgObject.width);
canvas.height = Math.ceil(svgObject.height);
var ctx = canvas.getContext("2d");
var svg = btoa(svgObject.template);
var b64Start = 'data:image/svg+xml;base64,';
var image64 = b64Start + svg;
var img = new Image();
// WAIT FOR IMAGE TO LOAD
img.onload = function () {
ctx.drawImage(img, 0, 0);
// NOW WE CAN RETURN VALUES!
callback(image64, canvas.toDataURL());
}
img.src = image64;
};
I am trying to convert an external svg icon to a base64 png using a canvas. It is working in all browsers except Firefox, which throws an error "NS_ERROR_NOT_AVAILABLE".
var img = new Image();
img.src = "icon.svg";
img.onload = function() {
var canvas = document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
var dataURL = canvas.toDataURL("image/png");
return dataURL;
};
Can anyone help me on this please? Thanks in advance.
Firefox does not support drawing SVG images to canvas unless the svg file has width/height attributes on the root <svg> element and those width/height attributes are not percentages. This is a longstanding bug.
You will need to edit the icon.svg file so it meets the above criteria.
As mentioned, this is an open bug caused by limitations on what Firefox accepts as specification for SVG sizes when drawing to a canvas. There is a workaround.
Firefox requires explicit width and height attributes in the SVG itself. We can add these by getting the SVG as XML and modifying it.
var img = new Image();
var src = "icon.svg";
// request the XML of your svg file
var request = new XMLHttpRequest();
request.open('GET', src, true)
request.onload = function() {
// once the request returns, parse the response and get the SVG
var parser = new DOMParser();
var result = parser.parseFromString(request.responseText, 'text/xml');
var inlineSVG = result.getElementsByTagName("svg")[0];
// add the attributes Firefox needs. These should be absolute values, not relative
inlineSVG.setAttribute('width', '48px');
inlineSVG.setAttribute('height', '48px');
// convert the SVG to a data uri
var svg64 = btoa(new XMLSerializer().serializeToString(inlineSVG));
var image64 = 'data:image/svg+xml;base64,' + svg64;
// set that as your image source
img.src = img64;
// do your canvas work
img.onload = function() {
var canvas = document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
var dataURL = canvas.toDataURL("image/png");
return dataURL;
};
}
// send the request
request.send();
This is the most basic version of this solution, and includes no handling for errors when retrieving the XML. Better error handling is demonstrated in this inline-svg handler (circa line 110) from which I derived part of this method.
This isn't the most robust solution, but this hack worked for our purposes. Extract viewBox data and use these dimensions for the width/height attributes.
This only works if the first viewBox encountered has a size that accurately can represent the size of the SVG document, which will not be true for all cases.
// #svgDoc is some SVG document.
let svgSize = getSvgViewBox(svgDoc);
// No SVG size?
if (!svgSize.width || !svgSize.height) {
console.log('Image is missing width or height');
// Have size, resolve with new SVG image data.
} else {
// Rewrite SVG doc
let unit = 'px';
$('svg', svgDoc).attr('width', svgSize.width + unit);
$('svg', svgDoc).attr('height', svgSize.height + unit);
// Get data URL for new SVG.
let svgDataUrl = svgDocToDataURL(svgDoc);
}
function getSvgViewBox(svgDoc) {
if (svgDoc) {
// Get viewBox from SVG doc.
let viewBox = $(svgDoc).find('svg').prop('viewBox').baseVal;
// Have viewBox?
if (viewBox) {
return {
width: viewBox.width,
height: viewBox.height
}
}
}
// If here, no viewBox found so return null case.
return {
width: null,
height: null
}
}
function svgDocToDataURL(svgDoc, base64) {
// Set SVG prefix.
const svgPrefix = "data:image/svg+xml;";
// Serialize SVG doc.
var svgData = new XMLSerializer().serializeToString(svgDoc);
// Base64? Return Base64-encoding for data URL.
if (base64) {
var base64Data = btoa(svgData);
return svgPrefix + "base64," + base64Data;
// Nope, not Base64. Return URL-encoding for data URL.
} else {
var urlData = encodeURIComponent(svgData);
return svgPrefix + "charset=utf8," + urlData;
}
}
The svg d3 graph needs to be downloaded.I have used saveSvgAsPngJpgSvg to initiate download .The code works fine on all other browsers expect IE11.
Fiddle
I have tried :
svgAsDataUri(svg, {}, function(svg_uri) {
render_width=1000;
render_height=1000;
var canvas = document.createElement('canvas');
canvas.height = render_height;
canvas.width = render_width;
document.body.appendChild(canvas);
// Create an image and draw the SVG onto the canvas
var image = new Image;
image.onload = function() {
canvas.getContext('2d').drawImage(this, 0, 0, render_width, render_height);
};
image.src = svg_uri;
setTimeout(function(){//download_in_ie(canvas, 'filename' + '.png');
if (canvas.msToBlob) { //for IE
var blob = canvas.msToBlob();
window.navigator.msSaveBlob(blob, 'dicomimage.png');
}
}, 3000);
});
using msSaveBlob as suggested in the given link results to securityError
How can i achieve this?
my mobile app first uses the camera element of html5 and then takes a picture. The picture then shows on a seperate div. I'm having problems naming the image & then saving both the image and the caption to localstorage. Are my attempts futile, or is there a way to do this?
Thank you for any help or guidance offered.
To save an image in localstorage you need to convert it to dataURL string. You can do this via the canvas element as shown below.
When you want to retrieve the image from localstorage and display it you can simply set the src attrib of an image element to the dataURL string.
// convert image to localstorage friendly data URL string
function getImageDataURL(img) {
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL('image/png');
return dataURL;
}
var image = new Image();
image.onload = function() {
var dataURL = getImageDataURL(image);
document.body.innerHTML = dataURL;
image.src = dataURL;
document.body.appendChild(image);
};
image.crossOrigin = 'anonymous';
image.src = '//placekitten.com/g/120/120';