Java實現(xiàn)滑動驗證碼生成(后端工具類)
一、滑動驗證碼生成思路
1、隨機(jī)選擇一張圖片
2、生成滑塊起點位置(x, y)
3、生成滑塊輪廓
4、摳出滑塊
5、將滑塊部位去除顏色
二、主要方法
這里使用的方法是:先摳出中間的正方形,再將凹凸槽的RGB渲染上去
1、扣主體
將自定義滑塊大小擴(kuò)大三分之二,用來做凸槽
2、摳凸槽
因為凸槽是個圓,所以可通過圓的標(biāo)準(zhǔn)方程
三、生成代碼
滑塊驗證碼實體類
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author: Yang * @create: 2022-10-25 * @Description: 滑動驗證碼實體 */ @Data @AllArgsConstructor @NoArgsConstructor public class ImageSlideVerify { private String bgImg;// 底部圖片 private String blockImg;// 滑塊圖片 private Integer x;// 開始x private Integer y;// 開始y private Integer bound;// 誤差值 }
生成滑塊驗證碼
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; /** * 滑動驗證碼 * @author Yang * */ public class ImageSlideVerifyUtil { private static Integer x, y;// x , y軸起點位置 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)對應(yīng):上右下左 // 生成滑塊 BufferedImage img = generateMin(image, image.getWidth(), image.getHeight(), size, cp); // 圖片轉(zhuǎn)base64 String bgImg = imageToBase64(image); String blockImg = imageToBase64(img); // TODO 保存圖片:用于測試,測試完畢刪除 // 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];// 四個位置有圓,0代表無,1代表有,下標(biāo)對應(yīng)上、右、下、左 boolean flag = false;// 記錄是否有圓 while(!flag) {// 如果沒有圓,則繼續(xù)循環(huán),至少要有一個圓(凸槽) 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); /** * 最大起點位置 * x:寬度 - 滑塊大小 * y:高度 - 滑塊大小 */ int maxX = width - ( size1 ); int maxY = height - ( size1 ); // 生成滑塊開始位置 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)); // 將原圖像素點覆蓋白色 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 { // 以白色覆蓋原圖像素點 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++) { /** * 判斷點是否在圓內(nèi):點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)); // 對應(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)); // 對應(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)); // 對應(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)); // 對應(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; } }
四、測試結(jié)果
這里看滑塊是白色背景,實際上是透明的
生成完成
到此這篇關(guān)于Java實現(xiàn)滑動驗證碼生成(后端工具類)的文章就介紹到這了,更多相關(guān)Java滑動驗證碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot整合Mybatis Plus和Swagger2的教程詳解
這篇文章主要介紹了Spring Boot整合Mybatis Plus和Swagger2的教程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02MyBatisPlus中@TableField注解的基本使用
這篇文章主要介紹了MyBatisPlus中@TableField注解的基本使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07springboot使用Logback把日志輸出到控制臺或輸出到文件
這篇文章給大家介紹springboot項目使用日志工具Logback把日志不僅輸出到控制臺,也可以輸出到文件的操作方法,本文通過實例圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2020-10-10java實現(xiàn)騰訊ocr圖片識別接口調(diào)用
這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)騰訊ocr圖片識別接口調(diào)用,拍車牌識別車牌號功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-11-11解決 IDEA 創(chuàng)建 Gradle 項目沒有src目錄問題
這篇文章主要介紹了解決 IDEA 創(chuàng)建 Gradle 項目沒有src目錄問題,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2018-06-06Spring MVC如何使用@RequestParam注解獲取參數(shù)
這篇文章主要介紹了Spring MVC實現(xiàn)使用@RequestParam注解獲取參數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10Java使用poi導(dǎo)出ppt文件的實現(xiàn)代碼
Apache POI 是用Java編寫的免費開源的跨平臺的 Java API,Apache POI提供API給Java對Microsoft Office格式檔案讀和寫的功能。本文給大家介紹Java使用poi導(dǎo)出ppt文件的實現(xiàn)代碼,需要的朋友參考下吧2021-06-06詳解如何在SpringBoot中優(yōu)雅地重試調(diào)用第三方API
在實際的應(yīng)用中,我們經(jīng)常需要調(diào)用第三方API來獲取數(shù)據(jù)或執(zhí)行某些操作,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12