How to do 'gm composite -gravity center change_image_url base_image_url' with GM Node.js?
How to call gm().command() & gm().in() or gm().out() to achieve the above?
After struggling for an hour, here is my solution for your question:
gm composite -gravity center change_image_url base_image_url
gm()
.command("composite")
.in("-gravity", "center")
.in(change_image_url)
.in(base_image_url)
.write( output_file, function (err) {
if (!err)
console.log(' hooray! ');
else
console.log(err);
});
Good luck! Hope it will be helpful to others as well :)
Install gm, (make sure you already install graphicsmagick
npm install gm
following is my example code to merge two image together (use gm.in)
var gm = require('gm');
gm()
.in('-page', '+0+0')
.in('bg.jpg')
.in('-page', '+10+20') // location of smallIcon.jpg is x,y -> 10, 20
.in('smallIcon.jpg')
.mosaic()
.write('tesOutput.jpg', function (err) {
if (err) console.log(err);
});
i am doing that this way:
var exec = require('child_process').exec
var command = [
'-composite',
'-watermark', '20x50',
'-gravity', 'center',
'-quality', 100,
'images/watermark.png',
'images/input.jpg', //input
'images/watermarked.png' //output
];
// making watermark through exec - child_process
exec(command.join(' '), function(err, stdout, stderr) {
if (err) console.log(err);
});
Why does nobody use composite command? (https://github.com/aheckmann/gm)
var gm = require('gm');
var bgImage = 'bg.jpg',
frontImage = 'front.jpg',
resultImage = 'result.jpg',
xy = '+100+150';
gm(bgImage)
.composite(frontImage)
.geometry(xy)
.write(resultImage, function (err) {
if (!err) console.log('All done');
});
UPDATE Oh, I watched history of source of this method. It becomes available only on 2014
If you want to resize and merge, you can use this:
gm()
.in('-geometry', '+0+0')
.in('./img/img1.png')
.in('-geometry', '300x300+100+200')
.in('./img/img2.png')
.flatten()
.write('resultGM.png', function (err) {
if (err) console.log(err);
});
Having the pleasure of being confined to a windows machine for the moment I solved this problem eventually by not using the "gm" module at all. For some reason, even though I have installed graphics-magick via its installer the node module refused to find it in my environment variables. But that could have something to do with the fact that I am trying to make an application with Electron.js (which is similar to Node.js but has its "gotcha's").
var exec = require("child_process").execSync;
var commandArray = [
__dirname + "/bin/graphicsMagick/gm.exe", // the relative path to the graphics-magick executable
"-composite",
"-gravity",
"center",
__dirname + "/data/images/qr/logo-small.png", // relative paths to the images you want to composite
__dirname + "/data/images/qr/qr-webpage.png",
__dirname + "/data/images/qr/qr-webpage-logo.png" // relative path to the result
];
var returnValue = exec(commandArray.join(" "));
For windows I think this is the correct portable way to do it.
Related
I would like to collect metrics on how long yarn commands such as yarn install take to complete and other metrics such as how often the commands don't complete successfully.
My .yarnrc file looks like this:
registry "https://artifactory-content.company.build/artifactory/api/npm/npm"
"--ignore-engines" true
"#sail:registry" "https://artifactory-content.company.build/artifactory/api/npm/npm-local"
"#company-internal:registry" "https://artifactory-content.company.build/artifactory/api/npm/npm-local"
lastUpdateCheck 1617811239383
yarn-path "./yarn-1.19.1.js"
From what I understand, when I run the yarn command, it invokes the yarn-1.19.1.js file. Would it be possible to create a wrapper such that when any yarn command is run, it logs the metrics at the command level and then executes the yarn-1.19.1.js file?
Another approach I ran across was modifying the package.json file and overriding the commands as mentioned here but this doesn't seem scalable as there might be new commands added later on.
Yes, you could create a wrapper script that invokes the Yarn core library. This is exactly what the Node.js that is yarn does:
#!/usr/bin/env node
'use strict';
var ver = process.versions.node;
var majorVer = parseInt(ver.split('.')[0], 10);
if (majorVer < 4) {
console.error('Node version ' + ver + ' is not supported, please use Node.js 4.0 or higher.');
process.exit(1);
} else {
try {
require(__dirname + '/../lib/v8-compile-cache.js');
} catch (err) {
}
var cli = require(__dirname + '/../lib/cli');
if (!cli.autoRun) {
cli.default().catch(function(error) {
console.error(error.stack || error.message || error);
process.exitCode = 1;
});
}
}
You could just edit that script like so:
const start = Date.now();
var cli = require(__dirname + '/../lib/cli');
if (!cli.autoRun) {
cli.default()
.then(function() {
const durationInMs = Date.now() - start;
// It succeeded, do your stuff.
})
.catch(function(error) {
console.error(error.stack || error.message || error);
process.exitCode = 1;
const durationInMs = Date.now() - start;
// It failed, do your stuff.
});
}
First plugin with XD and i can't seem to create a instance of class Color.
Their documentation doesn't show any examples and any that i find in other examples just shows new Color() and that i don't have to perform any require.
https://adobexdplatform.com/plugin-docs/reference/Color.html
Plugin ReferenceError: Color is not defined
at exportToBmpFunction (C:\Users\<useR>\AppData\Local\Packages\Adobe.CC.XD_adky2gkssdxte\LocalState\develop\BMP_Export\main.js:21:21)
What am i doing wrong?
async function exportToBmpFunction(selection) {
if (selection.items.length == 0) {
return;
}
// Generate PNG rendition of the selected node
let application = require("application");
let scenegraph = require("scenegraph");
let fs = require("uxp").storage.localFileSystem;
let shape = selection.items[0];
let file = await fs.getFileForSaving('what.png', { types: ["png"] });
let renditions = [{
node: shape,
outputFile: file,
type: application.RenditionType.PNG,
scale: 1,
background: new Color('#FF00CD', 1)
}];
application.createRenditions(renditions).then(function(results) {
// ...do something with outputFiles on disk...
});
}
module.exports = {
commands: {
exportToBmp: exportToBmpFunction
}
};
Turns out after digging through other classes in the same 'namespace' that their documentation is just flat out wrong in some places. This is what it should be.
const Color = require("scenegraph").Color;
let color = new Color('#FF00CD');
This happens to be in direct contradiction to examples of use of Color in the docs.
Yay for freehanding code!
How can I retrieve the MyDocuments path with NodeJS.
So I would like to get something in NodeJs with the following C# code:
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
Thx & Regards
Stefan
Found the answer:
var Q = require('Q');
var getUserDoc = function(callback) {
var Winreg = require('winreg');
var deferred = Q.defer();
var regKey = new Winreg({
hive: Winreg.HKCU,
key: '\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders'
});
var myDocFolder = regKey.values(function(err, items) {
for (var i in items) {
if (items[i].name === 'Personal') {
deferred.resolve(items[i].value);
}
}
});
deferred.promise.nodeify(callback);
return deferred.promise;
}
getUserDoc().then(function(result) {
console.log(result);
});
You should use the environment variable instead :
function getUserDoc() {
return process.env.USERPROFILE+'\\Documents';
}
This assumes that you run Win7 or above. For Win XP, it'd be \\My Documents. You can easily check for one or the other in your function.
Also, you can use the package path-extra which offers the shortcut homedir()
In this case you'd have to do :
var path = require('path-extra');
function getUserDoc() {
return path.homedir()+'\\Documents';
}
Both of these solutions allow you to not give your app the credentials for checking the registry.
And run way faster than the promise + registry hack you've found.
Update: path-extra do not supports homedir any more. https://github.com/jprichardson/node-path-extra/commit/ce7a0b67ce07ca06ca2eeabf62621e1327b1d113
+1 for ingenuity though, I've saved that snippet for possible use ;-)
The following code is supposed to read an image file and then add the file data into a canvas with the help of the Canvas module.
When I run this code I receive the error message Image is not defined. Is the image object that I'm trying to initialise from a module that I simply import?
var http = require('http'), fs = require('fs'),
Canvas = require('canvas');
http.createServer(function (req, res) {
fs.readFile(__dirname + '/image.jpg', function(err, data) {
if (err) throw err;
img = new Image();
img.src = data;
ctx.drawImage(img, 0, 0, img.width / 4, img.height / 4);
res.write('<html><body>');
res.write('<img src="' + canvas.toDataURL() + '" />');
res.write('</body></html>');
res.end();
});
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
I apologize if I'm wrong here, but it looks like you've found this code somewhere and tried to use it without actually understanding what's happening under the covers. Even if you were to fix the Image is not defined error, there are many others.
I have the fixed code at the end of this post, but I'd recommend thinking more deeply about these issues in the code from your question:
What is Image? Where does it come from? You've imported http, fs, and Canvas, so those things are obviously defined. However, Image hase not been defined anywhere and it is not a built-in.
As it turns out, Image is from the node-canvas module, which you've imported with Canvas = require('canvas'). This means that Image is available as Canvas.Image.
It's important to understand that this is because of the imports you've setup. You could just have easily have done abc = require('canvas'), and then Image would be available as abc.Image.
What is ctx? Where is that coming from?
Again, this is another variable that just hasn't been defined anywhere. Unlike Image, it isn't available as Canvas.ctx. It's just a random variable name that doesn't correspond to anything at this point, so trying to call drawImage on it is going to throw an exception.
What about canvas (lowercase)? What is that?
You are using canvas.toDataURL, but there is no variable called canvas anywhere. What are you expecting this piece of code to do? Right now it's just going to throw an exception saying that canvas is undefined.
I'd recommend reading documentation more closely and looking more closely at any example code you copy into your own applications in the future.
Here is the fixed code, with some comments to explain my changes. I figured this out by taking a quick look at the documentation at https://github.com/learnboost/node-canvas.
var http = require('http'), fs = require('fs'),
Canvas = require('canvas');
http.createServer(function (req, res) {
fs.readFile(__dirname + '/image.jpg', function(err, data) {
if (err) throw err;
var img = new Canvas.Image; // Create a new Image
img.src = data;
// Initialiaze a new Canvas with the same dimensions
// as the image, and get a 2D drawing context for it.
var canvas = new Canvas(img.width, img.height);
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, img.width / 4, img.height / 4);
res.write('<html><body>');
res.write('<img src="' + canvas.toDataURL() + '" />');
res.write('</body></html>');
res.end();
});
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
node-canvas now has a helper function, loadImage, that returns a Promise resolving to a loaded Image object. This prevents having to mess around with onload handlers like in the accepted answer.
const http = require('http');
const fs = require('fs');
const Canvas = require('canvas');
http.createServer(function (req, res) {
fs.readFile(__dirname + '/image.jpg', async function(err, data) {
if (err) throw err;
const img = await Canvas.loadImage(data);
const canvas = new Canvas(img.width, img.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, img.width / 4, img.height / 4);
res.write('<html><body>');
res.write('<img src="' + canvas.toDataURL() + '" />');
res.write('</body></html>');
res.end();
});
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
I want to merge 2 images using node.js. Or rather, i want to place one smaller image on cordinates x,y on a larger image.
Even more precise: I have an image of glasses, and an image of a face and i want to put the glasses on the face.
I did some googling, and found some image manipulating libraries, but none seem to be able to merge images.
You might need this: https://github.com/zhangyuanwei/node-images
Cross-platform image decoder(png/jpeg/gif) and encoder(png/jpeg) for Nodejs
images("big.jpg").draw(images("small.jpg"), 10, 10).save("output.jpg");
I do no have enough reputation to add a comment, or else I would to Schmidko's answer.
Sharp works well, however, overlayWith is deprecated and you instead need to use composite. See below:
sharp(path + 'example.jpg')
.composite([{input: path + 'logo.png', gravity: 'southeast' }])
.toFile(path + 'output.png');
If you would like to center the image being overlayed:
gravity: 'centre'
I've used:
https://github.com/learnboost/node-canvas
to do something similar (build a composite image from components on the fly).
It works great.
Here's some example code:
var Canvas = require('canvas'),
fs = require('fs'),
Image = Canvas.Image;
var _components = [{prefix:'f', count:12},
{prefix:'h', count:12},
{prefix:'i', count:12},
{prefix:'m', count:12}];
var _total = 1;
for (var i=_components.length - 1; i>=0; i--){
_components[i].mult = _total;
_total *= _components[i].count;
}
module.exports.ensureImageExists = function(img, cb){
fs.stat(__dirname + '/../public/images/rb/' + img, function(err, stats){
if (err){
if (err.code == 'ENOENT')
generateImage(img, cb);
else
cb(err);
}
else{
cb();
}
});
}
function generateImage(name, cb){
var re = /rb([0-9]*)\.png/
var num = parseInt(re.exec(name)[1]) % _total;
var parts = [];
for (var i=0; i<_components.length; i++){
var n = Math.floor(num / _components[i].mult);
parts.push(_components[i].prefix + (n + 1));
num -= n * _components[i].mult;
}
var canvas = new Canvas(45, 45),
ctx = canvas.getContext('2d');
drawParts();
function drawParts(){
var part = parts.shift();
if (!part)
saveCanvas();
else {
var img = new Image;
img.onload = function(){
ctx.drawImage(img, 0, 0, 45, 45);
drawParts();
};
img.src = __dirname + '/components/' + part + '.png';
}
}
function saveCanvas(){
canvas.toBuffer(function(err, buf){
if (err)
cb(err);
else
fs.writeFile(__dirname + '/../public/images/rb/' + name, buf, function(){
cb();
});
});
}
}
In this case, the components are selected based upon the name of the image, but you clearly could do otherwise. Also, I imagine you could just stream the image out if you wanted -- I write it to a file so it's available the next time it's requested.
I put a route like this in to handle the generation:
app.get('/images/rb/:img', requireLogin, function(req, res, next){
//first make sure image exists, then pass along so it is handled
//by the static router
rbgen.ensureImageExists(req.params.img, function(err){
next();
})
});
Tested some librarys for a similar task and implemented finally this one.
https://github.com/lovell/sharp.
Clean API and all you need to merge two images together.
Example:
sharp(path + 'example.jpg')
.overlayWith(path + 'label.png', { gravity: sharp.gravity.southeast } )
.toFile(path + 'output.png')