merge-images icon indicating copy to clipboard operation
merge-images copied to clipboard

DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

Open dcts opened this issue 2 years ago • 4 comments

I wanted to test merging images inside the browser with this code:

index.html

<h1>Testing MergeImages</h1>
<script src="https://unpkg.com/merge-images"></script>
<script>
  window.addEventListener("DOMContentLoaded", () => {
    console.log("Dom + mergeImages loaded ✅");
    console.log(mergeImages);

    const images = [
      "https://firebasestorage.googleapis.com/v0/b/homeboard-5d28b.appspot.com/o/smiles.wtf.testing%2F0_bg.png?alt=media&token=53eb4b7e-73b7-419b-83c0-32b4d6810e46",
      "https://firebasestorage.googleapis.com/v0/b/homeboard-5d28b.appspot.com/o/smiles.wtf.testing%2F1_body.png?alt=media&token=7c9e7214-fa87-40d5-a4ad-686a66ee3511",
      "https://firebasestorage.googleapis.com/v0/b/homeboard-5d28b.appspot.com/o/smiles.wtf.testing%2F2_face.png?alt=media&token=8c728305-664b-4435-8b41-1c7b01530265",
    ];

    mergeImages(images).then(b64 => console.log(b64));
  })
</script>

But I get this error:

DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

My environment:

Did I use the repo wrong or is this a bug? Thanks for any help! :)

dcts avatar Feb 28 '22 19:02 dcts

Hi Have you solved this problem yet?

melearntodie avatar Apr 05 '22 08:04 melearntodie

melearntodie no, this library seems not really up to date.

I used another method to merge images (with vanilla javascript and canvas operations), maybe its usefull to you?

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Merge Images</title>
</head>

<body>
  <h1>Merge Images</h1>
  <canvas id="canvas" width="600" height="600"></canvas>
</body>
</html>


<script>
  let imagesLoaded = 0;
  let canvas, ctx;
  let images;

  // add images you want to overlay
  const imageUrls = [
    "https://firebasestorage.googleapis.com/v0/b/homeboard-5d28b.appspot.com/o/smiles.wtf.testing%2F0_bg.png?alt=media&token=53eb4b7e-73b7-419b-83c0-32b4d6810e46",
    "https://firebasestorage.googleapis.com/v0/b/homeboard-5d28b.appspot.com/o/smiles.wtf.testing%2F1_body.png?alt=media&token=7c9e7214-fa87-40d5-a4ad-686a66ee3511",
    "https://firebasestorage.googleapis.com/v0/b/homeboard-5d28b.appspot.com/o/smiles.wtf.testing%2F2_face.png?alt=media&token=8c728305-664b-4435-8b41-1c7b01530265",
  ];

  document.addEventListener("DOMContentLoaded",() => {
    console.log("DOM LOADED");
    canvas = document.getElementById("canvas");
    ctx = canvas.getContext("2d");
    images = imageUrls.map(imageUrl => loadImage(imageUrl, drawCanvas))
  });

  function drawCanvas() {
    imagesLoaded += 1;
    if (imagesLoaded === images.length) {
      images.map(image => {
        ctx.drawImage(image, 0, 0, 600, 600);
      })
    }
  }

  function loadImage(src, onload) {
    const img = new Image();
    img.onload = onload;
    img.src = src;
    return img;
  }
</script>

Result

Bildschirmfoto vom 2022-04-05 11-01-19

dcts avatar Apr 05 '22 09:04 dcts

melearntodie no, this library seems not really up to date.

I used another method to merge images (with vanilla javascript and canvas operations), maybe its usefull to you?

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Merge Images</title>
</head>

<body>
  <h1>Merge Images</h1>
  <canvas id="canvas" width="600" height="600"></canvas>
</body>
</html>


<script>
  let imagesLoaded = 0;
  let canvas, ctx;
  let images;

  // add images you want to overlay
  const imageUrls = [
    "https://firebasestorage.googleapis.com/v0/b/homeboard-5d28b.appspot.com/o/smiles.wtf.testing%2F0_bg.png?alt=media&token=53eb4b7e-73b7-419b-83c0-32b4d6810e46",
    "https://firebasestorage.googleapis.com/v0/b/homeboard-5d28b.appspot.com/o/smiles.wtf.testing%2F1_body.png?alt=media&token=7c9e7214-fa87-40d5-a4ad-686a66ee3511",
    "https://firebasestorage.googleapis.com/v0/b/homeboard-5d28b.appspot.com/o/smiles.wtf.testing%2F2_face.png?alt=media&token=8c728305-664b-4435-8b41-1c7b01530265",
  ];

  document.addEventListener("DOMContentLoaded",() => {
    console.log("DOM LOADED");
    canvas = document.getElementById("canvas");
    ctx = canvas.getContext("2d");
    images = imageUrls.map(imageUrl => loadImage(imageUrl, drawCanvas))
  });

  function drawCanvas() {
    imagesLoaded += 1;
    if (imagesLoaded === images.length) {
      images.map(image => {
        ctx.drawImage(image, 0, 0, 600, 600);
      })
    }
  }

  function loadImage(src, onload) {
    const img = new Image();
    img.onload = onload;
    img.src = src;
    return img;
  }
</script>

Result

Bildschirmfoto vom 2022-04-05 11-01-19

cool good solution . thank for shared

melearntodie avatar Apr 10 '22 07:04 melearntodie

I think you have to add crossorigin param to the method because the images are from other domain:

        mergeImages(toMerge, {
            [...]
            crossOrigin: "Anonymous"
          })

See also: https://github.com/lukechilds/merge-images#optionscrossorigin

stritti avatar Aug 08 '22 09:08 stritti