KineticJS: Kinetic warning: Unable to get data URL - javascript

I have two Kineticjs canvases and when trying to create an image in one canvas from the other canvas I get this error after calling toImage() on the canvas with the new image:
Kinetic warning: Unable to get data URL. Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported
I am pretty sure the reason why I am getting this error is because the "toImage()
method requires that the image is hosted on a web server with the same domain as the code executing it." How can I get around this warning so that I can create objects from one canvas and add them to another?
The app I am creating will run locally and will never run online so I don't have to worry about security issues. Also I read around that I can enable cross origin resource sharing but that seems a little complex and over the top since they require the setting up of a web server I think.
So is there any trick I can do to make one canvas able to create an image in another canvas for a Chrome kineticjs web app? And then being able to successfully call toImage()?
Here is how I am creating the image in the canvas:
var folderImage = new Image();
//folderImage.crossOrigin="anonymous"; // gives me file error if unchecked
folderImage.onload = function() {
var folderPic = new Kinetic.Image({
x: 0,
y: 0,
image: folderImage,
width: sideLen,
height: sideLen
});
subFolderGroup.add(folderPic);
subTextGroup.moveToTop();
mainBody4Dynamic.draw();
};
folderImage.src = 'assets/images/folder.png';
And when I call toImage() in the other layer all I am calling is the layer.toImage()

The browser treats the user's local drive as other-domain. That's good because you don't want your browser "getting friendly" with your banking records on your hard drive.
This means running locally with local images will taint the canvas (a CORS violation).
The simplest workaround is to install a web-server on your local machine and host the web-page plus images on a single domain. (=== automatic CORS compliance). PHP and IIS both work well on a dev machine.
Another workaround is complying with CORS restrictions by hosting your images on an internet imaging host that has configured its server to deliver images in a CORS compliant manor. Then all you have to do is add myImage.crossOrigin="anonymous". I believe dropbox.com does this--or they used to.
While in development, it sometimes works to put both your .html and your images on the desktop.

Related

Babylon JS - SceneLoader from Local File

