Obtaining the urldata of a background-image with Javascript (possibly using canvas) - javascript

Let's assume there is a DIV element and it has CSS background-image property.
I want to get urldata(base64) of the background image with Javascript.
I can get urldata of IMG elements but how about this one ?
Thanks.

You can obtain the value of the background-image property with window.getComputedStyle, then create a canvas and an image, apply the value to the src of the image, draw it on the canvas, and finally get the data ? =°
function getBgImageData(el,callback) {
var url,
image,
canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
// Allows el to be an element or an id
if(typeof el==='string') {
el = document.getElementById(el);
}
// Gets the value of the background-image property
url = window.getComputedStyle(el,null).backgroundImage;
// Removes the url("") part
url = url.substring(5,url.length-2);
// Creates the image
image = new Image();
image.src = url;
image.onload = function() {
canvas.width = image.width;
canvas.height = image.height;
// Draws the image
ctx.drawImage(image,0,0);
if(callback) {
// Passes the data to the callback function
callback(canvas.toDataURL());
}
};
}
getBgImageData('someId',function(data) {
alert(data);
});
(getComputedStyle does not work in IE... but neither does Canvas)

Related

How to convert dataurl back to image and display on canvas

I have 3 canvases. I crop a region from canvas1 and display it on canvas 2 . Then I want to convert canvas 2 image to a URL and to see if can convert that URL back to a image. I want it to be displayed in canvas c4.Any help is appreciated.
// image is drawn here , I want this image to be converted to a dataURL
//then back to image and display it in canvas c4
var c2 = document.getElementById("area_c2");
var ctx = c.getContext("2d");
var ctx2 = c2.getContext("2d");
image_src.width = c2.width;
image_src.height = c2.height;
ctx2.drawImage(image_src, 0, 0,image_src.width, image_src.height);
var c4 = document.getElementById("area_c4");
var ctx4 = c4.getContext("2d");
var dataURL = c2.toDataURL();
var myImg = new Image;
myImg.src = dataURL;
myImg.width = c4.width;
myImg.height = c4.height;
ctx4.drawImage(myImg, 0, 0, image_src.width, image_src.height); //Image //is not displayed here , I want the image to take the size of the canvas
<canvas id ="area_c2" style="width:300px;height:300px;border:3px solid
black;z-index:1" >
</canvas>
<canvas id ="area_c4" style="width:300px;height:300px;border:3px solid
black;z-index:1;background:red">
</canvas>
The reason your solution did not work is because you did not wait for the onload event. Before the onload event the image will not render.
To convert a canvas to a data URL is simple, use the .toDataURL(); method of the canvas element.
Then to convert the data URL back to an canvas image, you would first have to create an Image element and set its source as the dataURL. After getting the image onload event you can draw the image onto the canvas. This could be accomplished as shown:
Assuming the data URL is in a variable called dataURL, the canvas context is in a variable called ctx.
var img = new Image;
img.onload = () => { ctx.drawImage(img, 0, 0); };
img.src = dataURL;
The final solution would go like this:
var cdata2 = c2.toDataURL();
var cimg2 = new Image;
cimg2.onload = () => { ctx4.drawImage(cimg2, 0, 0, c4.width, c4.height); };
PS: You don't have to scale the image object by specifying the width and height, the canvas will do that when you specify the destination width and height.

Convert SVG dataUrl to base64

