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.
Related
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.
I have a simple input box of type file and a button. I am trying to store the file in the session on click of button so that if page is refreshed it will be in session.
I tried using
function storeInSession(){
element = document.getElementById('attachments')
var file = element.files[0];
sessionStorage.setItem('fileInSession', file)
sessionFile = sessionStorage.getItem('fileInSession')
}
<input type="file" id="attachments">
<button onclick="storeInSession()">Upload</button>
Is there any way I can do this?
Storing images
The idea here is to be able to take an image that has been loaded into the current web page and store it into localStorage. As we established above, localStorage only supports strings, so what we need to do here is turn the image into a Data URL. One way to do this for an image, is to load into a canvas element. Then, with a canvas, you can read out the current visual representation in a canvas as a Data URL.
Let’s look at this example where we have an image in the document with an id of “elephant”:
// Get a reference to the image element
var elephant = document.getElementById("elephant");
// Take action when the image has loaded
elephant.addEventListener("load", function () {
var imgCanvas = document.createElement("canvas"),
imgContext = imgCanvas.getContext("2d");
// Make sure canvas is as big as the picture
imgCanvas.width = elephant.width;
imgCanvas.height = elephant.height;
// Draw image into canvas element
imgContext.drawImage(elephant, 0, 0, elephant.width, elephant.height);
// Get canvas contents as a data URL
var imgAsDataURL = imgCanvas.toDataURL("image/png");
// Save image into localStorage
try {
localStorage.setItem("elephant", imgAsDataURL);
}
catch (e) {
console.log("Storage failed: " + e);
}
}, false);
You can encode binary data to base64 format, and use it as string
The Problem: Imagine I have a td element structured as such:
<td td="" colspan="2">
<br>
<img src="ImageServlet" alt="random image" border="0" id="simpleRandomImg">
</td>
of course, with other HTML around it. The image contained within the servlet doesn't have a useful src indicated in the HTML (clearly) - however, when I open up the Network tab in Chrome, I can preview the loaded image itself and copy the image as a data URI - which gives me a stable URL like:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAAyCAIAAACWMwO2AAAhQklEQVR42u2dB1Sb5/nonTRt2pPkJGmSNm180zhNTkabuPGKMeAwxBaIJYEYWmhLSEIggRhaaAIaIEASEggQew+zzPLEdjyy07T/9t9129t129u9z7mP9LnfXxZCBuLeS/71c77zIRQCGj89z+993+d7vS/GH7GxsXH+wGAwCf5ITExMSkpKTk5OSUlJTU1N80d6etcetcetc...
so, clearly there exists a stable reference to the loaded image. And clearly my browser 'knows' what that reference is, because I can retrieve the link to it as a data URI - but there's no reference to that data URI in the actual HTTP response. This probably seems a lot less mystical to someone who understands JavaScript, but that someone is not myself - so could someone explain what's going on here, and if there is some way to gather the data image URI from the HTTP response?
Attemped Solutions:
Did a little digging around in the HTTP response and located this bit of JavaScript which, apparently, handles the changing of images:
function changeImage() {
// makes a new image load
var obj=document.getElementById('simpleRandomImg');
if (obj != null) {
// append a unique index to force browser to reload
obj.src='ImageServlet?'+(cnt++);
}
However, nothing I see there gives any indication as to the actual URI location of the image. As before, if I open the Google Chrome network tab and attempt to retrieve the data image URI from the individual response, it works and gives me a valid URI - so, clearly the browser is receiving it. How can I access it?
e: to be clear, I do not control the website in question, so I can't 'fix' it by just changing the internal javascript - I'm viewing the site and am interested in whether or not it's possible to retrieve the loaded images short of screenshotting the page itself.
Something like this should work. Canvas API has a function called toDataURI
function getDataUri(url, callback) {
var image = new Image();
image.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size
canvas.getContext('2d').drawImage(this, 0, 0);
// Get raw image data
callback(canvas.toDataURL('image/jpg').replace(/^data:image\/(png|jpg);base64,/, ''));
// ... or get as Data URI
callback(canvas.toDataURL('image/jpg'));
};
image.src = url;
}
// Usage
// beware of server cors settings..
getDataUri('image url here', function(dataUri) {
console.log(dataUri)
// Do whatever you'd like with the Data URI!
});
You can set the src of the image to your URI by using setAttribute, like so:
obj.setAttribute('src', uriString)
I'm trying to base64 encode a local file. It's next to my .js file so there's no uploading going on. Solutions like this (using XMLHttpRequest) get a cross-site scripting error.
I'm trying something like this (which doesn't work but it might help explain my problem):
var file = 'file.jpg'
var reader = new FileReader();
reader.onload = function(e) {
var res = e.target.result;
console.log(res);
};
var f = reader.readAsDataURL(file);
Anyone have any experience doing this locally?
Solutions like this (using XMLHttpRequest) get a cross-site
scripting error.
If using chrome or chromium browser, you could launch with --allow-file-access-from-files flag set to allow request of resource from local filesystem using XMLHttpRequest() or canvas.toDataURL().
You can use <img> element, <canvas> element .toDataURL() to create data URL of local image file without using XMLHttpRequest()
var file = "file.jpg";
var img = new Image;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
img.onload = function() {
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 0, 0);
var res = canvas.toDataURL("image/jpeg", 1); // set image `type` to `image/jpeg`
console.log(res);
}
img.src = file;
You could alternatively use XMLHttpRequest() as described at Convert local image to base64 string in Javascript.
See also How to print all the txt files inside a folder using java script .
For a details of difference of returned data URI from either approach see canvas2d toDataURL() different output on different browser
As described by #Kaiido at comment below
it will first decode it, at this stage it's still your file, then it
will paint it to the canvas (now it's just raw pixels) and finally it
will reencode it (it has nothing to do with your original file
anymore) check the dataURI strings... They're compeltely different and
even if you do the canvas operation from two different browsers,
you'll have different outputs, while FileReader will always give you
the same output, since it encode the file directly, it doesn't decode
it.
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');
}
});
});