今天有業務需要制作用戶頭像的需求,在網上找了個可以裁剪大圖制作自己希望大小的圖片的方法(基于Struts2)。特此記錄一下。
不廢話,具體的步驟如下:
<1> 使用html標簽上傳需要裁剪的大圖。
<2> 在頁面呈現大圖,使用Jcrop(Jquery)對大圖進行裁剪,并且可以進行預覽。
<3> 選擇好截取部分之后發送數據給Action,在服務器端使用 Java API 對大圖進行裁剪。
<4> 保存大圖裁剪好的頭像到指定目錄,完成業務。
下面一步一步做:
第一步:使用html標簽上傳需要裁剪的大圖。
這一步說白了也就是使用Struts2自帶的FileUpload功能,把圖片進行上傳具體代碼如下:
html頁面:
1
2
3
4
|
< form id = "ulform" action = "uploadPic.action" enctype = "multipart/form-data" method = "post" > < input type = "file" name = "pic" id = "file" value = "選擇圖片" /> < input type = "submit" value = "點擊上傳" /> </ form > |
Struts2配置文件
1
2
3
4
|
< action name = "uploadPic" class = "com.luoxiao.tbms.user.action.UserAction" method = "uploadPic" > < result name = "success" type = "redirect" >changePic.jsp</ result > < result name = "error" >changePic.jsp</ result > </ action > |
根據配置點擊提交按鈕,會提交表單,把圖片以流的形式發送給 UserAction的uploadPic方法,該方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public class UserAction{ private File pic; //(在此省略 get 和 set 方法) private String picFileName; //(省略get和set方法, 該屬性Struts2會自動賦值為上傳文件的文件名) public String uploadPic() { String[] str = { ".jpg" , ".jpeg" , ".bmp" , ".gif" }; // 獲取用戶登錄名 TbUser curruser = (TbUser) getValue(SCOPE_SESSION, "curruser" ); // 限定文件大小是4MB if (pic == null || pic.length() > 4194304 ) { //文件過大 return "error" ; } for (String s : str) { if (picFileName.endsWith(s)) { String realPath = ServletActionContext.getServletContext().getRealPath( "/uploadpic" ); // 在tomcat中保存圖片的實際路徑 == "webRoot/uploadpic/" File saveFile = new File( new File(realPath), "新文件名.jpg" ); // 在該實際路徑下實例化一個文件 // 判斷父目錄是否存在 if (!saveFile.getParentFile().exists()) { saveFile.getParentFile().mkdirs(); } try { // 執行文件上傳 // FileUtils 類名 org.apache.commons.io.FileUtils; // 是commons-io包中的,commons-fileupload 必須依賴 // commons-io包實現文件上次,實際上就是將一個文件轉換成流文件進行讀寫 FileUtils.copyFile(pic, saveFile); } catch (IOException e) { return "imageError" ; } } } return "success" ; } } |
這樣就可以把用戶選擇的圖片上傳到tomcat的webRoot/uploadpic/文件夾下。 然后訪問頁面,頁面中就可以顯示出剛剛上傳的大圖了。代碼如下。
- <div style="width: 500px; height: 500px;">
- <img style="margin-top:20px;" src="../uploadpic/上傳文件名稱.jpg"/>" id="target" alt="" />
- </div>
第一步完成。
第二步:使用Jcrop插件裁剪該圖片,并且在頁面中預覽。
Jcrop是一個基于JQuery的成熟的圖片裁剪的插件。如圖:
該插件使用比較簡單:
<1> 在裁剪圖片頁面中,引入兩個js文件,和1個Jcrop需要的css文件(Jcrop包中有,注意引入順序,先引入jquery):
- <script src="../js/jquery-1.8.3.min.js" type="text/javascript"></script>
- <script src="../js/jquery.Jcrop.js" type="text/javascript"></script>
- <link rel="stylesheet" href="../css/jquery.Jcrop.css" type="text/css" />
<2> 在html頁面中按照Jcrop要求的格式編寫兩個img標簽,一個用作裁剪后的預覽,一個用作顯示大圖,代碼如下:
- 預覽:
- <div style="width:200px;height:200px;overflow:hidden; border:1px solid gray;">
- <img id="preview" width="200px" height="200px" />
- </div>
- 原圖:
- <img src="../uploadpic/上傳大圖.jpg" id="target" alt="" />
<3> 在該頁面中寫js代碼,使其可以裁剪圖片并且預覽:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<script type= "text/javascript" > var x; var y; var width; var height; $( function (){ var jcrop_api, boundx, boundy; //使原圖具有裁剪功能 $( '#target' ).Jcrop({ onChange: updatePreview, onSelect: updatePreview, aspectRatio: 1 }, function (){ // Use the API to get the real image size var bounds = this .getBounds(); boundx = bounds[0]; boundy = bounds[1]; // Store the API in the jcrop_api variable jcrop_api = this ; }); //裁剪過程中,每改變裁剪大小執行該函數 function updatePreview(c){ if (parseInt(c.w) > 0){ $( '#preview' ).css({ width: Math.round(<span style= "color:#ff0000;" >200 </span>/ c.w * boundx) + 'px' , <span style= "color:#ff0000;" > //200 為預覽div的寬和高</span> height: Math.round(<span style= "color:#ff0000;" >200 </span>/ c.h * boundy) + 'px' , marginLeft: '-' + Math.round(200 / c.w * c.x) + 'px' , marginTop: '-' + Math.round(200 / c.h * c.y) + 'px' }); $( '#width' ).val(c.w); //c.w 裁剪區域的寬 $( '#height' ).val(c.h); //c.h 裁剪區域的高 $( '#x' ).val(c.x); //c.x 裁剪區域左上角頂點相對于圖片左上角頂點的x坐標 $( '#y' ).val(c.y); //c.y 裁剪區域頂點的y坐標 } }; }); </script> |
至此我們已經可以看到裁剪之后的樣子了,并且也可以得到裁剪區域的x,y,height,width屬性。
第三步:把截取的該區域的屬性傳遞給action,讓action根據所得屬性,利用javaAPI把原圖裁剪成小圖。
<1> 設置form表單與隱藏域表單組件,并且在裁剪的時候對該四個組件的value屬性賦值
1
2
3
4
5
6
7
8
9
|
< form action = "cutPic.action" method = "post" > 點擊 < input type = "hidden" name = "image.x" id = "x" /> < input type = "hidden" name = "image.y" id = "y" /> < input type = "hidden" name = "image.width" id = "width" /> < input type = "hidden" name = "image.height" id = "height" /> < input type = "submit" value = "確定" /> ,設置完成。 </ form > |
<2> 點擊確定,提交該表單,訪問action,配置如下:
1
2
3
|
< action name = "cutPic" class = "com.luoxiao.tbms.user.action.UserAction" method = "cutPic" > < result name = "success" type = "redirectAction" >../announcement/announcement_list.action</ result > </ action > |
<3>Struts2帶著四個參數訪問UserAction,并且會自動給UserAction中的image屬性賦值,該image屬性為OperateImage的一個實例對象,該類為裁剪圖片類,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
package com.luoxiao.util; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Iterator; import javax.imageio.ImageIO; import javax.imageio.ImageReadParam; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; public class OperateImage { // ===源圖片路徑名稱如:c:.jpg private String srcpath; // ===剪切圖片存放路徑名稱.如:c:.jpg private String subpath; // ===剪切點x坐標 private int x; private int y; // ===剪切點寬度 private int width; private int height; public OperateImage() { } /** 對圖片裁剪,并把裁剪完的新圖片保存 */ public void cut() throws IOException { FileInputStream is = null ; ImageInputStream iis = null ; try { // 讀取圖片文件 is = new FileInputStream(srcpath); /* * 返回包含所有當前已注冊 ImageReader 的 Iterator,這些 ImageReader 聲稱能夠解碼指定格式。 * 參數:formatName - 包含非正式格式名稱 . (例如 "jpeg" 或 "tiff")等 。 */ Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName("jpg"); ImageReader reader = it.next(); // 獲取圖片流 iis = ImageIO.createImageInputStream(is); /* * <p>iis:讀取源.true:只向前搜索 </p>.將它標記為 ‘只向前搜索'。 * 此設置意味著包含在輸入源中的圖像將只按順序讀取,可能允許 reader 避免緩存包含與以前已經讀取的圖像關聯的數據的那些輸入部分。 */ reader.setInput(iis, true); /* * <p>描述如何對流進行解碼的類<p>.用于指定如何在輸入時從 Java Image I/O * 框架的上下文中的流轉換一幅圖像或一組圖像。用于特定圖像格式的插件 將從其 ImageReader 實現的 * getDefaultReadParam 方法中返回 ImageReadParam 的實例。 */ ImageReadParam param = reader.getDefaultReadParam(); /* * 圖片裁剪區域。Rectangle 指定了坐標空間中的一個區域,通過 Rectangle 對象 * 的左上頂點的坐標(x,y)、寬度和高度可以定義這個區域。 */ Rectangle rect = new Rectangle(x, y, width, height); // 提供一個 BufferedImage,將其用作解碼像素數據的目標。 param.setSourceRegion(rect); /* * 使用所提供的 ImageReadParam 讀取通過索引 imageIndex 指定的對象,并將 它作為一個完整的 * BufferedImage 返回。 */ BufferedImage bi = reader.read( 0 , param); // 保存新圖片 ImageIO.write(bi, "jpg" , new File(subpath)); } finally { if (is != null ) is.close(); if (iis != null ) iis.close(); } } } |
<4> 給該類的實例的四個屬性 x,y,width,height賦值之后,訪問action中的cutPic方法,代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class UserAction extends BaseAction { private OperateImage image;(省略get set) private File pic; // 接收這個上傳的文件 private String picFileName; // Struts2提供的格式,在文件名后+FileName就是上傳文件的名字 /** * 裁剪頭像 */ public String cutPic(){ String name = ServletActionContext.getServletContext().getRealPath( "/uploadpic/原圖名.jpg" ); image.setSrcpath(name); image.setSubpath(ServletActionContext.getServletContext().getRealPath( "/uploadpic/裁剪目標圖名.jpg" )); try { image.cut(); //執行裁剪操作 執行完后即可生成目標圖在對應文件夾內。 } catch (IOException e) { e.printStackTrace(); } return "success" ; } } |
第四步:把截取好的頭像保存在具體文件夾下即可,裁剪過程完成。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/csd_xuming/article/details/8848939