title: 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported
body: <p>In Chrome I get the following error on jsfiddle when trying to test canvas drawing images from a remote url.</p>
  <p><strong>Error:</strong> Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.</p>
  <p><strong>On S3 bucket I have the following CORS policy, which allows for cross resource sharing:</strong></p>
  <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
  &lt;CORSConfiguration xmlns=&quot;http://s3.amazonaws.com/doc/2006-03-01/&quot;&gt;
  &lt;CORSRule&gt;
      &lt;AllowedOrigin&gt;*&lt;/AllowedOrigin&gt;
      &lt;AllowedMethod&gt;GET&lt;/AllowedMethod&gt;
  &lt;/CORSRule&gt;
  &lt;/CORSConfiguration&gt;
  </code></pre>
  <p><strong>If I curl the image using jsfiddle as the origin I get:</strong></p>
  <pre><code>curl -H 'Origin: https://fiddle.jshell.net' -I 'https://i.ezr.io/products3/472_ARDSCR.jpg?h=45&amp;w=165&amp;fit=scale'
  HTTP/1.1 200 OK
  Cache-Control: public,max-age=31536000
  Last-Modified: Wed, 07 Feb 2018 23:42:47 GMT
  Server: imgix-fe
  Content-Length: 6371
  Accept-Ranges: bytes
  Date: Fri, 16 Mar 2018 17:10:20 GMT
  Age: 3173253
  Connection: keep-alive
  Content-Type: image/jpeg
  Access-Control-Allow-Origin: *
  X-Content-Type-Options: nosniff
  X-Served-By: cache-lax8630-LAX, cache-sea1027-SEA
  X-Cache: HIT, HIT
  </code></pre>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var Rack = {
    init: function(params) {
      Rack.conf = params;
      Rack.bindEvents();
    },
    bindEvents: function() {
      Rack.conf.scaleDown.addEventListener("click", function() {
        Rack.clearCanvas();
        Rack.conf.scaleW = Rack.round(Rack.conf.scaleW - .1, 1);
        Rack.conf.scaleY = Rack.round(Rack.conf.scaleY - .1, 1);
  
        if (Rack.conf.scaleW &gt; 0 &amp;&amp; Rack.conf.scaleY &gt; 0) {
          Rack.build();
        }
      });
  
      Rack.conf.resetScale.addEventListener("click", function() {
        Rack.clearCanvas();
        Rack.conf.scaleW = 1;
        Rack.conf.scaleY = 1;
        Rack.build(true);
      });
  
      Rack.getRackJSON();
      Rack.setNumImages();
      Rack.build();
    },
    getRackJSON: function() { // will send ajax call based on item being added to the rack, will return json rack
      Rack.conf.rack = {
        "awards": [{
            "src": "https://i.ezr.io/products3/472_ARDSCR.jpg?h=45&amp;w=165&amp;fit=scale",
            "name": "Army Distinguished Service Cross",
            "sku": "472_ARDSCR",
            "x": 0,
            "y": 0,
            "width": 165,
            "height": 45,
            "attachments": [{
              "src": "https://i.ezr.io/products3/913NP.png?h=20",
              "name": "Bronze Oak Leaf",
              "sku": "913NP",
              "x": 73,
              "y": 13,
              "width": 20,
              "height": 20
            }]
          },
          {
            "src": "https://i.ezr.io/products3/470_ARDDR.jpg?h=45&amp;w=165&amp;fit=scale",
            "name": "Department of Defense Distinguished Service",
            "sku": "470_ARDDR",
            "x": 165,
            "y": 0,
            "width": 165,
            "height": 45
          }
        ]
      };
    },
    setNumImages() {
      for (var i = 0; i &lt; Rack.conf.rack.awards.length; i++) {
        var award = Rack.conf.rack.awards[i];
  
        ++Rack.conf.numImages;
  
        if (award.hasOwnProperty('attachments')) {
          Rack.conf.numImages += award.attachments.length;
        }
      }
    },
    loadImages: function(callback) {
      var numImagesLoaded = 0;
  
      for (var i = 0; i &lt; Rack.conf.rack.awards.length; i++) {
        var award = Rack.conf.rack.awards[i];
  
        Rack.conf.images[award.sku] = new Image();
        Rack.conf.images[award.sku].onload = function() {
          if (++numImagesLoaded &gt;= Rack.conf.numImages) {
            callback();
          }
        }
        Rack.conf.images[award.sku].src = award.src;
  
        if (award.hasOwnProperty('attachments')) {
          for (var j = 0; j &lt; award.attachments.length; j++) {
            var attachment = award.attachments[j];
  
            Rack.conf.images[attachment.sku] = new Image();
            Rack.conf.images[attachment.sku].crossOrigin = 'anonymous';
            Rack.conf.images[attachment.sku].onload = function() {
              if (++numImagesLoaded &gt;= Rack.conf.numImages) {
                callback();
              }
            }
            Rack.conf.images[attachment.sku].src = attachment.src;
          }
        }
      }
    },
    build: function(reset) {
      if (Rack.conf.outputType === 'jpg') {
        Rack.conf.ctx.fillStyle = "#ffffff";
        Rack.conf.ctx.fillRect(0, 0, Rack.conf.c.width, Rack.conf.c.height);
      }
  
      reset === true ? Rack.conf.ctx.setTransform(1, 0, 0, 1, 0, 0) : Rack.conf.ctx.scale(Rack.conf.scaleW, Rack.conf.scaleY);
  
      Rack.loadImages(function() {
        for (var i = 0; i &lt; Rack.conf.rack.awards.length; i++) {
          var award = Rack.conf.rack.awards[i];
  
          Rack.conf.ctx.drawImage(Rack.conf.images[award.sku], award.x, award.y, award.width, award.height);
  
          if (award.hasOwnProperty('attachments')) {
            for (var j = 0; j &lt; award.attachments.length; j++) {
              var attachment = award.attachments[j];
  
              Rack.conf.ctx.drawImage(Rack.conf.images[attachment.sku], attachment.x, attachment.y, attachment.width, attachment.height);
            }
          }
        }
      });
  
      Rack.conf.imageData = Rack.conf.c.toDataURL((Rack.conf.outputType === 'jpg' ? 'image/jpeg' : null), (Rack.conf.outputType === 'jpg' ? 1.0 : null));
    },
    clearCanvas: function() {
      Rack.conf.ctx.clearRect(0, 0, Rack.conf.c.width, Rack.conf.c.height);
    },
    round: function(number, precision) {
      var factor = Math.pow(10, precision);
      var tempNumber = number * factor;
      var roundedTempNumber = Math.round(tempNumber);
      return roundedTempNumber / factor;
    }
  };
  
  Rack.init({
    c: document.getElementById("myCanvas"),
    ctx: document.getElementById("myCanvas").getContext("2d"),
    outputType: 'png',
    scaleDown: document.getElementById('scale-down'),
    resetScale: document.getElementById('reset-scale'),
    images: {},
    numImages: 0,
    awards: null,
    imageData: null,
    scaleW: 1,
    scaleY: 1,
    rack: null
  });</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;canvas id="myCanvas" width="330" height="45"&gt;Your browser does not support the HTML5 canvas tag.&lt;/canvas&gt;
  &lt;div&gt;
    &lt;button id="scale-down" style="cursor:pointer;"&gt;
          Scale Down
      &lt;/button&gt;
    &lt;button id="reset-scale" style="cursor:pointer;"&gt;
          Reset
      &lt;/button&gt;
  &lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>