Convert Svg to Png on Client Side - javascript

I am working on a Web based application where user can create designs in Svg. i want to convert the svg design into png image file on client side. i found a solution of using canvas, this works well in firefox, but in chrome it generate security error.
check the code below thanks:-
var mainsvg=document.getElementById('svgforImg');
var canvas=document.getElementById('canvas');
var ctx = canvas.getContext("2d");
var data=mainsvg.innerHTML;
var DOMURL = self.URL || self.webkitURL || self;
var svg = new Blob([data], {
type: "image/svg+xml;charset=utf-8"
});
var url = DOMURL.createObjectURL(svg);
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
var imageurl = canvas.toDataURL("image/png");
}
Now my variable imageurl contains 'base64 png' image. this works in Firefox. But in chrome line
var imageurl = canvas.toDataURL("image/png");
generate security error.
Any help would be highly appreciated.

I think this is related to this question. From which server does the SVG originate? If it is a different one than the one your application is coming from (remember: sub-domains matter!), you could add the desired http-headers in the originating server.

Related

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;

Upload Picture as base64 String to Parse

I have following Problem.
I´m using a canvas to resize pictures a user uploaded to my webapp.
Then I retrieve the picture from the canvas as a base64 encoded string and try to upload it to the parse server.
Since parse supports base64 I thought it could work.
When i upload the images however, there is no image but instead this message for every image file i upload:
{"_ContentType":"image/jpg","_ApplicationId":"MY APPLICATION
ID","_JavaScriptKey":"MY JAVASCRIPT
KEY","_ClientVersion":"js1.3.5","_InstallationId":"THE INSTALLATION
ID","_SessionToken":"THE SESSION TOKEN OF THE CURRENT USER"}
I can retrieve the files, but what i get is no image.
Here is my code for uploading the pictures:
var fileUploadControl = $("#product_pictureUploadModal")[0];
if (fileUploadControl.files.length > 0) {
//THE USER SUCCESSFULLY SELECTED A FILE
var file = fileUploadControl.files[0];
if(file.type.match(/image.*/)){
//RESIZE THE IMAGE AND RETURN a base64 STRING
var resizedImage = resizeImage(file);
//CREATE A PARSE FILE
var name = "picture.jpg";
var parseFile = new Parse.File(name, {base64: resizedImage}, "image/jpg");
parseFile.save().then(function() {
//IMAGE SUCCESSFULLY UPLOADED
},
function(error){
alert(error.message);
});
}else{
//THE USER DIDNT CHOSE A PICTURE
}
}else{
//THE USER DIDNT SELECT A FILE
}
Here is my code for resizing the pictures:
function resizeImage(file){
var MAX_WIDTH = 400;
var image = new Image();
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var url = window.URL || window.webkitURL;
var src = url.createObjectURL(file);
image.src = src;
return image.onload = function(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
if(image.width > MAX_WIDTH){
if(image.width > image.height){
image.height = (image.height%image.width)*400;
}else{
image.height = (image.height/image.width)*400;
}
alert("image height " + image.height);
image.width = 400;
}
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0, image.width, image.height);
url.revokeObjectURL(src);
var fileRezized = encodeURIComponent(canvas.toDataURL("image/jpg"));
return fileRezized;
};
}
What am i missing here?
I hope you guys could help me. I put a lot of work and time in this already and I seem to not get any further than this.
I want to resize the image in the browser because otherwise upload speed might be too slow for some people, as my application will be available for mobile phones as well.
greetins from germany, marvin
When you get no dataURL back from the browser, it's often caused by a cross-domain security violation.
The users image likely does not originate on the same domain as your web page, so when you drawImage the users image to the canvas, you are "tainting" the canvas. This tainting will cause .toDataURL to be disallowed which will in turn cause the DataURL uploaded to your server to be empty.
One workaround
As a workaround, you can "round-trip" the user's image:
upload the users image to your server and save it in the same domain as your web pages.
reload the users browser page along with their image served from your own domain.
Another workaround: FileReader
If your users have modern browsers that support FileReader then you can let your users upload images from their local drives in a security compliant way.
Here's example code using FileReader:
function handleFiles(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var imageType = /image.*/;
if (!file.type.match(imageType)) {
continue;
}
var img = document.createElement("img");
img.classList.add("obj");
img.file = file;
var reader=new FileReader();
reader.onload=(function(aImg){
return function(e) {
aImg.onload=function(){
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
canvas.width=aImg.width;
canvas.height=aImg.height;
ctx.drawImage(aImg,0,0);
document.body.appendChild(document.createElement('br'));
document.body.appendChild(canvas);
var u=canvas.toDataURL();
var textarea=document.createElement('textarea');
textarea.value=u;
document.body.appendChild(textarea);
}
// e.target.result is a dataURL for the image
aImg.src = e.target.result;
};
})(img);
reader.readAsDataURL(file);
} // end for
} // end handleFiles
//
$("#fileElem").change(function(e){ handleFiles(this.files); });
body{ background-color: ivory; }
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Example: load images to canvas while satisfying security requirements.</h4>
<input type="file" id="fileElem" multiple accept="image/*">
<br>
There is an error in this line:
var fileRezized = encodeURIComponent(canvas.toDataURL("image/jpg"));
There is no mime-type image/jpg in canvas. This would actually default to image/png instead which I guess could confuse the receiver. Just correct the line to:
var fileRezized = encodeURIComponent(canvas.toDataURL("image/jpeg"));
I don't know parse.com, but also try doing this with this line:
var parseFile = new Parse.File(name, {base64: resizedImage}, "image/jpeg");
// ^^
Test case
var canvas = document.querySelector("canvas"), out = document.querySelector("div");
out.innerHTML = canvas.toDataURL("image/jpg") + "<br><br>"; // PNG
out.innerHTML += canvas.toDataURL("image/jpeg"); // JPEG
<canvas width=1 height=1></canvas><div></div>

