Create Image Watermark using Nodejs

Nay mình sẽ làm một chức năng đó là "watermark" cho hình ảnh. Watermark thường được dùng nhiều trong website, chẳng hạn người dùng muốn add một logo lên tấm hình của sản phẩm, ta có thể dùng cách này để thêm hàng loạt nhé


Trong Nodejs có một thư viện giúp ta xử lý vấn đề này "jimp"

npm install --save jimp

jimp : Là một thư viện xử lý hình ảnh được hổ trợ trên Nodejs, được viết bằng ngôn ngử javascript, có các loại hổ trợ sau
@jimp/jpeg
@jimp/png
@jimp/bmp
@jimp/tiff
@jimp/gif

Bạn có thể tìm hiểu thêm tại đây : https://www.npmjs.com/package/jimp

Okay, sau khi bạn đã cài đặt xong, ta tiến hàng setup nó thử xem sau : 

const Jimp = require("jimp");

const ORIGINAL_IMAGE =__dirname+"/images/create-project-laravel5_8-using-composer-01.jpg";

const LOGO = __dirname+"/images/logo.png";

//save image name
const FILENAME = "create-project-laravel5_8-using-composer-01.jpg"; 

const main = async (a) => {
 
  const [image, logo] = await Promise.all([
    Jimp.read(a),
    Jimp.read(LOGO)
  ]);

  logo.resize(logo.bitmap.width , Jimp.AUTO);

  const X=10; 
  const Y=10;

  return image.composite(logo, X, Y, [
    {
      mode: Jimp.BLEND_SCREEN,
      opacitySource: 0.1,
      opacityDest: 1
    }
  ]);
};

main(ORIGINAL_IMAGE).then(image => image.write(FILENAME));

Để chạy project chạy câu lệnh CMD sau:

node watermark.js 

Các bạn sẽ thấy được hình được save tại project, các bạn hãy mở lên xem thử nhé.
Trong bài viết này mình chỉ các bạn cách tạo watermark lên hình ảnh rồi, các bạn có thể kết hợp với bài viết Crawl Data Website Using Nodejs 
để có thể vừa download hình ảnh về và vừa làm watermark hình ảnh luôn một lượt nhé!

 

Full Code Crawl Data Website and Image Watermark 

//file: index.js
const rp = require("request-promise");
const cheerio = require("cheerio");
const request = require('request');
const url = require('url')
const https = require('https')
const sizeOf = require('image-size')
const fs = require("fs");
const dslink = "dslink.txt";
const domain = "https://hoanguyenit.com";
const img_width=500;
const img_heigth=250;

///watemat
const Jimp = require("jimp");
const LOGO = __dirname+"/images/logo.png";
const main = async (a) => {
    //  console.log( a);
    const [image, logo] = await Promise.all([
      Jimp.read(a),
      Jimp.read(LOGO)
    ]);
  
    logo.resize(logo.bitmap.width , Jimp.AUTO);
   // const X=30;
   // const Y=image.bitmap.height - logo.bitmap.height;
    //console.log(X +"/"+Y);
    const X=10;
    const Y=10;
  
    return image.composite(logo, X, Y, [
      {
        mode: Jimp.BLEND_SCREEN,
        opacitySource: 0.1,
        opacityDest: 1
      }
    ]);
  };
//end
  


var array = fs.readFileSync(dslink).toString().split("\n");
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
function removeItemAll(arr, value) {
    var i = 0;
    while (i < arr.length) {
        if (arr[i] === value) {
            arr.splice(i, 1);
        } else {
            ++i;
        }
    }
    return arr;
}
async function crawler() {
    await sleep(1000);
    for (i in array) {
        const linkchay = array[i];

        try {
            const options = {
                uri: linkchay,
                transform: function (body) {
                    //Khi lấy dữ liệu từ trang thành công nó sẽ tự động parse DOM
                    return cheerio.load(body);
                },
            };
            var $ = await rp(options);
        } catch (error) {
            console.log("Link dang dung:" + array[i]);
            return error;
        }

        /* Lấy tên và miêu tả của tutorial*/
        const title = $(".ten_title").text().trim();
        //const description = $(".entry-content > p").text().trim();

        /* Phân tích các table và sau đó lấy các posts.
           Mỗi table là một chương 
        */
        const tableContent = $(".info_content");
        let data = [];
        // Tên của chương đó.
        let chaperTitle = tableContent.find("p").text().trim();


        //Tìm bài viết ở mỗi chương
        let namefile = "";
        let chaperData = []
        const chaperLink = tableContent.find("p").find("img");
     
        for (let j = 0; j < chaperLink.length; j++) {
            const post = $(chaperLink[j]);
            const postLink = post.attr("src");
            //download
            const n = postLink.lastIndexOf("/");
            const filename = postLink.substring(n + 1, postLink.length);
            namefile = filename;
            download(postLink, filename, function () {
                //console.log("Link:"+linkchay);
            });
            const postTitle = post.text().trim();
            chaperData.push({
                postTitle,
                linkchay,
                filename,
            });
        }
        data.push({
            chaperTitle,
            chaperData,

        });


        // Lưu dữ liệu về máy
        fs.writeFileSync('data.json', JSON.stringify(data))
        console.log(linkchay + "------------->done");
        removeItemAll(array, linkchay);
        await sleep(1000);
    }


};

crawler();

async function getFilesizeInBytes(filename) {
    const stats = fs.statSync(filename);
    const fileSizeInBytes = stats.size;
    return fileSizeInBytes;
}

var download = function (uri, filename, callback) {
    var link = "";
    if (uri.search("https") == -1) {
        link = domain + "/" + uri;
    } else {
        link = uri;
    }
  
    const imgUrl = link;
    const options = url.parse(imgUrl);
    https.get(options, function (response) {
        const chunks = []
        response.on('data', function (chunk) {
          chunks.push(chunk)
        }).on('end', function() {
          const buffer = Buffer.concat(chunks)
          let width = sizeOf(buffer).width;
          let height = sizeOf(buffer).height;
          //check size image mà ta muốn lấy
          if(width>200 && height>200){
            request.head(link, function (err, res, body) {
                if(res.statusCode==200){
                    request(link).pipe(fs.createWriteStream('./images/' + filename)).on('close', callback);
                    setTimeout(function(){
                        main(__dirname+"/images/"+filename).then(image => image.write(__dirname+"/luu/"+filename));
                    },2000);
                   
                }
                
            });
          }
        })
    })

   
};

Đoạn code trên là mình kết hợp 2 bài viết lại với nhau để vừa download hình ảnh và vừa watermark cho hình ảnh luôn nhé

Bài Viết Liên Quan

Messsage

Ủng hộ tôi bằng cách click vào quảng cáo. Để tôi có kinh phí tiếp tục phát triển Website!(Support me by clicking on the ad. Let me have the money to continue developing the Website!)