Java implementation of Slider Puzzle verification code

Time:2022-5-10

This example shares the specific code of Java implementation of Slider Puzzle verification code for your reference. The specific contents are as follows

1. The back end randomly generates matting and background pictures with matting shadows, and the background saves the coordinates of random matting positions
2. The front end realizes sliding interaction, collages the matting on the matting shadow, and obtains the user’s sliding distance value, such as the following example

3. The front end transmits the user sliding distance value to the back end, and the back end checks whether the error is within the allowable range.

Here, the simple verification of the user’s sliding distance is the most basic verification. For higher security considerations, the whole track of the user’s sliding and the user’s access behavior on the current page may also be considered. These can be very complex, and even with the help of user behavior data analysis model, the ultimate goal is to increase the difficulty of illegal simulation and bypass. This paper focuses on how to realize the generation of sliding verification code step by step based on Java.

It can be seen that the sliding graphic verification code is mainly composed of two pictures, the cutout and the original image with the cutout shadow. There are two important features to ensure the difficulty of being brutally cracked: the shape of the cutout is random and the position of the original image where the cutout is located is random. In this way, we can create random, irregular and searchable matting and matching of the original graph in a limited graph set.

How to use code to extract a small picture with a specific random shape from a large picture?

First step, first determine an outline of the cutout image to facilitate the subsequent real start of image processing operation

The picture is composed of pixels, and each pixel corresponds to a color. The color can be expressed in RGB, plus a transparency. Understand a picture as a plane graph, with the upper left corner as the origin, the right X axis and the down Y axis. A coordinate value corresponds to the color of the pixel at the position, so that a picture can be converted into a two-dimensional array. Based on this consideration, the contour is also represented by a two-dimensional array. The element value inside the contour is 1 and the element value outside the contour corresponds to 0.

At this time, we have to think about how to generate this contour shape. There are coordinate systems, rectangles and circles. Yes, mathematical graphic functions are used. Typically, the function equation of a circle and the function of the edge of a rectangle are used, similar to:

(x-a) ²+ (y-b) ²= r ² In, there are three parameters a, B and R, that is, the coordinates of the center of the circle are (a, b) and the radius is r. These matting are placed on the coordinate system described above, and it is easy to calculate the specific value of the matting.

The example code is as follows:

static int targetWidth = 55;// Small picture length
static int targetHeight = 45;// Small graph width
static int circleR = 8;// radius
static int r1 = 4;// Distance point
 
    /**
     *@ createDate: January 24, 2019 10:52:42 am
     * @Title: getBlockData
     *@ Description: generate small outline
     * @author zhoujin
     * @return int[][]
     * @throws
     */
    private static int[][] getBlockData() {
        int[][] data = new int[targetWidth][targetHeight];
        double x2 = targetWidth -circleR; //47
 
        //Position of randomly generated circle
        double h1 = circleR + Math.random() * (targetWidth-3*circleR-r1);
        double po = Math.pow(circleR,2); //64
 
        double xbegin = targetWidth - circleR - r1;
        double ybegin = targetHeight- circleR - r1;
 
        //Standard equation of circle (x-a) ²+ (y-b) ²= r ², Identify the circle with center (a, b) and radius R
        //Calculate the outline of the required small figure, which is represented by a two-dimensional array. The two-dimensional array has two values, 0 and 1, where 0 means no color and 1 has color
        for (int i = 0; i < targetWidth; i++) {
            for (int j = 0; j < targetHeight; j++) {
                double d2 = Math.pow(j - 2,2) + Math.pow(i - h1,2);
                double d3 = Math.pow(i - x2,2) + Math.pow(j - h1,2);
                if ((j <= ybegin && d2 < po)||(i >= xbegin && d3 > po)) {
                        data[i][j] = 0;
                }  else {
                        data[i][j] = 1;
                }
            }
        }
        return data;
    }

Step two, after having this contour, you can determine the matting according to the value of the two-dimensional array, and shadow the matting position on the original image.

The operation is as follows:

