How to resize an image in Node.js? - node.js

I am scrapping information from e-commerce websites, in that information image also is there. Downloaded images are in different sizes. I want that images in default size. How to do it Node.js?

You can create a gulp/grunt task for this OR you can use available module called gm :GM MODULE
var gm = require('gm');
gm('/path/to/image.jpg')
.resize(353, 257)
.autoOrient()
.write(writeStream, function (err) {
if (!err) console.log(' hooray! ');
});

Related

Download image and resize in nodejs

What I am trying to do is download an image from google into my system repository in the project folder /download. Next, I am trying to get the image from the download repository and resize and again save the resized image in /thumbnail repository. Below is the code which I have written
//Google URL
var mainuri = 'http://images.sadhguru.org/sites/default/files/media_files/iso/en/64083-natures-temples.jpg';
var dir = './download';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
// CODE TO DOWNLOAD IMAGE FROM GOOGLE
var filename = dir+'/file.jpg';
request.head(mainuri, function(err, res, body){
console.log('content-type:', res.headers['content-type']);
console.log('content-length:', res.headers['content-length']);
request(mainuri).pipe(fs.createWriteStream(filename));
});
var resizedir = './thumbnail';
if (!fs.existsSync(resizedir)){
fs.mkdirSync(resizedir);
}
//CODE TO GET IMAGE FROM '/download' REPOSITORY AND RESIZE
var inputFile=require('path').join(__dirname,'../download/file.jpg'); //GET IMAGE FROM LOCAL
var outFile = 'thumbnail/newfile.jpg'; // SAVE RESIZED IMAGE PATH
// ------- CODE REMOVED - ERROR IS COMING HERE -----------
imageresize(inputFile, outFile); // FUNCTION THAT CONTAINS IMAGE RESIZE CODE
//imageresize FUNCTION
var imageresize = function(inputFile, outFile){
console.log(inputFile)
// input stream
let inStream = fs.createReadStream('C:/Users/rganji/caw/server/download/file.jpg');
// output stream
let outStream = fs.createWriteStream(outFile, {flags: "w"});
// on error of output file being saved
outStream.on('error', function() {
console.log("Error");
});
// on success of output file being saved
outStream.on('close', function() {
console.log("Successfully saved file");
});
// input stream transformer
// "info" event will be emitted on resize
let transform = sharp()
.resize({ width: 50, height: 50 })
.on('info', function(fileInfo) {
console.log("Resizing done, file not saved");
});
inStream.pipe(transform).pipe(outStream);
}
If I remove the code which I commented as CODE REMOVED - ERROR IS COMING HERE, then image is getting downloaded from google. If I call imageresize function then the /download directory is getting created but I couldnt find any image in the directory.
i.e, If I call the download from google and resizeimage functions separately, i.e calling image download from google first and imageresize next then they are working fine that is I can find images in both /download and /thumbnail directories. But If I call resizeimage function after google download then I couldnt find any image in both the repositories.
You need to wait for the image download to get finished before calling the imageresize function. Try this
request(mainuri).on('end', function() {
var inputFile=require('path').join(__dirname,'../download/file.jpg'); //GET IMAGE FROM LOCAL
var outFile = 'thumbnail/newfile.jpg'; // SAVE RESIZED IMAGE PATH
imageresize(inputFile, outFile);
});

Problems forming Imagemagick commands using nodejs gm module

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.

Write text on existing PNG with Node.js

I'm trying to create a simple dynamic-badge (png) to embed in static pages to let know the status of my application.
I'd like so to use an existing PNG image and write on it some text with Node.js.
I've found lot of libraries but all of them use Imagemagick or Cairo as native dependencies, I'd like to avoid to install anything else on the server.
I've then found lwip, but I can't really understand how to write text on an image with it. How can I do?
You could use Jimp. It has a print method:
var Jimp = require("jimp");
var fileName = 'test.png';
var imageCaption = 'Image caption';
var loadedImage;
Jimp.read(fileName)
.then(function (image) {
loadedImage = image;
return Jimp.loadFont(Jimp.FONT_SANS_16_BLACK);
})
.then(function (font) {
loadedImage.print(font, 10, 10, imageCaption)
.write(fileName);
})
.catch(function (err) {
console.error(err);
});
If you want to use a ttf file you can use gm
This will also align the text automatically so you don't have to keep track of your letter sizing / location.
const gm = require('gm').subClass({imageMagick: true});
gm('path/to/image.png')
.fill("#FFFFFF")
.font("./font.ttf", 20)
.drawText(15, 10, "your text", 'southeast') //can be any location
.write("./output.png", function (err) {
if (!err) console.log('done');
});

