Question

I am having an array of images which are stored on the server and I want base64 data of all the images.

What I have tried:

function getBase64Image(img) {
  var canvas = document.createElement("canvas");
  canvas.width = img.width;
  canvas.height = img.height;
  var ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0);
  return canvas.toDataURL("image/png");
}
var images = ['images/1.png', 'images/2.png', 'images/3.png', 'images/4.png', 'images/5.png'];
for (var i = 0; i < images.length; i++) {
  var img = new Image();
  img.src = images[i];
  img.onload = function() {
    var newData = getBase64Image(img);
    document.body.innerHTML += "<img src='" + newData + "'>";
  }
}

I know as the onload event is getting fired later once image is loaded but could not figure out the solution.

Was it helpful?

Solution 2

As the onload event is synchronous(handler is invoked once image is loaded/cached) in nature, need to use closure to access current(in a loop) image.

function getBase64Image(img) {
  var canvas = document.createElement("canvas");
  canvas.width = img.width;
  canvas.height = img.height;
  var ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0);
  return canvas.toDataURL("image/png");
}
var images = ['images/1.png', 'images/2.png', 'images/3.png', 'images/4.png', 'images/5.png'];
var tpArray = [];
for (var i = 0; i < images.length; i++) {
  var img = new Image();
  (function(img) {
    img.onload = function() {
      document.body.innerHTML += '<img src="' + getBase64Image(img) + '">';
    };
  })(img);
  img.src = images[i];
}

If order of the images in array is to be maintained, a callback will be required in onload-handler which will make sure that next index from array will be accessed once current images is processed.

function getBase64Image(img) {
  var canvas = document.createElement("canvas");
  canvas.width = img.width;
  canvas.height = img.height;
  var ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0);
  return canvas.toDataURL("image/png");
}
var images = ['images/1.png', 'images/2.png', 'images/3.png', 'images/4.png', 'images/5.png'];

function getBaseInOrder(array, callback) {
  var index = 0;
  var resArr = [];
  var getBaseOfImg = function(imgSrc) {
    var img = new Image();
    img.src = imgSrc;
    img.onload = (function(img) {
      return function() {
        var newData = getBase64Image(img);
        document.body.innerHTML += "<img src='" + newData + "' data-src='" + img.src + "'>";
        resArr.push(newData);
        ++index;
        if (index == array.length) {
          callback(resArr);
        } else {
          getBaseOfImg(array[index]);
        }
      }
    })(img);
  };
  getBaseOfImg(array[index]);
}
getBaseInOrder(images, function(baseData) {
  console.log(baseData);
});

OTHER TIPS

Take a look at 3 points (had a lot of headache few months ago with img.onload):

  • first to be sure that onload will work You should set the src to an image after the event is assigned

  • second - you'll have to add the random get parameter to image path. something like

    img.src = images[i] + '?' + Date.now();

  • and third - if this will not help, try to insert the original image to the browser (to be sure browser will load it)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top