I was coding some Three.js scenes earlier and encountered the following error in Chrome (v27):
Cross-origin image load denied by Cross-Origin Resource Sharing policy
It happened when I was trying to load an image from a file to use as a texture for a material I wanted to apply to a mesh. Basically, I wanted my plane to have a grass texture.
THREE.ImageUtils.loadTexture('images/grass.jpg')
Even though both the .html and the .jpg were in the same location (both local, same folder) the error occurred. Whilst the error, then, makes no sense, it is however ‘working as intended’. This is, it seems, a security ‘feature’ that is implemented in many browsers, not just Chrome.
Now, I didn’t want to downgrade the security of my browser by launching it as suggested by some:
chrome --allow-file-access-from-files
and I didn’t want to fire up a web server of any kind just for one placeholder texture, as suggested by others:
Basically, I was in a lazy mood and just wanted a simple security bypass. 🙂 If you do too then the following approach may be of interest…
In essence, we’re going to turn a binary image into text, store that text in a .js file, and then link that external javascript file into our project page.
- locate a free “data url maker” on the web, such as:
- upload your image file
- copy the resulting Data URI text — which looks like: “data:image/jpeg;base64…”
- paste it into a new text document
- use javascript to create an image element from the Data URI:
var grass = new Image(); grass.src = "data:image/jpeg;base64...";
- save the document in your project folder somewhere: “images/grassData.js”
- link to that external javascript file in the <head> of your project page:
http://images/grassData.js
- create a new Three.js texture using that image element:
var grassTexture = new THREE.Texture(grass); grassTexture.wrapS = THREE.RepeatWrapping; grassTexture.wrapT = THREE.RepeatWrapping; grassTexture.repeat.x = grassTexture.repeat.y = 32; grassTexture.needsUpdate = true;
- add the texture to a mesh:
var terrain = new THREE.Mesh( new THREE.PlaneGeometry(x,y,x*res,y*res), new THREE.MeshLambertMaterial({ map: grassTexture }); );
…and you’re done. No error. 🙂
Note that this is not intended as a permanent solution to the ‘problem’. It’s a quick hack to save you some time. When you deploy your website you want to make sure you’re loading images into textures the normal way to take advantage of caching and smaller file sizes.
Also note that some browsers have rather small limits (32k-ish) on the size of Data URIs, but Chrome/Safari don’t seem to care how large it is. My grass data was 2.3MB in size and loaded without a hitch. Just something to look out for if you’re using one of the other browsers.
Enjoy!
Thank you you saved my life with this code lol
Here is a better site for base64 encoding : http://websemantics.co.uk/online_tools/image_to_data_uri_convertor/
Bye, and thx
Awesome post! Thanks so much 🙂
That converter has a 32kB limit but if your image is only small it will work just fine as well. I’m glad you liked the hack.
You’re welcome.
very helpful tip, thanks so much
No worries!