canvas.toDataURL() not working properly except mozilla firefox

I have developed a coupon generator module in the site I create a coupon in the html format and fill that html value in canvas by using JavaScript function which is
function checkcanvas(id) {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var data = "<svg xmlns='http://www.w3.org/2000/svg' width='437' height='262'>"
+ "<foreignObject width='100%' height='100%'>"
+ "<div xmlns='http://www.w3.org/1999/xhtml' style='font-size:40px'>"
+ $("#coupon_td").html()
+ "</div>"
+ "</foreignObject>"
+ "</svg>";
var DOMURL = self.URL || self.webkitURL || self;
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;
if(id == 2) {
document.getElementById('base_64_img').value = canvas.toDataURL();
}
}
base_64_img is just a hidden element so I can post the data into my php code and create a image using base64 code.
The biggest issue I am facing that this code perfectly worked in Mozilla Firefox almost every version but not working in Google chrome.
In your code you are generating an "SVG IMAGE" and trying to convert into toDataURL().
var svg = new Blob([data], {type: "image/svg+xml;charset=utf-8"});
This is the problem, from this URL toDataURL :
If the type requested is not image/png, and the returned value starts
with data:image/png, then the requested type is not supported.
In this fiddlecode if you see the printed output , "data:image/png;base64". its supposed to be "data:image/svg;base64".
Instead of creating svg image, use canvas element and javascript to draw the related banner image and if you take the output then try copy & paste in your browser. ( it may work ).
Check this js plugin called SVG.toDataURL
Hope this helps.

Display Image using canvas in JavaScript/jQuery

I have the following code :
function createImage(source) {
var pastedImage = new Image();
pastedImage.onload = function() {
document.write('<br><br><br>Image: <img src="'+pastedImage.src+'" height="700" width="700"/>');
}
pastedImage.src = source;
}
Here I am displaying the image through html image tag which I wrote in document.write and provide appropriate height and width to image.
My question is can it possible to displaying image into the canvas instead of html img tag? So that I can drag and crop that image as I want?
But how can I display it in canvas?
Further I want to implement save that image using PHP but for now let me know about previous issue.
Try This
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image(); // Create new img element
img.onload = function(){
// execute drawImage statements here This is essential as it waits till image is loaded before drawing it.
ctx.drawImage(img , 0, 0);
};
img.src = 'myImage.png'; // Set source path
Make sure the image is hosted in same domain as your site. Read this for Javascript Security Restrictions Same Origin Policy.
E.g. If your site is http://example.com/
then the Image should be hosted on http://example.com/../myImage.png
if you try http://facebook.com/..image/ or something then it will throw security error.
Use
CanvasRenderingContext2D.drawImage.
function createImage(source) {
var ctx = document.getElementById('canvas').getContext('2d');
var pastedImage = new Image();
pastedImage.onload = function(){
ctx.drawImage(pastedImage, 0, 0);
};
pastedImage = source;
}
Also MDN seems to be have nice examples.

Categories