调用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 }
原文地址:https://www.cnblogs.com/vaal-water/p/5121014.html