Tuesday, February 20, 2018

how to resize an image and get it at the runtime in nodejs?

Image resize / thumbnail feature is most useful to display image in multiple thumbnails in the website as per image size.
We can resize an image in two way.
1) we can resize an image when the image is uploaded.
2)resize an image when actually need.

Type one has the main drawback is that if we need some more thumbnail image sizes after image uploaded or latter, we have to make this all thumbnails manually or we have to remove this images records and re-enter all data with the images.
To overcome this problem we will see the following demo, how to create resized / thumbnails image or get if available at runtime.

assume we have main images in "app/client/upload" directory and we have all resized images in "app/client/resize" directory. you can use this as directories path as per your project structure.

EX: Add middleware in your nodejs application using expressjs

var resize = require("./resize");

app.get("/resize/*", function(req, res) {
        console.log("resize url called:" + req.url);
        var url = req.url.replace("//", "/");
     
        var scale = url.split("/")[2];
        var originFolder = url.split("/")[3];
        var width = scale.split("x")[0];
        var height = scale.split("x")[1];
        var folder_ = path.join(originFolder);
        var filename = path.basename(url);
        var resizeFileName = path.join(path.resolve(__dirname + "/"), "app/client/resize", scale, originFolder, filename); // path.resolve(__dirname + "/"), "app/client/resize" => your resize directory full path
        var originalPath = path.join(path.resolve(__dirname + "/"), "app/client", originFolder, filename);// path.resolve(__dirname + "/"), "app/client" => your main image directory full path

        if (false === fs.existsSync(resizeFileName)) {
            resize.resizeImage(width, height, originFolder, scale, filename, originalPath, resizeFileName, res);
        } else {
            var img = fs.readFileSync(resizeFileName);
            res.writeHead(200, { 'Content-Type': 'image/jpg' });
            res.end(img, 'binary');
        }
    });

EX: resize.js

var path = require("path");
var fs = require("fs");
var im = require("imagemagick");
var gm = require("gm");
var sizeOf = require("image-size");
var async = require("async");

// Resize image
var resizeImage = function (resizeWidth, resizeHeight, originFolder, scale, fileName, originalPath, resizePath, res) {
    var resizeOption;
    var originalHeight, originalWidth;
    async.waterfall([
            function (callback) {
                originFolder = path.join(originFolder);
                var dimension = sizeOf(originalPath);
                originalHeight = dimension.height;
                originalWidth = dimension.width;
                callback(null);
            },
            function (callback) {
                resizeOption = "exact"; //OR aspectratio
                if (!!resizeOption) {
                    extension = path.extname(fileName).split(".")[1];
                    switch (extension) {
                        case "jpg":
                        case "jpeg":
                            //console.log("jpg processing");
                            contentType = "image/jpg";
                            break;
                        case "png":
                            //console.log("png processing");
                            contentType = "image/png";
                            break;
                        case "gif":
                            //console.log("gif processing");
                            contentType = "image/gif";
                            break;
                        case "svg+xml":
                            //console.log("gif processing");
                            contentType = "image/svg+xml";
                            break;
                        case "svg":
                            //console.log("gif processing");
                            contentType = "image/svg";
                            break;
                    }
                 
                    var objFile = fs.statSync(originalPath).isFile();
                    if (objFile === true) {
                        callback(null, resizeOption, contentType);
                    } else {
                        callback("Image not available.");
                    }
                }
            },
            function (resizeOption, contentType, callback) {
                if (true === fs.existsSync(resizePath)) {
                    callback(null, contentType);
                } else {
                    if ("exact" === resizeOption) {
                        gm(originalPath)
                            .thumbExact(resizeWidth, resizeHeight, resizePath,
                                function (err) {
                                    if (!err) {
                                        callback(null, contentType);
                                    } else {
                                        callback("error in gm(originalPath).thumbExact(): " + err);
                                    }
                                });
                    } else {
                        if (originalHeight > originalWidth) {
                            resizeWidth = resizeWidth / 2;
                        }
                        gm(originalPath)
                            .resize(resizeWidth)
                            .noProfile()
                            .write(resizePath, function (err) {
                                if (!err) {
                                    callback(null, contentType);
                                } else {
                                    callback("error method resize().noProfile().write(): " + err);
                                }
                            });
                    }
                }
            }
        ],
        function (err, contentType) {
            var img = fs.readFileSync(resizePath);
            res.writeHead(200, {
                'Content-Type': contentType
            });
            res.end(img, 'binary');
        });
};

module.exports = {
    resizeImage: resizeImage
};

EX: html file

<img src="http://localhost/resize/100x100/upload/image1.jpg">

<img src="http://localhost/resize/70x900/upload/image2.jpg">

<img src="http://localhost/resize/200x100/upload/image3.jpg">

from the above demo, a new image will create if not found in resize directory and if image found then it will show.

You have to create  100x100, 70x900, 200x100 and it's subdirectory upload in resizing directory.

Now you can use this feature easily on your website.

No comments:

Post a Comment