node圖片處理工具gm的使用:圖片水印、圖片驗證碼、圖片裁剪示例

請在這裏查看示例 gm示例

安裝

GraphicsMagick和ImageMagick的區別

  • GraphicsMagick是從ImageMagick中分離出來的,推薦下載ImageMagick
  • 加載GraphicsMagick(大小4.72 MB)
    var gm = require('gm')

  • 加載ImageMagick(大小23.8 MB)
    var gm = require('gm').subClass({imageMagick: true})// 注意使用的區別

  • 除了加載有區別,其他使用方式完全一樣

window版本

  • 下載imagemagick的window版本(在頁面靠下方),如圖:
    這裏寫圖片描述
  • 雙擊exe文件,進行安裝,安裝過程中要注意勾選以下選項
    這裏寫圖片描述

linux版本(ubuntu 16.04)

要點

圖片水印

var gm = require('gm').subClass({imageMagick: true})

gm('./public/images/a.png')// 原圖路徑
.font('./fonts/zhulangyingxingti.ttf')// 配置逐浪硬行體字庫路徑
.drawText(10, 10, '水印')
.write('./public/images/b.png', function (e) {// 輸出的圖片路徑
    if(e) {
        console.log(e.message)
    }else {
        console.log('done')
    }
})

drawText()中文亂碼

  • 字體文件使用中文名稱命名,運行時會報錯,所以不要使用中文命名
    這裏寫圖片描述
  • 如果確保字庫引入正確,還出現中文亂碼,那一定是字庫文件本身有問題,換一種字庫就可以了
  • 嘗試過字庫格式ttf、otf均支持
    詳見:
    字庫ttf和otf格式有什麼區別?

