Since I want to do a new project, I plan to do a simple picture verification code.
Let’s talk about the idea first: On the server side, find 8 pictures from a folder, then merge the 8 pictures into a large picture, and randomly generate a picture classification for users to verify in the 8 small pictures, such as puppies, beer, etc. On the front end, when accessing this page, load the picture, and the user selects the picture required on the picture. When the user logs in, determine whether the selected picture is actually a verification picture based on all coordinates selected by the user.
Let's put two renderings first:
In order to make the file search easier, the image file structure can be as follows:
This facilitates the generation of the Key Pictures that the user wants to choose, and combine them into a large picture with 8 small pictures.
Code above: This is to select 8 pictures, and recursively ensure that the selected pictures will not be repeated when selecting each picture.
//Select 8 images public static List<Object> getEightImages() { //Save the path of each image you get to ensure that the image will not be repeated List<String> paths = new ArrayList<String>(); File[] finalImages = new File[8]; List<Object> object = new ArrayList<Object>(); //Save tips String[] tips = new String[8]; for (int i = 0; i < 8; i++) { //Get random secondary directory int dirIndex = getRandom(secondaryDirNumbers); File secondaryDir = getFiles()[dirIndex]; //Save the random folder name in tips to tips[i] = secondaryDir.getName(); //Get the file in the secondary image directory File[] images = secondaryDir.listFiles(); int imageIndex = getRandom(imageRandomIndex); File image = images[imageIndex]; //Picture deduplication image = dropSameImage(image, paths, tips, i); paths.add(image.getPath()); finalImages[i] = image; } object.add(finalImages); object.add(tips); return object;}In generating these 8 images, save all file categories in an array. In this category, you can use random numbers to select a category as a key category, which is all the pictures that the user wants to select. Since the array is ordered, you can traverse the elements in the array to get the location of each key classification image, which is convenient for matching during user verification.
//Get the location, which image is returned, not the subscript. Starting from 1, the first element of the collection is tip public static List<Object> getLocation(String[] tips) { List<Object> locations = new ArrayList<Object>(); //Get Key Classification String tip = getTip(tips); locations.add(tip); int length = tips.length; for (int i = 0; i < length; i++) { if (tip.equals(tips[i])) { locations.add(i+1); } } return locations; }After selecting 8 pictures, the next step is to merge the pictures. To merge images, you can use the BufferedImage method: setRGB() method. If you don't understand it, you can read the API documentation, which has detailed instructions.
public static void mergeImage(File[] finalImages, HttpServletResponse response) throws IOException { //Read the image BufferedImage mergeImage = new BufferedImage(800, 400, BufferedImage.TYPE_INT_BGR); for (int i = 0; i < 8; i++) { File image = finalImages[i]; BufferedImage bufferedImage = ImageIO.read(image); int width = bufferedImage.getWidth(); int height = bufferedImage.getHeight(); //Read RGB from the image int[] imageBytes = new int[width*height]; imageBytes = bufferedImage.getRGB(0, 0, width, height, imageBytes, 0, width); if ( i < 4) { mergeImage.setRGB(i*200, 0, width, height, imageBytes, 0, width); } else { mergeImage.setRGB((i -4 )*200, 200, width, height, imageBytes, 0, width); } } ImageIO.write(mergeImage, "jpg", response.getOutputStream()); //ImageIO.write(mergeImage, "jpg", destImage); }In the controller layer, first save the key classification into the session, and make prompts and image verification for users to choose image classification. Then output the image stream to the response to generate the verification image.
response.setContentType("image/jpeg"); response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); List<Object> object = ImageSelectedHelper.getEightImages(); File[] finalImages = (File[]) object.get(0); String[] tips = (String[]) object.get(1); //The image locations of all keys, that is, the image that the user must select List<Object> locations = ImageSelectedHelper.getLocation(tips); String tip = locations.get(0).toString(); System.out.println(tip); session.setAttribute("tip", tip); locations.remove(0); int length = locations.size(); for (int i = 0; i < length; i++) { System.out.println("Actual Key image location:" + locations.get(i)); } session.setAttribute("locations", locations); ImageMerge.mergeImage(finalImages, response);In jsp, generate small image tags for user clicks. When the user clicks the image, add a child div tag to the parent div, position it as relative, and set zIndex, and then add an img tag to the div, position it as absolute. When the user clicks, you can get the click event, get the click coordinates based on the click event, and then subtract the coordinates of the parent div to get the relative coordinates. You can determine the coordinate origin according to your preferences. The coordinate origin here is the lower right corner of the 8th picture.
<div><br> <div id="base"><br> <img src="<%=request.getContextPath()%>/identify" onclick="clickImg(event)" id="bigPicture"><br> </div><br> <br> </div><br><br> function clickImg(e) { var baseDiv = document.getElementById("base"); var topValue = 0; var leftValue = 0; var obj = baseDiv; while (obj) { leftValue += obj.offsetLeft; topValue +=obj.offsetTop; obj = obj.offsetParent; } //Solve the problem that firefox cannot get click events var clickEvent = e ? e : (window.event ? window.event : null); var clickLeft = clickEvent.clientX + document.body.scrollLeft - document.body.clientLeft - 10; var clickTop = clickEvent.clientY + document.body.scrollTop - document.body.clientTop - 10; var divId = "img_" + index++; var divEle = document.createElement("div"); divEle.setAttribute("id", divId); divEle.style.position = "relative"; divEle.style.zIndex = index; divEle.style.width = "20px"; divEle.style.height = "20px"; divEle.style.display = "inline"; divEle.style.top = clickTop - topValue - 150 + 10 + "px"; divEle.style.left = clickLeft - leftValue - 300 + "px"; divEle.setAttribute("onclick", "remove('" + divId + "')"); baseDiv.appendChild(divEle); var imgEle = document.createElement("img"); imgEle.src = "<%=request.getContextPath()%>/resources/timo.png"; imgEle.style.width = "20px"; imgEle.style.height = "20px"; imgEle.style.top = "0px"; imgEle.style.left = "0px"; imgEle.style.position = "absolute"; imgEle.style.zIndex = index; divEle.appendChild(imgEle); }After the user selects login, the server side makes judgment based on the user's coordinates selected.
public List<Integer> isPass(String result) { String[] xyLocations = result.split(","); //Save on which images the coordinates selected by the user falls List<Integer> list = new ArrayList<Integer>(); //Each set of coordinates System.out.println("Number of user selected pictures:"+xyLocations.length); for (String xyLocation: xyLocations) { String[] xy = xyLocation.split("//|//|"); int x = Integer.parseInt(xy[0]); int y = Integer.parseInt(xy[1]); //8,4 picture interval if ( x > -75 && x <= 0) { if ( y > -75 && y <= 0) { //No. 8 list.add(8); } else if ( y >= -150 && y <= -75 ) { //No. 4 list.add(4); } } else if ( x > -150 && x <= -75) { //7,3 picture interval if ( y > -75 && y <= 0) { //No. 7 list.add(7); } else if ( y >= -150 && y <= -75 ) { //No. 3 list.add(3); } } else if ( x > -225 && x <= -150) { //6,2 picture interval if ( y > -75 && y <= 0) { //No. 6 list.add(6); } else if ( y >= -150 && y <= -75 ) { //No. 2 list.add(2); } } else if ( x >= -300 && x <= -225) { //5,1 picture interval if ( y > -75 && y <= 0) { //No. 5 list.add(5); } else if ( y >= -150 && y <= -75 ) { //No. 1 list.add(1); } } else { return null; } } return list; }Refresh to generate a new picture. Since ajax does not support binary streams, you can use the native xmlHttpRequest object to add html5 blob to complete it.
function refresh() { var url = "<%=request.getContextPath()%>/identify"; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = "blob"; xhr.onload = function() { if (this.status == 200) { var blob = this.response; //Release blob after loading successfully bigPicture.onload = function(e) { window.URL.revokeObjectURL(bigPicture.src); }; bigPicture.src = window.URL.createObjectURL(blob); } } xhr.send();The overall code of the verification code has been completed, and there are still some details to be processed.
The above is all about this article, I hope it will be helpful to everyone's learning.