图片滑块校验JAVA后端实现方式

首先我们写 图片剪切工具类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);
    }

控制台输出
当然这是图片校验认证的信息,我们存了一个uuid,用来给获取图片的用户唯一标识

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);
    }

感谢阅读,还望不赐吝教。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值