docs: function generate(files, options, callback) {
    files = Array.isArray(files) ? files : glob.sync(files);
    if (files.length == 0) return callback(new Error('no files specified'));
  
    options = options || {};
    if (Array.isArray(options.format)) {
      options.format = options.format.map(function(x){return FORMATS[x]});
    }
    else if (options.format || !options.customFormat) {
      options.format = [FORMATS[options.format] || FORMATS['json']];
    }
    options.name = options.name || 'spritesheet';
    options.spritesheetName = options.name;
    options.path = path.resolve(options.path || '.');
    options.fullpath = options.hasOwnProperty('fullpath') ? options.fullpath : false;
    options.square = options.hasOwnProperty('square') ? options.square : false;
    options.powerOfTwo = options.hasOwnProperty('powerOfTwo') ? options.powerOfTwo : false;
    options.extension = options.hasOwnProperty('extension') ? options.extension : options.format[0].extension;
    options.trim = options.hasOwnProperty('trim') ? options.trim : options.format[0].trim;
    options.algorithm = options.hasOwnProperty('algorithm') ? options.algorithm : 'growing-binpacking';
    options.sort = options.hasOwnProperty('sort') ? options.sort : 'maxside';
    options.padding = options.hasOwnProperty('padding') ? parseInt(options.padding, 10) : 0;
    options.prefix = options.hasOwnProperty('prefix') ? options.prefix : '';
    options.divisibleByTwo = options.hasOwnProperty('divisibleByTwo') ? options.divisibleByTwo : false;
    options.cssOrder = options.hasOwnProperty('cssOrder') ? options.cssOrder : null;
  
    files = files.map(function (item, index) {
      var resolvedItem = path.resolve(item);
      var name = "";
      if (options.fullpath) {
        name = item.substring(0, item.lastIndexOf("."));
      }
      else {
        name = options.prefix + resolvedItem.substring(resolvedItem.lastIndexOf(path.sep) + 1, resolvedItem.lastIndexOf('.'));
      }
      return {
        index: index,
        path: resolvedItem,
        name: name,
        extension: path.extname(resolvedItem)
      };
    });
  
  
    if (!fs.existsSync(options.path) && options.path !== '') fs.mkdirSync(options.path);
  
    async.waterfall([
      function (callback) {
        generator.trimImages(files, options, callback);
      },
      function (callback) {
        generator.getImagesSizes(files, options, callback);
      },
      function (files, callback) {
        generator.determineCanvasSize(files, options, callback);
      },
      function (options, callback) {
        generator.generateImage(files, options, callback);
      },
      function (callback) {
        generator.generateData(files, options, callback);
      }
    ],
      callback);
  }