publiclab/image-sequencer

View on GitHub
src/ReplaceImage.js

Summary

Maintainability
B
4 hrs
Test Coverage
// Uses a given image as input and replaces it with the output.
// Works only in the browser.
function ReplaceImage(ref, selector, steps, options) {
  if(!ref.options.inBrowser) return false; // This isn't for Node.js
  var tempSequencer = ImageSequencer({ui: false});
  var this_ = ref;
  if (window.hasOwnProperty('$')) var input = $(selector);
  else var input = document.querySelectorAll(selector);
  var images = [];
  for (var i = 0; i < input.length; i++) {
    if (input[i] instanceof HTMLImageElement) images.push(input[i]);
  }

  function replaceImage (img, steps) {
    var url = img.src;
    // refactor to filetypeFromUrl()
    var ext = url.split('?')[0].split('.').pop();

    var xmlHTTP = new XMLHttpRequest();
    xmlHTTP.open('GET', url, true);
    xmlHTTP.responseType = 'arraybuffer';
    xmlHTTP.onload = function(e) {
      var arr = new Uint8Array(this.response);

      // in chunks to avoid "RangeError: Maximum call stack exceeded"
      // https://github.com/publiclab/image-sequencer/issues/241
      // https://stackoverflow.com/a/20048852/1116657
      var raw = '';
      var i, j, subArray, chunk = 5000;
      for (i = 0, j = arr.length; i < j; i += chunk) {
        subArray = arr.subarray(i, i + chunk);
        raw += String.fromCharCode.apply(null, subArray);
      }

      var base64 = btoa(raw);
      var dataURL = 'data:image/' + ext + ';base64,' + base64;
      make(dataURL);
    };

    if(url.substr(0, 11).toLowerCase() != 'data:image/') xmlHTTP.send();
    else make(url);

    function make(url) {
      tempSequencer.loadImage(url, function(){
        // this.addSteps(steps).run({stop:function(){}},function(out){
        var sequence = this.addSteps(steps);
        if (ref.detectStringSyntax(steps))
          sequence = this.stringToSteps(steps);
        sequence.run({stop:function(){}}, function(out){
          img.src = out;
        });
      });
    }
  }

  for (var i = 0; i < images.length; i++) {
    replaceImage(images[i], steps);
    if (i == images.length - 1)
      options.callback();
  }
}

module.exports = ReplaceImage;