前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于jquery的imgAreaSelect.js插件+JAVA后台实现图片裁剪保存功能

基于jquery的imgAreaSelect.js插件+JAVA后台实现图片裁剪保存功能

作者头像
哎_小羊
发布2018-01-02 15:08:18
6.1K1
发布2018-01-02 15:08:18
举报
文章被收录于专栏:哎_小羊

前段时间,项目在做个人信息设置,其中有一项是设置用户头像信息,需要将用户选择的头像按照用户需要进行剪切,同时保存为大(120*120)、中(75*75)、小(35*35)三种格式的图像,分别显示到不同的位置。

需求很简单,就是这么easy,这个其中重点就是用户可以自己对选择的头像进行截取,最终选择了基于jquery的imgareaselect.js。既然插件都有了,那就开工吧!

第一步: 前端下载必须的js插件,后台使用java自带imageio包处理,不需要其他jar包。 jquery.imgareaselect-0.9.10.zip jquery.js

第二步: 新建静态页面index.html (页面有点丑哈。。。)

代码语言:javascript
复制
<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" >确&nbsp;定</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

代码语言:javascript
复制
$(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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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
 *
 */
@Service
public 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

代码语言:javascript
复制
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哦!

截取图
截取图
效果图
效果图
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015-10-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图片处理
图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档