Alex028502
Alex028502

Reputation: 3824

image corrupted when I run imagemagick convert inside node.js with exec and then pipe the result to a file

Here is a test program called test-program.js where I run an imagemagick command, and try print stdout of the command to stdout of this program, and then save it to a file:

const util = require('util');
const exec = util.promisify(require('child_process').exec);

(async function() {
  const cmd = `convert -background red -fill black -gravity center -size 50x50 label:':)' jpg:-`;
  const result = await exec(cmd);
  console.log(result.stdout);
})();

I try to run it like this

node test-program.js > test.jpg

and the jpg will not open

enter image description here

However, if I run it right on the command line like this:

convert -background red -fill black -gravity center -size 50x50 label:':)' jpg:- > test.jpg

enter image description here the jpg is fine

here are two versions of the program that do work as expected:

call command with node, but make the command write directly to the file

const util = require('util');
const exec = util.promisify(require('child_process').exec);

(async function() {
  const cmd = `convert -background red -fill black -gravity center -size 50x50 label:':)' test.jpg`;
  const result = await exec(cmd);
  console.log(result.stdout);
})();

just write 'hello' into the file with a simpler command:

const util = require('util');
const exec = util.promisify(require('child_process').exec);

(async function() {
  const cmd = `echo hello`;
  const result = await exec(cmd);
  console.log(result.stdout);
})();

So I am pretty sure the command is executing as it should, that it is producing the output it should, and that the wrapper usually writes the output to stdout without a problem. (or maybe with an extra line at the end)

I have also tried converting the string to a buffer with no luck.

Upvotes: 2

Views: 321

Answers (1)

Alex028502
Alex028502

Reputation: 3824

if it helps anybody, two changes are needed to make it work on node 12:

const result = await exec(cmd, {encoding: null}); // enconding: null
process.stdout.write(result.stdout); // instead of console log

like this:

const util = require('util');
const exec = util.promisify(require('child_process').exec);

(async function() {
  const cmd = `convert -background red -fill black -gravity center -size 50x50 label:':)' jpg:-`;
  const result = await exec(cmd, {encoding: null});
  process.stdout.write(result.stdout);
})();

thanks for your suggestion @mark-setchell

Upvotes: 3

Related Questions