/**
     *
     *@ createDate: January 24, 2019 10:51:30 am
     * @Title: cutByTemplate
     *@ Description: with this contour, you can determine the matting according to the value of this two-dimensional array and add a shadow at the matting position on the original image,
     * @author zhoujin
     *@ param oriimage original
     *@ param targetimage jigsaw puzzle
     *@ param templateimage color
     * @param x
     * @param y void
     * @throws
     */
    private static void cutByTemplate(BufferedImage oriImage, BufferedImage targetImage, int[][] templateImage, int x, int y){
        int[][] martrix = new int[3][3];
        int[] values = new int[9];
        //Create shape area
        for (int i = 0; i < targetWidth; i++) {
            for (int j = 0; j < targetHeight; j++) {
                int rgb = templateImage[i][j];
                //Discoloration treatment of corresponding position in the original drawing
                int rgb_ori = oriImage.getRGB(x + i, y + j);
 
                if (rgb == 1) {
                    targetImage.setRGB(i, j, rgb_ori);
 
                    //Matting region Gaussian blur
                    readPixel(oriImage, x + i, y + j, values);
                    fillMatrix(martrix, values);
                    oriImage.setRGB(x + i, y + j, avgMatrix(martrix));
                }else{
                    //Set the background to transparent here
                    targetImage.setRGB(i, j, rgb_ori & 0x00ffffff);
                }
            }
        }
    }
 
 
   private static void readPixel(BufferedImage img, int x, int y, int[] pixels) {
        int xStart = x - 1;
        int yStart = y - 1;
        int current = 0;
        for (int i = xStart; i < 3 + xStart; i++)
            for (int j = yStart; j < 3 + yStart; j++) {
                int tx = i;
                if (tx < 0) {
                    tx = -tx;
 
                } else if (tx >= img.getWidth()) {
                    tx = x;
                }
                int ty = j;
                if (ty < 0) {
                    ty = -ty;
                } else if (ty >= img.getHeight()) {
                    ty = y;
                }
                pixels[current++] = img.getRGB(tx, ty);
 
            }
    }
 
    private static void fillMatrix(int[][] matrix, int[] values) {
        int filled = 0;
        for (int i = 0; i < matrix.length; i++) {
            int[] x = matrix[i];
            for (int j = 0; j < x.length; j++) {
                x[j] = values[filled++];
            }
        }
    }
 
    private static int avgMatrix(int[][] matrix) {
        int r = 0;
        int g = 0;
        int b = 0;
        for (int i = 0; i < matrix.length; i++) {
            int[] x = matrix[i];
            for (int j = 0; j < x.length; j++) {
                if (j == 1) {
                    continue;
                }
                Color c = new Color(x[j]);
                r += c.getRed();
                g += c.getGreen();
                b += c.getBlue();
            }
        }
        return new Color(r / 8, g / 8, b / 8).getRGB();
    }

After the first two steps, the matting and the original image with Gaussian fuzzy matting shadow are obtained. Returns the base64 code and matting coordinates of the generated matting and large shaded image.