I'm using a plugin (dom-to-image) to generate a SVG content from a div.
It returns me a dataURL like this:
data image/xml, charset utf-8, <svg...
If a put this on a <img src the image is shown to normally.
The intent is to grab this dataURL, convert it to base64 so I can save it as an image.png on a mobile app.
Is it possible?
I tryied this solution https://stackoverflow.com/a/28450879/1691609
But coudn't get to work.
The console fire an error about the dataUrl
TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.
==== UPDATE :: PROBLEM EXPLANATION/HISTORY ====
I'm using Ionic Framework, so my project is an mobile app.
The dom-to-image is already working cause right now, its rendering a PNG through toPng function.
The problem is the raster PNG is a blurry.
So I thought: Maybe the SVG will have better quality.
And it IS!! Its 100% perfect, actually.
On Ionic, I'm using 2 step procedure to save the image.
After get the PNG generated by the dom-to-img(base64) dataURL, I convert it to a Blob and then save into device.
This is working, but the final result, as I said, is blurry.
Then with SVG maybe it will be more "high quality" per say.
So, in order to do "minimal" change on a process that s already working :D I just need to convert an SVG into base64 dataURL....
Or, as some of you explained to me, into something else, like canvas...
I don't know any much :/
===
Sorry for the long post, and I really, really thank your help guys!!
EDIT COUPLE OF YARS LATER
Use JS fiddle for a working example: https://jsfiddle.net/msb42ojx/
Note, if you don't own DOM content (images), and those images don't have CORS enabled for everyone (Access-Control-Allow-Origin header), canvas cant render those images
I'm not trying to find out why is your case not working, here is how I did when I had something similar to do:
get the image sourcce (dom-to-image result)
set up a canvas with that image inside (using the image source)
download the image from canvas in whatever image you like: png, jpeg whatever
by the way you can resize the image to a standard format
document.getElementById('mydownload').onclick= function(){
var wrapper = document.getElementById('wrapper');
//dom to image
domtoimage.toSvg(wrapper).then(function (svgDataUrl) {
//download function
downloadPNGFromAnyImageSrc(svgDataUrl);
});
}
function downloadPNGFromAnyImageSrc(src)
{
//recreate the image with src recieved
var img = new Image;
//when image loaded (to know width and height)
img.onload = function(){
//drow image inside a canvas
var canvas = convertImageToCanvas(img);
//get image/png from convas
var pngImage = convertCanvasToImage(canvas);
//download
var anchor = document.createElement('a');
anchor.setAttribute('href', pngImage.src);
anchor.setAttribute('download', 'image.png');
anchor.click();
};
img.src = src;
// Converts image to canvas; returns new canvas element
function convertImageToCanvas(image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);
return canvas;
}
// Converts canvas to an image
function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
}
}
#wrapper{
background: red;
color: blue;
}
<script src="https://rawgit.com/tsayen/dom-to-image/master/src/dom-to-image.js"></script>
<button id='mydownload'>Download DomToImage</button>
<div id="wrapper">
<img src="http://i.imgur.com/6GvKdxY.jpg"/>
<div> DUDE IS WORKING</div>
<img src="http://i.imgur.com/6GvKdxY.jpg"/>
</div>
I translated #SilentTremor's solution into React/JS-Class:
class SVGToPNG {
static convert = function (src) {
var img = new Image();
img.onload = function () {
var canvas = SVGToPNG.#convertImageToCanvas(img);
var pngImage = SVGToPNG.#convertCanvasToImage(canvas);
var anchor = document.createElement("a");
anchor.setAttribute("href", pngImage.src);
anchor.setAttribute("download", "image.png");
anchor.click();
};
img.src = src;
};
static #convertImageToCanvas = function (image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);
return canvas;
};
static #convertCanvasToImage = function (canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
};
}
export default SVGToPNG;
Usage:
let dataUrl = someCanvas.toDataURL("image/svg+xml");
SVGToPNG.convert(dataUrl);

image smaller than the original on canvas to make drawImage()

