Esempio n. 1
0
        handler: function (request, reply) {
            var fileInfo = request.payload.userPhoto;
            var extension = ".jpg";
            var personId = request.params.id;
            switch (fileInfo.headers['content-type']) {
                case 'image/png':
                    extension = '.png';
                    break;
                case "image/jpeg":
                case 'image/jpg':
                default:
                    extension = '.jpg';
                    break;
            }

            var gm = gma.subClass({ imageMagick: true });
            gm(fileInfo.path).size(function (err, value) {
                if (err || !value) {
                    console.log("Error getting image size", err, value);
                    return reply(err);
                }
                var width = Math.min(value.width, value.height);
                var resizeAndSave = function (path, size, outPath, callback) {
                    gm(path)
                        .resize(size, size)
                        .stream(function (err, stdout, stderr) {
                            var writeStream = Fs.createWriteStream(outPath);
                            stdout.pipe(writeStream)
                                .on('close', function () {
                                    callback();
                                });
                        });
                }

                gm(fileInfo.path).crop(width, width, (value.width - width) / 2, (value.height - width) / 2)
                    .stream(function (err, stdout, stderr) {
                        var cropName = uploadFolder + personId + "_crop" + extension;
                        var writeStream = Fs.createWriteStream(cropName);
                        stdout.pipe(writeStream)
                            .on('close', function () {
                                async.parallel([
                                    function (cb) {
                                        resizeAndSave(cropName, Math.min(600, width), uploadFolder + personId + '_large' + extension, cb);
                                    },
                                    function (cb) {
                                        resizeAndSave(cropName, Math.min(300, width), uploadFolder + personId + '_medium' + extension, cb);
                                    },
                                    function (cb) {
                                        resizeAndSave(cropName, Math.min(150, width), uploadFolder + personId + '_small' + extension, cb);
                                    }
                                ], function (err) {
                                    Fs.unlink(cropName);
                                    Fs.unlink(fileInfo.path);
                                    People.update({id: personId, hasPhoto: true}, function (err, person) {
                                        reply();
                                    })
                                });
                            });
                    });

            })
        }
Esempio n. 2
0
var fs=require('fs');
var images=require('gm');
var gm=images.subClass({imageMagick:true});

module.exports=exports=function(path){
  var apath=path.split('/');
  var name=apath.pop();
  var dir=apath.join('/');
  gm(path).resize(null,300).write(dir+'/small-'+name,function(err){
    if(err)console.log(err);
  });
}
Esempio n. 3
0
function getGm() {
  return gmExists? _gm : _gm.subClass({ imageMagick: true });
}
    var imageInfoTask = function() {
        var options = this.options({
                mapSrcToName: function(src) {
                    var fullname = path.basename(src);
                    var nameParts = fullname.split('.');

                    // If there is are more than 2 parts, pop the last one
                    if (nameParts.length >= 2) {
                        nameParts.pop();
                    }
                    return nameParts.join('.');
                },
                mapSrcToUrl: function(src) {
                    return src;
                }
            }),
            srcFiles = this.filesSrc,
            cssTemplate = options.cssTemplate,
            cssVarMap = options.cssVarMap || function noop () {},
            that = this;
        var gmInstance = options.imageMagick ? gm.subClass({ imageMagick: true }) : gm;


        // Verify all properties are here
        if (this.files.length === 0) {
            return grunt.fatal("this task requires 'files'");
        }

        // Create an async callback
        var done = this.async();


        var processFile = function(file, callback) {
            if (!file.dest || file.src.length === 0) {
                callback("missing 'dest' or 'src'");
                return;
            }

            var cleanCoords = [];
            var processSrc = function(src, callback) {
                // obtain the size of an image
                gmInstance(src).size(function(err, size) {
                    if (err) {
                        callback(err);
                        return;
                    }
                    var coords = {
                        name: options.mapSrcToName(src),
                        image: options.mapSrcToUrl(src),
                        x: 0,
                        y: 0,
                        offset_x: 0,
                        offset_y: 0,
                        width: size.width,
                        height: size.height,
                        total_width: size.width,
                        total_height: size.height,
                    };

                    cleanCoords.push(coords);

                    callback();
                });
            };
            
            // Hitting spawn EMFILE without this.
            var maxGmConcurrency = 10;

            async.eachLimit(file.src, maxGmConcurrency, processSrc, function(err) {
                if (err) {
                    callback(err);
                }

                var cssFormat = 'spritesmith-custom';
                var cssOptions = options.cssOpts || {};

                // If there's a custom template, use it
                if (cssTemplate) {
                    json2css.addMustacheTemplate(cssFormat, fs.readFileSync(cssTemplate, 'utf8'));
                } else {
                    // Otherwise, override the cssFormat and fallback to 'json'
                    cssFormat = options.cssFormat || cssFormats.get(file.dest) || 'json';
                }

                cleanCoords[cleanCoords.length - 1].last = true;

                cleanCoords.sort(function(a, b) {
                    var x = a['name'];
                    var y = b['name'];
                    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
                });

                // Render the variables via json2css
                var cssStr = json2css(cleanCoords, {'format': cssFormat, 'formatOpts': cssOptions});

                // Write it out to the CSS file
                var destCSSDir = path.dirname(file.dest);
                grunt.file.mkdir(destCSSDir);
                fs.writeFileSync(file.dest, cssStr, 'utf8');

                // Fail task if errors were logged.
                if (that.errorCount) { callback('error count ' + that.errorCount); }

                grunt.verbose.writeln('File "' + file.dest + '" created.');
                callback();
            });
        };

        async.each(this.files, processFile, function(err) {
            if (err) {
                grunt.fatal(err);
                done(false);
            }

            done(true);
        });
    };
  grunt.registerMultiTask('base64Less', 'Base64 encode files. Into less file format.', function() {
    var data = this.data,
    done = this.async(),
    cwd = './',
    filesToProcess = grunt.file.expand({cwd: cwd},data.process);
    
    output = "";

    if(!data.prefix){
	data.prefix = "";
    }

    if(!data.dest){
	grunt.warn("dest needs to be set.");
        return false;
    }
    
    if(data.resize && data.resize.imageMagick){
    	    gm = gm.subClass({ imageMagick: true });
    }

    if(!filesToProcess.length){
	grunt.log.writeln("Nothing to process in "+data.process);
	done();
    }else{
	grunt.log.writeln("Processing  "+filesToProcess.length+" files...");
	for(var i = 0; i < filesToProcess.length; i++){
		var lessFileName = filesToProcess[i].substring(filesToProcess[i].lastIndexOf("/")+1),
		    lessSafeFileName = lessFileName.replace(".","_"),
		    fileName = filesToProcess[i];
		if(data.resize){
			var dimensions = sizer(fileName);
			function doneCallback(error){
				pending.push(lessSafeFileName);
				errorResize(error,data.prefix,lessSafeFileName,fileName,data.dimensions);
			}
			if(data.resize.width && !data.resize.height){
				if(dimensions.width !== data.resize.width){
					gm(fileName).resize(data.resize.width).write(fileName,doneCallback);
					grunt.log.writeln('Resizing file '+fileName+' to width '+data.resize.width);
				}else{
					output += create(data.prefix,lessSafeFileName,fileName,data.dimensions);
				}
			}else if(!data.resize.width && data.resize.height){
				if(dimensions.height !== data.resize.height){
					gm(fileName).resize(null,data.resize.height).write(fileName,doneCallback);
					grunt.log.writeln('Resizing file '+fileName+' to height '+data.resize.height);
				}else{
					output += create(data.prefix,lessSafeFileName,fileName,data.dimensions);
				}
			}else if(data.resize.width && data.resize.height){
				if(dimensions.width !== data.resize.width && dimensions.height !== data.resize.height){
					if(data.resize.force){
						gm(fileName).resize(data.resize.width,data.resize.height,"!").write(fileName,doneCallback);
					}else{
						gm(fileName).resize(data.resize.width,data.resize.height).write(fileName,doneCallback);
					}
					grunt.log.writeln('Resizing file '+fileName+' to width '+data.resize.width+' height '+data.resize.height+' force: '+data.resize.force);
				}else{
					output += create(data.prefix,lessSafeFileName,fileName,data.dimensions);
				}
			}
		}else{
			output += create(data.prefix,lessSafeFileName,fileName,data.dimensions);
		}
	}
	
	completeTimer = setInterval(function checkIfDone(){
		if(pending.length === 0){
			grunt.file.write(data.dest, output);	
			clearInterval(completeTimer);
			done();
		}
	}, 1000);

    }
  });
