0

Help! I'm trying to combine images using canvas but the output always comes out as a blank box. I can't figure out what is going wrong, my code is below:

const Canvas = require('canvas');

const theLayers=['https://raw.githubusercontent.com/Iceee1000/SpaceVizsla/main/MediaAssets/pixelVizsla/testing_01.png',
'https://raw.githubusercontent.com/Iceee1000/SpaceVizsla/main/MediaAssets/pixelVizsla/B_02.png',
'https://raw.githubusercontent.com/Iceee1000/SpaceVizsla/main/MediaAssets/pixelVizsla/testing_02.png'];

//not-working function to combine multiple layers of images from the web.
const CombineLayers = async(layers) => {
  console.log('combining layers')

  let canvas=Canvas.createCanvas(250, 250);
  let context=canvas.getContext('2d');

  for (let layer of layers){ 
    
    var img = new Image();
    img.origin = 'anonymous';
    img.src = layer;
    img.onload = function(){
      context.drawImage(img, 0, 0, 250, 250);
    }
    
}

  return canvas.toDataURL("image/png");
};


const dothings=async()=>{
  const result= await CombineLayers(theLayers);
  console.log(result);
}
dothings();
Iceee
  • 31
  • 1
  • 4
  • What do you mean by "combine images" exactly? `drawImage` overwrites the existing canvas. – ggorlen Apr 12 '22 at 18:13
  • using "drawImage" to combine the images by drawing one on top of the other. Solved below. – Iceee Apr 12 '22 at 18:40
  • Thanks for the self-answer. You can load from a URL without axios, but you'll need to await the onloads with promises (or, less ideally, chain callbacks) before running `canvas.toDataURL("image/png")`. See [Loading images before rendering JS canvas](https://stackoverflow.com/questions/61336830/loading-images-before-rendering-js-canvas/61337279#61337279) – ggorlen Apr 12 '22 at 19:03

1 Answers1

0

Solved my issue: Can not just image data directly from a URL, I needed to load/buffer it first. Solved below with axios:

const Canvas = require('canvas');
const axios = require('axios')

function getBase64(url) {
  return axios
    .get(url, {
      responseType: 'arraybuffer'
    })
    .then(response => Buffer.from(response.data, 'binary').toString('base64'))
}

const theLayers=['https://imageURL.png',
'https://imageURL.png',
'https://imageURL.png'];

const CombineLayers = async(layers) => {
  console.log('combining layers')

  let canvas=Canvas.createCanvas(250, 250);
  let context=canvas.getContext('2d');

  for (let layer of layers){ 

    const data = await getBase64(layer);
    let datastring='data:image/png;base64,'+data
    const img = await Canvas.loadImage(datastring);
    context.drawImage(img, 0, 0, 250, 250);
    
    
}

  return canvas.toDataURL("image/png");
};


const dothings=async()=>{
  const result= await CombineLayers(theLayers);
  console.log(result);
}
dothings();
Iceee
  • 31
  • 1
  • 4