zoukankan      html  css  js  c++  java
  • 调用imagemagick做响应图片

    设计出图后经常需要改下尺寸放在别的项目上使用,每次都是设计手工处理,其实图片服务可以做更多事情,比如借助强大的im,可以通过url控制图片尺寸

      1 var childProcess = require('child_process')
      2 var path = require('path')
      3     ,http = require('http')
      4     ,fs = require('fs')
      5 
      6 const dns_host = 'xxx.net' //图片源站地址
      7 const PATH_IMGS = '/home/work/demo/images' //目录存放
      8 const PATH_IMG_TMP = '/home/work/demo/images' //临时目录
      9 //图片尺寸参数
     10 // /pic/_hd/cd/19/d6d821de10662d5352ff2d6bbaf2_960_420.cj.100x100x15.jpg
     11 const REG_RESIZE_OPT = /.(d+)?x(d+[!><]?)?x(d+)?.jpg/  
     12 //图片质量 默认85
     13 //  /pic/_hd/cd/19/d6d821de10662d5352ff2d6bbaf2_960_420.cj.q100.100x100x15.jpg
     14 const REG_QUALITY_OPT = /.q(d+).jpg/  //图片质量参数
     15 
     16 http.createServer(function(req, res) {
     17     var imgurl = req.url
     18         ,cdn_path = imgurl
     19     var options = cdn_path.match(REG_RESIZE_OPT )
     20     var img_suffix = path.extname(cdn_path)
     21     var opt_img = {}
     22     if (options){
     23         opt_img =
     24             {
     25             "width" : options[1] || ''
     26             ,"height" : options[2] || ''
     27             ,"mode" : options[3] | 0 || 1
     28             ,"imgurl" : imgurl
     29             }
     30         cdn_path = cdn_path.replace(REG_RESIZE_OPT, img_suffix)
     31     }
     32 
     33     options = cdn_path.match(REG_QUALITY_OPT)
     34     if (options) {
     35         opt_img.quality = options[1] | 0
     36         cdn_path = cdn_path.replace(REG_QUALITY_OPT, img_suffix)
     37     }
     38     opt_img.quality = opt_img.quality || 85
     39     if (opt_img.quality >= 100) delete opt_img.quality
     40 
     41     
     42     http.get('http://' + dns_host + cdn_path , function(response){
     43         //因为图片size变了 去掉content-length
     44         delete response.headers['content-length']
     45         res.writeHead(response.statusCode , response.headers)
     46         if (200 !== response.statusCode) return response.pipe(res)
     47         
     48 
     49 
     50         var file_tmp = path.resolve(PATH_IMG_TMP , 'tmp_' + (+new Date).toString(24) + (img_suffix || ''))
     51         //抓取远程图片 临时存图
     52         var writeStream = fs.createWriteStream(file_tmp)
     53         response.pipe(writeStream)
     54 
     55         writeStream.on('error' ,function(err){
     56             console.log('err' , err)
     57             res.end(err.toString())
     58         })
     59 
     60         response.on('end' ,function(err){
     61             imgWorker(file_tmp , opt_img , (err ,imgsrc) => {
     62                 if (err) return res.end(err.toString())
     63                 imgsrc = imgsrc || file_tmp
     64                 var read_stream = fs.createReadStream(imgsrc)
     65                 read_stream.pipe(res)
     66                 read_stream.on('end' ,function(){
     67                     fs.unlink(file_tmp)
     68                 })
     69             })
     70         })
     71 
     72 
     73     })
     74 }).listen(8791) //web服务端口
     75 
     76 function mkdirp(p){
     77     p = path.dirname(p)
     78     if (fs.existsSync(p)) return
     79 
     80     p = p.split('/')
     81     var pathnow = ''
     82     p.forEach(function(pi){
     83         pathnow += pi + '/'
     84         if (!fs.existsSync(pathnow) )  fs.mkdirSync(pathnow)
     85      })
     86 
     87 }
     88 
     89 function imgWorker( file_tmp ,opt ,cbk){
     90     opt = opt || {}
     91     
     92 
     93     const bindPath = '/usr/local/ImageMagick/bin/'
     94     var bindIdentity = bindPath + 'identify'
     95 
     96     /*
     97      * mode 0 等比
     98      * mode 1 剪切
     99      * mode 2 压缩填充
    100      * */
    101     if (!opt.height) opt.mode = 0
    102     
    103     convert()
    104 
    105     function convert(){
    106         var binConvert = bindPath + 'convert'
    107         var img_save_path = PATH_IMGS + opt.imgurl
    108         mkdirp(img_save_path)
    109         /*
    110         convert -resize 1024 file.jpg newfile.jpg
    111         得到图片宽为1024,高根据原始图片比例计算而来
    112 
    113         convert -resize x768 file.jpg newfile.jpg
    114         得到的图片高位768,宽根据原始图片比例计算而来
    115 
    116         convert -resize 1024×768! file.jpg newfile.jpg
    117         固定宽高缩放,不考虑原是图宽高的比例,把图片缩放到指定大小。
    118 
    119         convert -resize “1024×768>” file.jpg newfile.jpg
    120         只有当src.jpg的宽大于1024或高大于768时候,才进行缩小处理,否则生成newfile.jpg和file.jpg具有一样的尺寸。
    121 
    122         convert -resize “1024×768<” file.jpg newfile.jpg
    123         只有当src.jpg的宽小于1024或高小于768时候,才进行放大处理,否则生成newfile.jpg和file.jpg具有一样的尺寸。
    124 
    125         http://www.imagemagick.org/discourse-server/viewtopic.php?t=18545
    126 
    127         */
    128 
    129         var childArgs = []
    130 
    131         /*
    132          * NorthWest, North, NorthEast, West, Center, East, SouthWest, South, SouthEast
    133          * NorthWest是左上角对齐 ,SouthEast是右下角对齐
    134          * 通过resize参数第二位可以控制对应对齐方式 默认Center 居中 
    135          */
    136         if (opt.mode) {
    137             var _m = opt.mode.toString()
    138             var gravity = ['NorthWest', 'North', 'NorthEast', 'West'
    139                         , 'Center', 'East', 'SouthWest', 'South', 'SouthEast']
    140                             [(_m.slice(1,2) || 4) | 0]
    141             var color = ['' ,'white' ,'black'][(_m.slice(2,3) || 0) | 0]
    142             opt.mode = _m.slice(0,1) | 0
    143         }
    144         switch (opt.mode){
    145             case 2:
    146                 /*
    147                  * mode为2x 图片压缩填入指定尺寸 底色填充
    148                  * you can resize to the larger dimension and then pad the image
    149                  * convert image -resize "275x275" -gravity center -background white -extent 275x275 resultimage
    150                  */
    151                 childArgs.push('-resize')
    152                 childArgs.push(opt.width + 'x' + opt.height )
    153                 childArgs.push('-gravity')
    154                 childArgs.push(gravity)
    155                 if (color) {
    156                     childArgs.push('-background')
    157                     childArgs.push(color)
    158                 }
    159 
    160                 childArgs.push('-extent')
    161                 childArgs.push( opt.width + 'x' +  opt.height  )
    162                 break
    163             case 1:
    164                 /*
    165                 * mode为1x 图片拉伸 溢出剪切
    166                 */
    167                 var    cut = '+0+0'
    168                 childArgs.push('-resize')
    169                 childArgs.push(opt.width + 'x' + opt.height + '^')
    170                 childArgs.push('-gravity')
    171                 childArgs.push(gravity)
    172 
    173                 childArgs.push('-crop')
    174                 childArgs.push( opt.width + 'x' +  opt.height + cut )
    175 
    176                 break
    177             default:
    178                 /*
    179                 * 原图等比例缩放  比例不符合时以原图为准
    180                 */
    181                 var opt_size = opt.width || ''
    182                 if (opt.height) opt_size += 'x' + opt.height
    183                 if (opt_size){
    184                     childArgs.push('-resize')
    185                     childArgs.push(opt_size)
    186                 }
    187         }
    188         //去除元数据 相机信息 ps信息等
    189         childArgs.push('+profile')
    190         childArgs.push('"*"')
    191         childArgs.push('-strip')
    192 
    193         if (opt.quality){
    194             childArgs.push('-quality')
    195             childArgs.push(opt.quality)
    196         }
    197 
    198 
    199         childArgs.push(file_tmp)
    200         childArgs.push(img_save_path)
    201 
    202         console.log(childArgs)
    203 
    204         childProcess.execFile(binConvert, childArgs, function(err, stdout, stderr) {
    205             err && console.log(err)
    206             cbk(err  , img_save_path)
    207         })
    208     }
    209 
    210 }

    node前端是nginx 对处理过的图片就可以直接使用了

     1 server {
     2     listen  80;
     3     server_name xxx.com;
     4 
     5     location /favicon.ico {
     6         return 418;
     7     }
     8 
     9     location / {
    10         root /home/work/demo/images ;
    11         try_files $uri $uri/  @router;
    12 
    13     }
    14     location @router {
    15         proxy_pass http://127.0.0.1:8791;
    16     }
    17 }
  • 相关阅读:
    Ant Design Pro V5 + Django Restful Framework Token认证后台实现(二)
    Ant Design Pro V5 + Django Restful Framework Token认证后台实现(一)
    D365 FO产生随机字符串
    D365 FO Array增加排序
    转:Microsoft Dynamics AX内部版本号概述
    vue 组件通信总结
    脑图
    Flask 和 Django 中间件对比
    k8s 理论知识总结
    Flask 源码简析
  • 原文地址:https://www.cnblogs.com/vaal-water/p/5121014.html
Copyright © 2011-2022 走看看