圖片驗證碼

  • 準備一張背景雜亂的圖片和藝術字體的英文字庫
    這裏寫圖片描述
  • index.html

    <img src="/gm/captchaAdd"><!-- 前端通過img標籤請求驗證碼 -->
  • app.js

    var express = require('express')
    var session = require('express-session')
    ...
    
    var cap = {// 通過函數隨機出一個驗證碼對象,包括文字和在雜亂背景上的位置(這裏假如如下)
        text: 'ab12',
        pos: [20, 50],
    }
    
    // 生成驗證碼
    app.all('/gm/captchaAdd', function(req, res, next) {
        var url = './public/images/'+(''+Math.cap()).replace('.', '')+'.png'// 設置驗證碼的輸出路徑,且給一個隨機文件名
    
        gm('./lib/images/captchaBg.png')// 一張背景雜亂的圖片作爲驗證碼的背景
        .font('./lib/src/SelfRighteousness-Regular.ttf')// 一種略藝術的英文字庫
        .fontSize(50)// 設置字體大小
        .drawText(cap.pos[0], cap.pos[1], cap.text)// 寫入隨機的驗證碼
        .crop(100, 40, cap.pos[0], cap.pos[1])// 將相應的文字部分裁剪出來,作爲驗證碼
        .noise(1// 加入噪點
        .write(url, function (e) {// 隨機一個文件名,並輸出驗證碼
            if(e) {
                console.log(e.message)
            }else {
                req.session.captcha = cap// 將驗證碼對象寫入session,用來登錄時跟用戶輸入的作比較
                res.download(url)// 這裏用download方法發送圖片,前端千萬不能用ajax方式請求
            }
        })
    })
    
    // 用戶登錄
    app.all('/user/login', function(req, res, next) {
        if(req.body.captcha.toLocaleLowerCase() != req.session.captcha.text.toLocaleLowerCase()) {
            res.send({message: '驗證碼不正確'})
        }else {
            ...
        }
    })
  • 效果如下
    1. 這裏寫圖片描述 2. 這裏寫圖片描述 3. 這裏寫圖片描述
  • 最後可以通過AI開放平臺提供的文字識別技術來測試機器識別的效果
  • 升級版驗證碼(參考慕課網)
    • 用戶使用某個用戶名嘗試登陸,如果錯誤,將給該用戶名在數據庫記錄一次錯誤
    • 該用戶名錯誤次數達到3次,要求需等待半小時後才能再次嘗試登錄該用戶名,且必須輸入驗證碼
    • 所以當用戶來到登錄頁面時,在輸入用戶名之後(或從cookie拿到記錄的用戶名),需要發送一個請求去驗證此用戶名是否需要輸入驗證碼,如需要,將驗證碼輸入框顯示出來
    • 這個有個問題就是,其他用戶可以通過故意錯誤的登錄某些用戶名,來使這些用戶名永遠處於等半小時的狀態,導致永遠無法登陸(不過爲了用戶安全,犧牲一點用戶體驗也是值得的)

詳見:
使用session實現一次性驗證碼

頭像裁剪

  • 下面我給出4種方式的思路
  • 方式1(本篇提供的demo即使用此方法)
    • 前端使用上傳插件Webuploader來提供上傳圖片的功能
    • 前端使用Jcrop來提供裁剪的位置
    • 後端使用gm根據給出的裁剪位置對上傳的圖片進行裁剪
  • 方式2(可以藉助jquery-plugins/h5Crop/插件,該插件我會繼續完成)
    • 前端利用canvas實現裁剪和壓縮,將處理後的base64傳給後端
    • 後端將base64轉化成圖片,返回給前端進行展示
  • 方式3
    • 前端把圖片傳給後端
    • 後端壓縮處理過之後,返回給前端(附帶圖片唯一標識)
    • 前端使用Jcrop獲取圖片的裁剪位置,將裁剪位置和圖片唯一標識傳給後端
    • 後端對對應的圖片進行裁剪
  • 方式4(這個需要藉助我的另一個裁剪插件,提供了2種方式進行裁剪,效果跟qq裁剪頭像一樣,以後會開源)
    • 前端裁剪
      • 前端通過js對圖片進行平移、縮放操作
      • 再通過canvas的drawImage方法繪製操作後的圖片
      • 再通過canvas的toDataURL進行壓縮同時獲取最終的base64
      • 傳base64到後端,後端轉爲圖片,返回圖片路徑,前端進行展示
    • 後端裁剪
      • 前端通過js對圖片進行平移、縮放操作
      • 將操作後獲取的裁剪參數(裁剪框的大小、縮放的比率、壓縮的比率)和圖片文件一同傳給後端
      • 後端對上傳的文件進行裁剪,返回圖片路徑,前端進行展示
    • 需使用到的ImageMagick小細節
      • 讀取本地圖片資源gm('upload\\temp\\crop\\20180601\\49076530-6584-11e8-9542-0d60dcc7daa8.jpg'))
      • 讀取外鏈圖片資源gm('http://localhost:3000/upload/temp/crop/20180601/49076530-6584-11e8-9542-0d60dcc7daa8.jpg'))
      • 讀取base64圖片資源'inline:' + 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBD...')(注意不適用超過5000個字符的base64字符串,否則會轉換失敗)
      • 爲了解決base64過長時ImageMagick處理會失敗,我們使用node來轉換base64爲圖片
      • 縮放圖片傳入百分比gm('xxx.png').resize('50%'))
      • 壓縮圖片傳入值gm('xxx.png').quality(50))
      • 不管是前端canvas壓縮還是後端ImageMagick壓縮,最後的輸出的格式都要是jpeg或jpg,否則壓縮後的大小很可能會變大
    • 效果展示(動圖較大,請耐心等待)
      這裏寫圖片描述
  • 優缺點對比
    • 方式1:後端只要寫1個接口(Webuploader對圖片可以進行壓縮)
    • 方式2:兼容性IE>=10,減少後端工作量
    • 方式3:適中,後端需要寫2個接口(上傳圖片接口和裁剪圖片接口)
    • 方式4:編寫複雜,但是擴展性好,可自由選擇一種方式

參考

gm官方文檔

nodejs圖片處理工具gm用法

nodejs gm drawText使用(中文、字體、大小及顏色)

ImageMagick常用操作

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章