New Babylon JS user, looking to get up to speed with this fantastic framework. Have had a play with the Sandbox and online Editor, worked up my own coded model from scratch using the standard components - Box, Sphere etc. My question relates to how to get more complex custom geometry loaded. Very comfortable with 3D CAD - STL/OBJ files, got some exports going from Blender to .Babylon format which import great into Babylon's online Sandbox & Editors. However, I can't seem to get the SceneLoader going to read a file from local C:/ drive. Code extract below:
// Create new Babylon Scene
var scene = new BABYLON.Scene(engine);
// Change scene background color
scene.clearColor = new BABYLON.Color3(1, 1, 1);
// Create and positions a free camera
var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 10, 0), scene);
// Target the camera to scene origin
camera.setTarget(BABYLON.Vector3.Zero());
// Attach camera to the canvas
camera.attachControl(canvas, true);
// Define built-in 'box' shape.
var box = BABYLON.Mesh.CreateBox("sphere1", 1, scene);
// Define 'ground' plane
var ground = BABYLON.Mesh.CreateGround("ground1", 100, 100, 100, scene);
ground.position.y = 0;
//Load local .babylon file from root Dir
BABYLON.SceneLoader.Load("", "Test.babylon", engine, scene);
My model has a standard box for geometry with ground plane. All renders great in Babylon - until I add the SceneLoader line. When I add this I get stuck on the Babylon Loading intro splash screen (rotating Babylon logo). If I comment out the last line of code above the model renders fine with the box.
Have had a look at various forum pages on this and wrecked my brain to point of being stuck e.g: http://www.html5gamedevs.com/topic/20924-stlobj-file-loader/ & https://www.eternalcoding.com/?p=313
I believe Google Chrome may be locking out local file links for security, have tried running in -Allow-Local-File-Access mode, still stuck on loading page. Do I need a web server (I wouldn't know where to start!) or can I run Babylon scenes locally?
First issue posed by OP: Browser is not loading mesh from file system.
Solution: Use a web server such as Simple HTTP Server (Python). The way to do this is slightly different depending on your Python version. To check Python version on Windows, open command prompt and type python --version. Remember the version number for later :)
Setting up simple web server with Python with command prompt:
Navigate to the directory with your index.html file in File Explorer
Left click on to a blank space inside the path box (where it says This PC > Documents, etc...)
Type cmd and it will open Command Prompt in the current directory
Enter the appropriate command...
python -m SimpleHTTPServer [optional port number] if you are using Python 2
python -m http.server [optional port number] if you are using Python 3
I usually leave out the port number and simply type python -m http.server.
Now open your preferred browser and enter localhost:8000 into your address bar. (8000 is the default port number. If you specified a port, use the number which you specified.) It should load your mesh if the code has no errors.
Second issue posed by OP: SceneLoader.Load method overrides previously loaded meshes.
Solution:
If you only need to import a few meshes, use either BABYLON.SceneLoader.Append(...) or BABYLON.SceneLoader.ImportMesh(...). However, this method is inconvenient for managing many assets.
Alternatively, use BABYLON.AssetsManager(...). Since Babylon.js loads models in asynchronously, the asset manager allows ease of use through callback functions. In other words, you can find your assets by name by using scene.getMeshByName("yourMesh") if you type inside the callback function. Here is a simple demo.
I know this question is a few years old, but in case anyone still has issues with this I hope this answer helps.
So I’m not 100% sure about this answer, but hopefully it will help. I followed this tutorial (Skip down to the section where the scene gets loaded). One issue is definitely the cross origin thing, the other how you call the SceneLoader.Load method.
When I try the code from the tutorial with regular Chrome I see three warnings in my web console. Two errors about Test.babylon.manifest (using your example file naming) and one about Test.babylon. You can ignore the ones regarding manifests afaik. The important one is the error about Test.babylon itself. So by default Cross origin requests are not allowed and the babylon file does not load (as expected).
Now, when I close Chrome and reopen it by running open -a "Google Chrome" --args --allow-file-access-from-files in the terminal (I’m on OSX Yosemite), and then load the page, the object loads fine. I still see two errors about manifests in the web console, but they can be ignored.
Note how the BABYLON.SceneLoader.Load function is being called. The import process is asynchronous, and the last parameter looks to be a callback function for what to do once the object has successfully loaded, so I don't think you can just pass scene as in your original code. Check out the function docs.
Ok - porgress.
I got it going using SceneLoader.ImportMesh but I had to setup a simple HTTP Server using Python (v3). This link helped a lot: http://www.linuxjournal.com/content/tech-tip-really-simple-http-server-python
So you run the Python HTTP server from the directory that the Babylon index.html is based in, and it runs as if HTTP bypassing local file access constraints in Chrome.
So my problem is all but answered. I now have my mesh geometry from the Test.Baylon file into my main scene. Still having issues using SceneLoader.Load as the new scene coming in supercedes my original scene and the original geometry disappears. David - I think you're right on the function being needed, although I thought this was optional. As I said, the Tutorial example creates a newScene and renders within the function, in my case I don't know what to do in the function... maybe just 'return'?

Three.js - Cannot use local image for loadTexture

i am trying to use a local image for loadTexture in Three.js but i get the following error:
Uncaught SecurityError: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image at .... may not be loaded.
I have a java application running on apache tomcat (locally) which serves my image with the following url: http://localhost:8084/sve/img/wood-texture.jpg.
Here is my javascript code where i try to load the image:
var woodTexture = new THREE.ImageUtils.loadTexture('http://localhost:8084/sve/img/wood-texture.jpg');
I am using Google Chrome (Version 40.0.2214.111 m) to run my Three.js program. I also try to start chrome like this: chrome.exe --allow-file-access-from-files. But i get the same error.
Does anyone have any solution for this?
It's probably easiest to make sure the texture is served by the same server as your three.js app.
If you still need it to come from another server (the Java app on the other port in your example) you need to make the Java app set some CORS headers.
For example: "Access-Control-Allow-Origin: *"
See https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS for more info.

External javascript library error. (Blur.js)