how to generate video thumbnail in node.js?

I am building an app with node.js, I successfully uploaded the video, but I need to generate a video thumbnail for it. Currently I use node exec to execute a system command of ffmpeg to make the thumbnail.
exec("C:/ffmpeg/bin/ffmpeg -i Video/" + Name + " -ss 00:01:00.00 -r 1 -an -vframes 1 -f mjpeg Video/" + Name + ".jpg")
This code is coming from a tutorial from http://net.tutsplus.com/tutorials/javascript-ajax/how-to-create-a-resumable-video-uploade-in-node-js/
the code above did generate a jpg file but it's not a thumbnail but a video screen shot, I wonder is there any other method to generate video thumbnail, or how to exec the ffmpeg command to make a real thumbnail (resized), and I prefer png file.
Reference to GitHub fluent-ffmpeg project.
Repeating example from original StackOverflow answer:
var proc = new ffmpeg('/path/to/your_movie.avi')
.takeScreenshots({
count: 1,
timemarks: [ '600' ] // number of seconds
}, '/path/to/thumbnail/folder', function(err) {
console.log('screenshots were saved')
});
Resize by adding a -s widthxheight option to your command.
There is a node module for this:
video-thumb
It basically just wraps a call to exec ffmpeg
I recommend using https://www.npmjs.com/package/fluent-ffmpeg to call ffmpeg from Node.js
Using media-thumbnail, you can easily generate thumbnails from your videos. The module basically wraps the ffmpeg thumbnail functionality.
const mt = require('media-thumbnail')
mt.forVideo(
'./path/to/video.mp4',
'./path/to/thumbnail.png', {
width: 200
})
.then(() => console.log('Success'), err => console.error(err))
You can also create thumbnails from your images using this package.
Instead I would recommend using thumbsupply. In addition to provide you with thumbnails, it caches them to improve performance significantly.
npm install --save thumbsupply
After installing the module, you can use it in a following way.
const thumbsupply = require('thumbsupply')("com.example.application");
thumbsupply.generateThumbnail('some-video.mp4')
.then(thumb => {
// serve thumbnail
})
app.post('/convert', upload.any(), (req, res) => {
console.log("calling", req.files)
let thumbNailName = req.files[0].filename.split('.')
var gm = require('gm');
gm('./src/Upload/'+req.files[0].filename)// get pdf file from storage folder
.thumb(
50, // Width
50, // Height
'./src/thumbnail/'+thumbNailName[0]+'.png', // Output file name
80, // Quality from 0 to 100
function (error, stdout, stderr, command) {
if (!error) {
console.log("processing");
} else {
console.log("error")
}
}
);
})

NodeJS: Asynchronous file read problems

New to NodeJS.
Yes I know I could use a framework, but I want to get a good grok on it before delving into the myriad of fine fine tools that are out there.
my problem:
var img = fs.readFileSync(path);
the above works;
fs.readFile(path, function (err, data)
{
if (err) throw err;
console.log(data);
});
the above doesn't work;
the input path is : 'C:\NodeSite\chrome.jpg'
oh and working on Windows 7.
any help would be much appreciated.
Fixed
Late night/morning programming, introduces errors that are hard to spot. The path was being set from two different places, and so the source path were different in both cases. Thankyou for your help. I am a complete numpty. :)
If you are not setting an encoding when reading a file, you will get the binary content.
So for example, the following snippet will output the content of the test file using UTF-8 encoding. If you don't use an encoding, you will get an output like "" on your console (raw binary buffer).
var fs = require('fs');
var path = "C:\\tmp\\testfile.txt";
fs.readFile(path, 'utf8', function (err, data) {
if (err) throw err;
console.log(data);
});
Another issue (especially on windows-based OS's) can be the correct escaping of the target path. The above example shows how path's on Windows have to be escaped.
java guys will just use this javascript asynchronous command as if in pure java , troublefreely :
var fs = require('fs');
var Contenu = fs.readFileSync( fILE_FULL_Name , 'utf8');
console.log( Contenu );
That should take care of small & big files.

Resources