I am trying to run an imageMagick command on AWS Lambda and using the gm module. I keep getting an error no decode delegate for this image format `' # error/constitute.c/ReadImage/544. I believe this error indicates that my syntax isn't correct for the command. I've tried many ways. I can run this command on the command line on my Linux system fine.
Here's the command. (adapted from here)
convert test.jpg -crop 120x120+300+300 -colorspace gray -format "%[fx:100*mean]%%" info:
Here's my function.
gm(imgobj,'test.jpg').command('convert')
.in('-crop', '120x120+300+300','-colorspace','gray','-format','%[fx:100*mean]%%')
.out('info:')
.stream(function (err, stdout, stderr) {
});
gm nodejs module. is here.
SOLVED!
gm(imgobj,'test.jpg').command('convert')
.in('-crop', '120x120+300+300')
.in('-colorspace', 'gray')
.toBuffer(function(err, buffer) {
if(err) throw err;
gm(buffer, 'test.jpg').identify({bufferStream: true, format:'%[fx:100*mean]'},function(err, data) {
if(err) throw err;
console.log('identify',data);
});
});
The documentations mentions this "GOTCHA":
When working with input streams and any 'identify'operation (size,
format, etc), you must pass {bufferStream: true} if you also need to
convert (write() or stream()) the image afterwards (NOTE: this buffers
the readStream in memory!).
The documentation says to use: gm().identify(format, callback) and this seems to work for me without setting bufferStream: true. I suppose that is correct since I do not "need to stream the image afterwards." However, for general knowledge, I looked at the source and figured out how to pass both params {bufferStream: true, format:'%[fx:100*mean]'} format being the escape argument.
Related
I know the solution is very simple, but it's an hour I'm banging my head.
In Windows 10, if i launch the command "dir", i got this result:
Il volume nell'unità D non ha etichetta.
in Node js i try to exec the dir command in this way:
var child = exec('dir', {'encoding': 'UTF-8'}, (err, stdout, stderr) => {
console.log(stdout);
});
and i got this result:
Il volume nell'unit� C non ha etichetta.
Ah, damned accented letter!
I tried using UTF-16 and then, convert to string:
var child = exec('dir', {'encoding': 'UTF-16'}, (err, stdout, stderr) => {
let b: Buffer = stdout;
let o: string;
o = stdout.toString('UTF-8');
console.log(o);
});
I get the same cursed result:
"Il volume nell'unit� C non ha etichetta."
Can you help me to solve this rebus?
What am I doing wrong?
It almost seems that the exec command does not accept UTF-8 encoding
In fact, if I run this script to force conversion from UTF-8 to string:
var child = exec(j.cmd, {'encoding': 'UTF-8'}, (err, stdout, stderr) => {
var utf8 = require('utf8');
var o: string = utf8.decode(stdout)
console.log(o);
});
i got this error:
..\node_modules\utf8\utf8.js:194
throw Error('Invalid UTF-8 detected');
Any idea?
When you use dir in the command prompt the renderer knows which character encoding stdout is using, decodes the text bytes and renders the characters with the selected font.
When you exec a command, node does not know which character encoding stdout is using, so you tell it. The problem is you are telling it the wrong thing. To see which character encoding it is, go chcp. But, out-of-the-box, node only supports some of the dozens of characters encodings.
The solution is to tell the command prompt to use one they have in common. Since you are getting paths from the filesystem and the filesystem (NTFS) uses the Unicode character set for paths, UTF-8 is a great choice.
So, this should work:
exec('#chcp 65001 >nul & dir', {encoding: "UTF-8"},
(err, stdout, stderr) => console.log(stdout));
But, the chcp command has a delayed effect and isn't applied to the dir command. Here is one way of working around that:
exec('#chcp 65001 >nul & cmd /d/s/c dir', {encoding: "UTF-8"},
(err, stdout, stderr) => console.log(stdout));
Running a batch file might be a simpler way to get two separate commands to run with sequential effect but that would require setup and clean up.
Node.js does not support your encoding which used by windows cmd.exe, so you have to use a library like iconv-lite to convert it.
var child = exec('dir', {'encoding': 'buffer'}, (err, stdout, stderr) => {
console.log(iconv.decode(stdout, 'CP936'));
});
use buffer to get the original raw strings
replace your encoding string rather than 'CP936'. You can found it in cmd.exe > Properties > codepage.
Update: replace with your country's encoding also works fine. In my case, 'GB18030' or 'GBK' contains 'CP936', both can be used.
Is's my code that works on localhost, but not on EC2 (I used Elastic BeanStalk). I get error: Stream yields empty buffer on toBuffer function. Can somebody explain how to fix it? I saw this post, but I didn't understand how to add JPEG support in EC2.
var _45px = { width: 45, dstnKey: fileName, destinationPath: "thumbnails" };
function convert(response, next) {
console.time("convertImage");
console.log("Reponse content type : " + response.ContentType);
console.log("Conversion");
GM(response.Body, fullName).antialias(true).density(300).setFormat('jpeg').toBuffer(
function(err, buffer) {
if (err) {
next(err);
} else {
console.timeEnd("convertImage");
next(null, buffer);
}
});
}
I faced a similar problem with PNG format. The problem arises because EC2 instances does not have support for PNG and JPEG, so we need to install the required dependencies accordingly, else the imagemagick (or graphicmagick) does not return any stream value as output.
For adding PNG support I have tried uninstalling graphicsmagick module and then installed the dependencies and reinstalled graphicsmagick:
apt-get install libpng-dev,
apt-get install graphicsmagick
(In your case this would be imagemagick)
This solved the problem. I believe for jpeg support the library would be:
libjpeg-dev.
These are for EC2 ubuntu instances
I've been trying to convert a transparent EPS file to a transparent PNG file using graphicsmagic for node (http://aheckmann.github.io/gm/).
It needs to behave the same way as the following command (preserving transparency of the EPS)
convert -colorspace srgb in.eps out.png
The above command works as expected but when I try it in node with the following code it does not retain transparency.
var gm = require('gm').subClass({ imageMagick: true });
gm("in.eps").colorspace("srgb").write("out.png", function (err) {
if (!err) {
console.log('done');
}
});
I've also tried forcing the type TrueColorAlpha and setting the bit depth but to no avail.
Hopefully someone van advise on what I'm doing wrong or which information I'm missing.
For anyone stumbling upon this problem as well, this solved it for me.
var gm = require('gm').subClass({ imageMagick: true });
gm("in.eps").in("-colorspace").in("srgb").write("out.png", function (err) {
if (!err) {
console.log('done');
}
});
You need to add two custom in parameters to apply colorspace to the input EPS image.
How do you "Convert" a file from one type to another using gm? (e.g .png > .jpg)
I found this but it doesn't seem that the node.js version has the same method:
You'll need to change the format of the output file.
var writeStream = fs.createWriteStream("output.jpg");
gm("img.png").setFormat("jpg").write(writeStream, function(error){
console.log("Finished saving", error);
});
http://aheckmann.github.io/gm/docs.html#setformat
I'm using http.request to download JPEG file. I am then using fs.writeFile to try to write the JPEG file out to the hard drive.
None of my JPEG files can be opened, they all show an error (but they do have a file size). I have tried all of the different encodings with fs.writeFile.
What am I messing up in this process?
Here's what the working one is showing when viewing it raw:
And here is what the bad one using fs.writeFile is showing:
Figured it out, needed to use res.setEncoding('binary'); on my http.request.
Thank you, looking to the previous response, I was able to save de media correctly:
fs.writeFile(
filepath + fileName + extension,
mediaReceived, // to use with writeFile
{ encoding: "binary" }, // to use with writeFile ***************WORKING
(err) => {
if (err) {
console.log("An error ocurred while writing the media file.");
return console.log(err);
}
}
);