利用jQuery与Java实现在线图片的剪切
一 参考资料
1 jquery Jcrop 头像,logo截图
http://terje.blog.163.com/blog/static/11924371201101311319664/
2 javascript+java截取图像,图像处理
http://www.blogjava.net/b47248054/articles/200685.html
3 js+java 截取照片中的头像
http://blog.csdn.net/dsj188/article/details/4313662
4 java+jsp 截头像图片
http://ldf2008rw.iteye.com/blog/502793
5 Java生成缩略图之Thumbnailator
http://rensanning.iteye.com/blog/1545708
Thumbnailator 是一个为Java界面更流畅的缩略图生成库。从API提供现有的图像文件和图像对象的缩略图中简化了缩略过程,两三行代码就能够从现有图片生成缩略图,且 允许微调缩略图生成,同时保持了需要写入到最低限度的代码量。同时还支持根据一个目录批量生成缩略图。 http://code.google.com/p/thumbnailator/ 这个不错!支持!
二 解决思路
1 通过smart-upload文件上传组件将图片上传到服务器,并得到图片文件地址传递到前台的img组件显示
2 在客户端用JS获取图片X坐标,Y坐标,宽度和高度这四个参数并设置到隐藏元素.
3 java后台根据图片关键的四个参数实现图片剪切并在服务器端生成图片文件
4 通过生成图片的地址在前台展现
开发环境: XP3
开发工具: JDK1.6+MyEclipse6.5+Tomcat6
工程图片:
三 实现方式
1 选用JQuery插件:Jcrop
官方网站: http://deepliquid.com/content/Jcrop.html
项目地址: http://code.google.com/p/jcrop/
效果图片如下:
2 通过图片剪切工具类,主要代码如下:
- /**
- * 图像切割(改) *
- * @param srcImageFile 源图像地址
- * @param dirImageFile 新图像地址
- * @param x 目标切片起点x坐标
- * @param y 目标切片起点y坐标
- * @param destWidth 目标切片宽度
- * @param destHeight 目标切片高度
- */
- public static void abscut(String srcImageFile,String dirImageFile, int x, int y, int destWidth,
- int destHeight) {
- try {
- Image img;
- ImageFilter cropFilter;
- // 读取源图像
- BufferedImage bi = ImageIO.read(new File(srcImageFile));
- int srcWidth = bi.getWidth(); // 源图宽度
- int srcHeight = bi.getHeight(); // 源图高度
- if (srcWidth >= destWidth && srcHeight >= destHeight) {
- Image image = bi.getScaledInstance(srcWidth, srcHeight,
- Image.SCALE_DEFAULT);
- // 改进的想法:是否可用多线程加快切割速度
- // 四个参数分别为图像起点坐标和宽高
- // 即: CropImageFilter(int x,int y,int width,int height)
- cropFilter = new CropImageFilter(x, y, destWidth, destHeight);
- img = Toolkit.getDefaultToolkit().createImage(
- new FilteredImageSource(image.getSource(), cropFilter));
- BufferedImage tag = new BufferedImage(destWidth, destHeight,
- BufferedImage.TYPE_INT_RGB);
- Graphics g = tag.getGraphics();
- g.drawImage(img, 0, 0, null); // 绘制缩小后的图
- g.dispose();
- // 输出为文件
- ImageIO.write(tag, "JPEG", new File(dirImageFile));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
四 具体代码如下:
1 index.jsp(上传图片页面)
- <%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
- %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title></title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <script src="/scripts/clearFile.js" type="text/javascript"></script>
- <script type="text/javascript">
- /**检查图片上传类型*/
- function checkImgType(obj){
- var imgFile = '';
- //获取图片的全路径
- var imgFilePath = getImgFullPath(obj);
- var endIndex = imgFilePath.lastIndexOf("\\");
- var lastIndex = imgFilePath.length-endIndex-1;
- if (endIndex != -1)
- imgFile= imgFilePath.substr(endIndex+1,lastIndex);
- else
- imgFile = imgFilePath;
- var tag = true;
- endIndex = imgFilePath.lastIndexOf(".");
- if (endIndex == -1)
- tag = false;
- var ImgName = imgFilePath.substr(endIndex+1,lastIndex);
- ImgName = ImgName.toUpperCase();
- if (ImgName !="GIF" && ImgName !="JPG" && ImgName !="PNG" && ImgName !="BMP"){
- tag=false;
- }
- if (!tag) {
- alert("上传图片的文件类型必须为: *.gif,*.jpg,*.png,*.bmp,请重新选择!")
- Upload.clear(obj);
- return false;
- }
- document.form1.submit();
- }
- function getImgFullPath(obj) {
- if (obj) {
- //ie
- if (window.navigator.userAgent.indexOf("MSIE") >= 1) {
- obj.select();
- return document.selection.createRange().text;
- }
- //firefox
- else if (window.navigator.userAgent.indexOf("Firefox") >= 1) {
- if (obj.files) {
- return obj.files.item(0).getAsDataURL();
- }
- return obj.value;
- }
- return obj.value;
- }
- }
- </script>
- </head>
- <body>
- <form name=form1 method=post enctype="multipart/form-data" action="<%=path%>/imgUpload">
- <div style="margin-left: 35%;margin-top: 20%">
- <table width="100%" border="0" align="center" cellpadding="0" cellspacing="0" >
- <tr>
- <td > 图片上传<font color='red'>*.gif,*.jpg,*.png,*.bmp</font></td>
- </tr>
- <tr>
- <td width="80%">
- <input type="file" name="imgFile" id="imgFile" maxlength="160" onchange="checkImgType(this);" width="300px"/>
- </td>
- </tr>
- </table>
- </div>
- </form>
- </body>
- </html>
2 ImgUploadServlet.java(图片上传处理类)
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.IOException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import javax.imageio.ImageIO;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class ImgUploadServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- public static final String IMGROOT = "/uploads/";
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doPost(request,response);
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- String userWebAppPath = getWebAppPath();
- /**检查是否有图片上传文件夹*/
- checkImageDir(userWebAppPath);
- /**图片上传的相对路径*/
- String imgUploadPath = null;
- String imgWebAppPath = null;
- /**图片后缀*/
- String imgFileExt = null;
- /**图片名称:以当前日期*/
- SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddhhmmss");
- String imgFileId = formatter.format(new Date());
- //图片初始化高度与宽度
- String width = null;
- String height = null;
- int imgWidth = 0;
- int imgHeight = 0;
- try {
- com.jspsmart.upload.SmartUpload smartUpload = new com.jspsmart.upload.SmartUpload();
- smartUpload.initialize(getServletConfig(), request, response);
- smartUpload.upload();
- com.jspsmart.upload.Request rqest = smartUpload.getRequest();
- //指定图片宽度和高度
- width = rqest.getParameter("width");
- if(null == width){
- width = "700";
- }
- height= rqest.getParameter("height");
- if(null == height){
- height = "600";
- }
- imgWidth = Integer.parseInt(width);
- imgHeight = Integer.parseInt(height);
- //文件个数
- int fileCounts = smartUpload.getFiles().getCount();
- for (int i = 0; i <fileCounts; i++) {
- com.jspsmart.upload.File myFile = smartUpload.getFiles().getFile(i);
- if (!myFile.isMissing()) {
- imgFileExt = myFile.getFileExt();
- //组装图片真实名称
- imgFileId += i + System.currentTimeMillis() + "." + imgFileExt;
- //图片生成路径
- imgWebAppPath = userWebAppPath + imgFileId;
- //生成图片文件
- myFile.saveAs(imgWebAppPath);
- //图片的相对路径
- imgUploadPath = IMGROOT + imgFileId;
- //检查图片大小
- BufferedImage src = ImageIO.read(new File(imgWebAppPath)); // 读入文件
- int imgSrcWidth = src.getWidth(); // 得到源图宽
- //重新指定大小
- imgWidth = imgSrcWidth > imgWidth ? imgWidth : imgSrcWidth;
- int imgSrcHeight = src.getHeight(); // 得到源图长
- imgHeight = imgSrcHeight > imgHeight ? imgHeight : imgSrcHeight;
- //按照图片的设置大小生成
- ImageCut.scale(imgWebAppPath, imgWebAppPath,imgWidth,imgHeight);
- File f = new File(imgWebAppPath);
- if(f.exists()){
- System.out.println("创建"+imgWidth+"*"+imgHeight+"图片成功");
- }
- }
- }
- }catch(Exception ex){
- ex.printStackTrace();
- }
- String path = "/imgcrop.jsp?tag=0&oldImgPath="+imgUploadPath+"&imgFileExt="+imgFileExt+"&imgRoot="+IMGROOT+"&width="+imgWidth+"&height="+imgHeight;
- System.out.println("path: "+path);
- request.getRequestDispatcher(path).forward(request,response);
- }
- private String getWebAppPath(){
- String webAppPath = this.getServletContext().getRealPath("/");
- String userWebAppPath = webAppPath+IMGROOT;
- return userWebAppPath;
- }
- private void checkImageDir(String userWebAppPath) {
- File file = new File(userWebAppPath);
- if(!file.exists()){
- file.mkdir();
- }
- }
- }
3 imgcrop.jsp(图片展现并剪切页面)
- <%@ page language="java" pageEncoding="UTF-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
- %>
- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title>图片剪辑</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- <link rel="stylesheet" href="styles/jquery.Jcrop.css" type="text/css" />
- <link rel="stylesheet" href="styles/demos.css" type="text/css" />
- <script src="scripts/jquery.min.js"></script>
- <script src="scripts/jquery.Jcrop.js"></script>
- </head>
- <body STYLE='OVERFLOW:SCROLL;OVERFLOW-X:HIDDEN;OVERFLOW-Y:HIDDEN'>
- <form name=form1 method=post action="<%=path%>/imgCrop">
- <table width="60%" border="0" align="center" cellpadding="0" cellspacing="0" >
- <tr>
- <td id="cropTd" style="display:none"><input type="button" value="剪切照片" id="cropButton"/></td>
- </tr>
- <tr>
- <td id="imgTd" style="width:${param.width}px;height:${param.height}px;" align="center" style="padding-top:5px;">
- <c:choose>
- <c:when test="${param.tag eq 0}">
- <img src="<%=path%>${param.oldImgPath}" id="imgCrop" name="imgCrop" border="0" />
- </c:when>
- <c:when test="${param.tag eq 1}">
- <img src="<%=path%>${param.imgName}" id="imgCrop" name="imgCrop" border="0" />
- </c:when>
- </c:choose>
- </td>
- </tr>
- <tr>
- <td>
- <label>X1 <input type="text" size="4" id="labelX" name="labelX" /></label>
- <label>Y1 <input type="text" size="4" id="labelY" name="labelY" /></label>
- <label>X2 <input type="text" size="4" id="labelX2" name="labelX2" /></label>
- <label>Y2 <input type="text" size="4" id="labelY2" name="labelY2" /></label>
- <label>W <input type="text" size="4" id="labelW" name="labelW" /></label>
- <label>H <input type="text" size="4" id="labelH" name="labelH" /></label>
- </td>
- </tr>
- <tr>
- <td colspan="2"><a href="index.jsp">返回上传图片</a></td>
- </tr>
- </table>
- <input type="hidden" id="x" name="x" />
- <input type="hidden" id="y" name="y" />
- <input type="hidden" id="x2" name="x2" />
- <input type="hidden" id="y2" name="y2" />
- <input type="hidden" id="w" name="w" />
- <input type="hidden" id="h" name="h" />
- <!-- 源图片宽度和高度 -->
- <input type="hidden" id="width" name="width" value="${param.width}"/>
- <input type="hidden" id="height" name="height" value="${param.height}"/>
- <input type="hidden" id="oldImgPath" name="oldImgPath" value="${param.oldImgPath}"/>
- <input type="hidden" id="imgRoot" name="imgRoot" value="${param.imgRoot}"/>
- <input type="hidden" id="imgFileExt" name="imgFileExt" value="${param.imgFileExt}"/>
- </form>
- </body>
- </html>
- <script type="text/javascript">
- jQuery(document).ready(function(){
- jQuery('#imgCrop').Jcrop({
- onChange: showCoords,
- onSelect: showCoords
- });
- jQuery('#cropButton').click(function(){
- var x = jQuery("#x").val();
- var y = jQuery("#y").val();
- var w = jQuery("#w").val();
- var h = jQuery("#h").val();
- if(w == 0 || h == 0 ){
- alert("您还没有选择图片的剪切区域,不能进行剪切图片!");
- return;
- }
- alert("你要剪切图片的X坐标: "+x + ",Y坐标: " + y + ",剪切图片的宽度: " + w + ",高度:" + h );
- if(confirm("确定按照当前大小剪切图片吗")){
- document.form1.submit();
- }
- });
- });
- function showCoords(c)
- {
- jQuery('#x').val(c.x);
- jQuery('#y').val(c.y);
- jQuery('#x2').val(c.x2);
- jQuery('#y2').val(c.y2);
- jQuery('#w').val(c.w);
- jQuery('#h').val(c.h);
- jQuery('#labelX').val(c.x);
- jQuery('#labelY').val(c.y);
- jQuery('#labelX2').val(c.x2);
- jQuery('#labelY2').val(c.y2);
- jQuery('#labelW').val(c.w);
- jQuery('#labelH').val(c.h);
- //显示剪切按键
- jQuery('#cropTd').css("display","");
- }
- </script>
4 ImgCropServlet.java(执行图片剪切类)
- import java.io.File;
- import java.io.IOException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class ImgCropServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doPost(request, response);
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- System.out.println("x: " + request.getParameter("x") + "," + request.getParameter("y") + "," + request.getParameter("w") + "," + request.getParameter("h"));
- // 用户经过剪辑后的图片的大小
- Integer x = Integer.parseInt(request.getParameter("x"));
- Integer y = Integer.parseInt(request.getParameter("y"));
- Integer w = Integer.parseInt(request.getParameter("w"));
- Integer h = Integer.parseInt(request.getParameter("h"));
- //获取原显示图片路径
- String oldImgPath = request.getParameter("oldImgPath");
- //图片后缀
- String imgFileExt = request.getParameter("imgFileExt");
- String imgRoot = request.getParameter("imgRoot");
- Integer width = Integer.parseInt(request.getParameter("width"));
- Integer height = Integer.parseInt(request.getParameter("height"));
- //WEB应用程序根路径
- String webAppPath = getServletContext().getRealPath("/");
- /**图片名称:以当前日期*/
- SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddhhmmss");
- String imgFileId = formatter.format(new Date());
- String imgName = imgRoot + imgFileId + System.currentTimeMillis() + "." + imgFileExt;
- //组装图片真实名称
- String createImgPath = webAppPath + imgName;
- //之前上传的图片路径
- webAppPath += oldImgPath;
- System.out.println("原图片路径: " + webAppPath + ",新图片路径: " + createImgPath);
- //进行剪切图片操作
- ImageCut.abscut(webAppPath, createImgPath, x,y,w, h);
- File f = new File(createImgPath);
- if(f.exists()){
- System.out.println("剪切图片大小: "+w+"*"+h+"图片成功!");
- }
- String path = "/imgcrop.jsp?tag=1&oldImgPath="+oldImgPath+"&imgFileExt="+imgFileExt+"&imgRoot="+imgRoot + "&imgName="+imgName+"&height=" + height + "&width=" + width;
- System.out.println("imgCrop: " + path);
- request.getRequestDispatcher(path).forward(request,response);
- }
- }
5 ImageCut.java(图片剪切工具类)
- import java.io.*;
- import java.awt.*;
- import java.awt.image.*;
- import java.awt.Graphics;
- import java.awt.color.ColorSpace;
- import javax.imageio.ImageIO;
- public class ImageCut {
- /**
- * 图像切割(改) *
- * @param srcImageFile 源图像地址
- * @param dirImageFile 新图像地址
- * @param x 目标切片起点x坐标
- * @param y 目标切片起点y坐标
- * @param destWidth 目标切片宽度
- * @param destHeight 目标切片高度
- */
- public static void abscut(String srcImageFile,String dirImageFile, int x, int y, int destWidth,
- int destHeight) {
- try {
- Image img;
- ImageFilter cropFilter;
- // 读取源图像
- BufferedImage bi = ImageIO.read(new File(srcImageFile));
- int srcWidth = bi.getWidth(); // 源图宽度
- int srcHeight = bi.getHeight(); // 源图高度
- if (srcWidth >= destWidth && srcHeight >= destHeight) {
- Image image = bi.getScaledInstance(srcWidth, srcHeight,
- Image.SCALE_DEFAULT);
- // 改进的想法:是否可用多线程加快切割速度
- // 四个参数分别为图像起点坐标和宽高
- // 即: CropImageFilter(int x,int y,int width,int height)
- cropFilter = new CropImageFilter(x, y, destWidth, destHeight);
- img = Toolkit.getDefaultToolkit().createImage(
- new FilteredImageSource(image.getSource(), cropFilter));
- BufferedImage tag = new BufferedImage(destWidth, destHeight,
- BufferedImage.TYPE_INT_RGB);
- Graphics g = tag.getGraphics();
- g.drawImage(img, 0, 0, null); // 绘制缩小后的图
- g.dispose();
- // 输出为文件
- ImageIO.write(tag, "JPEG", new File(dirImageFile));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 缩放图像
- *
- * @param srcImageFile 源图像文件地址
- * @param result 缩放后的图像地址
- * @param scale 缩放比例
- * @param flag 缩放选择:true 放大; false 缩小;
- */
- public static void scale(String srcImageFile, String result, int scale,
- boolean flag) {
- try {
- BufferedImage src = ImageIO.read(new File(srcImageFile)); // 读入文件
- int width = src.getWidth(); // 得到源图宽
- int height = src.getHeight(); // 得到源图长
- if (flag) {
- // 放大
- width = width * scale;
- height = height * scale;
- } else {
- // 缩小
- width = width / scale;
- height = height / scale;
- }
- Image image = src.getScaledInstance(width, height,Image.SCALE_DEFAULT);
- BufferedImage tag = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
- Graphics g = tag.getGraphics();
- g.drawImage(image, 0, 0, null); // 绘制缩小后的图
- g.dispose();
- ImageIO.write(tag, "JPEG", new File(result));// 输出到文件流
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- * 重新生成按指定宽度和高度的图像
- * @param srcImageFile 源图像文件地址
- * @param result 新的图像地址
- * @param _width 设置新的图像宽度
- * @param _height 设置新的图像高度
- */
- public static void scale(String srcImageFile, String result, int _width,int _height) {
- scale(srcImageFile,result,_width,_height,0,0);
- }
- public static void scale(String srcImageFile, String result, int _width,int _height,int x,int y) {
- try {
- BufferedImage src = ImageIO.read(new File(srcImageFile)); // 读入文件
- int width = src.getWidth(); // 得到源图宽
- int height = src.getHeight(); // 得到源图长
- if (width > _width) {
- width = _width;
- }
- if (height > _height) {
- height = _height;
- }
- Image image = src.getScaledInstance(width, height,Image.SCALE_DEFAULT);
- BufferedImage tag = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
- Graphics g = tag.getGraphics();
- g.drawImage(image, x, y, null); // 绘制缩小后的图
- g.dispose();
- ImageIO.write(tag, "JPEG", new File(result));// 输出到文件流
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- * 图像类型转换 GIF->JPG GIF->PNG PNG->JPG PNG->GIF(X)
- */
- public static void convert(String source, String result) {
- try {
- File f = new File(source);
- f.canRead();
- f.canWrite();
- BufferedImage src = ImageIO.read(f);
- ImageIO.write(src, "JPG", new File(result));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 彩色转为黑白
- *
- * @param source
- * @param result
- */
- public static void gray(String source, String result) {
- try {
- BufferedImage src = ImageIO.read(new File(source));
- ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
- ColorConvertOp op = new ColorConvertOp(cs, null);
- src = op.filter(src, null);
- ImageIO.write(src, "JPEG", new File(result));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }