Java實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼生成(后端工具類)
一、滑動(dòng)驗(yàn)證碼生成思路
1、隨機(jī)選擇一張圖片
2、生成滑塊起點(diǎn)位置(x, y)
3、生成滑塊輪廓
4、摳出滑塊
5、將滑塊部位去除顏色
二、主要方法
這里使用的方法是:先摳出中間的正方形,再將凹凸槽的RGB渲染上去
1、扣主體
將自定義滑塊大小擴(kuò)大三分之二,用來(lái)做凸槽
2、摳凸槽
因?yàn)橥共凼莻€(gè)圓,所以可通過(guò)圓的標(biāo)準(zhǔn)方程
三、生成代碼
滑塊驗(yàn)證碼實(shí)體類
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author: Yang * @create: 2022-10-25 * @Description: 滑動(dòng)驗(yàn)證碼實(shí)體 */ @Data @AllArgsConstructor @NoArgsConstructor public class ImageSlideVerify { private String bgImg;// 底部圖片 private String blockImg;// 滑塊圖片 private Integer x;// 開(kāi)始x private Integer y;// 開(kāi)始y private Integer bound;// 誤差值 }
生成滑塊驗(yàn)證碼
import com.yang.domain.vo.ImageSlideVerify; import org.apache.tomcat.util.codec.binary.Base64; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Transparency; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Random; import java.util.UUID; import javax.imageio.ImageIO; /** * 滑動(dòng)驗(yàn)證碼 * @author Yang * */ public class ImageSlideVerifyUtil { private static Integer x, y;// x , y軸起點(diǎn)位置 private static Integer blockSize; // 塊大小 public static void main(String[] args) throws IOException { File file = new File("4.jpeg"); cutting(file, 80); cutting(file); } // 切割 public static ImageSlideVerify cutting(File file, int size) { FileInputStream fis; blockSize = size; try { fis = new FileInputStream(file); BufferedImage image = ImageIO.read(fis);// 將文件流轉(zhuǎn)圖像流 // 生成圓位置 Integer cp[] = circle();// 下標(biāo)對(duì)應(yīng):上右下左 // 生成滑塊 BufferedImage img = generateMin(image, image.getWidth(), image.getHeight(), size, cp); // 圖片轉(zhuǎn)base64 String bgImg = imageToBase64(image); String blockImg = imageToBase64(img); // TODO 保存圖片:用于測(cè)試,測(cè)試完畢刪除 // ImageIO.write(img, "png", new File("4-1.png")); // ImageIO.write(image, "png", new File("4-2.png")); ImageSlideVerify imageSlideVerify = new ImageSlideVerify(bgImg, blockImg, x, y, 3); return imageSlideVerify; } catch (IOException e) { e.printStackTrace(); } return null; } // 切割 public static ImageSlideVerify cutting(File file) { return cutting(file, 60); } // 圓的位置 private static Integer[] circle() { Integer c[] = new Integer[4];// 四個(gè)位置有圓,0代表無(wú),1代表有,下標(biāo)對(duì)應(yīng)上、右、下、左 boolean flag = false;// 記錄是否有圓 while(!flag) {// 如果沒(méi)有圓,則繼續(xù)循環(huán),至少要有一個(gè)圓(凸槽) for(int i = 0; i < 4; i++) { c[i] = new Random().nextInt(2); if(c[i] == 1) { flag = true; } } } return c; } /** * 生成小滑塊位置 * @param img * @param width 圖片寬度 * @param height 圖片高度 * @param size 滑塊大小, 正方形,寬高相等 * @return * @throws IOException */ private static BufferedImage generateMin(BufferedImage img, int width, int height, int size, Integer[] cp) throws IOException { /** * 滑塊大?。憾x大小 + 三分之一 */ int size1 = size + (size / 3 * 2); /** * 最大起點(diǎn)位置 * x:寬度 - 滑塊大小 * y:高度 - 滑塊大小 */ int maxX = width - ( size1 ); int maxY = height - ( size1 ); // 生成滑塊開(kāi)始位置 x = new Random().nextInt(maxX); y = new Random().nextInt(maxY); // 創(chuàng)建滑塊圖像 BufferedImage img1 = new BufferedImage(size1, size1, BufferedImage.TYPE_INT_RGB); Graphics2D gr = img1.createGraphics(); // 圖像背景透明 img1 = gr.getDeviceConfiguration().createCompatibleImage(size1, size1, Transparency.TRANSLUCENT); // 拷貝rgb for(int i = 0; i < size1; i++) { for(int j = 0; j < size1; j++) { if(i < size / 3 || i > size + size / 3 || j < size / 3 || j > size + size / 3) { continue; } // 渲染RGB img1.setRGB(i, j, img.getRGB(i + x, j + y)); // 將原圖像素點(diǎn)覆蓋白色 Color color = new Color(255,255,255); img.setRGB(i + x, j + y, color.getRGB()); } } // 設(shè)置圓(凸槽) setCircle(img, img1, x, y, cp); return img1; } /** * 設(shè)置圓 * @param oldImg * @param img * @param x * @param y * @param cp * @throws IOException */ private static void setCircle(BufferedImage oldImg, BufferedImage img, int x, int y, Integer[] cp) throws IOException { // 以白色覆蓋原圖像素點(diǎn) Color color = new Color(255,255,255); int d = blockSize / 3 + 2; // 直徑 int r = d / 2;// 半徑 /** * TODO 以下待改進(jìn) */ if(cp[0] == 1) {// 上 // 中心位置 int w = img.getWidth() / 2; for(int i = w - r, r1 = 0; i < w + r; i++, r1++) { for(int j = 0, r2 = 0; j < d; j++, r2++) { /** * 判斷點(diǎn)是否在圓內(nèi):點(diǎn)p(x, y), 圓心r(x, y) * 有:(px - rx)^2 + (py - ry)^2 <= rx*ry */ if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - 11) <= r * r) { if(oldImg.getRGB(x + i, y + j) == color.getRGB()) { continue; } img.setRGB(i, j, oldImg.getRGB(x + i, y + j)); // 對(duì)應(yīng)位置透明 oldImg.setRGB(x + i, y + j, color.getRGB()); } } } } if(cp[1] == 1) {// 右 // 中心位置 int h = img.getHeight() / 2; for(int i = img.getWidth() - d, r1 = 0; i < img.getWidth(); i++, r1++) { for(int j = h - r, r2 = 0; j < h + r; j++, r2++) { if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - r) <= r * r) { if(oldImg.getRGB(x + i, y + j) == color.getRGB()) continue; img.setRGB(i, j, oldImg.getRGB(x + i, y + j)); // 對(duì)應(yīng)位置透明 oldImg.setRGB(x + i, y + j, color.getRGB()); } } } } if(cp[2] == 1) {// 下 // 中心位置 int w = img.getWidth() / 2; for(int i = w - r, r1 = 0; i < w + r; i++, r1++) { for(int j = img.getHeight() - d, r2 = 0; j < img.getHeight(); j++, r2++) { if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - r) <= r * r) { if(oldImg.getRGB(x + i, y + j) == color.getRGB()) continue; img.setRGB(i, j, oldImg.getRGB(x + i, y + j)); // 對(duì)應(yīng)位置透明 oldImg.setRGB(x + i, y + j, color.getRGB()); } } } } if(cp[3] == 1) {// 左 // 中心位置 int h = img.getHeight() / 2; for(int i = 0, r1 = 0; i < d; i++, r1++) { for(int j = h - r, r2 = 0; j < h + r; j++, r2++) { if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - r) <= r * r) { if(oldImg.getRGB(x + i, y + j) == color.getRGB()) continue; img.setRGB(i, j, oldImg.getRGB(x + i, y + j)); // 對(duì)應(yīng)位置透明 oldImg.setRGB(x + i, y + j, color.getRGB()); } } } } } /** * 圖像轉(zhuǎn)base64 * @param img * @return */ private static String imageToBase64(BufferedImage img){ ByteArrayOutputStream stream = new ByteArrayOutputStream(); try { // 設(shè)置圖片的格式 ImageIO.write(img, "png", stream); byte[] bytes = Base64.encodeBase64(stream.toByteArray()); String base64 = new String(bytes); return "data:image/jpeg;base64,"+base64; } catch (IOException e) { e.printStackTrace(); } return null; } }
四、測(cè)試結(jié)果
這里看滑塊是白色背景,實(shí)際上是透明的
生成完成
到此這篇關(guān)于Java實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼生成(后端工具類)的文章就介紹到這了,更多相關(guān)Java滑動(dòng)驗(yàn)證碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實(shí)現(xiàn)圖片寫(xiě)入高清字體及帶邊框的方法
這篇文章主要介紹了java實(shí)現(xiàn)圖片寫(xiě)入高清字體及帶邊框的方法,涉及java針對(duì)圖片及文字的相關(guān)操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07Spring Boot整合Mybatis Plus和Swagger2的教程詳解
這篇文章主要介紹了Spring Boot整合Mybatis Plus和Swagger2的教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02MyBatisPlus中@TableField注解的基本使用
這篇文章主要介紹了MyBatisPlus中@TableField注解的基本使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07springboot使用Logback把日志輸出到控制臺(tái)或輸出到文件
這篇文章給大家介紹springboot項(xiàng)目使用日志工具Logback把日志不僅輸出到控制臺(tái),也可以輸出到文件的操作方法,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-10-10java實(shí)現(xiàn)騰訊ocr圖片識(shí)別接口調(diào)用
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)騰訊ocr圖片識(shí)別接口調(diào)用,拍車牌識(shí)別車牌號(hào)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11解決 IDEA 創(chuàng)建 Gradle 項(xiàng)目沒(méi)有src目錄問(wèn)題
這篇文章主要介紹了解決 IDEA 創(chuàng)建 Gradle 項(xiàng)目沒(méi)有src目錄問(wèn)題,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-06-06Spring MVC如何使用@RequestParam注解獲取參數(shù)
這篇文章主要介紹了Spring MVC實(shí)現(xiàn)使用@RequestParam注解獲取參數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10Java使用poi導(dǎo)出ppt文件的實(shí)現(xiàn)代碼
Apache POI 是用Java編寫(xiě)的免費(fèi)開(kāi)源的跨平臺(tái)的 Java API,Apache POI提供API給Java對(duì)Microsoft Office格式檔案讀和寫(xiě)的功能。本文給大家介紹Java使用poi導(dǎo)出ppt文件的實(shí)現(xiàn)代碼,需要的朋友參考下吧2021-06-06詳解如何在SpringBoot中優(yōu)雅地重試調(diào)用第三方API
在實(shí)際的應(yīng)用中,我們經(jīng)常需要調(diào)用第三方API來(lái)獲取數(shù)據(jù)或執(zhí)行某些操作,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12