基于jquery的imgAreaSelect.js插件+JAVA后台实现图片裁剪保存功能
来源:互联网 发布:腾讯视频for mac官方 编辑:程序博客网 时间:2024/05/19 20:22
前段时间,项目在做个人信息设置,其中有一项是设置用户头像信息,需要将用户选择的头像按照用户需要进行剪切,同时保存为大(120*120)、中(75*75)、小(35*35)三种格式的图像,分别显示到不同的位置。
需求很简单,就是这么easy,这个其中重点就是用户可以自己对选择的头像进行截取,最终选择了基于jquery的imgareaselect.js。既然插件都有了,那就开工吧!
第一步:
前端下载必须的js插件,后台使用java自带imageio包处理,不需要其他jar包。
jquery.imgareaselect-0.9.10.zip
jquery.js
第二步:
新建静态页面index.html (页面有点丑哈。。。)
<html lang="en"><head> <meta charset="UTF-8"> <title>jquery.imgareaselect图像区域剪切</title> <meta id="i18n_pagename" content="index-common"> <meta name="viewport" content="width=device-width"> <meta name="keywords" content="" /> <meta name="description" content=""/> <link rel="stylesheet" href="css/imgareaselect-default.css"> <link rel="stylesheet" href="css/index.css"></head><body> <div> <input type="file" style="display: none" id="upImg" onchange="changeImg(this)"> <label for="upImg" id="preview"> <img id="imghead" src="images/normal.png" width="198" height="198" alt="头像"> </label> </div> <div class="boxFooter"> <input type="hidden" name="x1" value="0"> <input type="hidden" name="y1" value="0"> <input type="hidden" name="x2" value="100"> <input type="hidden" name="y2" value="100"> <button name="confirm" id="subPhoto" >确 定</button> <div id="imgmsg"></div> </div> <script src="js/jquery.js"></script> <!-- 加载js文件 --> <script src="js/jquery.imgareaselect.min.js"></script> <script src="js/image.js"></script></body></html>
说明:该页面是模拟前端截取图像,并将起始位置坐标和图片base64编码发送给后端,后端进行处理。
第三步:
新建前端处理js文件image.js
$(document).ready(function () { //提交图片剪切信息到后台 $("#subPhoto").click(function(){ var x1 = $("input[name='x1']").val(); var y1 = $("input[name='y1']").val(); var x2 = $("input[name='x2']").val(); var y2 = $("input[name='y2']").val(); var img64 = $("#imghead").attr("src"); alert(x1+":"+y1+":"+x2+":"+y2); var url = ""; var param = { 'x1': x1, 'y1': y1, 'x2': x2, 'y2': y2, 'image': img64 } $.post(url,param,function(data){ alert(data); }); })}); //点击图像区域选择图片function changeImg(obj){ //图片选择处理 var file = obj; var MAXWIDTH = 198; var MAXHEIGHT = 198; var MAXSIZE = 2048*1024; var div = document.getElementById('preview'); if (file.files && file.files[0]){ if (file.files[0].size > MAXSIZE) { alert("more than " + (MAXSIZE/1024/1024) + "M"); return false; }; div.innerHTML ='<img id=imghead>'; var img = document.getElementById('imghead'); img.onload = function(){ var rect = clacImgZoomParam(MAXWIDTH, MAXHEIGHT, img.offsetWidth, img.offsetHeight); img.width = rect.width; img.height = rect.height; img.style.marginTop = rect.top+'px'; } var reader = new FileReader(); reader.onload = function(evt){ img.src = evt.target.result; } reader.readAsDataURL(file.files[0]); } //图片剪切区域处理 $('#imghead').imgAreaSelect({ x1:0, y1:0, x2:100, y2:100, aspectRatio: '1:1', //比例 handles: true, onSelectChange: function(img, selection){//图片剪切区域变化时触发 $("#imgmsg").html("x1:"+selection.x1+", y1:"+selection.y1+", x2:"+selection.x2+", y2:"+selection.y2); }, onSelectEnd: function (img, selection) {//图片剪切区域结束时触发 $('input[name="x1"]').val(selection.x1); $('input[name="y1"]').val(selection.y1); $('input[name="x2"]').val(selection.x2); $('input[name="y2"]').val(selection.y2); } }); }//设置图片显示区域为固定大小,方便后台按统一比例截取图片function clacImgZoomParam( maxWidth, maxHeight, width, height ){ var param = {top:0, left:0, width:width, height:height}; if( width>maxWidth || height>maxHeight ){ rateWidth = width / maxWidth; rateHeight = height / maxHeight; if( rateWidth > rateHeight ){ param.width = maxWidth; param.height = Math.round(height / rateWidth); }else { param.width = Math.round(width / rateHeight); param.height = maxHeight; } } param.left = Math.round((maxWidth - param.width) / 2); param.top = Math.round((maxHeight - param.height) / 2); return param;}
说明:该js文件不难,大家都应该能看懂,调用imgAreaSelect.js的地方在$(‘#imghead’).imgAreaSelect({…})里面,这块也不难看懂,在 onSelectChange: function(img, selection){})这个地方图片剪切区域变化时触发,我们可以做一些其他的处理,比如预览截取部分的图像等等。clacImgZoomParam()方法主要是用于对用户选择的图像进行限定固定高度和宽度,方便后台按照统一的比例计算截取的坐标位置。
第四步:
后台接收并处理图片,后台是基于SpringMVC的,不熟悉的可以自学下下。
UserController.java
package com.gochina.tc.api;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import com.gochina.tc.po.ResultPo;import com.gochina.tc.service.UserService;/** * 用户信息处理 * @author hwy * */@Controller@RequestMapping(value = "/user")public class UserController { @Autowired private UserService userService; @RequestMapping(value = "/uploadImage",method = RequestMethod.POST) public ResultPo uploadUserImage( @RequestParam(value = "image",required = true) String base64Code, @RequestParam(value = "x1",required = true) int x1, @RequestParam(value = "y1",required = true) int y1, @RequestParam(value = "x2",required = true) int x2, @RequestParam(value = "y2",required = true) int y2){ String result = userService.uploadUserImage(base64Code, x1, y1, x2, y2); if(result.equals("")){ return new ResultPo(false, "上传用户图像失败"); }else{ return new ResultPo("success", result); } }}
UserService.java
package com.gochina.tc.service;/** * 用户信息处理service * @author hwy * */public interface UserService { /** * 上传并处理用户图片 */ public String uploadUserImage(String base64Code,int x1,int y1,int x2,int y2);}
UserServiceImpl.java
package com.gochina.tc.service.impl;import java.io.File;import java.text.SimpleDateFormat;import java.util.Date;import java.util.UUID;import org.springframework.stereotype.Service;import com.gochina.tc.util.ImageUtil;/** * 用户信息处理serviceImpl * @author hwy * */@Servicepublic class UserServiceImpl implements UserService { /** * 用户上传图片处理 */ public String uploadUserImage(String base64Code,int x1,int y1,int x2,int y2){ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String dateStr = sdf.format(new Date()); String path = "D:/user_image/" + dateStr + "/"; String url = "http://127.0.0.1:8080/user_image/" + dateStr + "/"; File f = new File(path); if(!f.exists()){ f.mkdirs(); } String fileName = UUID.randomUUID().toString().replaceAll("-", "")+".jpg"; String temp_fileName = path + "t_" + fileName; String b_fileName = path + "b_" + fileName; String m_fileName = path + "m_" + fileName; String s_fileName = path + "s_" + fileName; String result = ""; try{ //创建原始文件(先强制修改为jpg格式) boolean isCreate = ImageUtil.base64ToImage(base64Code, path + fileName); if(isCreate){ float scale = ImageUtil.getScaleCutImage(path + fileName);//比例 int width = (int) ((x2-x1)*scale); int height = width; int start_x = (int) (x1*scale); int start_y = (int) (y1*scale); //剪切图片 ImageUtil.cutImage(path + fileName, temp_fileName, start_x, start_y, width, height); //剪切以后的图片压缩到固定大小的图片 ImageUtil.reduceImageByWidthHeight(temp_fileName, b_fileName, 200, 200);//200*200大图 ImageUtil.reduceImageByWidthHeight(temp_fileName, m_fileName, 120, 120);//120*120中图 ImageUtil.reduceImageByWidthHeight(temp_fileName, s_fileName, 70, 70);//70*70小图 result = url + fileName; } }catch(Exception e){ e.printStackTrace(); } return result; }}
说明:该文件处理流程大致为,1、创建原始文件,将base64编码转换成图片,并强制修改为jpg格式。2、获取图片的压缩比例,并计算剪切图片的长宽和起始坐标。3、按照要求剪切图片。4、将剪切以后的图片压缩到固定大小的图片。
ImageUtil.java
package com.gochina.tc.util;import java.awt.Color;import java.awt.Rectangle;import java.awt.image.BufferedImage;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import java.util.Iterator;import javax.imageio.ImageIO;import javax.imageio.ImageReadParam;import javax.imageio.ImageReader;import javax.imageio.stream.ImageInputStream;import sun.misc.BASE64Decoder;import com.sun.image.codec.jpeg.JPEGCodec;import com.sun.image.codec.jpeg.JPEGEncodeParam;import com.sun.image.codec.jpeg.JPEGImageEncoder;/** * 上传的图片进行截取,压缩处理 * @author hwy * */public class ImageUtil { /** * 长高等比例缩小图片 * @param srcImagePath 读取图片路径 * @param toImagePath 写入图片路径 * @param ratio 缩小比例 * @throws IOException */ public static void reduceImageByRatio(String srcImagePath,String toImagePath,float ratio) throws IOException{ FileOutputStream out = null; try{ //读入文件 File file = new File(srcImagePath); // 构造Image对象 BufferedImage src = javax.imageio.ImageIO.read(file); int width = src.getWidth(); int height = src.getHeight(); // 缩小边长 BufferedImage tag = new BufferedImage((int)(width / ratio), (int)(height / ratio), BufferedImage.TYPE_INT_RGB); // 绘制 缩小后的图片 tag.getGraphics().drawImage(src, 0, 0, (int)(width / ratio), (int)(height / ratio), null); out = new FileOutputStream(toImagePath); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(tag); param.setQuality(0.75f, true);// 默认0.75 encoder.setJPEGEncodeParam(param); encoder.encode(tag); }catch(Exception e){ e.printStackTrace(); }finally{ if(out != null){ out.close(); } out = null; System.gc(); } } /** * 缩小图片到固定长高 * @param srcImagePath 读取图片路径 * @param toImagePath 写入图片路径 * @param width 缩小后图片宽度 * @param height 缩小后图片长度 * @throws IOException */ public static void reduceImageByWidthHeight(String srcImagePath, String toImagePath, int width, int height) throws IOException{ FileOutputStream out = null; try{ //读入文件 File file = new File(srcImagePath); // 构造Image对象 BufferedImage src = javax.imageio.ImageIO.read(file); // 缩小边长 BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 绘制缩小后的图片 tag.getGraphics().drawImage(src, 0, 0, width, height, null); out = new FileOutputStream(toImagePath); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(tag); param.setQuality(1f, true);// 默认0.75 encoder.setJPEGEncodeParam(param); encoder.encode(tag); }catch(Exception e){ e.printStackTrace(); }finally{ if(out != null){ out.close(); } out = null; System.gc(); } } /** * 剪切图片 * @param srcpath * @param subpath * @param x * @param y * @param width * @param height * @throws IOException */ public static void cutImage(String srcpath,String subpath,int x,int y,int width,int height) throws IOException { FileInputStream is = null; ImageInputStream iis = null; try { // 读取图片文件 is = new FileInputStream(srcpath); Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName("jpg"); ImageReader reader = it.next(); // 获取图片流 iis = ImageIO.createImageInputStream(is); reader.setInput(iis, true); ImageReadParam param = reader.getDefaultReadParam(); // 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域,通过 Rectangle 对象的左上顶点的坐标(x,y)、宽度和高度可以定义这个区域。 Rectangle rect = new Rectangle(x, y, width, height); // 提供一个 BufferedImage,将其用作解码像素数据的目标。 param.setSourceRegion(rect); BufferedImage bi = reader.read(0, param); // 保存新图片 ImageIO.write(bi, "jpg", new File(subpath)); }finally { if(is != null){ is.close(); } if(iis != null){ iis.close(); } } } /** * 获取图片缩放尺寸 * @param srcImagePath * @return * @throws IOException */ public static float getScaleCutImage(String srcImagePath) throws IOException{ //读入文件 File file = new File(srcImagePath); // 构造Image对象 BufferedImage src = javax.imageio.ImageIO.read(file); int width = src.getWidth(); int height = src.getHeight(); float scale = 0f; if(width >= height){ scale = (float)width/200; }else if(width < height){ scale = (float)height/200; } return scale; } /** * @Descriptionmap 对字节数组字符串进行Base64解码并生成图片 * @param base64 图片Base64数据 * @param path 图片路径 * @return */ public static boolean base64ToImage(String base64, String path) { // 图像数据为空 if(base64 == null){ return false; } if(base64.indexOf("base64") != -1){ base64 = base64.substring(base64.indexOf("base64")+7, base64.length()); } // Base64解码 BASE64Decoder decoder = new BASE64Decoder(); try{ byte[] bytes = decoder.decodeBuffer(base64); for(int i=0;i<bytes.length;i++){ // 调整异常数据 if(bytes[i] < 0){ bytes[i] += 256; } } // 生成jpeg图片 OutputStream out = new FileOutputStream(path); out.write(bytes); out.flush(); out.close(); //非jpg格式的图片强转为jpg if(base64.indexOf("image/jpeg") == -1){ imageToJPG(path, path); } return true; }catch(Exception e){ e.printStackTrace(); return false; } } /** * 将图片格式转成jpg的支持( GIF->JPG GIF->PNG PNG->GIF(X) PNG->JPG) * @param src1 * @param result * @throws IOException */ public static void imageToJPG(String src1,String result) throws IOException{ File f = new File(src1); f.canRead(); BufferedImage src = ImageIO.read(f); ImageIO.write(src, "jpg", new File(result)); }}
说明:这个工具类注释写的比较详细,也不难看懂。有几个地方需要注意下:
1、imageToJPG()方法,将图片格式转成jpg的暂时只支持( GIF->JPG 、GIF->PNG 、PNG->GIF(X)、 PNG->JPG)这几种形式。
2、base64ToImage()方法,对字节数组字符串进行Base64解码并生成图片,里面前端传过来的数据串会带有类似data:image/png;base64,这段标示,我们需要将这部分截取掉才可以生成图片。
3、getScaleCutImage()方法,计算scale的时候,基数为200,这个要跟前端的图片显示区域保持一致,不然截取的图片就不正确了。
4、reduceImageByRatio()方法,长高等比例缩小图片中, param.setQuality(0.75f, true); 设置图片的质量,这个默认图像质量是0.75,如果想高质量保存,就设置为接近1即可,当然图片容量大小就会跟着变化了。
好了,大功即将告成!先来看下页面的效果如何吧!
当然这个效果比较low,不是很好看,仅仅是个demo而已,再来贴个项目线上的效果图吧,这个不low哦!
- 基于jquery的imgAreaSelect.js插件+JAVA后台实现图片裁剪保存功能
- php+jquery插件imgAreaSelect图片裁剪保存
- 利用jquery的imgAreaSelect插件实现图片裁剪示例
- 利用jquery的imgAreaSelect插件实现图片裁剪示例
- 利用jquery的imgAreaSelect插件实现图片裁剪示例
- 利用jquery的imgAreaSelect插件实现图片裁剪示例
- imgareaselect+java实现图片裁剪保存
- PHP Uploadify+jQuery.imgAreaSelect插件+AJAX 实现图片上传裁剪 仿微博头像上传功能
- PHP Uploadify+jQuery.imgAreaSelect插件+AJAX 实现图片上传裁剪 仿微博头像上传功能
- imgareaselect jquery.imgareaselect.js 页面图片插件
- jQuery插件imgAreaSelect图片裁剪使用详解
- 基于jQuery插件imgAreaSelect和ArcGIS server模仿实现百度地图的截图功能
- Jquery 裁剪图片插件imgAreaSelect应用注意点整理
- imgareaselect + php实现图片裁剪
- imgareaselect图片裁剪、js裁剪案例
- 使用imgareaselect 辅助后台进行图片裁剪
- 选取图片裁剪并上传功能的实现(后台java实现)
- 带裁剪的图片上传功能jquery插件
- java+内存分配及变量存储位置的区别
- yum卡在Running Transaction Testde
- java中的内存操作流
- http:笔记
- 不只是给面试加分 -- Java WeakReference的理解与使用
- 基于jquery的imgAreaSelect.js插件+JAVA后台实现图片裁剪保存功能
- 莫教引动虚阳发,精竭容枯百病 侵
- 开源.NET排列组合组件KwCombinatorics使用(二)——排列生成
- 戒淫格言
- IPTABLES命令
- apache无法解析php文件
- mysql创建函数失败问题解决办法
- GPS小程序
- Windows 函数调用