效果:
服务器存在张请求路径为 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 }
浙公网安备 33010602011771号