首先我们写 图片剪切工具类ImgCutUtil
说白了就是通过这个工具获取一个裁剪图片的编码
(一)获取裁剪图片相关信息
1.裁剪图片获取图片转换流base64
代码前半段是转换流操作,裁剪参数确保随机生成
Map<Object,Object> map = new HashMap<Object,Object>();
Random rand = new Random();
int ImgIndex = rand.nextInt(6); //生成0-6以内的随机数
if(ImgIndex==0){
ImgIndex = 1;
}
//String path = PathUtil.getClassPath()+"baseImg/"+ImgIndex+".jpg";//
String path = "e://aoteman.png";//
System.out.println("图片路径-->"+path);
File picture = new File(path);
BufferedImage sourceImg = ImageIO.read(new FileInputStream(picture));
BASE64Encoder enco = new BASE64Encoder();
//原图
ByteArrayOutputStream YYbao = new ByteArrayOutputStream();//io流
ImageIO.write(sourceImg, "jpg", YYbao);//写入流中
byte[] bytess = YYbao.toByteArray();//转换成字节
String src_base64 = enco.encodeBuffer(bytess).trim();//转换成base64串
src_base64 = src_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
map.put("src_base64",src_base64)
/*************************裁剪图片获得base64*************************/
int CJX = rand.nextInt(200); //生成0-700以内的随机数
// int CJX = rand.nextInt(400); //生成0-700以内的随机数
int CJY = rand.nextInt(100); //生成0-480以内的随机数
// int CJY = rand.nextInt(300); //生成0-480以内的随机数
System.out.println("随机x起点-->"+CJX);
System.out.println("随机y起点-->"+CJY);
if(CJX<10){
System.out.println("太少了");
CJX = CJX + 100;
System.out.println("增加后-->"+CJX);
}
/*if(CJX<50){
System.out.println("太少了");
CJX = CJX + 50;
System.out.println("增加后-->"+CJX);
}*/
int CutX1 = CJX; //裁剪X轴起点
int CutY1 = CJY; //裁剪Y轴起点
int CutW1 = 50; //裁剪宽度
//int CutH1 = 120; //裁剪高度
int CutH1 = 50; //裁剪高度
System.out.println(CutX1+"、"+CutY1+"、"+CutW1+"、"+CutH1);
ImageCut imageCut1 = new ImageCut(CutX1, CutY1, CutW1, CutH1);
String CutPng_base64 = imageCut1.cut(path, null);
/********************************************************/
2.图片裁剪的部分变黑
/************************图片局部变黑************************/
for (int i = 0; i < sourceImg.getWidth(); i++) {
for (int j = 0; j < sourceImg.getHeight(); j++) {
int rgb = data[i][j];
// 原图中对应位置变色处理
int rgb_ori = sourceImg.getRGB(i, j);
if (rgb == 1) {
//颜色处理
int r = (0XFF000000 & rgb_ori);
int g = (0XFF000000 & (rgb_ori >> 8));
int b = (0XFF000000 & (rgb_ori >> 16));
int Gray = (r*2 + g*5 + b*1) >> 3;
//原图对应位置颜色变化
sourceImg.setRGB( i, j, Gray);
}
}
}
/**********************************************************/
3.让裁剪变黑后的图片转成base64
/************************阴影图片转base64************************/
BASE64Encoder encoder = new BASE64Encoder();
ByteArrayOutputStream YYbaos = new ByteArrayOutputStream();//io流
ImageIO.write(sourceImg, "jpg", YYbaos);//写入流中
byte[] bytes = YYbaos.toByteArray();//转换成字节
String YYPng_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串
YYPng_base64 = YYPng_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
/**********************************************************/
map.put("CJX", CJX); //裁剪开始X坐标
map.put("CJY", CJY); //裁剪开始Y坐标
map.put("YYPng_base64", YYPng_base64); //阴影图片base
map.put("CutPng_base64", CutPng_base64);//裁剪图片base
return map;
4.裁剪后的图片进行流转换操作
/**
* 对图片裁剪,并把裁剪完成新图片保存 。
* @param srcpath 源图片路径
* @param subpath 剪切图片存放路径
* @throws IOException
*/
public String cut(String srcpath, String subpath,int cutx,int cuty,int cutw,int cuth) throws IOException {
FileInputStream fis = null;
ImageInputStream iis = null;
try {
// 读取图片文件
fis = new FileInputStream(new File(srcpath));
// 获取文件的后缀名
String postFix = getPostfix(srcpath);
//转为指定的解码格式
Iterator<ImageReader> it = getImageReadersByFormatName(postFix);
ImageReader reader = it.next();
// 获取图片流
iis = ImageIO.createImageInputStream(fis);
//iis:读取源.true:只向前搜索 .将它标记为 ‘只向前搜索’。
//此设置意味着包含在输入源中的图像将只按顺序读取,可能允许 reader 避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
reader.setInput(iis, true);
//描述如何对流进行解码的类.用于指定如何在输入时从 Java Image I/O
//框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件 将从其 ImageReader 实现的
//getDefaultReadParam 方法中返回 ImageReadParam 的实例。
ImageReadParam param = reader.getDefaultReadParam();
//图片裁剪区域。Rectangle 指定了坐标空间中的一个区域,通过 Rectangle 对象的左上顶点的坐标(x,y)、宽度和高度可以定义这个区域。
Rectangle rect = new Rectangle(cutx, cuty, cutw, cuth);
// 提供一个 BufferedImage,将其用作解码像素数据的目标。
param.setSourceRegion(rect);
//使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象,并将 它作为一个完整的BufferedImage 返回。
BufferedImage bi = reader.read(0, param);
//io流
ByteArrayOutputStream catBaos = new ByteArrayOutputStream();
//写入流中
ImageIO.write(bi, "jpg", catBaos);
//转换成字节
byte[] cutBytes = catBaos.toByteArray();
BASE64Encoder encoder = new BASE64Encoder();
//转换成base64串
String cutPngBase64 = encoder.encodeBuffer(cutBytes).trim();
//删除 \r\n
cutPngBase64 = cutPngBase64.replaceAll("\n", "").replaceAll("\r", "");
return cutPngBase64;
} finally {
if (fis != null){
fis.close();
}
if (iis != null){
iis.close();
}
}
}
5.根据后缀名称转为指定的解码格式
代码中只放了jpg,png图片格式的,根据需求自己去放。
/**
* jpg图片格式
*/
private static final String IMAGE_FORM_OF_JPG = "jpg";
/**
* png图片格式
*/
private static final String IMAGE_FORM_OF_PNG = "png";
/**
* 获取后缀名称
* @param inputFilePath 图片地址
* @return
*/
public String getPostfix(String inputFilePath) {
return inputFilePath.substring(inputFilePath.lastIndexOf(".") + 1);
}
/**
* 根据后缀名称转为指定的解码格式
* @param postFix 后缀名称
* @return
*/
public Iterator<ImageReader> getImageReadersByFormatName(String postFix) {
switch (postFix) {
case IMAGE_FORM_OF_JPG:
return ImageIO.getImageReadersByFormatName(IMAGE_FORM_OF_JPG);
case IMAGE_FORM_OF_PNG:
return ImageIO.getImageReadersByFormatName(IMAGE_FORM_OF_PNG);
default:
return ImageIO.getImageReadersByFormatName(IMAGE_FORM_OF_JPG);
}
}
(二)放入项目进行滑块校验
1.获取滑块校验的图片
这里在ImgCutUtil里把图片的路径写成本机固定的图片了,根据需求大家自行可以动态获取。
/**
* 去图片验证页面
* @param session
* @return
* @throws IOException
*/
@RequestMapping(value = "/goUploadImg.do", method = RequestMethod.GET)
@ResponseBody
public Object goUploadImg(HttpSession session) throws IOException {
Map<Object, Object> map = new HashMap<Object, Object>();
//截切图片得到横向截距 纵向截距 和 图片编码 截图编码
map = new ImgCutUtil().getBase();
//生成随机数列
String uuid = uuidUtil.uuidReplace();
//前台图片展示为原图的一半
System.out.println(uuid);
int CJX = (int) map.get("CJX")/2;
System.out.println("hahhhahha" + CJX);
//将生成的随机数列和横向截距存入session中
session.setAttribute(uuid, CJX);
//返回uuid
map.put("uuid", uuid);
return JSONArray.toJSONString(map);
}
控制台输出
2.进行滑块校验
这里说明一下 这里是把UUID和剪切X轴的距离放入Sesion中,便于我们后台随意拿取,校验成功我这里让他发送验证码,失败返回状态
/**
* @return com.deyi.govaffair.pojo.OutputObject
* @Description 发送短信方法
* @Param [noteDTO]
**/
@RequestMapping(value = "send", method = RequestMethod.POST)
public OutputObject messageSend(@RequestBody NoteDTO noteDTO, HttpSession session) {
//查询该账户是否存在
UserInfoPo byUserAccount = userInfoService.findByUserAccount(noteDTO.getUserAccount());
if (byUserAccount != null) {
return new OutputObject(StatusCode.PHONE_NUMBER_RIGISTED.getCode(), StatusCode.PHONE_NUMBER_RIGISTED.getMessage(), new ArrayList());
}
//从Session中获取uuid的值对应的裁剪横向距离
int CJX = (int) session.getAttribute(noteDTO.getUuid());
//用户拉取裁剪图片的横向距离
int moveEnd_X = noteDTO.getMoveEnd_X();
if (moveEnd_X > CJX - 10 && moveEnd_X < CJX + 10) { //偏差在10之内
System.out.println("拼接成功");
//map.put("YZ", "1");
LOGGER.info("发送短信:{}", noteDTO);
if (EmptyUtil.isEmpty(noteDTO.getUserAccount())) {
return new OutputObject(StatusCode.PHONE_NUMBER_IS_NULL.getCode(), StatusCode.PHONE_NUMBER_IS_NULL.getMessage(), new ArrayList());
}
String code = RandomUtil.getRandom(4);
//调用发送短信服务,发送成功之后存储到redis
/*
* phoneNumber 手机号
* verificationCode 验证码
* expire过期时间(分钟)
*/
Map<String, String> map1 = new HashMap<>();
map1.put("phoneNumber", noteDTO.getUserAccount());
map1.put("verificationCode", code);
map1.put("expire", "10");
RongLianSmsSendUtils.sendVerificationCode(map1);
redisManager.set(RedisPrefix.MESSAGE_CODE.getInfo() + noteDTO.getUserAccount(), code, 600);
return new OutputObject(StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMessage(), 1);
}
return new OutputObject(StatusCode.FAIL.getCode(), StatusCode.FAIL.getMessage(), 0);
}
感谢阅读,还望不赐吝教。