Node Js NPM sharp. cannot write .gif to file - node.js

I am currently making an image resizer for a website (it resizes an image based on the the width of the container it is in).
I can successfully save and server jpeg's and png's however i cannot seem to save .gif's to a file.
This code works for the jpg's and png's
sharp(imgPath)
.resize(containWidth, Null)
.withoutEnlargement()
.toFile(modImgPath, function(err) {
if(err){console.log(err)}
});
I can get the gif's to display in the browser (With the code below) however i cannot save them to file.
sharp(imgPath)
.resize(modImgPath, null)
.withoutEnlargment()
.toBuffer(function(err, outputBuffer) {
if (err) {console.log(err)}
}
Iv looked into how to save image buffers to file however nothing seems to work.

Currently the gif output seems to be unsupported in sharp.
https://github.com/lovell/sharp/issues/162
https://github.com/lovell/sharp/issues/245
One solution, though I haven't tried to see if it works, is to change the output to another format. This will save the first frame of your gif.

Related

How can I stop ImageMagick failing due to SIGKILL?

I'm trying to resize GIF and PNG images using imagemagick.
Sometimes it fails just trying to identify the images:
im.identify(tempFilePath, function(err, features){
if (err) {
console.log(err);
return next();
}
}
So usually the process completes without issue, with both PNG and GIF. But when I upload a specific GIF image (sent to me by user, is a working gif file), I get this error:
{"error":{"timedOut":false,"killed":true,"code":null,"signal":"SIGKILL"}
I can't figure out what this means, seems like it maybe has to do with memory? Is there a way to prevent this from happening?

Load images from local directory in Fabric

I am trying to load images from a local folder using fabric.js in node.
There seems to be very little up to date documentation on how to do this.
Most example use fabric.Image.fromURL(imageurl)
As far as I'm aware, this only works for web urls, not local paths.
Correct me if I'm wrong, but I have tried
fabric.Image.fromURL(imgpath, (img) => {
...
}
which throws the error Coul not load img: /image/path/img.jpg
Where
fs.readFile(imagepath, (err, i) => {
...
})
will successfully read the file, i will be a buffer.
What is the correct way to load a local image.
I know there is a fabric.Image.fromObject but I have no idea what type of object it wants.
I am currently loading the image into a 2d canvas object, converting it with canvas.toDataURL() and putting that url into fabric.Image.fromURL() which works but converting the image to a url is very slow due to large images. There must be a way to load the image directly and avoid this problem.
If you are using fabricjs 3+, that uses the new jsdom, you can use the file urls!
fabric.Image.fromURL(file://${__dirname}${filepath});
Check here on the fabricJS codebase how they handle reading files in browser and node for the visual test images
https://github.com/fabricjs/fabric.js/blob/master/test/lib/visualTestLoop.js#L139
try this one:
fabric.Image.fromURL(require("../../assets/mockup/100.png"), (img) => {...}

How to render/generate image according to text/string in nodejs?

How can i generate an image of a string that has:
a size in px
embossed effect of the letters in the image
a font
a color
and other less important stuff that i think i can figure out once i achieve whats above like:
rotation of text
drop shadow
basically the user will send a request on how he wants his image to be.
but when i receive the request how should i make use of nodejs to render a png or a base64 url to send it back to the user. is there any libraries or way to achieve this.
i did some previous research and it doesn't seem like there is a frameworks that helps render text with a font and text style like emboss
You can try node canvas implementation: https://github.com/Automattic/node-canvas
Basically you can "draw" anything you want like if you'd be using browser js canvas, but some things may be different
Update - This will cover updating attributes of an image, not pulling text from image and updating that - you may need an image analysis library for that
Use the sharp library to manipulate the image as desired. https://github.com/lovell/sharp
http://sharp.dimens.io/en/stable/
A simple example that resizes (docs will show how to make the changes you want outside of this):
const request = require('request').defaults({ encoding: null });
request.get(imgUrl, params, function (err, res, body) {
sharp(body)
.resize(params.width, params.height)
.toFormat('jpeg')
.toBuffer()
.then((outputBuffer) => {
// outputBuffer contains JPEG image data no wider than params.width and no higher
// than params.height while maintaining quality of image.
let output = "data:" + res.headers["content-type"] + ";base64," + new Buffer(outputBuffer).toString('base64');
return output;
});
The output here will be the base64 image

Pipe image output from Graphics Magic to response without base64 encoding

I have a Node server where, instead of storing cropped images, I want to crop them in response to an AJAX call, and send them to the client that way. I'm storing the information of what to crop and how to crop it in cookies and the body. On the server I crop it, encode it in base64, and send it back the user. Here is what my code looks like
res.set('Content-Type', 'image/jpeg');
gm(request(body.URL))
.crop(req.cookies[name+"Width"],req.cookies[name+"Height"],req.cookies[name+"X"],req.cookies[name+"Y"])
.stream(function streamOut (err, stdout, stderr) {
if (err) return next(err);
stdout.pipe(base64encode()).pipe(res);
stdout.on('error', next);
});
This works, but I don't like it. I was only able to get this to work by encoding it in base64, but on the client side this is seems slow to decode this to an image. I would rather just send an image directly, but I was unable to get this to work. Pipping the image without decoding it resulted in a gibberish response from the server. Is there a better way to do this? Or does the unsaved image have to be encoded in order to send?
I have no idea how you write node.js - it all looks like a bunch of dots and parentheses to me, but using what I know about the GraphicsMagick command line, I tried this and it does what I think you want - which is to write a JPEG encoded result on stdout:
// Send header "Content-type: image/jpeg"...
var gm = require('gm');
var input = 'input.jpg';
gm(input).resize(350).toBuffer('JPG',function (err, buffer) {
if (err) return handle(err);
process.stdout.write(buffer);
})
Update
Have you considered ruling out the AJAX aspects and just using a static src for your image that refers to the node script? As I said, I do not know node and Javascript but if I generate a thumbnail via a PHP script, I would add this into the HTML
<img src="/php/thumb.php"/>
So that just invokes a PHP script to generate an image. If you remove the /php/thumb.php and replace that with however you have named the node script I suggested above, it should tell you whether the problem is the AJAX or the GraphicsMagick aspects...

Composite images in Graphicsmagick

I'm trying to request an image from an API and "paste" it on top of another image. In Photoshop, I would paste the image into a new layer and then merge the layers. I can accomplish this with Graphicsmagick using gm's composite().
gm().command("composite")
.in("path/to/topImg.png")
.in("path/to/bottomImg.png")
.toBuffer('PNG', function(err, buffer) {
if (!err) {return buffer;}
});
However, composite only takes file paths. So let's say I want to get the logo from http://www.google.com. I could save the image, use it in the code above, and then delete it. What I'm looking for is a way to accomplish this without having to save the image to disk first.
You can use URL directly as image path, without downloading and saving it
gm()
.command("composite")
.in("http://someurl...")
.in("http://someurl...")
.toBuffer('PNG', function(err, buffer) {
if (!err) {return buffer;}
});
But GraphicsMagick uses the HTTP support from libxml2, which does not currently support HTTPS. So if you want to download images over HTTPS you will need external program.

Resources