Basically, this plugin is responsible for this really neat effect:
http://www.blurjs.com/
But when I try to implement it on my site in chrome I get this error message in my console:
Unable to get image data from canvas because the canvas has been tainted by cross-origin
data. demo.html:1
Uncaught Error: unable to access image data: Error: unable to access local image data:
ReferenceError: netscape is not defined
Implementation below:
$('.navbar').blurjs({
source: 'body',
overlay: 'rgba(0,100,100,0.1)'
});
What's really annoying is the same error pops up in his example file! So what's going on? Tested in chrome and opera and firefox. Exactly the same errors in his example file.
Same error in a jsfiddle:
http://jsfiddle.net/8QeAQ/7/
I even downloaded his whole site, and though it works online, locally the identical files get this error. Very strange. Very disappointing, looked like a great library. Be very grateful if someone could find a fix.
This images below show the untouched files, forked straight from github, so what's going on?
Try uploading it to a remote computer. It sounds like the error is to do with mixing origins (specifically, the image is from a different origin than the html/javascript). That can be a problem when testing locally also, because browsers often don't trust local stuff either.
I think this is because the Cross-domain issues on your page with the image files.
Blur.js use the getImageData() method to get image data. getImageData() method requires that the image is hosted on a web server with the same domain as the code executing it.
For example, the page from a.example.com, will not be allowed to use getImageData() method to get the data of image which references from other domain such as b.example.com, even they pointed to the same web server;
Just before tempImg.src = formattedSource; add tempImg.crossOrigin = '';///=anonymous this will solve the problem!
tempImg.crossOrigin = '';///=anonymous
tempImg.src = formattedSource;
Blur.js is written in a way which does not allow it to access local files on your system if you launch your JavaScript locally (file//:). It only works if your script and image files are on a web server (http//:).
You can use WampServer to create a localhost server and test your website on your machine. Just install it, place your files into its www directory, and open http//:localhost/"yourFile".

can not get canvas.getContext('2d').getImageData(x,x,x,x)

can not get the imageData
the browser console "Unable to get image data from canvas because the canvas has been tainted by cross-origin data."
In order to prevent shenanigans, the browser keeps track of image data. When you put an image from a different domain on your canvas, the canvas becomes "tainted" and the browser won't let you look at its pixels anymore.
This is necessary to prevent a variety of XSS/CSRF attacks.
See Pointy's answer for an explanation. This can be an annoying problem when testing files from the local filesystem. On Google Chrome / Chromium there's a workaround: Call it with the following command line option:
chromium-browser --allow-file-access-from-files

Can I get the data of a cross-site <img/> tag as a blob?

I am trying to save a couple of images that are linked to by a webpage to offline storage. I'm using IndexedDB on Firefox and FileSystem API on Chrome. My code is actually an extension, so on Firefox I'm running on Greasemonkey, and on Chrome as a content script. I want this to be automated.
I am running into problem when I retrieve the image file. I'm using example code from the article titled Storing images and files in IndexedDB, but I get an error: the images I'm trying to download are on a different subdomain and the XHR fails.
XMLHttpRequest cannot load http://...uxgk.JPG. Origin http://subdomain.domain.com is not allowed by Access-Control-Allow-Origin.
On Firefox I could probably use GM_xmlhttpRequest and it'd work (the code works on both browsers when I'm in same-origin URLs), but I still need to solve the problem for Chrome, in which other constraints (namely, needing to interact with frames on the host page) require me to incorporate my script in the page and forfeit my privileges.
So it comes back to that I'm trying to figure out a way to save images that are linked to (and may appear in) the page to IndexedDB and/or FileSystem API. I either need to realize how to solve the cross-origin problem in Chrome (and if it requires privileges, then I need to fix the way I'm interacting with jQuery) or some kind of reverse createObjectURL. At the end of the day I need a blob (File object, as far as I understand) to put into the IndexedDB (Firefox) or to write to FileSystem API (Chrome)
Help, anyone?
Edit: my question may actually really come down to how I can use jQuery the way I want without losing my content script privileges on Chrome. If I do, I could use cross-origin XHRs on Chrome as well. Though I'd much rather get a solution that doesn't rely on that. Specifically since I'd like this solution if I get the script incorporated into the webpage, and not require it to be a content script/userscript.
Edit: I realized that the question is only about cross-site requests. Right now I have one of three ways to get the image blob, with the help of #chris-sobolewski, these questions and some other pages (like this), which can be seen in this fiddle. However, all of these require special privileges in order to run. Alas, since I'm running on a page with frames, because of a known defect in Chrome, I can't access the frames. So I can load a script into each frame by using all_frames: true, but I really want to avoid loading the script with every frame load. Otherwise, according to this article, I need to escape the sandbox, but then it comes back to privileges.
Since you are running on Chrome and Firefox, your answer is fortunately, yes (kind of).
function base64img(i){
var canvas = document.createElement('canvas');
canvas.width = i.width;
canvas.height = i.height;
var context = canvas.getContext("2d");
context.drawImage(i, 0, 0);
var blob = canvas.toDataURL("image/png");
return blob.replace(/^data:image\/(png|jpg);base64,/, "");
}
this will return the base64 encoded image.
from there you just call the function something along these lines:
image = document.getElementById('foo')
imgBlob = base64img(image);
Then go ahead and store imgBlob.
Edit: As file size is a concern, you can also store the data as a canvasPixelArray, which is width*height*4 bytes in size.
imageArray = context.getImageData( 0, 0 ,context.canvas.width,canvasContext.canvas.height );
Then JSONify the array and save that?

Categories

Resources