使用Jcrop.js和jQuery.form.js,用ImageIO等進行頭像上傳縮放及裁剪
首先,Java程式碼裡帶一個獲取ImageReader的Iterator
/** * 從網上摘抄的。 * 返回包含所有當前已註冊 ImageReader 的 Iterator,這些 ImageReader 聲稱能夠解碼指定格式。 * 引數:postFix - 包含非正式格式名稱 .(例如 "jpeg" 或 "tiff")等 。 * * @param postFix * 檔案的字尾名 * @author 劉各歡 * @return */ public Iterator<ImageReader> getImageReadersByFormatName(String postFix) { switch (postFix) { case "jpg": return ImageIO.getImageReadersByFormatName("jpg"); case "jpeg": return ImageIO.getImageReadersByFormatName("jpeg"); case "gif": return ImageIO.getImageReadersByFormatName("gif"); case "bmp": return ImageIO.getImageReadersByFormatName("bmp"); case "png": return ImageIO.getImageReadersByFormatName("png"); default: return ImageIO.getImageReadersByFormatName("jpg"); } }
第一步,用jQuery.form.js的ajaxSubmit()提交上傳的原始圖片,對圖片進行縮放並返回等比例大小的圖片,限制返回的圖片最大尺寸為1000px X 500px
Java核心程式碼如下:
返回的引數中帶有縮放後的影象長寬資訊,在前臺js處獲取到,對Jcrop進行初始化。/** * * imgFileZoom:傳入一個圖片檔案輸入流,寫入縮放後的圖片到輸出流 * * @author 劉各歡 * @param postFix * @param in * @param out * @param showHeight 網頁顯示區域的高 * @param showWidth 網頁顯示區域的寬 * @return * @throws IOException * @since Ver 1.1 */ public Map<String,String> imgFileZoom(String postFix,InputStream in,FileOutputStream out,int showHeight,int showWidth) throws IOException{ //FileInputStream is = null; ImageInputStream iis = null; Map<String,String> map = new HashMap<String,String>(); try { // 讀取圖片檔案 //is = new FileInputStream(in); // 獲取檔案的字尾名 System.out.println("圖片格式為:" + postFix); /* * 返回包含所有當前已註冊 ImageReader 的 Iterator,這些 ImageReader 聲稱能夠解碼指定格式。 * 引數:formatName - 包含非正式格式名稱 .(例如 "jpeg" 或 "tiff")等 。 */ Iterator<ImageReader> it = this.getImageReadersByFormatName(postFix); ImageReader reader = it.next(); // 獲取圖片流 iis = ImageIO.createImageInputStream(in); /* * <p>iis:讀取源.true:只向前搜尋 </p>.將它標記為 ‘只向前搜尋’。 * 此設定意味著包含在輸入源中的影象將只按順序讀取,可能允許 reader 避免快取包含與以前已經讀取的影象關聯的資料的那些輸入部分。 */ reader.setInput(iis, true); int realWidth = reader.getWidth(0); int realHeight = reader.getHeight(0); double ratio = 1.0; if(realWidth>showWidth){ BigDecimal d1 = new BigDecimal(showWidth); BigDecimal d2 = new BigDecimal(realWidth); ratio = d1.divide(d2, 8,BigDecimal.ROUND_HALF_UP).doubleValue(); }else if(realHeight>showHeight){ BigDecimal d1 = new BigDecimal(showHeight); BigDecimal d2 = new BigDecimal(showHeight); ratio = d1.divide(d2, 8,BigDecimal.ROUND_HALF_UP).doubleValue(); }else{ ratio = 1.0; } BigDecimal ratioDecimal = new BigDecimal(ratio); BigDecimal realWidthDecimal = new BigDecimal(realWidth); BigDecimal realHeightDecimal = new BigDecimal(realHeight); BigDecimal outputWidthDecimal = BigDecimal.ONE; BigDecimal outputHeightDecimal = BigDecimal.ONE; outputWidthDecimal = realWidthDecimal.multiply(ratioDecimal); outputHeightDecimal = realHeightDecimal.multiply(ratioDecimal); int outputWidth = outputWidthDecimal.intValue(); int outputHeight = outputHeightDecimal.intValue(); //裝入最終轉換過的圖片的寬高 map.put("outputWidth", String.valueOf(outputWidth)); map.put("outputHeight", String.valueOf(outputHeight)); /* * 使用所提供的 ImageReadParam 讀取通過索引 imageIndex 指定的物件,並將 它作為一個完整的 * BufferedImage 返回。 */ BufferedImage bi = reader.read(0); /* * 縮放圖片 */ Image imageSmall = bi.getScaledInstance(outputWidth, outputHeight, Image.SCALE_DEFAULT); BufferedImage small = new BufferedImage(outputWidth, outputHeight, BufferedImage.TYPE_INT_RGB); Graphics g = small.getGraphics(); g.drawImage(imageSmall, 0, 0, null); // 繪製縮小後的圖 將Image繪製到BufferedImage中 g.dispose(); //寫入新圖片到輸出流 ImageIO.write(small, postFix, out); } finally { if (in != null) in.close(); if (iis != null) iis.close(); if (out != null) out.close(); } return map; } /** * * updateZoomTxService:對上傳的頭像圖片進行縮放,並返回一些引數 * * @author 劉各歡 * @param pic * @param req * @return * @since Ver 1.1 */ public Map<String,Object> uploadZoomTx(MultipartFile pic,String uid,HttpServletRequest req){ //從CommonInfo中讀取上傳檔案的路徑 String pathString = CommonInfo.touxiangPath+"/zoom/"; String fileName = ""; Map<String,Object> map = new HashMap<String,Object>(); //判斷檔案是否已經被獲取到 if (pic.getSize() > 0) { //user.setImage(pathString + pic.getOriginalFilename()); //判斷檔案儲存路徑是否存在 File file = new File(pathString); if (!file.exists() && !file.isDirectory()) { file.mkdirs(); } try { String ext=pic.getOriginalFilename().substring(pic.getOriginalFilename().lastIndexOf(".")+1,pic.getOriginalFilename().length()); fileName = System.currentTimeMillis()+uid+"."+ext; //建立縮放過的檔案輸出流 FileOutputStream fout = new FileOutputStream(pathString + fileName ); map.put("imgInfo",this.imgFileZoom(ext.toLowerCase(),pic.getInputStream(),fout,500,1000)); map.put("imgUrl", fileName); if(fout!=null) fout.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } return map; }
前臺核心程式碼(ajaxSubmit()及成功後的觸發):
$("#uploadTxBtn").click(function(){ var option = { type: "post", success : function(data){ zoomPicName = data['imgUrl']; $("#p_img").attr("src", "../../touxiang/zoom/"+data['imgUrl']); $("#p_img").show(); $("#preview_block").show(); $("#p_img_preview").attr("src", "../../touxiang/zoom/"+data['imgUrl']); $("#p_img").width(data['imgInfo']['outputWidth']); $("#p_img").height(data['imgInfo']['outputHeight']); $("#uploadZoomTx").height(parseInt(data['imgInfo']['outputHeight'])+150); caijian(); } }; $("#uploadZoomTx").ajaxSubmit(option); });
Jcrop相關初始化的js程式碼:
function caijian(){
// Create variables (in this scope) to hold the API and image size
var jcrop_api, boundx, boundy;
$('#p_img').Jcrop({
onChange: updatePreview,
onSelect: updatePreview,
aspectRatio: 1,
setSelect: [0,0,100,100]
},function(){
// Use the API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
console.log(1111);
console.log(bounds);
// Store the API in the jcrop_api variable
jcrop_api = this;
});
function updatePreview(c)
{
if (parseInt(c.w) > 0)
{
console.log(c);
img_x = c.x;
img_y = c.y;
img_w = c.w;
img_h = c.h;
var rx = 100 / c.w;
var ry = 100 / c.h;
$('#p_img_preview').css({
width: Math.round(rx * boundx) + 'px',
height: Math.round(ry * boundy) + 'px',
marginLeft: '-' + Math.round(rx * c.x) + 'px',
marginTop: '-' + Math.round(ry * c.y) + 'px'
});
}
};
}
第二步:
使用者拖拽完裁剪框,點選裁剪按鈕之後,上傳四個引數,分別是起始點的橫縱座標和裁剪區域的寬度高度,
此次過程只上傳引數,並沒有上傳圖片,後臺根據引數對上一步已經縮放的圖片再次進行裁剪和縮放。
js程式碼略去,後臺Java核心程式碼如下:
/**
*
* imgFileCut:傳入一個圖片檔案輸入流,寫入裁減後的圖片到輸出流
*
* @author 劉各歡
* @param postFix
* @param in
* @param out
* @param x
* @param y
* @param width
* @param height
* @param showHeight
* @param showWidth
* @throws IOException
* @since Ver 1.1
*/
public void imgFileCut(String postFix,InputStream in,FileOutputStream out,int x,int y,int width,int height) throws IOException{
ImageInputStream iis = null;
try {
/*
* 返回包含所有當前已註冊 ImageReader 的 Iterator,這些 ImageReader 聲稱能夠解碼指定格式。
* 引數:formatName - 包含非正式格式名稱 .(例如 "jpeg" 或 "tiff")等 。
*/
Iterator<ImageReader> it = getImageReadersByFormatName(postFix);
ImageReader reader = it.next();
// 獲取圖片流
iis = ImageIO.createImageInputStream(in);
/*
* <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);
/*
* 縮放圖片
*/
Image imageSmall = bi.getScaledInstance(100, 100, Image.SCALE_DEFAULT);
BufferedImage small = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
Graphics g = small.getGraphics();
g.drawImage(imageSmall, 0, 0, null); // 繪製縮小後的圖 將Image繪製到BufferedImage中
g.dispose();
// 儲存新圖片
ImageIO.write(small, postFix, out);
} finally {
if (in != null)
in.close();
if (iis != null)
iis.close();
if (out != null)
out.close();
}
}
public String saveTx(String zoomedImageName, String img_x, String img_y,
String img_w, String img_h) {
String zoomedImagePath = CommonInfo.touxiangPath+"/zoom/"+zoomedImageName;
String finalImagePath = CommonInfo.touxiangPath+zoomedImageName;
File zoomedImagefile = new File(zoomedImagePath);
try {
InputStream in = new FileInputStream(zoomedImagefile);
File finalImage = new File(finalImagePath);
FileOutputStream out = new FileOutputStream(finalImage);
int x = new BigDecimal(img_x).intValue();
int y = new BigDecimal(img_y).intValue();
int w = new BigDecimal(img_w).intValue();
int h = new BigDecimal(img_h).intValue();
String postFix=zoomedImageName.substring(zoomedImageName.lastIndexOf(".")+1,zoomedImageName.length()).toLowerCase();
this.imgFileCut(postFix, in, out, x, y, w, h);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("儲存頭像失敗");
return "error";
}
return "success";
}
Control中的主呼叫方法:
/**
*
* updateZoomTx:對上傳的原始頭像進行等比例縮放,並返回檔名等一些引數
*
* @author 劉各歡
* @param pic
* @param req
* @return
* @since Ver 1.1
*/
@ResponseBody
@RequestMapping(value = "/uploadZoomTx.do")
public Map<String,Object> updateZoomTx(MultipartFile pic,HttpServletRequest req){
Map<String,Object> map = null;
if(req.getSession()!=null&&req.getSession().getAttribute("curruser")!=null){
String uid = "";
uid = ((User)(req.getSession().getAttribute("curruser"))).getId();
map =userService.uploadZoomTx(pic,uid,req);
}else{
map=new HashMap<String,Object>();
map.put("error","error");
}
return map;
}
/**
*
* saveTx: 對上一步縮放過的影象進行裁剪並縮放,存在本地硬碟
*
* @author 劉各歡
* @param zoomedImageName
* @param img_x
* @param img_y
* @param img_w
* @param img_h
* @param req
* @return
* @since Ver 1.1
*/
@ResponseBody
@RequestMapping(value = "/saveTx.do")
public String saveTx(String zoomedImageName,String img_x,String img_y,String img_w,String img_h,HttpServletRequest req){
String re =userService.saveTx( zoomedImageName,img_x, img_y, img_w, img_h);
if(req.getSession()!=null&&req.getSession().getAttribute("curruser")!=null){
User user = (User)(req.getSession().getAttribute("curruser"));
user.setImage(zoomedImageName);
userService.saveOrUpdate(user);
return "ok";
}else{
return "error";
}
}
關於利用HTML5的canvas或者flash進行擷取的也想過,考慮到相容性,還是先這樣吧。
預覽效果:
相關推薦
使用Jcrop.js和jQuery.form.js,用ImageIO等進行頭像上傳縮放及裁剪
首先,Java程式碼裡帶一個獲取ImageReader的Iterator /** * 從網上摘抄的。 * 返回包含所有當前已註冊 ImageReader 的 Iterator,這些 ImageReader 聲稱能夠解碼指定格式。 *
當同時使用bootstrap-datepicker.js和jquery.validate.js這兩款插件,至少要選擇兩次時間,才能驗證成功的問題
ont element 表單元素 進行 觸發 this hang font 改變 當用 bootstrap-datepicker.js 這個插件選擇時間,再用jquery.validate.js進行驗證,當時間不為空時則驗證通過。可能由於在時間插件彈出來時,input框的值
jquery.js和jquery.min.js的區別
jquery.js裡的程式碼是沒有進行處理的程式碼,適合人們閱讀和研究。 jquery.min.js裡的程式碼是進行過特殊處理的,所以容量比較小。 所以開發時,使用非壓縮的的,生產上使用壓縮的。 最後歡迎大家訪問我的個人網站:1024s
基於jQuery和cropper點選頭像上傳並預覽裁剪圖片
使用jquery上傳前,預覽圖片,裁剪,示例使用php接收上傳的檔案,並且儲存為裁剪後的圖片。不需要上傳後再裁剪圖片,只需要本地裁剪好即可,裁剪的時候也可以旋轉圖片。裁剪控制元件使用了,cropper。 html程式碼 <!DOCTYPE html> <html la
springMVC上傳檔案,MultipartHttpServletRequest、MultipartFile進行檔案上傳
這裡使用apache的開源jar包完成上傳功能,使用jar包分別是:common-fileupload.jar和common-io.jar 先編寫上傳檔案幫助類,如果需要區分檔案型別,可以將檔案字尾擷取進行判斷; springmvc-mvc.xml配置,這裡主要配置spri
iOS 調取本地相簿/相機,剪裁圖片進行頭像上傳
開啟本地相簿或開啟本地相機拍照,獲取圖片裁剪圖片,上傳圖片 加入標頭檔案 #import <MobileCoreServices/MobileCoreServices.h> #import <AVFoundation/AVFoundat
通過終端命令列進行WebDav伺服器配置,實現使用PUT進行檔案上傳【圖文詳解】
HTTP的常見方法 》GET 獲取指定資源 》POST 2M 向指定資源提交資料進行處理請求,在RESTful風格中用於新增資源 》HEAD 獲取指定資源頭部資訊 》PUT 替換指定資源(不支援瀏覽器操作) 》DE
用jquery-form.js提交帶文件的數據
offset 發布 文件選擇 需要 保存 con file -m 選擇 最近做一個項目需要同時向後臺傳文件和數據,經過多方考證,選擇了使用jquery-form.js插件。所以總結一下,僅大家參考; html部分: <form enctype="multipart/
25.用js和jquery實現下拉列表的左右選擇
select2 hit color nts -type utf ctype block 標簽 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/x
js 五 jquery的使用,調用
name attr tar 添加 offset read query -- 文檔 4 this 關鍵字 this 表示當前函數或方法的調用者 1 全局函數由window調用,所以全局函數中的this 指的是window對象 2 事件處理函數中使用t
同時使用vue.js和jquery時,jq事件無響應解決辦法
先載入vue.js,讓頁面渲染完成後載入jq,給jq繫結ready事件 $(document).ready(function(){ $(function() { //jq事件 }); }); 更新 ……ready載入太玄學了,測試3/10的
js和jQuery調用搜狐IP地址查詢介面
介面返回的資料是: var returnCitySN = {"cip": "119.137.53.105", "cid": "440306", "cname": "廣東省深圳市寶安區"}; js呼叫: <script src="http://p
分別用js和jQuery是實現表格的全選中和全不選
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>使用jQuery和js完成複選框的全選和全不選</title> <script
Form表單提交後獲取後臺資料,需要jquery-form.js指令碼
<script type="text/javascript" src="js/jquery-form.js"></script> <script type="text/javascript"> $(documen
jquery.form.js 利用ajaxSubmit ajax上傳Excel,
@RequestMapping(value="importClubPersonInfoFromExcel.json", method={RequestMethod.POST}) @ResponseBody public Map<String,Object> importClubPersonIn
js和jquery實現回到頂層
left ret poi add 寬度 fadein soft 距離 jquery實現 js <!DOCTYPE html> <html> <head> <title>返回頂部</title> <styl
ECSHOP中transport.js和jquery的沖突的簡單解決辦法
order adding fun ring func 資源 代碼 spa pac ECSHOP中transport.js和jquery的沖突的簡單解決辦法 一流資源網近日在ECSHOP網站加入了幾個JS特效代碼,在谷歌、火狐下正常,在各版本IE下都不常,左思不得其解。
更好的實現js數組連接,用到的知識apply.
講解 ber array 方便 this var 但是 ken 兩個 最近做的萬達的一個能源管理平臺中用到了數據連接,當時想都沒想直接寫了一個a.concat(b)。今天在掘金看到了一個優化的方案。是這樣:a.push.apply(a,b);其中a,b分別為兩個數組。仔細一
跨域問題相關知識詳解(原生js和jquery兩種方法實現jsonp跨域)
syn con 加載 developer 兩種方法 ray exe 編寫 分組 1、同源策略 同源策略(Same origin policy),它是由Netscape提出的一個著名的安全策略。同源策略是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽
將原生JS和jquery裏面的DOM操作進行了一下整理
ont child ace attr move 節點 沒有 設置 復制 創建元素節點 1.原生: document.createElement("div") 2.jquery: $("<div></div>") 創建文本節點並加入元素節點中