使用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核心代码如下:

	/**
	 *
	 * 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;
	}

返回的参数中带有缩放后的图像长宽信息,在前台js处获取到,对Jcrop进行初始化。

前台核心代码(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进行截取的也想过,考虑到兼容性,还是先这样吧。

相关资源:http://download.csdn.net/detail/lgh06/8343359 免积分

预览效果:

时间: 2024-10-29 19:10:13

使用Jcrop.js和jQuery.form.js,用ImageIO等进行头像上传缩放及裁剪的相关文章

jQuery插件ImgAreaSelect 实例讲解一(头像上传预览和裁剪功能)

上一节随笔中,我们已经知道了关于jQuery插件ImgAreaSelect基本的知识:那么现在看一下实例: 首先,要知道我们应该实现什么功能? (1)图片能够实现上传预览功能 (2)拖拽裁剪图片,使其能够显示裁剪后的区域 (3)显示要裁剪区域的坐标 其次,该如何引用该插件呢? 那就具体看一下吧! 第一步:先将样式和文件包引入(根据你自己的位置引入) <!--引入imgareaselect的css样式--> <link rel="stylesheet" type=&qu

jquery.form.js笔记

由于项目的原因,需要异步上传文件,网上找了找,很多都是用jquery.form插件的,于是乎找资料,调代码,做点小笔记. 官方资料:http://www.malsup.com/jquery/form/ demo: 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>File Upload Demo&l

jquery.form.js实现将form提交转为ajax方式提交的使用方法

本文实例讲述了jquery.form.js实现将form提交转为ajax方式提交的方法.分享给大家供大家参考.具体分析如下: 这个框架集合form提交.验证.上传的功能. 这个框架必须和jquery完整版结合,否则使用min则无效. 原理:利用js进行对form进行组装成ajax的url和data,原理还是用ajax来提交,其实这完全可以自己写,但是有这个框架可能会更简单. 一.最简单例子: 第一步:引用js <!--这里的min是自己用js压缩工具对完整版进行的压缩 并不是真正的min,所以好

jQuery.form.js jQuery ajax异步提交form

jQuery.form.js是一个form插件,支持ajax表单提交和ajax文件上传. 官网下载地址:http://plugins.jquery.com/form/ API ajaxForm 增加所有需要的事件监听器,为ajax提交表单做准备.ajaxForm并不能提交表单.在document的ready函数中,使用ajaxForm来为ajax提交表单进行准备. 接受0个或1个参数.参数可以是一个回调函数,也可以是一个Options对象. $("#formid").ajaxForm(

jQuery表单插件jquery.form.js

概述 jQuery Form Plugin能够让你简洁的将以HTML形式提交的表单升级成采用AJAX技术提交的表单. 插件里面主要的方法, ajaxForm和ajaxSubmit,能够从form组件里采集信息确定如何处理表单的提交过程. 两个方法都支持众多的可选参数,能够让你对表单里数据的提交做到完全的控制. 入门指导 一.在你的页面里写一个表单.一个普通的表单,不需要任何特殊的标记: <form id="myForm" action="login.action&quo

jQuery.form.js使用

jQuery.form.js是一个form插件,支持ajax表单提交和ajax文件上传. 下载地址 百度云:http://pan.baidu.com/s/1eQoYE46 360云:http://yunpan.cn/Qi7B5wdiewUMP  访问密码 06b6 微云:http://url.cn/QMQ79w 1 <!DOCTYPE html> 2 3 <html> 4 <head> 5 <meta name="viewport" conte

jQuery插件 -- Form表单插件jquery.form.js

jquery.form.js官网 jQuery Form插件是一个优秀的Ajax表单插件,可以非常容易地.无侵入地升级HTML表单以支持Ajax.jQuery Form有两个核心方法 -- ajaxForm() 和 ajaxSubmit(), 它们集合了从控制表单元素到决定如何管理提交进程的功能.另外,插件还包括其他的一些方法: formToArray().formSerialize().fieldSerialize().fieldValue().clearForm(). clearFields

jquery.form.js 实现异步上传

前台: <form id="formSeacrh" action="/ResumeInfo/uploadFile" method="post" enctype="multipart/form-data"> <div class="form-horizontal"> <div class="form-group" style="height:100p

jquery.form.js实现异步上传

前台页面 1 @{ 2 Layout = null; 3 } 4 <!DOCTYPE html> 5 <html> 6 <head> 7 <meta name="viewport" content="width=device-width" /> 8 <script src="~/Scripts/jquery-1.7.2.min.js"></script> 9 <scri