效果:

  服务器存在张请求路径为 http://domain:port/path的图片,可以使用http://domain:port/userfiles/path?imageView2/pattern/w/宽度值/h/高度值    ,的方式请求得到裁切后的图片

  eg:正常请求图片路径

  http://static.ywl.com:8082/uploadfile/article/2015/11/17/1447744108428.jpg

  ,如果想要请求该图片的720x280尺寸则可以使用

  http://static.ywl.me:8082/userfiles//uploadfile/article/2015/11/17/1447744108428.jpg?imageView2/1/w/720/h/280

  参数中pattern共六种分别表示不同的裁切方式,具体见代码注释。

准备

  要求平台安装了GraphicsMagick(java自带的图片处理类库不够完美),使用的im4java.jar来操作该软件

  GraphicsMagick的安装:

    windows下直接到官网下载exe安装,linux下如果直接下载安装包比较麻烦(需要一些额外的依赖),我使用yum安装的

      1 yum list GraphicsMagick*     

      结果:

      Available Packages
      GraphicsMagick.i686                
      GraphicsMagick.x86_64              
      GraphicsMagick-c++.i686       
      GraphicsMagick-c++.x86_64     
      GraphicsMagick-c++-devel.i686    
      GraphicsMagick-c++-devel.x86_64  
      GraphicsMagick-devel.i686      
      GraphicsMagick-devel.x86_64    
      GraphicsMagick-doc.noarch     
      GraphicsMagick-perl.x86_64

     2 选择一个合适的版本进行安装 yum install GraphicsMagick.x86_64

     3 输入gm命令验证安装成功。

  im4java.jar的maven依赖

      <dependency>
        <groupId>org.im4java</groupId>
        <artifactId>im4java</artifactId>
        <version>1.4.0</version>
      </dependency>

 

代码

  1 package com.nautilus.servlet;
  2 
  3 import java.awt.Graphics;
  4 import java.awt.GraphicsConfiguration;
  5 import java.awt.GraphicsDevice;
  6 import java.awt.GraphicsEnvironment;
  7 import java.awt.HeadlessException;
  8 import java.awt.Image;
  9 import java.awt.Toolkit;
 10 import java.awt.Transparency;
 11 import java.awt.image.BufferedImage;
 12 import java.awt.image.CropImageFilter;
 13 import java.awt.image.FilteredImageSource;
 14 import java.awt.image.ImageFilter;
 15 import java.io.File;
 16 import java.io.IOException;
 17 import java.io.UnsupportedEncodingException;
 18 import java.text.SimpleDateFormat;
 19 import java.util.ArrayList;
 20 import java.util.Date;
 21 import java.util.Locale;
 22 
 23 import javax.imageio.ImageIO;
 24 import javax.servlet.ServletException;
 25 import javax.servlet.ServletOutputStream;
 26 import javax.servlet.http.HttpServlet;
 27 import javax.servlet.http.HttpServletRequest;
 28 import javax.servlet.http.HttpServletResponse;
 29 import javax.swing.ImageIcon;
 30 
 31 import org.im4java.core.ConvertCmd;
 32 import org.im4java.core.IMOperation;
 33 import org.im4java.core.IdentifyCmd;
 34 import org.im4java.process.ArrayListOutputConsumer;
 35 import org.im4java.process.Pipe;
 36 import org.im4java.process.ProcessStarter;
 37 import org.springframework.web.util.UriUtils;
 38 
 39 import com.nautilus.common.Config;
 40 
 41 /**
 42  * 请求随意尺寸的已存在图片<br/>
 43  * eg:正常请求图片路径/image/goods/a.png,如果想要请求该图片的800x600尺寸则可以使用/userfiles/image/goods/a.png?imageView2/0/w/800/h/600
 44  * 其格式为:/userfiles/原路径/imageView2/<mode>/w/<LongEdge>/h/<ShortEdge>
 45     mode有0、1、2、3、4、5。
 46     其中0、4、5使用长边短边作为限制条件适合手机端调用,因为手机端没有绝对的宽高(横竖)
 47     1、2、3使用宽高作为限制条件适合pc端调用
 48     
 49     具体模式说明如下:
 50     (-1为不指定)
 51     0:/0/w/<LongEdge>/h/<ShortEdge> 限定缩略图的长边最多为longEdge,短边最多为shortEdge,进行等比缩放,不裁剪。,如果只指定 longEdge 参数则表示限定长边(短边自适应),只指定 shortEdge
 52      参数则表示限定短边(长边自适应)。
 53     <br/>
 54     4: /4/w/<LongEdge>/h/<ShortEdge>  限定缩略图的长边最少为<LongEdge>,短边最少为<ShortEdge>,进行等比缩放,不裁剪。如果只指定 w 参数或只指定 h 参数,表示长边短边限定为同样的值。这个模式很适合在手持设备做图片的全屏查看(把这里的长边短边分别设为手机屏幕的分辨率即可),生成的图片尺寸刚好充满整个屏幕(某一个边可能会超出屏幕)。
 55     <br/>
 56     5:/5/w/<LongEdge>/h/<ShortEdge> 限定缩略图的长边最少为<LongEdge>,短边最少为<ShortEdge>,进行等比缩放,居中裁剪。如果只指定 w 参数或只指定 h 参数,表示长边短边限定为同样的值。同上模式4,但超出限定的矩形部分会被裁剪。
 57     <br/>
 58     1: /1/w/<Width>/h/<Height> 限定缩略图的宽最少为<Width>,高最少为<Height>,进行等比缩放,居中裁剪。转后的缩略图通常恰好是 <Width>x<Height> 的大小(有一个边缩放的时候会因为超出矩形框而被裁剪掉多余部分)。如果只指定 w 参数或只指定 h 参数,代表限定为长宽相等的正方图。 
 59     <br/>
 60     2: /2/w/<Width>/h/<Height> 限定缩略图的宽最多为<Width>,高最多为<Height>,进行等比缩放,不裁剪。如果只指定 w 参数则表示限定宽(长自适应),只指定 h 参数则表示限定长(宽自适应)。它和模式0类似,区别只是限定宽和高,不是限定长边和短边。从应用场景来说,模式0适合移动设备上做缩略图,模式2适合PC上做缩略图。 
 61     <br/>
 62     3: /3/w/<Width>/h/<Height> 限定缩略图的宽最少为<Width>,高最少为<Height>,进行等比缩放,不裁剪。如果只指定 w 参数或只指定 h 参数,代表长宽限定为同样的值。你可以理解为模式1是模式3的结果再做居中裁剪得到的。 
 63  * @author fei.jiang
 64  *
 65  */
 66 public class UserfilesDownloadServlet extends HttpServlet {
 67 
 68     static {
 69         String osName = System.getProperty("os.name").toLowerCase();
 70         if (osName.indexOf("win") >= 0) { // linux下不要设置此值,不然会报错
 71             ProcessStarter.setGlobalSearchPath("C:\\Program Files (x86)\\GraphicsMagick-1.3.22-Q16");
 72         }
 73     }
 74 
 75 //    private static ConvertCmd cmd = new ConvertCmd(true);
 76 //    private static IdentifyCmd identifyCmd = new IdentifyCmd(true);
 77     
 78 
 79     public void fileOutputStream(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 80         String filepath = req.getRequestURI();
 81         // imageView2/0/w/<LongEdge>/h/<ShortEdge>
 82         String view = (String) req.getParameterMap().keySet().toArray()[0];
 83         filepath = getAbsPath(filepath);
 84         File file = new File(filepath);
 85         if(!file.exists() || file.isDirectory()){
 86             resp.sendError(404);
 87             System.out.println(filepath+"不存在");
 88             return;
 89         }
 90 //        System.out.println(filepath);
 91 //        System.out.println(view);
 92         int mode = getMode(view);
 93         int w = getW(view);// -1表示不限制
 94         int h = getH(view);// -1表示不限制
 95         // 长短边和宽高的区别:长边不一定是宽
 96         
 97         /**********/
 98          // ETag header
 99       String etag=req.getRequestURI()+""+req.getQueryString();
100       resp.setHeader("ETag", etag);//If-None-Match
101       // Last-Modified header  //If-Modified-Since
102       resp.setHeader("Last-Modified",new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US).format(new Date(file.lastModified())));
103       if(etag.equals(req.getHeader("If-None-Match"))){
104           
105           long headerValue = req.getDateHeader("If-Modified-Since");
106           long lastModified = new File(filepath).lastModified();
107           if (headerValue != -1) {
108 
109               // If an If-None-Match header has been specified, if modified since
110               // is ignored.
111               if ((lastModified < headerValue + 1000)) {
112                   // The entity has not been modified since the date
113                   // specified by the client. This is not an error case.
114                   resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
115                   return;
116               }
117           }
118       }
119         /**********/
120         if (0 == mode) {
121             doMode0(req, resp, filepath, w, h);
122         } else if (1 == mode) {
123             doMode1(req, resp, filepath, w, h);
124         } else if (2 == mode) {
125             doMode2(req, resp, filepath, w, h);
126         } else if (3 == mode) {
127             doMode3(req, resp, filepath, w, h);
128         } else if (4 == mode) {
129             doMode4(req, resp, filepath, w, h);
130         } else if (5 == mode) {
131             doMode5(req, resp, filepath, w, h);
132         }
133     }
134 
135     /**
136      * 限定缩略图的长边最多为longEdge,短边最多为shortEdge,进行等比缩放,不裁剪。,如果只指定 longEdge 参数则表示限定长边(短边自适应),只指定 shortEdge
137      * 参数则表示限定短边(长边自适应)。
138      * 
139      * @param req
140      * @param resp
141      * @param filepath
142      *            :文件所在绝对路径
143      * @param longEdge
144      *            :长边
145      * @param shortEdge
146      *            :短边
147      */
148     private void doMode0(HttpServletRequest req, HttpServletResponse resp, String filepath, int longEdge, int shortEdge) {
149         try {
150 //            Image src = Toolkit.getDefaultToolkit().getImage(filepath); // 读入文件
151 //            src=toBufferedImage(src);
152 //            int width = src.getWidth(null); // 得到源图宽
153 //            int height = src.getHeight(null); // 得到源图长
154             String msize=getImageSize(filepath);
155             int width = (int) Double.parseDouble(msize.split(",")[0]);//getWidth(filepath); // 得到源图宽
156             int height = (int) Double.parseDouble(msize.split(",")[1]);//getHeight(filepath); // 得到源图长
157             //
158             int l = width > height ? width : height;// 长边
159             int s = width > height ? height : width;// 短边
160 
161             double scale = 1.0;// 缩放比例
162             if (longEdge < 0) {
163                 scale = (double) shortEdge / (double) s;
164             } else if (shortEdge < 0) {
165                 scale = (double) longEdge / (double) l;
166             } else {
167                 double scalew = (double) longEdge / (double) l;
168                 double scaleh = (double) shortEdge / (double) s;
169                 scale = scalew > scaleh ? scaleh : scalew;// 取较小的缩放比例
170             }
171             width = (int) (width * scale);
172             height = (int) (height * scale);
173 //            Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
174 //            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
175 //            Graphics g = tag.getGraphics();
176 //            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
177 //            g.dispose();
178             ConvertCmd cmd = new ConvertCmd(true);
179             IMOperation op = new IMOperation();
180             op.addImage(filepath);
181             op.resize(width, height);
182             op.addImage("-");
183             ServletOutputStream sos = resp.getOutputStream();
184             Pipe pipeOut = new Pipe(null,sos);
185             cmd.setOutputConsumer(pipeOut);
186             cmd.run(op);
187 //            sos.close();
188         } catch (Exception e) {
189             System.out.println("can not find " + filepath);
190             e.printStackTrace();
191         }
192     }
193 
194     /**
195      * 限定缩略图的宽最少为<Width>,高最少为<Height>,进行等比缩放,居中裁剪。转后的缩略图通常恰好是 <Width>x<Height>
196      * 的大小(有一个边缩放的时候会因为超出矩形框而被裁剪掉多余部分)。如果只指定 w 参数或只指定 h 参数,代表限定为长宽相等的正方图。
197      * 
198      * @param req
199      * @param resp
200      * @param filepath
201      *            :文件所在绝对路径
202      * @param w:宽
203      * @param h:高
204      */
205     private void doMode1(HttpServletRequest req, HttpServletResponse resp, String filepath, int w, int h) {
206         try {
207 //            Image src = Toolkit.getDefaultToolkit().getImage(filepath);
208 //            src=toBufferedImage(src);
209 ////            BufferedImage src = ImageIO.read(new File(filepath)); // 读入文件
210 //            int width = src.getWidth(null); // 得到源图宽
211 //            int height = src.getHeight(null); // 得到源图长
212             String msize=getImageSize(filepath);
213             int width = (int) Double.parseDouble(msize.split(",")[0]);//getWidth(filepath); // 得到源图宽
214             int height = (int) Double.parseDouble(msize.split(",")[1]);//getHeight(filepath); // 得到源图长
215             double scale = 1.0;// 缩放比例
216             if (w < 0) {
217                 w = h;
218             }
219             if (h < 0) {
220                 h = w;
221             }
222             //计算缩放比例
223             double scalew = (double) w / (double) width;
224             double scaleh = (double) h / (double) height;
225             scale = scalew > scaleh ? scalew : scaleh;// 取较大的缩放比例
226             int cwidth = (int) (width * scale);//缩放后未裁剪的宽
227             int cheight = (int) (height * scale);//缩放后未裁剪的高
228             //计算裁剪坐标
229             int x=0,y=0;
230             if(cwidth>w)x=(cwidth-w)/2;
231             if(cheight>h)y=(cheight-h)/2;
232 //            Image image = src.getScaledInstance(cwidth, cheight, Image.SCALE_SMOOTH);
233 //            // 四个参数分别为图像起点坐标和宽高
234 //            // 即: CropImageFilter(int x,int y,int width,int height)
235 //            ImageFilter cropFilter = new CropImageFilter(x, y, w, h);
236 //            Image img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter));
237 //            BufferedImage tag = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
238 //            Graphics g = tag.getGraphics();
239 //            g.drawImage(img, 0, 0, null);
240 //            g.dispose();
241 //            ServletOutputStream sos = resp.getOutputStream();
242 //            ImageIO.write(tag, "jpeg", sos);
243             ConvertCmd cmd = new ConvertCmd(true);
244             IMOperation op = new IMOperation();
245             op.addImage(filepath);
246             op.resize(cwidth, cheight);
247             op.crop(w, h, x, y);/** w:裁剪的宽度 * h:裁剪的高度 * x:裁剪的横坐标 * y:裁剪纵坐标 */
248             op.addImage("-");
249             ServletOutputStream sos = resp.getOutputStream();
250             Pipe pipeOut = new Pipe(null,sos);
251             cmd.setOutputConsumer(pipeOut);
252             cmd.run(op);
253             
254 //            sos.close();
255         } catch (Exception e) {
256             System.out.println("can not find " + filepath);
257             e.printStackTrace();
258         }
259     }
260 
261     /**
262      * 限定缩略图的宽最多为<Width>,高最多为<Height>,进行等比缩放,不裁剪。如果只指定 w 参数则表示限定宽(长自适应),只指定 h 参数则表示限定长(宽自适应)。它和模式0类似,区别只是限定宽和高,不是限定长边和短边。从应用场景来说,模式0适合移动设备上做缩略图,模式2适合PC上做缩略图
263      * 
264      * @param req
265      * @param resp
266      * @param filepath
267      *            :文件所在绝对路径
268      * @param w:宽
269      * @param h:高
270      */
271     private void doMode2(HttpServletRequest req, HttpServletResponse resp, String filepath, int w, int h) {
272         try {
273 //            Image src = Toolkit.getDefaultToolkit().getImage(filepath); // 读入文件
274 //            src=toBufferedImage(src);
275 //            int width = src.getWidth(null); // 得到源图宽
276 //            int height = src.getHeight(null); // 得到源图长
277             String msize=getImageSize(filepath);
278             int width = (int) Double.parseDouble(msize.split(",")[0]);//getWidth(filepath); // 得到源图宽
279             int height = (int) Double.parseDouble(msize.split(",")[1]);//getHeight(filepath); // 得到源图长
280 
281             double scale = 1.0;// 缩放比例
282             if (w < 0) {
283                 scale = (double) h / (double) height;
284             } else if (h < 0) {
285                 scale = (double) w / (double) width;
286             } else {
287                 double scalew = (double) w / (double) width;
288                 double scaleh = (double) h / (double) height;
289                 scale = scalew > scaleh ? scaleh : scalew;// 取较小的缩放比例
290             }
291             width = (int) (width * scale);
292             height = (int) (height * scale);
293 //            Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
294 //            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
295 //            Graphics g = tag.getGraphics();
296 //            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
297 //            g.dispose();
298 //            ServletOutputStream sos = resp.getOutputStream();
299 //            ImageIO.write(tag, "jpeg", sos);
300             ConvertCmd cmd = new ConvertCmd(true);
301             IMOperation op = new IMOperation();
302             op.addImage(filepath);
303             op.resize(width, height);
304             op.addImage("-");
305             ServletOutputStream sos = resp.getOutputStream();
306             Pipe pipeOut = new Pipe(null,sos);
307             cmd.setOutputConsumer(pipeOut);
308             cmd.run(op);
309 //            sos.close();
310         } catch (Exception e) {
311             System.out.println("can not find " + filepath);
312             e.printStackTrace();
313         }
314     }
315 
316     /**
317      * 限定缩略图的宽最少为<Width>,高最少为<Height>,进行等比缩放,不裁剪。如果只指定 w 参数或只指定 h 参数,代表长宽限定为同样的值。你可以理解为模式1是模式3的结果再做居中裁剪得到的。
318      * @param req
319      * @param resp
320      * @param filepath
321      *            :文件所在绝对路径
322      * @param w:宽
323      * @param h:高
324      */
325     private void doMode3(HttpServletRequest req, HttpServletResponse resp, String filepath, int w, int h) {
326         try {
327 //            Image src = Toolkit.getDefaultToolkit().getImage(filepath); // 读入文件
328 //            src=toBufferedImage(src);
329 //            int width = src.getWidth(null); // 得到源图宽
330 //            int height = src.getHeight(null); // 得到源图长
331             String msize=getImageSize(filepath);
332             int width = (int) Double.parseDouble(msize.split(",")[0]);//getWidth(filepath); // 得到源图宽
333             int height = (int) Double.parseDouble(msize.split(",")[1]);//getHeight(filepath); // 得到源图长
334 
335             double scale = 1.0;// 缩放比例
336             if (w < 0) {
337                 w = h;
338             }
339             if (h < 0) {
340                 h = w;
341             }
342             //计算缩放比例
343             double scalew = (double) w / (double) width;
344             double scaleh = (double) h / (double) height;
345             scale = scalew > scaleh ? scalew : scaleh;// 取较大的缩放比例
346             int cwidth = (int) (width * scale);//缩放后未裁剪的宽
347             int cheight = (int) (height * scale);//缩放后未裁剪的高
348 //            Image image = src.getScaledInstance(cwidth, cheight, Image.SCALE_SMOOTH);
349 //            BufferedImage tag = new BufferedImage(cwidth, cheight, BufferedImage.TYPE_INT_RGB);
350 //            Graphics g = tag.getGraphics();
351 //            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
352 //            g.dispose();
353 //            ServletOutputStream sos = resp.getOutputStream();
354 //            ImageIO.write(tag, "jpeg", sos);
355             ConvertCmd cmd = new ConvertCmd(true);
356             IMOperation op = new IMOperation();
357             op.addImage(filepath);
358             op.resize(cwidth, cheight);
359             op.addImage("-");
360             ServletOutputStream sos = resp.getOutputStream();
361             Pipe pipeOut = new Pipe(null,sos);
362             cmd.setOutputConsumer(pipeOut);
363             cmd.run(op);
364 //            sos.close();
365         } catch (Exception e) {
366             System.out.println("can not find " + filepath);
367             e.printStackTrace();
368         }
369     }
370 
371     /**
372      * 限定缩略图的长边最少为<LongEdge>,短边最少为<ShortEdge>,进行等比缩放,不裁剪。如果只指定 w 参数或只指定 h 参数,表示长边短边限定为同样的值。这个模式很适合在手持设备做图片的全屏查看(把这里的长边短边分别设为手机屏幕的分辨率即可),生成的图片尺寸刚好充满整个屏幕(某一个边可能会超出屏幕)。
373      * @param req
374      * @param resp
375      * @param filepath :文件所在绝对路径
376      * @param longEdge :长边
377      * @param shortEdge :短边
378      */
379     private void doMode4(HttpServletRequest req, HttpServletResponse resp, String filepath, int longEdge, int shortEdge) {
380         try {
381 //            Image src = Toolkit.getDefaultToolkit().getImage(filepath); // 读入文件
382 //            src=toBufferedImage(src);
383 //            int width = src.getWidth(null); // 得到源图宽
384 //            int height = src.getHeight(null); // 得到源图长
385             String msize=getImageSize(filepath);
386             int width = (int) Double.parseDouble(msize.split(",")[0]);//getWidth(filepath); // 得到源图宽
387             int height = (int) Double.parseDouble(msize.split(",")[1]);//getHeight(filepath); // 得到源图长
388             //
389             int l = width > height ? width : height;// 长边
390             int s = width > height ? height : width;// 短边
391 
392             double scale = 1.0;// 缩放比例
393             if (longEdge < 0) {
394                 longEdge = shortEdge;
395             } 
396             if (shortEdge < 0) {
397                 shortEdge = longEdge;
398             }
399             
400             double scalew = (double) longEdge / (double) l;
401             double scaleh = (double) shortEdge / (double) s;
402             scale = scalew > scaleh ? scalew : scaleh;// 取较大的缩放比例
403             width = (int) (width * scale);
404             height = (int) (height * scale);
405 //            Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
406 //            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
407 //            Graphics g = tag.getGraphics();
408 //            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
409 //            g.dispose();
410 //            ServletOutputStream sos = resp.getOutputStream();
411 //            ImageIO.write(tag, "jpeg", sos);
412             ConvertCmd cmd = new ConvertCmd(true);
413             IMOperation op = new IMOperation();
414             op.addImage(filepath);
415             op.resize(width, height);
416             op.addImage("-");
417             ServletOutputStream sos = resp.getOutputStream();
418             Pipe pipeOut = new Pipe(null,sos);
419             cmd.setOutputConsumer(pipeOut);
420             cmd.run(op);
421 //            sos.close();
422         } catch (Exception e) {
423             System.out.println("can not find " + filepath);
424 //            e.printStackTrace();
425         }
426     }
427 
428     /**
429      * 限定缩略图的长边最少为<LongEdge>,短边最少为<ShortEdge>,进行等比缩放,居中裁剪。如果只指定 w 参数或只指定 h 参数,表示长边短边限定为同样的值。同上模式4,但超出限定的矩形部分会被裁剪。
430      * @param req
431      * @param resp
432      * @param filepath :文件所在绝对路径
433      * @param longEdge:长边
434      * @param shortEdge:短边
435      */
436     private void doMode5(HttpServletRequest req, HttpServletResponse resp, String filepath, int longEdge, int shortEdge) {
437         try {
438             if (longEdge < 0) {
439                 longEdge = shortEdge;
440             }
441             if (shortEdge < 0) {
442                 shortEdge = longEdge;
443             }
444             
445 //            Image src = Toolkit.getDefaultToolkit().getImage(filepath); // 读入文件
446 //            src=toBufferedImage(src);
447 //            int width = src.getWidth(null); // 得到源图宽
448 //            int height = src.getHeight(null); // 得到源图长
449             String msize=getImageSize(filepath);
450             int width = (int) Double.parseDouble(msize.split(",")[0]);//getWidth(filepath); // 得到源图宽
451             int height = (int) Double.parseDouble(msize.split(",")[1]);//getHeight(filepath); // 得到源图长
452             //
453             boolean wl =width>height;
454             int l = wl ? width : height;// 长边
455             int s = wl ? height : width;// 短边
456             
457             double scale = 1.0;// 缩放比例
458             //计算缩放比例
459             double scalel = (double) longEdge / (double) l;
460             double scales = (double) shortEdge / (double) s;
461             scale = scalel > scales ? scalel : scales;// 取较大的缩放比例
462             //缩放后的宽高
463             int cwidth = (int) (width * scale);//缩放后未裁剪的宽
464             int cheight = (int) (height * scale);//缩放后未裁剪的高
465             int swidth = wl?longEdge:shortEdge;//裁剪尺寸宽
466             int sheight = wl?shortEdge:longEdge;//裁剪尺寸高
467             //计算裁剪坐标
468             int x=0,y=0;//x,y肯定都是非负数,其中至少一个是正数
469             if(cwidth>swidth)x=(cwidth-swidth)/2;
470             if(cheight>sheight)y=(cheight-sheight)/2;
471 //            Image image = src.getScaledInstance(cwidth, cheight, Image.SCALE_SMOOTH);
472 //            // 四个参数分别为图像起点坐标和宽高
473 //            // 即: CropImageFilter(int x,int y,int width,int height)
474 //            ImageFilter cropFilter = new CropImageFilter(x, y, swidth, sheight);
475 //            Image img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter));
476 //            BufferedImage tag = new BufferedImage(swidth, sheight, BufferedImage.TYPE_INT_RGB);
477 //            Graphics g = tag.getGraphics();
478 //            g.drawImage(img, 0, 0, null); // 绘制缩小后的图
479 //            g.dispose();
480 //            ServletOutputStream sos = resp.getOutputStream();
481 //            ImageIO.write(tag, "jpeg", sos);
482             ConvertCmd cmd = new ConvertCmd(true);
483             IMOperation op = new IMOperation();
484             op.addImage(filepath);
485             op.resize(cwidth, cheight);
486             op.crop(swidth, sheight, x, y);/** w:裁剪的宽度 * h:裁剪的高度 * x:裁剪的横坐标 * y:裁剪纵坐标 */
487             op.addImage("-");
488             ServletOutputStream sos = resp.getOutputStream();
489             Pipe pipeOut = new Pipe(null,sos);
490             cmd.setOutputConsumer(pipeOut);
491             cmd.run(op);
492 //            sos.close();
493         } catch (Exception e) {
494             System.out.println("can not find " + filepath);
495 //            e.printStackTrace();
496         }
497     }
498     /**ImageIO.read()读取图片会产生ICC信息的丢失,此处将Image转换为BufferedImage因为Image.getScaledInstance得到空数据*/
499     private BufferedImage toBufferedImage(Image image) {
500         if (image instanceof BufferedImage) {
501             return (BufferedImage)image;
502          }
503      
504         // This code ensures that all the pixels in the image are loaded
505          image = new ImageIcon(image).getImage();
506      
507         // Determine if the image has transparent pixels; for this method's
508         // implementation, see e661 Determining If an Image Has Transparent Pixels
509         //boolean hasAlpha = hasAlpha(image);
510      
511         // Create a buffered image with a format that's compatible with the screen
512          BufferedImage bimage = null;
513          GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
514         try {
515             // Determine the type of transparency of the new buffered image
516             int transparency = Transparency.OPAQUE;
517            /* if (hasAlpha) {
518                  transparency = Transparency.BITMASK;
519              }*/
520      
521             // Create the buffered image
522              GraphicsDevice gs = ge.getDefaultScreenDevice();
523              GraphicsConfiguration gc = gs.getDefaultConfiguration();
524              bimage = gc.createCompatibleImage(
525                  image.getWidth(null), image.getHeight(null), transparency);
526          } catch (HeadlessException e) {
527             // The system does not have a screen
528          }
529      
530         if (bimage == null) {
531             // Create a buffered image using the default color model
532             int type = BufferedImage.TYPE_INT_RGB;
533             //int type = BufferedImage.TYPE_3BYTE_BGR;//by wang
534             /*if (hasAlpha) {
535                  type = BufferedImage.TYPE_INT_ARGB;
536              }*/
537              bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
538          }
539      
540         // Copy image to buffered image
541          Graphics g = bimage.createGraphics();
542      
543         // Paint the image onto the buffered image
544          g.drawImage(image, 0, 0, null);
545          g.dispose();
546      
547         return bimage;
548      }
549     /**
550      * @param view
551      * @return
552      */
553     private int getMode(String view) {
554         return Integer.parseInt(view.split("/")[1]);
555     }
556 
557     /**
558      * @param view
559      * @return
560      */
561     private int getH(String view) {
562         return Integer.parseInt(view.split("/")[5]);
563     }
564 
565     /**
566      * @param view
567      * @return
568      */
569     private int getW(String view) {
570         return Integer.parseInt(view.split("/")[3]);
571     }
572 
573     /**
574      * 获取文件的绝对路径
575      * 
576      * @param filepath
577      * @return
578      */
579     private String getAbsPath(String filepath) {
580         // 获得文件的路径
581         int index = filepath.indexOf(Config.USERFILES_BASE_URL);
582         if (index >= 0) {
583             filepath = Config.USERFILES_BASEDIR + filepath.substring(index + Config.USERFILES_BASE_URL.length());
584         }
585         try {
586             filepath = UriUtils.decode(filepath, "UTF-8");
587         } catch (UnsupportedEncodingException e1) {
588             System.out.println(String.format("解释文件路径失败,URL地址为%s", filepath));
589             e1.printStackTrace();
590             // logger.error(String.format("解释文件路径失败,URL地址为%s", filepath), e1);
591         }
592         return filepath;
593     }
594     /**
595      * 图片信息
596      * 
597      * @param imagePath
598      * @return
599      */
600     private String getImageSize(String imagePath) {
601         String line = null;
602         try {
603             IdentifyCmd identifyCmd = new IdentifyCmd(true);
604             IMOperation op = new IMOperation();
605             op.format("%w,%h");
606             op.addImage(1);
607             ArrayListOutputConsumer output = new ArrayListOutputConsumer();
608             identifyCmd.setOutputConsumer(output);
609             identifyCmd.run(op, imagePath);
610             ArrayList<String> cmdOutput = output.getOutput();
611             line = cmdOutput.get(0);
612         } catch (Exception e) {
613             e.printStackTrace();
614         }
615         return line;
616     }
617     @Override
618     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
619         fileOutputStream(req, resp);
620     }
621 
622     @Override
623     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
624         fileOutputStream(req, resp);
625     }
626 }
 1 package com.nautilus.common;
 2 
 3 import java.util.ArrayList;
 4 import java.util.HashMap;
 5 import java.util.List;
 6 import java.util.Map;
 7 
 8 import org.springframework.context.ApplicationContext;
 9 
10 
11 /**
12  * 全局配置参数
13  * 
14  * <pre>
15  * Class Name: Config
16  * Modifications:
17  * Modifier Wei Rongting; 2012-5-21; Create new Class Config.
18  * </pre>
19  */ 
20 @SuppressWarnings("serial")
21 public class Config {
22     
23     public static String USERFILES_BASEDIR;
24     /**
25      * 上传文件基础虚拟路径
26      */
27     public static final String USERFILES_BASE_URL = "/userfiles/";
28 }

 

 

  

  

posted on 2015-12-22 11:45  feilaila  阅读(278)  评论(0)    收藏  举报