首先,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