text-watermark
Version:
A watermark library based on ImageMagick for Node.js that can be used to put text watermarks on images.
202 lines (166 loc) • 6.25 kB
JavaScript
/*
* @Package: text-watermark
* @Author: sahildua2305
* @Date: 2016-05-24 06:44:49
* @Last Modified by: Sahil Dua
* @Last Modified time: 2016-05-26 01:09:13
*/
;
var fs = require('fs');
var im = require('imagemagick');
var path = require('path');
var ratify = require('node-ratify');
// Default options for watermarking
var defaultOptions = {
"text" : "Sample Text Watermark",
"color" : "rgba(0,0,0,0.5)",
"scale" : "100%",
"rotation" : "dia",
"position" : "Center",
"override-image" : false
};
/**
* _parseOptions
* @param {Object} imageData image data as read by ImageMagick
* @param {String} source original image path
* @param {Object} options watermark options
* @return {Object} watermark final options to be passed to ImageMagick for watermarking
*/
function _parseOptions(imageData, source, options) {
var finalObj = {};
var width = imageData.width;
var height = imageData.height;
var watermarkText = ratify.isEmpty(options.text) ? defaultOptions.text : options.text;
var color = ratify.isEmpty(options.color) ? defaultOptions.color : options.color;
var scale = ratify.isEmpty(options.scale) ? defaultOptions.scale : options.scale;
var rotation = ratify.isEmpty(options.rotation) ? defaultOptions.rotation : options.rotation;
var position = defaultOptions.position;
var font = options.font;
var outputPath = null;
var angle = null;
// check if image needs to be overridden or not
// update the outputPath accordingly
if(options['override-image'] && ratify.isBoolean(options['override-image'])
&& options['override-image'].toString() === 'true') {
outputPath = source;
}
else {
outputPath = ratify.isEmpty(options.outputPath) ? (path.dirname(source) + "/watermark_" + path.basename(source)) : options.outputPath;
}
var pointWidth = width;
var pointHeight = height;
// check if given scale value is valid or not
// if it is, scale the pointWidth and pointHeight accordingly
if(scale.toString().indexOf("%") == -1) {
scale = defaultOptions.scale;
}
else {
var scaleFactor = (parseFloat(scale) / 100);
pointWidth *= scaleFactor;
pointHeight *= scaleFactor;
}
var pointSize = Math.sqrt(pointWidth * pointWidth + pointHeight * pointHeight) / watermarkText.length;
if(rotation.toString() == "dia") {
angle = (Math.atan(height / width) * (180 / Math.PI)) * -1;
}
else {
angle = parseInt(rotation.toString());
}
var args = [];
// original image path
args.push(source);
// size of final image
args.push("-size");
args.push(width + "x" + height);
// scale factor
args.push("-resize");
args.push(scale);
// set font, if passed in options
if(!ratify.isEmpty(font)) {
args.push("-font");
args.push(font);
}
// color of watermark text on the final image
args.push("-fill");
args.push(color);
// pointSize calculated on the basis of original image size and length of the watermark text
args.push("-pointsize");
args.push(pointSize);
// alignment of the watermark text
args.push("-gravity");
args.push(position);
// angle of the watermark text wrt to X-axis
args.push("-annotate");
args.push(angle);
// watermark text
args.push(watermarkText);
// path of final image with watermark path
args.push(outputPath);
finalObj.args = args;
finalObj.outputPath = outputPath;
return finalObj;
}
/**
* addWatermark
* @param {String} source original image path
* @param {Object} options watermark options
* @param {Function} callback callback function containing errors, if any
*/
function addWatermark(source, options, callback) {
var error;
// check for valid/invalid arguments
if((arguments.length < 2)
|| (arguments.length === 2 && !ratify.isFunction(arguments[1]))
|| (arguments.length > 2 && !ratify.isFunction(arguments[2]))) {
throw new Error('Text-Watermark::addWatermark : Invalid arguments');
}
else if(arguments.length === 2 && ratify.isFunction(arguments[1])) {
callback = arguments[1];
options = null;
}
// if no image source is found
if(!source || source == "") {
error = new Error('Text-Watermark::addWatermark : No image source');
return callback(error);
}
// check if source file exists at the specified path
fs.lstat(source, function(err, stats) {
if(err) {
error = new Error('Text-Watermark::addWatermark : Image file doesn\'t exist at source ' + source);
return callback(error);
}
else if(!stats.isFile()) {
error = new Error('Text-Watermark::addWatermark : Invalid image source at ' + source);
return callback(error);
}
else {
// use default options if options aren't properly specified
if(!options || typeof options !== 'object')
options = defaultOptions;
im.identify(source, function(err, imageData) {
if(err) {
error = new Error('Text-Watermark::addWatermark : Error while processing image file : ' + err);
return callback(error);
}
var finalObj = _parseOptions(imageData, source, options);
im.convert(finalObj.args, function(err, stdout) {
if(err) {
error = new Error('Text-Watermark::addWatermark : Error in applying watermark : ' + err);
return callback(error);
}
else {
console.log('Text-Watermark::addWatermark : Watermark applied. You can check the output file at : ' + finalObj.outputPath);
return callback(null);
}
});
});
}
});
return;
}
exports = module.exports = {
addWatermark : addWatermark,
version : JSON.parse(
require('fs').readFileSync(__dirname + '/package.json', 'utf-8')
).version
};