The picture on the HTML page is represented as a canvas, but I have problems getting the source image name of this canvas, using javascript.
Page: https://www.futbin.com/22/squad-builder
I found this image in the page resources:
But how to get it programmically? I mean, if i have:
var canvas = document.getElementById('field-area')
How to get the file name? Result should be "field_1920x1080.png?v=8"
You can use HTMLCanvasElement.toDataURL to get the image drawn on the canvas base64 encoded
var canvas = document.getElementById('field-area');
var b64url = canvas.toDataURL('image/png');
This will return the url for the image itself, i don't think you can get the Asset name directly from a canvas element without inspecting the code on the website
EJBEAN is right, the canvas element doesn't know what resources were used to draw.
Why don't you use dataset to keep an eye on what you used?
var canvas = document.getElementById('field-area');
// ... draw resource here
canvas.dataset.resource = "field_1920x1080.png";
It's an easy way to keep data stored for any element on your page.
Related
I'm working on a web application that involves loading images into a canvas object, then manipulating those images beyond recognition. I need to hide the original source image file (a jpeg) so that the user on the client side should not be able to use dev tools to see the original image.
I have tried to encode the images as a base64 and load it via a JSON data file, but even with this method, the inspector tool still shows the original image file (when it is set as the src of my javascript image object). Is there some way that I can encrypt and decrypt the image files, so that the user has no way of seeing the original image (or have it be some garbled image, for example)? Preferably I'd like to do this on the client side, as all my code is client side at the moment. Thanks in advance!
Here is my code for loading the base64 encoded image data via a JSON file:
//LOAD JSON INSTEAD?
$.getJSON( "media/masks.json", function( data ) {
console.log("media/masks.json LOADED");
//loop through data
var cnt = 0;
for (var key in data)
{
if (data.hasOwnProperty(key))
{
// here you have access to
//var id = key;
var imgData = data[key];
//create image object from data
var image = new Image();
image.src = imgData;
console.log('img src: '+ imgData);
var elementId = $scope.masks[cnt].id;
// copy the images to canvases
imagecanvas = document.createElement('CANVAS');
imagecanvas.width = image.width;
imagecanvas.height = image.height;
imagecanvas.getContext('2d').drawImage(image,0,0);
imageCanvases[elementId] = imagecanvas;
}
cnt++;
}
});
This is what I see in the Chrome dev tools Network inspector (exactly what I'm trying to avoid):
I need to hide the original source image file (a jpeg) so that the user on the client side should not be able to use dev tools to see the original image.
That's not possible. There is always a way to get at the image using developer tools. Even if there wasn't, a simple screen capture would defeat whatever measures you put in place.
I'm using fabric.js for my canvas application, toDataURL method works properly except when there is a image on canvas. When i add an image to canvas and call toDataURL it shows me a blank page.
//When i call it from chrome console
canvas.toDataURL();
//It returns a working data url with no problem.
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAAGkCAYAAAAPPajHAAAgAElEQ…fpmwgogX1TrjoqP0FACewngtZh+iYCSmDflKuOyk8Q+H+CKCqUW0spTgAAAABJRU5ErkJggg=="
//When i execute same code in a .js file it returns a data url which shows a blank image.
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAAGkCAYAAAAPPajHAAAKC0lEQ…sBAmEBAw6XJzoBA/YDBMICBhwuT3QCBuwHCIQFDDhcnugEHt/IAaW9dzALAAAAAElFTkSuQmCC"
It's interesting that it's working on chrome dev console but not works in .js file even if it's same code. I noticed that working data url finishes with '==' but other one not. However i don't know what this means.
You didn't give much to analyze but I'll go from there on my gut feeling.
The image you are using is probably violating Cross-Origin Resource Sharing (CORS) requirements. When this happens the canvas will return a blank image when you try to get the pixel data either by using canvas.toDataURL() or context.getImageData().
It basically happens when the image is not located on the same domain as the page or is loaded from the file:// protocol.
You can try to add the following to the image object before setting the source:
image.crossOrigin = 'anonymous';
image.src = '...';
From tag:
<img crossOrigin='anonymous' src='...' alt='' />
This will request permission from the server to use the image cross-origin. If the server allows you should be fine.
If not you will either have to copy the image to your own server so it loads from the same domain as your page, or create a proxy page that loads the image externally and serves it to your page from the proxy page (it sounds complicated but really isn't).
If the image does not show up at all on the canvas you are probably not using load callback which you need since image loading is asynchronous. If so just add:
image.onload = function() {
/// now you can draw the image to canvas
}
image.crossOrigin = 'anonymous';
image.src = '...';
The problem is solved. The point i missed is, i was calling toDataURL function before canvas is loaded, that's why it was showing me a blank page.
canvas.loadFromJSON(json,function(){
var dataURL = canvas.toDataURL();
});
This solved my problem when i gave toDataURL() function as a callback to loadFromJSON function.
But after a while i had a different issue about CORS when i tried to upload my images from s3 bucket and i solved this problem as upward solution.
I was facing the same issues when I was trying to generate images from the canvas using Fabricsjs and generate PDF from images using JSPDF so below is my case I also spend hours on this may this can help someone to save time.
Load the canvas from JSON that i.e
canvas.loadFromJSON(json, canvas.renderAll.bind(canvas), function(obj, object) {
//fabric.log(obj, object);
});
Canvas was drawing images all fine then I was generating the images from that canvas it was a case of multiple images in a single canvas and I was generating PDF based on each page of the canvas.
Instead of this
canvas.toDataURL('image/png', 0.1)
I used this and it starts returning me the propper images dataurl
var imgData = document.getElementById('canvas_0').toDataURL();
Below are snippets
$("#pdfSelector .canvas-container").each(function(index, value){ // canvas selector
html2canvas($("#canvas_"+index), { // html2canvas used to get images
onrendered: function(canvas) { // on successfully render of images
//var imgData = canvas.toDataURL('image/png', 0.1);
var imgData = document.getElementById('canvas_0').toDataURL();
const imgProps= doc.getImageProperties(imgData);
const pdfWidth = doc.internal.pageSize.getWidth();
const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
doc.addImage(imgData, 'PNG', 0, 0, pdfWidth, pdfHeight, 'page_'+index, 'FAST');
}
});
});
I am using this as a virtual signature pad: http://thomasjbradley.ca/lab/signature-pad/ . It can either automatically generate a signature from a typed name or let the user sign with their mouse. I need to capture the image and send it to a Java server. It uses an HTML5 canvas.
It works correctly for the drawn image, but trying to capture the automatically generated image results in a blank image with no text.
I am using this code as it said in the site's API section:
var api = $('.sigPad').signaturePad();
autoGeneratedData = api.getSignatureImage();
and then sending autoGeneratedData to the server.
I also tried to capture the canvas directly:
var canvas = document.getElementById('sigCanvas');
var imageData = canvas.toDataURL('image/png');
but ran into the same issue.
I need to take HTML5 canvas output as video or swf png sequence.
I found the following link on stackoverflow for capturing images.
Capture HTML Canvas as gif/jpg/png/pdf?
But can anyone suggest if we want the output to be video or swf of png sequence?
EDIT:
Ok now I understood how to capture the canvas data to store on server, I tried it and it is working fine if I use only shapes, rectangle or some other graphic, but not if I draw external images on canvas element.
Can anyone tell me how to capture canvas data completely whether we use graphic or external images for drawing on canvas?
I used the following code:
var cnv = document.getElementById("myCanvas");
var ctx = cnv.getContext("2d");
if(ctx)
{
var img = new Image();
ctx.fillStyle = "rgba(255,0,0,0.5)";
ctx.fillRect(0,0,300,300);
ctx.fill();
img.onload = function()
{
ctx.drawImage(img, 0,0);
}
img.src = "my external image path";
var data = cnv.toDataURL("image/png");
}
after taking the canvas data into my "data" variable I created a new canvas and draw the captured data on that, the red rectangle drawn on the second canvas but that external image doesn't.
Thanks in advance.
I would suggest:
Use setInterval to capture the contents of your Canvas as a PNG data URL.
function PNGSequence( canvas ){
this.canvas = canvas;
this.sequence = [];
};
PNGSequence.prototype.capture = function( fps ){
var cap = this;
this.sequence.length=0;
this.timer = setInterval(function(){
cap.sequence.push( cap.canvas.toDataURL() );
},1000/fps);
};
PNGSequence.prototype.stop = function(){
if (this.timer) clearInterval(this.timer);
delete this.timer;
return this.sequence;
};
var myCanvas = document.getElementById('my-canvas-id');
var recorder = new PNGSequence( myCanvas );
recorder.capture(15);
// Record 5 seconds
setTimeout(function(){
var thePNGDataURLs = recorder.stop();
}, 5000 );
Send all these PNG DataURLs to your server. It'll be a very large pile of data.
Using whatever server-side language you like (PHP, Ruby, Python) strip the headers from the data URLs so that you are left with just the base64 encoded PNGs
Using whatever server-side language you like, convert the base64 data to binary and write out temporary files.
Using whatever 3rd party library you like on the server, convert the sequence of PNG files to a video.
Edit: Regarding your comment of external images, you cannot create a data URL from a canvas that is not origin-clean. As soon as you use drawImage() with an external image, your canvas is tainted. From that link:
All canvas elements must start with their origin-clean set to true.
The flag must be set to false if any of the following actions occur:
[...]
The element's 2D context's drawImage() method is called with an HTMLImageElement or an HTMLVideoElement whose origin is not the same as that of the Document object that owns the canvas element.
[...]
Whenever the toDataURL() method of a canvas element whose origin-clean flag is set to false is called, the method must raise a SECURITY_ERR exception.
Whenever the getImageData() method of the 2D context of a canvas element whose origin-clean flag is set to false is called with otherwise correct arguments, the method must raise a SECURITY_ERR exception.
To start out, you want to capture the pixel data from the canvas on a regular interval (using JavaScript timers probably). You can do this by calling context.getImageData on the canvas's context. That will create a series of images that you can turn into a video stream.
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#pixel-manipulation
I have image data (either JPEG or PNG) in a Javascript variable. How do I display the image in an HTML document? These are very large images and code like this doesn't work because the URI is too long:
// doesn't work because the URI is too long
$('img#target').attr('src', 'data:...');
Using canvas is probably the answer but I cannot figure out how to load it with the image data.
In case you are wondering: no, I cannot just download the image data directly to the img tag. It came from the server encrypted and was decrypted within the browser using Javascript.
Thanks,
-- Art Z.
To use a data URL to draw on a canvas:
var img = new Image;
img.onload = function(){
myCanvasContext.drawImage(img,0,0);
};
img.src = "data:...";
Per this question/answer be sure that you set the onload before the src.
You say that "the URI is too long", but it is not clear what you mean by this. Only IE8 has a 32kB limit on the data URI; for other browsers it should work fine. If you are experiencing an error, please describe it.
It turns out that
$('img#target').attr('src', 'data:...');
does work in all except IE. My problem originated elsewhere.