P5.js: Issues with CORS in image

Created on 4 Mar 2019  Â·  4Comments  Â·  Source: processing/p5.js

Nature of issue?

  • [x] Existing feature enhancement

Most appropriate sub-area of p5.js?

  • [x] Image
  • [x] Other (specify if possible) - DOM

Which platform were you using when you encountered this?

  • [x] Desktop/Laptop

Details about the bug:

  • p5.js version: 0.7.3
  • Web browser and version: All browsers
  • Operating System: All OS
  • Steps to reproduce this:
let a, b, c, d, canvas;
function setup() {
 a = createImg("https://i.imgur.com/Jvh1OQm.jpg");
 b = loadImage("https://i.imgur.com/Jvh1OQm.jpg");
 c = loadImage("Jvh1OQm.jpg");
 d = createImg("Jvh1OQm.jpg");
 canvas = createCanvas(400, 400);
}

function draw() {
image(a, 0, 0, 400, 400);
image(b, 0, 0, 200, 200);

}
function keyPressed()
{
  let pixel = canvas.get(10,10, 1, 1);
  console.log(pixel);

}
function mousePressed()
{
    saveCanvas('image_cors', canvas, 'jpg');
}

Feature enhancement details:

  • The current implementation of cross origin in p5.dom.js is always setting ,
    img.crossOrigin = 'Anonymous';
    This can result in two Http requests, even in the case where the image is in the same domain, leading to potential slowdown. This article can be referred to for this issue : https://webglfundamentals.org/webgl/lessons/webgl-cors-permission.html

  • One more issue is that , when we are setting up the crossOrigin parameter for every image, in
    createImg function, the domain from which we are requesting the image , can stop sending us the image, even if it can be used outside the canvas. Since images created by createImg function are not always used inside the canvas, this implementation can block images, which can be rendered inside the img tag, but not inside the canvas, from rendering in the img tag also. So I think we should set this attribute only for images to be used in the canvas, but I am not sure about the implementation (maybe image function can be modified to check for the attribute ? )

( This issue is a follow up to #3482, as a discussion )

image

All 4 comments

my 2 cents considering browser security restrictions, not sure what will be the best hack for this problem.
what i found in image/loading_displaying.js

 * The path to the image should be relative to the HTML file
 * that links in your sketch. Loading an image from a URL or other
 * remote location may be blocked due to your browser's built-in
 * security.

also i see a link to mdn https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image
with below code snippet. but as you can see in this highlighted section they suggest the solution works only if you had control of the host serving the images as well.

 if (path.indexOf('data:image/') !== 0) {
    img.crossOrigin = 'Anonymous';
  }

  // start loading the image
  img.src = path;

  return pImg;
};

@salus-sage Thank you very much for your suggestions !
I agree that CORS is not guaranteed to work if we are attempting to load images from a host not in our control.
Some more observations I was able to make are :

  • You can still use most of the CORS blocked images (such as loading and drawing on the canvas) if you do not specify the crossOrigin header. But in these cases the canvas is 'tainted' and we cannot get pixel data, or download the canvas .
  • If we use CORS for every image, there is no chance of getting the browser tainted , but it blocks a majority of the images which can still be used for non canvas purposes , or cases where you don't download or need the pixel data.

It would be great if we can establish a balance between these two conditions, while maintaining the ease of use for the users.

Regarding the first point, these concerns are in fact largely unfounded, i.e. you won't observe the hypothesized additional round trip if you try and monitor your HTTP traffic using Charles, Fiddler or Wireshark. By saying "_asking for permission takes 2 HTTP requests so it's slower than not asking_", the author suggests that setting the crossOrigin attribute to 'anonymous' would trigger a preflight request which precedes the actual CORS request we're sending. While that could be true of some cross-origin AJAX requests constructed using the Fetch API or XMLHttpRequest, the CORS requests we are dealing with here fall into the category of "simple requests" and thus are not preflighted.

  • If we use CORS for every image, there is no chance of getting the browser tainted , but it blocks a majority of the images which can still be used for non canvas purposes , or cases where you don't download or need the pixel data.

I agree with you here, and this is the real issue – we should always provide a reasonable default. The current implementation of createImg() is seriously flawed because it will simply fail on the vast majority of images on the Web as they don't come with an Access-Control-Allow-Origin response header. On the other hand, without any hints from the user, there is no way we can tell ahead of time whether the image is intended to be used with canvas. Therefore, I propose that we

  • undo 6ed05304fe2da3eef00ab04a0db7d285843aad17, so that we do not use CORS by default, and
  • do one of the following to resolve #3463:

    • add a [crossOrigin] parameter to createImg(), enabling the user to opt for a CORS reuquest explicitly

    • add a crossOriginMode() function that sets a global state, making it more in line with existing APIs like colorMode(), angleMode() and imageMode()

However,one caveat with crossOriginMode() though is that people might mistakenly expect it to affect loadImage() as well, so I'd rather go with the additional parameter. Having said that, I'd still love to hear your thoughts on this, @Ajayneethikannan, @outofambit, @lmccart. It wouldn't take long for me to implement the proposed changes once we have reached a rough consensus.

Was this page helpful?
0 / 5 - 0 ratings