Esempio n. 6
0
var express = require('express'),
    fs = require('fs'),
    router = express.Router(),
    crypto = require('crypto'),
    moment = require("moment"),
    config = require("../server/config"),
    path = require('path'),
    gm = require('gm'),
    imageMagick = gm.subClass({ imageMagick : true });

/**
 * path:  /captcha/get
 * 获取验证码
 */
router.get('/get', function(req, res) {
    var staticPath = path.join(siteDir, 'public'),
        bg = "/captcha/",
        bgName = "bg.jpg",
        readPath = path.join(staticPath, bg, bgName),
        str = ['a','b','c','d','e','f','g','h','i','j','k','m','l','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'],
        code = str[Math.round(Math.random() * (str.length-1))];
        // width = req.query.width,
        // height = req.query.height;
    code += str[Math.round(Math.random() * (str.length-1))];
    code += str[Math.round(Math.random() * (str.length-1))];
    code += str[Math.round(Math.random() * (str.length-1))];
    // code += str[Math.round(Math.random() * (str.length-1))];

    // 绘制验证码图片
    var _img = imageMagick(readPath)
    /* 比较模糊的
import fs from 'fs-extra'
import gm from 'gm'
import path from 'path'
import { flow, map } from 'lodash/fp'
import data from '../data.js'

const im = gm.subClass({ imageMagick: true });

const outputPath = path.resolve(__dirname, '../Game/assets/')

const writeTitle = (entry) => {
  return new Promise((resolve, reject) => {

    const year = entry.period && entry.period[0] ? `(${entry.period[0]})` : ''

    im(800, 600)
      .background('none')
      .font('Press-Start-2P-Regular', 8)
      .fill('#fff')
      .out(`caption: ${entry.label} ${year}`)
      .trim()
      .write(`${outputPath}/title_${entry.id}.png`, function (err) {
        err ? Promise.reject(err) : Promise.resolve()
      })
  })
}

const writeTitles = flow(
  map(writeTitle),
)
Esempio n. 8
0
module.exports = function config(opts, callback) {
  opts = opts || {};

  // already done
  if (opts && opts.__cfg) {
    return callback(null, opts);
  }

  // convert negatives (already done by CLI, but not vor module)
  if (opts.noFix) {
    opts.fix = false;
    delete opts.noFix;
  }
  if (opts.noNine) {
    opts.nine = false;
    delete opts.noNine;
  }
  if (opts.noCrop) {
    opts.crop = false;
    delete opts.noCrop;
  }

  var cfg = _.extend({
    __cfg: true,

    type: undefined,
    cli: false,
    input: undefined,
    platforms: undefined,
    radius: 0,
    locale: undefined,
    minDpi: constants.dpi.mdpi,
    maxDpi: constants.dpi.xxhdpi,
    orientation: undefined,
    fix: true,
    nine: true,
    crop: true,
    label: false,
    outputDir: undefined,
    assetsDir: undefined,
    alloy: undefined,
    trace: false,
    inputWidth: undefined,
    inputHeight: undefined,
    inputRatio: undefined

  }, opts);

  // validate radius
  if (cfg.radius !== 0) {
    cfg.radius = parseInt(cfg.radius, 10);

    if (cfg.radius < 0 || cfg.radius > 50) {
      return callback('The `radius` percentage should be between 0 and 50.');
    }
  }

  var isProject = false,
    isWidget = false;

  // no outputDir given
  if (!cfg.outputDir) {

    isProject = fs.existsSync(path.join(process.cwd(), 'tiapp.xml'));
    isWidget = fs.existsSync(path.join(process.cwd(), 'widget.json'));

    // CWD is no project
    if (!isProject && !isWidget) {
      return callback('Either specify `outputDir` or run in a project root');
    }

    cfg.outputDir = process.cwd();
  }

  // detect Alloy
  if (cfg.alloy === undefined) {
    cfg.alloy = fs.existsSync(path.join(cfg.outputDir, 'app', 'config.json'));
  }

  // detect widget
  if (cfg.widget === undefined) {
    cfg.widget = isWidget;
  }

  if (cfg.widget && cfg.type !== 'asset') {
    return callback('You can only target a widget using the `assets` command.')
  }

  // set assetsDir
  if (!cfg.assetsDir) {
    if (cfg.widget) {
      cfg.assetsDir = 'assets';
    } else if (cfg.alloy) {
      cfg.assetsDir = path.join('app', 'assets');
    } else {
      cfg.assetsDir = 'Resources';
    }
  }

  // convert dpi constants
  if (cfg.minDpi && !_.isNumber(cfg.minDpi)) {
    cfg.minDpi = constants.dpi[cfg.minDpi] || undefined;
  }
  if (cfg.maxDpi && !_.isNumber(cfg.maxDpi)) {
    cfg.maxDpi = constants.dpi[cfg.maxDpi] || undefined;
  }

  // get platforms from widgets
  // widget.json
  if (isWidget) {
    try {

      var widgetjson = JSON.parse(fs.readFileSync(path.join(cfg.outputDir, 'widget.json')));
      if (_.isObject(widgetjson) && widgetjson.platforms) {
        cfg.platforms = widgetjson.platforms.split(',');
      }

    // no widget.json
    } catch (err) {}
  }


  var tiappxml, match;

  // no platforms
  if (!cfg.platforms) {
    var deploymentTargets = [];

    // tiapp.xml found
    try {

      // convert to string
      tiappxml = '' + fs.readFileSync(path.join(cfg.outputDir, 'tiapp.xml'));

      var re = /<target[^>]+device="([a-z]+)"[^>]*>true<\/target>/gi;

      // add each deployment target
      while ((match = re.exec(tiappxml)) !== null) {
        deploymentTargets.push(match[1]);
      }
    }

    // no tiapp.xml
    catch (err) {}

    // use deployment targets
    if (_.size(deploymentTargets) > 0) {
      cfg.platforms = deploymentTargets;
    }

    // use all
    else {
      cfg.platforms = _.clone(constants.platforms);
    }
  }

  // parse string
  else if (_.isString(cfg.platforms)) {

    // use all
    if (cfg.platforms === 'all') {
      cfg.platforms = _.clone(constants.platforms);
    }

    // split
    else {
      cfg.platforms = cfg.platforms.split(',');
    }
  }

  // convert platforms to short-hand flags
  _.each(constants.platforms, function(platform) {
    cfg[platform] = _.indexOf(cfg.platforms, platform) !== -1;
  });

  if (cfg.ios) {
    cfg.iphone = cfg.ipad = true;
  } else {
    cfg.ios = cfg.iphone || cfg.ipad;
  }


  // no orientation
  if (!cfg.orientation && cfg.type === 'splash') {
    var orientation;

    // tiapp.xml found
    try {

      // convert to string
      tiappxml = tiappxml || '' + fs.readFileSync(path.join(cfg.outputDir, 'tiapp.xml'));

      // mobileweb
      if (cfg.mobileweb) {

        // always mixed
        orientation = 'all';
      }

      // iphone
      if (cfg.iphone && orientation !== 'all') {

        // splash is always portrait on iphone
        orientation = 'portrait';
      }

      // ipad
      if (cfg.ipad && orientation !== 'all') {
        var landscape = !!tiappxml.match(/UISupportedInterfaceOrientations~ipad((?!~iphone)[\s\S])+UIInterfaceOrientationLandscape/);
        var portrait = !!tiappxml.match(/UISupportedInterfaceOrientations~ipad((?!~iphone)[\s\S])+UIInterfaceOrientationPortrait/);

        if (landscape != portrait) {
          orientation = landscape ? 'landscape' : 'portrait';
        } else {
          orientation = 'all';
        }
      }

      // android
      if (cfg.android && orientation !== 'all') {

        // main activity locked
        if ((match = tiappxml.match(/android:screenOrientation="(landscape|portrait)"((?!<activity)[\s\S])+android.intent.action.MAIN/))) {

          if (!orientation) {
            orientation = match[1];
          } else if (orientation !== match[1]) {
            orientation = 'all';
          }
        }
      }

      // blackberry
      if (cfg.blackberry && orientation !== 'all') {

        // locked
        if ((match = tiappxml.match(/<blackberry>[\s\S]*<orientation>(landscape|portrait)<\/orientation>[\s\S]*<\/blackberry>/))) {

          if (!orientation) {
            orientation = match[1];
          } else if (orientation !== match[1]) {
            orientation = 'all';
          }
        }
      }
    }

    // no tiapp.xml
    catch (err) {}

    // orientation locked for all platforms
    if (orientation && orientation !== 'all') {
      cfg.orientation = orientation;
    }
  }

  // all
  else if (cfg.orientation === 'all') {
    cfg.orientation = undefined;
  }

  // normalize input path - if any
  if (cfg.input) {
    try {
      cfg.input = fs.realpathSync(cfg.input);
    } catch (err) {
      return callback('could not find `input` path: ' + cfg.input);
    }
  }

  // no input
  if (cfg.type && !cfg.input) {
    var def;

    if (cfg.type === 'asset') {

      _.some([
        path.join(cfg.outputDir, cfg.assetsDir, 'iphone', 'images'),
        path.join(cfg.outputDir, cfg.assetsDir, 'android', 'images', 'res-xxxhdpi'),
        path.join(cfg.outputDir, cfg.assetsDir, 'android', 'images', 'res-xxhdpi')
      ], function(potentialDef) {

        if (fs.existsSync(potentialDef)) {
          def = potentialDef;
          return true;
        }

        return false;

      });

      if (!def) {
        return callback('missing required argument `input` or one of the default paths');
      }

    } else {
      var potentialDef = path.join(cfg.outputDir, cfg.assetsDir, 'iphone', (cfg.type === 'splash') ? 'Default-Portrait-736h@3x.png' : 'iTunesArtwork@2x');

      if (fs.existsSync(potentialDef)) {
        def = potentialDef;
      } else {
        return callback('missing required argument `input` or default: ' + potentialDef);
      }
    }

    // use default
    cfg.input = def;
  }

  // requires original dimensions
  if (cfg.type !== 'asset') {

    if (cfg.cli) {
      logger.info('Reading input dimensions');
    }

    var im = gm.subClass({
      imageMagick: true
    });

    // read input
    im(cfg.input).ping().size(function(err, size) {

      if (err) {
        return callback(err);
      }

      cfg.inputWidth = size.width;
      cfg.inputHeight = size.height;

      finish(cfg, callback);
    });

  } else {
    finish(cfg, callback);
  }
};
Esempio n. 9
0
import 'babel-polyfill'
import AWS from 'aws-sdk'
import _gm from 'gm'
const gm = _gm.subClass({ imageMagick: true, appPath: '/usr/local/bin/' })

function s3Get(bucket, key) {
  const s3 = new AWS.S3()
  const params = {
    Bucket: bucket,
    Key: key
  }
  return new Promise((resolve, reject) => {
    s3.getObject(params, (err, data) => {
      if (err) {
        reject(err)
      }
      else {
        resolve(data)
      }
    })
  })
}

function s3Put(bucket, key, data) {
  const s3 = new AWS.S3()
  const params = {
    Bucket: bucket,
    Key: key,
    Body: data
  }
  return new Promise((resolve, reject) => {
Esempio n. 10
0
    //预处理完成后,方可生成各种规格的缩略图文件
    function 预处理图片(file) {

        console.log('开始预处理,图片格式为:' + file.format)

        switch (file.format) {
            //对于jpeg,提供一个原比例90压缩率的版本
            case 'jpg':
                var qualityPath = file.path + '_quality80'
                gm(file.path).interlace('Line').noProfile().quality(80).write(qualityPath, function (err) {
                    var fileName = file.fileId + '_quality' + '_' + file.width + 'x' + file.height + '.' + file.format

                    options.type = '优化后的原图'
                    var gs = new GridStore(DB.dbServer, fileName, fileName, "w", options)
                    gs.writeFile(qualityPath, function (err) {
                        if (!err) {
                            //开始生成并保存各种缩略图
                            resize(file, ownerID)
                            unlink(qualityPath)
                        } else {
                            unlink(file.path)
                        }
                    })
                })
                break;
            //对于gif,不优化直接进行压缩
            case 'gif':
                resize(file, ownerID)
                break;
            case 'psd':
                var dstPath = file.path + '_psd_to_jpg.jpg'
                console.log('开始预处理PSD', file.path)
                gm.subClass({ imageMagick: true })(file.path + '[0]').setFormat('jpg').interlace('Line').quality(90).write(dstPath, function (err) {
                    if (!err) {
                        unlink(file.path)
                        file.path = dstPath
                        file.format = 'jpg'
                        var fileName = file.fileId + '_quality' + '_' + file.width + 'x' + file.height + '.' + file.format
                        //注意case jpg中也使用相同的type
                        options.metadata.type = "优化后的原图"
                        var gs = new GridStore(DB.dbServer, fileName, fileName, "w", options)
                        gs.writeFile(dstPath, function (err) {
                            if (!err) {
                                //开始生成并保存各种缩略图
                                resize(file, ownerID)
                            } else {
                                uploadInfo.err.push('无法保存' + file.name)
                                unlink(dstPath)
                            }
                        })
                    } else {
                        console.log(err)
                        unlink(file.path)
                    }
                })
                break;
            //直接进行尺寸压缩,不进行任何优化
            case 'png':
                resize(file, ownerID)
                break;

        }
    }
Esempio n. 11
0
var fs = require('fs');
var gm = require('gm')
    // Promise.promisifyAll(require('fs-extra'));

var Promise = require('bluebird');
var PSD = require('psd'); // already promise enabled
var jsonfile = Promise.promisifyAll(require('jsonfile'));
var im = Promise.promisifyAll(gm.subClass({
    imageMagick: true
}));
var nsg = require('node-sprite-generator');
var _ = require('lodash');

var img = "img/085_rasterized.psd";
var imgOutput = "img/output/085_layer.png";
var imgLayerMeta = "json/085.json";
var spriteMeta = "json/085_sprite.json";

var data = {};


PSD.open(img)
    .then(function(psd) {
        // write metadata
        data.layers = psd.tree().export().children;

        data.layers.forEach(function(d,i){
        	// make an index thats the reverse of what this lists 
        	// imagemagick reverses layer order parsing
        	d.plateIndex = i;
        	d.imIndex = (data.layers.length) - i;
Esempio n. 12
0
 constructor (gmPath) {
   this.gm = gmPath
     // Add trailing separator ('/' on Posix, '\\' on Windows)
     ? graphicsMagick.subClass({ appPath: path.normalize(gmPath + path.sep) })
     : graphicsMagick
 }
Esempio n. 13
0
"use strict";
/* global module: false, console: false, __dirname: false, process: false */

var express = require('express');
var upload = require('jquery-file-upload-middleware');
var bodyParser = require('body-parser');
var fs = require('fs');
var _ = require('lodash');
var app = express();
var gmagic = require('gm');
var gm = gmagic.subClass({imageMagick: true});
var config = require('../server-config.js');
var extend = require('util')._extend;
var url = require('url');

app.use(require('connect-livereload')({ ignore: [/^\/dl/, /^\/img/] }));
// app.use(require('morgan')('dev'));

app.use(bodyParser.json({limit: '5mb'}));
app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
  limit: '5mb',
  extended: true
})); 