I am developing a system for image filter with html5 canvas, however, as I am at the beginning I have emerged me some doubts and mistakes.
Here's what I've developed so far:
$(document).ready(function() {
$("#uploadImagem").change(function(e) {
var _URL = window.URL || window.webkitURL,
arquivo = e.target.files[0],
tipoImagem = /image.*/,
reader,
imagem;
if(!arquivo.type.match(tipoImagem)) {
alert("Somente imagens são aceitas!");
return;
}
imagem = new Image();
imagem.onload = function() {
if(this.width > 600 || this.height > 400) {
alert("Somente imagens com largura máxima de 600px e altura máxima de 400px");
return;
} else {
$("#filtrarImagem").width(this.width).height(this.height);
}
};
imagem.src = _URL.createObjectURL(arquivo);
reader = new FileReader();
reader.onload = fileOnload;
reader.readAsDataURL(arquivo);
});
function fileOnload(e) {
var $img = $("<img>", {src: e.target.result}),
canvas = $("#filtrarImagem")[0],
context = canvas.getContext("2d");
$img.load(function() {
context.drawImage(this, 0, 0);
});
}
});
When I do imagem.onload... I wish, if the image pixels were greater than 600 and 400 he gave the alert and stop there, but even so the image appears on the canvas.
In the same imagem.onload... function, if the image pixels correspond to the canvas required (id = "filtrarImagem") is the size of the image, but the image to the canvas becomes smaller than the original uploaded, and she was to occupy all the canvas and get the original size.
How to continue?
You have two separate handlers for image loading. There is no need to set two image sources with the same URL, just reuse a single image for both checking size and setting canvas size as well as draw it into the canvas.
I would suggest the following steps (you tagged the question with jQuery but I would highly recommend working in vanilla JavaScript when you work with non-DOM oriented elements such as canvas).
Example
if (typeof window.URL === "undefined") window.URL = window.webkitURL;
$("input")[0].onchange = function(e) {
var arquivo = e.target.files[0],
imagem = new Image();
if (!arquivo.type.match(/image.*/)) {
alert("Somente imagens são aceitas!");
return;
}
// STEP 1: load as image
imagem.onload = doSetup;
imagem.src = URL.createObjectURL(arquivo)
};
// STEP 2: now that we have the image loaded we can check size and setup canvas
function doSetup() {
URL.revokeObjectURL(this.src); // clean up memory for object-URL
if (this.width > 600 || this.height > 400) {
alert("Too big!");
return; // exit!
}
// image OK, setup canvas
var c = $("canvas")[0]; // work with the element itself, not the jQuery object
c.width = this.width; // important: use canvas.width, not style or css
c.height = this.height;
// draw in image
var ctx = c.getContext("2d");
ctx.drawImage(this, 0, 0);
// NEXT: ... from here, invoke filter etc.
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file"><br><canvas></canvas>
The jQuery width() and height() functions use CSS to change the size of the canvas which does not do what you would expect it to do. Change the width and height attributes of the canvas element directly.
The reason why your check for the size does not prevent the image from being drawn, is because your check is in the handler for imagem.onload in $("#uploadImagem").change while the drawing happens in $img.onload assigned from reader.onload. These two events are processed independently. One of them returning prematurely does not prevent the other from being executed.

Javascript - Cordova - Android - Return base64 encoded canvas drawn with local image file

I need to write a new HTML file from a string using file system, I'm using Cordova 2.4.0. . That HTML would have some images loaded from a local folder, so because I need just one file (a HTML without png/jpg images alongside it) I'm trying to encode this images and apply them through CSS as background images (The CSS code is embeded in the same String, future HTML file). Well, the way I make these modifications to the string is by using functions returns. For example:
padding-top: 5%; background-image: url(' + agregaImagenLocal('../img/ESTELAR.png') + '); background-color: white;
The function "agregaImagenLocal(pathToLocalImage)" :
function agregaImagenLocal(pathToLocalFile) {
var canvas = document.getElementById('canvasOculto');
var imagen = new Image(150,100);
canvas.width = imagen.width;
canvas.height = imagen.height;
var contextoCanvas = canvas.getContext('2d');
imagen.onload = function () {
contextoCanvas.drawImage(imagen, 0, 0);
urlImagenLocal = canvas.toDataURL();
}
imagen.src = pathToLocalFile;
return urlImagenLocal //???????
}
I was doing this without the "onload" event, so it returned a blank image. But with this function inside the "onload" I don't know how to return the base64 encoded image to the first function.
This is the function to convert an Image (by file path) to Base64:
function convertImgToBase64(url, callback, outputFormat){
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
var img = new Image;
img.crossOrigin = 'Anonymous';
img.onload = function(){
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img,0,0);
var dataURL = canvas.toDataURL(outputFormat || 'image/png');
callback.call(this, dataURL);
// Clean up
canvas = null;
};
img.src = url;
}
Once the conversion is made, you can use jQuery to set the background CSS using the Base64 code.
var imageUrl = ""; //Your Local Image Path HERE
convertImgToBase64(imageUrl, function(base64Img){
$('.output').css("background-image", base64Img);
}
This will set the source of an element with the class 'output' to the base64 image.

INDEX_SIZE_ERR when drawImage on canvas

I need to draw an Image object to a canvas but I've got an INDEX_SIZE_ERR exception in Firefox and IE10 but not in Chrome nor Safari...
According to the W3C: If one of the sw or sh arguments is zero, the implementation must raise an INDEX_SIZE_ERR exception..
Here is the code that causes the problem:
function writePhotoOnCanvas(data, width, height) {
// Get the canvas
var canvasGallery = document.getElementById("canvasGallery");
// Clear the canvas
canvasGallery.width = canvasGallery.width;
// Get its context
var ctxCapture = canvasGallery.getContext("2d");
// Create an image in order to draw in the canvas
var img = new Image();
// Set image width
img.width = width;
// Set image height
img.height = height;
// To do when the image is loaded
img.onload = function() {
console.log("img.width="+img.width+", img.height="+img.height);
console.log("width="+width+", height="+height+", canvasGallery.width="+canvasGallery.width+", canvasGallery.height="+canvasGallery.height);
// Draw the picture
try {
ctxCapture.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvasGallery.width, canvasGallery.height);
} catch(e) {
console.error(e.message);
}
};
// Set image content from specified photo
img.src = data;
}
The console shows:
img.width=640, img.height=480
width=640, height=480, canvasGallery.width=589, canvasGallery.height=440
Index or size is negative or greater than the allowed amount
What is the source of the problem?
Thanks
You are manually setting the width and height of the image (img.width = width; img.height = height;). I don't really understand why you are doing this, but it is likely unnecessary.
These should be calculated automatically from the image data you load. Try to remove them to see what the actual size of the data is.
The image width and height are read-only properties so they will cause the code to break in some browser.
If you absolutely want to set the width and height before loading the image you can do:
var img = new Image(width, height);
Then you can read img.width and img.height when image has loaded (or read img.naturalWidth and img.naturalHeight to get the original dimension).
There is no need though to do this. Simply call your drawImage() like this:
ctxCapture.drawImage(img, 0, 0, canvasGallery.width, canvasGallery.height);
This will use the full dimension of the image and scale it to the canvasGallery's dimension.
Tip: If you are using this function to load several images you will want to exchange img with this inside your onload handler.
Modified code:
function writePhotoOnCanvas(data, width, height) {
var canvasGallery = document.getElementById("canvasGallery");
var ctxCapture = canvasGallery.getContext("2d");
/// setting width to clear does not work in all browser, to be sure:
ctxCapture.clearRect(0, 0, canvasGallery.width, canvasGallery.height);
var img = new Image();
img.onload = function() {
// Draw the picture
try {
ctxCapture.drawImage(this, 0, 0,
canvasGallery.width, canvasGallery.height);
} catch(e) {
console.error(e.message);
}
};
// Set image content from specified photo
img.src = data;
}

Categories

Resources