/**
     *@ Description: read local pictures and generate puzzle verification code
     * @author zhoujin
     *@ return map < string, Object > returns the base64 code and matting coordinates of the generated matting and large image with matting shadow
     */
    public static Map<String,Object> createImage(File file, Map<String,Object> resultMap){
        try {
            BufferedImage oriImage = ImageIO.read(file);
            Random random = new Random();
            //The distance between X axis and targetwidth at the right end and the distance between Y axis and targetheight at the bottom is more than
            int widthRandom = random.nextInt(oriImage.getWidth()-  2*targetWidth) + targetWidth;
            int heightRandom = random.nextInt(oriImage.getHeight()- targetHeight);
            logger. Info ("original size {} x {}, randomly generated coordinates x and y are ({}, {})", oriimage getWidth(),oriImage. getHeight(),widthRandom,heightRandom);
 
            BufferedImage targetImage= new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_4BYTE_ABGR);
            cutByTemplate(oriImage,targetImage,getBlockData(),widthRandom,heightRandom);
 
            resultMap. put("bigImage", getImageBASE64(oriImage));// Big picture
            resultMap. put("smallImage", getImageBASE64(targetImage));// Small picture
            resultMap.put("xWidth",widthRandom);
            resultMap.put("yHeight",heightRandom);
        } catch (Exception e) {
            logger. Info ("abnormal creation of graphic verification code", e);
        } finally{
            return resultMap;
        }
    }
 
 
    /**
     *@ Description: read network pictures and generate puzzle verification code
     * @author zhoujin
     *@ return map < string, Object > returns the base64 code and matting coordinates of the generated matting and large image with matting shadow
     */
    public static Map<String,Object> createImage(String imgUrl, Map<String,Object> resultMap){
        try {
            //Read pictures through URL
            URL url = new URL(imgUrl);
            BufferedImage bufferedImage = ImageIO.read(url.openStream());
            Random rand = new Random();
            int widthRandom = rand.nextInt(bufferedImage.getWidth()-  targetWidth - 100 + 1 ) + 100;
            int heightRandom = rand.nextInt(bufferedImage.getHeight()- targetHeight + 1 );
            logger. Info ("original image size {} x {}, randomly generated coordinates x and y are ({}, {})", bufferedimage getWidth(),bufferedImage. getHeight(),widthRandom,heightRandom);
 
            BufferedImage target= new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_4BYTE_ABGR);
            cutByTemplate(bufferedImage,target,getBlockData(),widthRandom,heightRandom);
            resultMap. put("bigImage", getImageBASE64(bufferedImage));// Big picture
            resultMap. put("smallImage", getImageBASE64(target));// Small picture
            resultMap.put("xWidth",widthRandom);
            resultMap.put("yHeight",heightRandom);
        } catch (Exception e) {
            logger. Info ("abnormal creation of graphic verification code", e);
        } finally{
            return resultMap;
        }
    }
 
 
    /**
     * @Title: getImageBASE64
     *@ Description: picture to Base64
     * @author zhoujin
     * @param image
     * @return
     * @throws IOException String
     */
    public static String getImageBASE64(BufferedImage image) throws IOException {
        byte[] imagedata = null;
        ByteArrayOutputStream bao=new ByteArrayOutputStream();
        ImageIO.write(image,"png",bao);
        imagedata=bao.toByteArray();
        BASE64Encoder encoder = new BASE64Encoder();
        String BASE64IMAGE=encoder.encodeBuffer(imagedata).trim();
        BASE64IMAGE = BASE64IMAGE. replaceAll("\r|\n", "");  // Delete \ R \ n
        return BASE64IMAGE;
    }

Control layer code implementation and verification code:

/**
     *@ param @ return parameter description
     *@ return baserestresult return type
     *@ Description: generate Slider Puzzle verification code
     */
    @RequestMapping(value = "/getImageVerifyCode.do", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})
    public BaseRestResult getImageVerifyCode() {
        Map<String, Object> resultMap = new HashMap<>();
        //Read the pictures in the local path and select one at random
        File file = new File(this.getClass().getResource("/image").getPath());
        File[] files = file.listFiles();
        int n = new Random().nextInt(files.length);
        File imageUrl = files[n];
        ImageUtil.createImage(imageUrl, resultMap);
 
        //Read network pictures
        //ImageUtil.createImage("/7986d66f29bfeb6015aaaec33d33fcd1d875ca16316f-2bMHNG_fw658",resultMap);
        session.setAttribute("xWidth", resultMap.get("xWidth"));
        resultMap.remove("xWidth");
        resultMap.put("errcode", 0);
        resultMap.put("errmsg", "success");
        return new BaseRestResult(resultMap);
    }
 
 
    /**
     *Check Slider Puzzle verification code
     *
     *@ param movelength move distance
     *@ return baserestresult return type
     *@ Description: generate graphic verification code
     */
    @RequestMapping(value = "/verifyImageCode.do", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})
    public BaseRestResult verifyImageCode(@RequestParam(value = "moveLength") String moveLength) {
        Double dMoveLength = Double.valueOf(moveLength);
        Map<String, Object> resultMap = new HashMap<>();
        try {
            Integer xWidth = (Integer) session.getAttribute("xWidth");
            if (xWidth == null) {
                resultMap.put("errcode", 1);
                resultMap. Put ("errmsg", "verification expired, please try again");
                return new BaseRestResult(resultMap);
            }
            if (Math.abs(xWidth - dMoveLength) > 10) {
                resultMap.put("errcode", 1);
                resultMap. Put ("errmsg", "verification failed");
            } else {
                resultMap.put("errcode", 0);
                resultMap. Put ("errmsg", "verification passed");
            }
        } catch (Exception e) {
            throw new EsServiceException(e.getMessage());
        } finally {
            session.removeAttribute("xWidth");
        }
        return new BaseRestResult(resultMap);
}

Front end display picture code:

< img SRC = "data: image / PNG; Base64, + returned Base64 picture code" ALT = "matting" >
< img SRC = "data: image / PNG; Base64, + Base64 picture code returned" ALT = "original image with matting shadow" >

So far, the key code of the slider verification code implemented by Java in the background is completed!

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support developpaer.