var listFiles = function (req, options, callback) {

    var files = [];
    var counter = 1;
    var finish = function () {
        if (!--counter)
            callback(files);
'use strict';

var gmLib = require('gm'),
  fs = require('fs'),
  lib = require('grunt-ez-frontend/lib/lib.js'),
  path = require('path'),
  mkdirp = require('mkdirp'),
  async = require('async'),
  Deferred = require( "JQDeferred" ),
  gm = gmLib.subClass({ imageMagick : true });


var doResize = function (imagePath, opts) {
  
  var dfd = Deferred();

  async.each(opts.sizes, function (size, cb) {
    var 
      imgStream = fs.createReadStream(imagePath),
      basename = path.basename(imagePath),
      sizeInText = lib.format('_{0}_', size),
      outputPath = path.join(opts.outputFolder, 
        sizeInText, 
        path.relative(opts.relativePath, imagePath)
      );

    mkdirp(path.dirname(outputPath), function (err) {
      if (err) {
        throw err;
      }
Esempio n. 15
0
module.exports = function({base = 2, to = 1, copy = false, im = false} = {}) {

	let baseRatio = (3 === parseInt(base, 10)) ? 3 : 2;
	let toRatio = (Array.isArray(to) ? to.map(i => parseInt(i, 10)) : [parseInt(to, 10)]).filter(i => (base !== i) && -1 < [3, 2, 1].indexOf(i));
	toRatio = toRatio.length ? toRatio : [1];

	const cvtBase	= baseRatio;
	const cvtCopy	= Boolean(copy);
	const cvtOne	= -1 < toRatio.indexOf(1);
	const cvtTwo	= -1 < toRatio.indexOf(2);
	const cvtGm		= im ? graphicsMagick.subClass({imageMagick: true}) : graphicsMagick;

	function getImage(path) {
		return new Promise(function(resolve, reject) {
			return cvtGm(path).identify(function(err, info) {
				if(err) {
					return reject(err);
				}
				return resolve(new Image(info));
			});
		});
	}

	const createBuffer = function(image, to) {
		const { width: baseWidth, height: baseHeight, path } = image;
		const width = Math.ceil(baseWidth / cvtBase * to);
		const height = Math.ceil(baseHeight / cvtBase * to);
		const borderWidth = Math.ceil(width / to) * to - width;
		const borderHeight = Math.ceil(height / to) * to - height;

		let flow = cvtGm(path).resize(width, height, '!');

		if(borderWidth || borderHeight) {
			flow = flow
				.borderColor('transparent')
				.border(borderWidth, borderHeight)
				.crop(width + borderWidth, height + borderHeight, Math.floor(borderWidth / 2), Math.floor(borderHeight /2));
		}
		return new Promise(function(resolve, reject) {
			return flow.toBuffer(function(err, buffer) {
				if(err) {
					return reject(err);
				}
				const name = image.nameRetina(to);
				return resolve({buffer, name});
			});
		});
	}

	const createImages = function(image) {
		const promises = [];
		cvtOne && promises.push(createBuffer(image, 1));
		cvtTwo && promises.push(createBuffer(image, 2));
		cvtCopy && promises.push(createBuffer(image, cvtBase));
		return Promise.all(promises);
	};

	const addImagesTo = function(context) {
		return function(images) {

			images.forEach(image => context.push(new CreateFile({
				path : image.name,
				contents: Buffer.concat([image.buffer])
			})));
			return null;
		}
	};

	return through.obj(function(file, encoding, callback) {
		if(!file.isBuffer() && !file.isStream()) {
			return callback();
		}
		return getImage(file.path).then(createImages).then(addImagesTo(this)).then(callback).catch(console.warn.bind(console));
	});
};
Esempio n. 16
0
//server routing dependencies
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var bodyParser = require('body-parser');

//for image processing
var fs = require('fs');
var im = require('gm');
var gm = im.subClass({imageMagic:true});

//application dependencies
var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();
var http = require('http').Server(app);

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
app.use(favicon(__dirname + '/public/favico.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
Esempio n. 17
0
	fs.exists(cfg.input, function(exists) {

		// input doesn't exist
		if (!exists) {
			return callback('Input not found: ' + cfg.input);
		}

		// NOTE: non-sync version didn't work in paralel
		fs.createDirSync(path.dirname(spec.output));

		var im = gm.subClass({
			imageMagick: true
		});

		// read
		var convert = im(cfg.input);

		var flatten = !spec.alpha && !(cfg.nine && spec.ninePath);

		// flatten
		if (flatten) {
			convert = convert.flatten();
		}

		var specRatio = spec.width / spec.height;

		var containWidth, containHeight;

		// nine or fill
		if (!cfg.crop || (cfg.nine && spec.ninePath)) {

			// only scale down
			if (cfg.inputWidth > spec.width || cfg.inputHeight > spec.height) {

				if (cfg.inputRatio > specRatio) {
					containWidth = spec.width;
					containHeight = Math.round(spec.width / cfg.inputRatio);
				} else {
					containWidth = Math.round(spec.height * cfg.inputRatio);
					containHeight = spec.height;
				}

				// resize fitting dimensions (using in() or order will be wrong for fill)
				convert = convert
					.in('-resize').in(spec.width + 'x' + spec.height);

			} else {
				containWidth = cfg.inputWidth;
				containHeight = cfg.inputHeight;
			}

			// nine
			if (cfg.nine && spec.ninePath) {

				// extent with 1px transparent border
				convert = convert
					.borderColor('none')
					.border(1, 1);

				// draw black pixels
				convert = convert
					.fill('black')

				// stretchable area
				.drawPoint(1, 0)
					.drawPoint(containWidth, 0)
					.drawPoint(0, 1)
					.drawPoint(0, containHeight)

				// padding box (required since API 21)
				.drawLine(containWidth + 1, 1, containWidth + 1, containHeight)
					.drawLine(1, containHeight + 1, containWidth, containHeight + 1);

				// fill
			} else {

				// calculate required padding
				var padLeft = Math.floor((spec.width - containWidth) / 2);
				var padTop = Math.floor((spec.height - containHeight) / 2);

				// enlarge canvas using outer pixel to fill (all using in() or order will be wrong)
				convert = convert
					.in('-define')
					.in('distort:viewport=' + spec.width + 'x' + spec.height + '-' + padLeft + '-' + padTop)
					.in('-distort').in('SRT').in('0')
					.in('+repage');
			}

			// crop
		} else {

			var resize = (function() {
				var contentRatio, z, smallerWidth, smallerHeight, factor,
					result = {
						width: spec.width,
						height: spec.height
					};

				// user has given content dimensions
				if (cfg.width && cfg.height) {
					contentRatio = cfg.width / cfg.height;

					// e.g. specs landscape, content is portrait
					if (specRatio > contentRatio) {
						z = spec.height / cfg.height;

						// e.g. specs portrait, content is landscape
					} else {
						z = spec.width / cfg.width;
					}

					// don't scale up
					if (z > 1) {
						logger.warn('Target size is bigger then content: ' + spec.output.cyan);

					} else {
						smallerWidth = Math.round(cfg.inputWidth * z);
						smallerHeight = Math.round(cfg.inputHeight * z);

						// width or height won't cover specs anymore if content needs to fit as well
						if (smallerWidth < spec.width || smallerHeight < spec.height) {
							factor = Math.max(spec.width / smallerWidth, spec.height / smallerHeight);
							logger.warn('For '.white + (spec.width + 'x' + spec.height).cyan + ' to contain '.white + (cfg.width + 'x' + cfg.height).cyan + ' the input needs to be at least: '.white + (Math.ceil(cfg.inputWidth * factor) + 'x' + Math.ceil(cfg.inputHeight * factor)).cyan);

						} else {
							result.width = smallerWidth;
							result.height = smallerHeight;
						}
					}
				}

				return result;

			})();

			// resize covering dimensions
			convert = convert.resize(resize.width, resize.height, '^');

			// crop from center to exact dimensions
			convert = convert
				.gravity('Center')
				.crop(spec.width, spec.height, 0, 0);
		}

		// border radius (http://www.rubblewebs.co.uk/imagemagick/display_example.php?example=69)
		if (spec.type === 'icon' && !flatten && cfg.radius > 0 && _.size(_.difference(spec.platforms, ['ios', 'ipad', 'iphone', 'apple-watch'])) > 0) {
			var radius = Math.ceil((spec.width / 100) * cfg.radius);

			// in
			convert = convert
				.in('-size').in(spec.width + 'x' + spec.height)
				.in('xc:none')
				.in('-fill').in('white')
				.in('-draw').in('roundRectangle 0,0 ' + (spec.width - 1) + ',' + (spec.height - 1) + ' ' + radius + ',' + radius);

			// out
			convert = convert
				.compose('SrcIn')
				.out('-composite');
		}

		// annotate
		if (cfg.label) {
			var fontSize = Math.round((containWidth || spec.width) / 11);

			convert = convert
				.fill('#F00')
				.font(path.join(__dirname, 'Calibri.ttf'))
				.fontSize(fontSize);

			if (cfg.nine && spec.ninePath) {
				convert = convert.drawText(1, (containHeight || spec.height) / 2, spec.name);
			} else {
				convert = convert.drawText(0, 0, spec.name);
			}
		}

		// headers
		convert = convert
			.noProfile()
			.units('PixelsPerInch')
			.density(spec.dpi, spec.dpi);

		// rotate
		if (spec.rotate) {
			convert = convert.rotate('white', spec.rotate);
		}

		// remove alpha
		if (flatten) {
			convert = convert.out('-background', 'white', '-alpha', 'off');
		}

		// write
		convert.write(spec.output, function(err) {

			if (err) {
				return callback(err.code === 'ENOENT' ? 'Please install ImageMagick.' : err);
			}

			// async feedback for CLI
			if (cfg.cli) {
				logger.info('Generated: ' + spec.output.cyan);
			}

			// pass back output
			callback(null, spec.output);

		});

		// show command
		if (cfg.trace) {
			logger.debug('Executing: ' + convert.args().join(' ').cyan);
		}

	});
Esempio n. 18
0
'use strict';

var async = require('async');
var GM = require('gm');
var gm = GM.subClass({ imageMagick: true });

//## Doesn't seem to work. Filesize or something is wrong which results in gray bottom in images

exports.resize = function resize (source, sizes, callback) {
  var name = source.filename;

  async.map(sizes, function (size, done) {
    gm(source, name + size.suffix + '.jpg')
    .resize(size.width, size.height, '>')
    .filesize({ bufferStream: true }, function (err, filesize) {
      if(err) {
        return done(err);
      }

      var image = this.stream('jpg');

      image.filesize = parseInt(filesize);
      image.filename = name + size.suffix + '.jpg';
      done(null, image);
    });
  }, callback);
};
Esempio n. 19
0
var db = require('./middleware/db').db
var fs = require('fs');
var gm = require('gm');
var im = gm.subClass({imageMagick: true})
var conf = require('./middleware/config');
var Email = require('email').Email;

db.query('SELECT * FROM photo WHERE processed = 0', function(err, photos) {
	photos.forEach(function(photo) {
		var parts = photo.path.split('/');
		photo.path = parts[parts.length -1];
		waterMark(photo.path, function(err) {
			if (err) throw err;
			db.query('UPDATE photo SET processed = 1 WHERE id = ' + photo.id, function(err) {
				if(err) throw err;
			})
			db.query('UPDATE photo SET path=? WHERE id = ' + photo.id, '/pictures/photos/' + photo.path, function(err) {
				if(err) throw err;
			})
		});
	});
	email(function(err) {
		if(err) throw err;
	});
})



function waterMark (file, cb) {
	var origin = __dirname + '/img/tmp/' + file;
	var dest = __dirname + '/public/pictures/photos/' + file;
Esempio n. 20
0
var plugin = function(schema, options) {

  options = options || {};

  if (typeof(options.directory) !== 'string') throw new Error('option "directory" is required');
  if (typeof(options.properties) !== 'object') throw new Error('option "properties" is required');
  if (typeof(options.storage) !== 'object') throw new Error('option "storage" is required');
  _.defaults(options, { idAsDirectory: false, gm: {} });
  _.defaults(options.gm, {  });

  var gm = gmSuper.subClass(options.gm);

  var storageOptions = options.storage;
  storageOptions.schema = schema;

  if (typeof(storageOptions.providerName) !== 'string') throw new Error('option "storage.providerName" is required');
  var ProviderPrototype = findProvider(storageOptions.providerName);
  var providerOptions = storageOptions.options || {};
  var providerInstance = new ProviderPrototype(providerOptions);

  if (typeof providerInstance.getUrl !== 'function') {
    throw new Error('Provider ' + storageOptions.providerName + ' does not have a method getUrl');
  }

  if (typeof providerInstance.createOrReplace !== 'function') {
    throw new Error('Provider ' + storageOptions.providerName + ' does not have a method createOrReplace');
  }

  var propertyNames = Object.keys(options.properties);
  propertyNames.forEach(function(propertyName) {

    var propertyOptions = options.properties[propertyName];
    if (!propertyOptions) throw new Error('property "' + propertyName + '" requires an specification');

    var styles = propertyOptions.styles || {};
    var styleNames = Object.keys(styles);

    if (styleNames.length === 0) {
      throw new Error('property "' + propertyName + '" needs to define at least one style');
    }

    var addOp = {};
    var propSchema = addOp[propertyName] = {};

    styleNames.forEach(function(styleName) {
      propSchema[styleName] = {
        size: Number, // Size of the File
        oname: String, // Original name of the file
        mtime: Date,
        ctime: Date,
        path: String, // Storage Path
        defaultUrl: String, // Default (non-secure, most of the time public) Url
        format: String, // Format of the File(provided by identify).
        dims: { // Dimensions of the Image
          h: Number, // Height
          w: Number // Width
        }
      };
    });

    // Add the Property
    schema.add(addOp);

  }); // for each property name

  // Finally we set the method 'attach'
  // => propertyName: String. Name of the property to attach the file to.
  // => attachmentInfo: {
  //    path: String(required). Path to the file in the file system.
  //    name: String(optional). Original Name of the file.
  //    mime: String(optional). Mime type of the file.
  // }
  schema.methods.attach = function(propertyName, attachmentInfo, cb) {

    var selfModel = this;
    if (propertyNames.indexOf(propertyName) == -1) return cb(new Error('property "' + propertyName + '" was not registered as an attachment property'));
    var propertyOptions = options.properties[propertyName];
    var styles = propertyOptions.styles || {};

    if (!attachmentInfo || typeof(attachmentInfo) !== 'object') return cb(new Error('attachmentInfo is not valid'));
    if (typeof(attachmentInfo.path) !== 'string') return cb(new Error('attachmentInfo has no valid path'));
    if (!attachmentInfo.name) {
      // No original name provided? We infer it from the path
      attachmentInfo.name = path.basename(attachmentInfo.path);
    }

    existsFn(attachmentInfo.path, function(exists) {

      if (!exists) {
        return cb(new Error('file to attach at path "' + attachmentInfo.path + '" does not exists'));
      }

      fs.stat(attachmentInfo.path, function(err, stats) {

        if (!stats.isFile()) {
          return cb(new Error('path to attach from "' + attachmentInfo.path + '" is not a file'));
        }

        var getFileExtension = Promise.promisify(gm.prototype.format, gm(attachmentInfo.path));


        Promise.resolve(mime.extension(mime.lookup(attachmentInfo.path)))
        .then(function(format) {
          // First we need to check whether or not the format is supported.
          // If it's not, throw an error
          return supportedDecodingFormats.indexOf(format.toUpperCase()) !== -1;
        })
        .catch(function(err) {
          // Failing here means that the file format is not a supported image.
          // So return false for `canTransform`
          return false;
        })
        .then(function(canTransform) {

          var fileExt = path.extname(attachmentInfo.path);
          var styles = propertyOptions.styles || {};

          return Promise.all(_.map(styles, function(style, name) {
            _.defaults(style, {
              options: {},
              transform: function(i) { return i; }
            });

            return Promise.resolve({
              image: canTransform ? style.transform(gm(attachmentInfo.path)) : null,
              file: canTransform ? null : fs.createReadStream(attachmentInfo.path),
              style: style,
              styleName: name,
              attachmentInfo: attachmentInfo,
              fileExt: fileExt
            });
          }));

        })

        .then(function(variants) {

          // Now write files to the temporary path.
          // @todo: in the future, this should probably just pass the gm image/stream
          // object to the provider.
          return Promise.all(_.map(variants, function(variant) {
              var styleFileExt = variant.style.options.format ? ('.' + variant.style.options.format) : variant.fileExt;
              var styleFileName = path.basename(variant.attachmentInfo.path, variant.fileExt);
              styleFileName += '-' + variant.styleName + styleFileExt;
              var styleFilePath = path.join(path.dirname(variant.attachmentInfo.path), styleFileName);

              var writeImageToFile = Promise.promisify(gm.prototype.write, variant.image);

              return (
                variant.image ?
                  writeImageToFile(styleFilePath) :
                  (function() {
                    return new Promise(function(resolve) {
                        variant.file.pipe(fs.createWriteStream(styleFilePath))
                            .on('finish', resolve);
                    });
                  })()
              )
              .catch(function(err) {
                  console.log(err);
              })
              .then(function() {
                return _.merge(variant, { styleFilePath: styleFilePath });
              });
          }));

        })

        .then(function(variants) {

          // Pass each individual file off to the registered provider
          return Promise.all(_.map(variants, function(variant) {

            var ext = path.extname(variant.styleFilePath);
            var filenameId = options.filenameId ? selfModel[options.filenameId] : selfModel.id;
            var storageStylePath = path.join(
              options.directory,
              propertyName,
              [filenameId, variant.styleName + ext].join(options.idAsDirectory ? '/':'-')
            );

            // if (storageStylePath[0] != '/') {
            //   storageStylePath = '/' + storageStylePath;
            // }

            var getFileStats = Promise.promisify(fs.stat);
            var getImageStats = Promise.promisify(gm(variant.styleFilePath).identify);
            var createOrReplaceFile = Promise.promisify(providerInstance.createOrReplace, providerInstance);

              // Providers expect both stat and identify results for the output image
            return Promise.all([
              getFileStats(variant.styleFilePath),
              getImageStats()
              .catch(function() { return null; })
            ])
            .spread(function(stats, atts) {
              return {
                style: {
                  name: variant.styleName,
                  options: variant.style
                },
                filename: variant.styleFilePath,
                stats: stats,
                propertyName: propertyName,
                model: selfModel,
                path: storageStylePath,
                defaultUrl: null, // let the storage assign this
                features: atts
              };
            })
            .then(function(providerInput) {
              return createOrReplaceFile(providerInput);
            })
            .then(function(storageResult) {
              return _.merge(variant, {
                storageResult: storageResult,
                propertyName: propertyName
              });
            });

          }));

        })

        .then(function(variants) {

          _.forEach(variants, function(variant) {
            var propModel = selfModel[variant.propertyName];
            var modelStyle = propModel[variant.storageResult.style.name];

            _.merge(modelStyle, {
              defaultUrl: variant.storageResult.defaultUrl,
              path: variant.storageResult.path,
              size: variant.storageResult.stats.size,
              mime: variant.storageResult.mime,
              ctime: variant.storageResult.stats.ctime,
              mtime: variant.storageResult.stats.mtime,
              oname: variant.attachmentInfo.name, // original name of the file
            }, variant.storageResult.features ? {
              format: variant.storageResult.features.format,
              depth: variant.storageResult.features.depth,
              dims: {
                h: variant.storageResult.features.size.height,
                w: variant.storageResult.features.size.width,
              }
            } : {});
          });

          return variants;

        })

        .then(function() { cb(null); })
        .catch(function(err) { return cb(err); })
        .done();

      });

    });

  }; // method attach
};