分享:Java 開發精美藝術二維碼
阿新 • • 發佈:2018-12-17
Java 開發精美藝術二維碼
看到網路上各種各樣的二維碼層出不窮,好像很炫酷的樣子,一時興起,我也要製作這種炫酷二維碼效果
例如:
根據以往例子
根據之前所做的小專案 java 開發二維碼系統
以這個為基礎,將實現精美藝術二維碼
基本程式碼:
// 建立二維碼物件 Qrcode qrcode = new Qrcode(); // 設定二維碼的糾錯級別 // L(7%) M(15%) Q(25%) H(30%) qrcode.setQrcodeErrorCorrect('L'); // 一般糾錯級別小一點 // 設定二維碼的編碼模式 Binary(按照位元組編碼模式) qrcode.setQrcodeEncodeMode('B'); // 設定二維碼的版本號 1-40 1:20*21 2:25*25 40:177*177 qrcode.setQrcodeVersion(7); // 生成二維碼中要儲存的資訊 String qrData = "https://ainyi.com"; // 設定一下二維碼的畫素 int width = 300; int height = 300; BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 繪圖 Graphics2D gs = bufferedImage.createGraphics(); gs.setBackground(Color.WHITE); gs.setColor(Color.BLACK); gs.clearRect(0, 0, width, height); // 清除下畫板內容 // 設定下偏移量,如果不加偏移量,有時會導致出錯 int pixoff = 2; byte[] d = qrData.getBytes("utf-8"); if(d.length > 0 && d.length <120){ boolean[][] s = qrcode.calQrcode(d); for(int i=0;i<s.length;i++){ for(int j=0;j<s.length;j++){ if(s[j][i]){ gs.fillRect(j*3+pixoff, i*3+pixoff, 3, 3); } } } } gs.dispose(); bufferedImage.flush(); ImageIO.write(bufferedImage, "png", new File("E:/code/qrcode.png"));
準備工作
java 可以實現生成二維碼,需要用到 Qrcode 的 jar 包
- java、jsp
- struts2 以及相關 jar 包
- Qrcode.jar
- 檔案上傳相關 jar 包
- 自己編寫摸索出來的藝術二維碼演算法
- 響應式
實現流程
因為要實現精美藝術二維碼,把黑白二維碼的黑色部分,點狀部分替換成有顏色的點,匯聚成一張精美的二維碼
那麼實現的關鍵點就是:==替換==
將製作好的小圖片素材,按照編號命名,三個碼眼使用大圖片素材,其他使用不相同小圖片素材,繪製二維碼圖片的時候,將畫筆改為將插入圖片素材 drawImage
根據不同型別的藝術二維碼(不同的素材),使用不同的演算法
話不多說,上程式碼
/** * QrcodeText 二維碼 * @author krry * @version 1.0 * */ public class QrcodeText{ private static int width = 975; private static int height = 975; // 設定偏移量,不設定可能導致解析出錯 private static int pixoff = 25; // 畫素大小 private static int pix = 25; // 二維碼陣列的長度 private static int codeLength; // 隨機數,生成[0,2]之間的隨機整數,取長度為3的陣列下標 private static int max = 3; //素材圖片容器 private static BufferedImage image_eye; private static BufferedImage image11; private static BufferedImage image12; private static BufferedImage image13; private static BufferedImage image21; private static BufferedImage image22; private static BufferedImage image23; private static BufferedImage image31; private static BufferedImage image32; private static BufferedImage image33; private static BufferedImage image41; private static BufferedImage image42; private static BufferedImage image43; /** * 生成二維碼 * @param message 二維碼內容 * @param type 二維碼型別 如:鎖屏 * @param filename 二維碼型別下的標號 如1 * @param arti 使用演算法型別 如0 熱門 * @param transparent 是否透明 1:透明 0背景是白色 * @param request 請求 * @return */ public static String qrcode(String message,String type,String filename,String arti,String transparent,HttpServletRequest request){ String pathName = null; FileOutputStream outputStream = null; try{ //建立二維碼物件 Qrcode qrcode = new Qrcode(); //設定二維碼的糾錯級別 //L(7%) M(15%) Q(25%) H(30%) qrcode.setQrcodeErrorCorrect('L'); //一般糾錯級別小一點 //設定二維碼的編碼模式 Binary(按照位元組編碼模式) qrcode.setQrcodeEncodeMode('B'); //設定二維碼的版本號 1-40 1:20*21 2:25*25 40:177*177 qrcode.setQrcodeVersion(5); //獲取圖片快取流物件 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //獲取畫筆 Graphics2D gs = image.createGraphics(); //判斷是否使用二維碼背景顏色是透明 if(transparent.equals("yes")){ //設定透明 image = gs.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT); gs = image.createGraphics(); } else { gs.setBackground(Color.WHITE); gs.clearRect(0, 0, width, height); } //設定內容 String content = message; byte[] contentsBytes = content.getBytes("utf-8"); //二維碼 boolean[][] code = qrcode.calQrcode(contentsBytes); //獲取二維碼陣列的長度 codeLength = code.length; //碼眼部分全部設定為false for(int i=0;i<7;i++){ for(int j=0;j<7;j++){ code[i][j]=false; } for(int j=codeLength-7;j<codeLength;j++){ code[i][j]=false; code[j][i]=false; } } //獲取資源地址 String aspath = request.getServletContext().getRealPath("/resource"); //載入圖片 loadImage(aspath,type,filename); //繪製二維碼,選擇演算法 if(arti.equals("0")) drawQrcodeHot(gs, code); //熱門演算法 else if(arti.equals("1")) drawQrcodeOrdi(gs, code); //最初演算法 else if(arti.equals("2")) drawQrcodeRiTojiao(gs, code); //三角演算法 //如果型別不是單碼,則裝載背景圖片,將二維碼寫進背景圖片中,只有單碼沒有背景 if(!type.equals("dan")){ //裝載背景圖片 BufferedImage imageBG = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\bg.jpg")); //獲取背景圖片的畫筆 Graphics2D bg = imageBG.createGraphics(); //位置座標 int x = 0; int y = 0; //如果型別是方形,判斷二維碼在背景圖片的位置,單碼圖片縮小到640畫素 if(type.equals("fang")){ x = (imageBG.getWidth() - 640) / 2; y = (imageBG.getHeight() - 640) / 2; } //如果型別是名片,判斷二維碼在背景圖片的位置,單碼圖片縮小到640畫素 if(type.equals("ming")){ x = (imageBG.getWidth() - 100) / 2; y = (imageBG.getHeight() - 640) / 2; } //如果型別是鎖屏,判斷二維碼在背景圖片的位置,單碼圖片縮小到640畫素 if(type.equals("suo")){ x = (imageBG.getWidth() - 640) / 2; y = (imageBG.getHeight() - 1100) / 2; } //將單碼圖片寫進背景圖片中,單碼圖片縮小到640畫素 bg.drawImage(image, x, y, 640, 640, null); //釋放畫筆 bg.dispose(); gs.dispose(); //生成二維碼圖片 String realPath = request.getRealPath("/"); //String realPath = 伺服器專案的地址; pathName = new Date().getTime()+".jpg"; outputStream = new FileOutputStream(new File(realPath+"upload\\", pathName)); ImageIO.write(imageBG, "jpg", outputStream); } else { //如果型別是單碼,直接釋放輸出 //釋放畫筆 gs.dispose(); //生成二維碼圖片 String realPath = request.getRealPath("/"); //String realPath = 伺服器專案的地址; pathName = new Date().getTime()+".png"; outputStream = new FileOutputStream(new File(realPath+"upload\\", pathName)); ImageIO.write(image, "png", outputStream); } } catch (Exception e){ e.printStackTrace(); } finally { try { //關閉流 outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return pathName; } /** * 載入圖片素材 * @param aspath * @param type * @param filename */ public static void loadImage(String aspath,String type,String filename){ try { //載入碼眼 image_eye = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\eye.png")); //裝載50*50的圖片素材 image11 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\11.png")); image12 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\12.png")); image13 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\13.png")); //裝載100*50的圖片素材 image21 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\21.png")); image22 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\22.png")); image23 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\23.png")); //裝載50*100的圖片素材 image31 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\31.png")); image32 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\32.png")); image33 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\33.png")); //裝載100*100的圖片素材 image41 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\41.png")); image42 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\42.png")); image43 = ImageIO.read(new FileInputStream(aspath+"\\images\\ImageMaker\\"+type+"\\"+filename+"\\43.png")); } catch (Exception e) { e.printStackTrace(); } } /** * 繪製 演算法0 熱門二維碼 素材有50*50 50*100 100*50 100*100 * @param gs 畫筆 * @param code 二維碼陣列 */ public static void drawQrcodeHot(Graphics2D gs,boolean[][] code){ //把圖片素材放進陣列 BufferedImage[] img1 = {image11,image12,image13}; BufferedImage[] img2 = {image21,image22,image23}; BufferedImage[] img3 = {image31,image32,image33}; BufferedImage[] img4 = {image41,image42,image43}; //通用地繪製碼眼 gs.drawImage(image_eye, pix, pix, pix*7, pix*7, null); gs.drawImage(image_eye, (codeLength-7)*pix+pixoff, pix, pix*7, pix*7, null); gs.drawImage(image_eye, pix, (codeLength-7)*pix+pixoff, pix*7, pix*7, null); Random random = new Random(); // 繪製 for (int i = 0; i < codeLength; i++) { for (int j = 0; j < codeLength; j++) { if (code[i][j]) { if (i+1 < codeLength && j+1 < codeLength && code[i][j + 1] && code[i + 1][j + 1] && code[i + 1][j]){ //隨機取圖片,畫100*100的圖 int s4 = random.nextInt(max); gs.drawImage(img4[s4], i * pix + pixoff, j * pix + pixoff, pix * 2, pix * 2, null); code[i][j + 1] = code[i + 1][j] = code[i + 1][j + 1] = false; } else if(j+1 < codeLength && code[i][j+1]){ //隨機取圖片,畫50*100的圖 int s3 = random.nextInt(max); gs.drawImage(img3[s3], i * pix + pixoff, j * pix + pixoff, pix, pix*2, null); code[i][j+1] = false; } else if (i+1 < codeLength && code[i+1][j]) { //隨機取圖片,畫100*50的圖 int s2 = random.nextInt(max); gs.drawImage(img2[s2], i * pix + pixoff, j * pix + pixoff, pix * 2, pix, null); code[i+1][j] = false; } else { //隨機取圖片,畫50*50的圖 int s1 = random.nextInt(max); gs.drawImage(img1[s1], i * pix + pixoff, j * pix + pixoff, pix, pix, null); } } } } } /** * 繪製 演算法2 二維碼 素材有50*50 50*100 100*50 100*100 其中100*100是三個角的演算法,右上角沒有填充 * @param gs 畫筆 * @param code 二維碼陣列 */ public static void drawQrcodeRiTojiao(Graphics2D gs,boolean[][] code){ System.out.println("三角啊"); //把圖片素材放進陣列 BufferedImage[] img1 = {image11,image12,image13}; BufferedImage[] img2 = {image21,image22,image23}; BufferedImage[] img3 = {image31,image32,image33}; BufferedImage[] img4 = {image41,image42,image43}; //通用地繪製碼眼 gs.drawImage(image_eye, pix, pix, pix*7, pix*7, null); gs.drawImage(image_eye, (codeLength-7)*pix+pixoff, pix, pix*7, pix*7, null); gs.drawImage(image_eye, pix, (codeLength-7)*pix+pixoff, pix*7, pix*7, null); Random random = new Random(); // 繪製 for (int i = 0; i < codeLength; i++) { for (int j = 0; j < codeLength; j++) { if (code[i][j]) { if (i+1 < codeLength && j+1 < codeLength && code[i][j + 1] && code[i + 1][j + 1]){ //隨機取圖片,畫100*100的圖 右上角沒有填充 int s4 = random.nextInt(max); gs.drawImage(img4[s4], i * pix + pixoff, j * pix + pixoff, pix * 2, pix * 2, null); code[i][j + 1] = code[i + 1][j + 1] = false; } else if(j+1 < codeLength && code[i][j+1]){ //隨機取圖片,畫50*100的圖 int s3 = random.nextInt(max); gs.drawImage(img3[s3], i * pix + pixoff, j * pix + pixoff, pix, pix*2, null); code[i][j+1] = false; } else if (i+1 < codeLength && code[i+1][j]) { //隨機取圖片,畫100*50的圖 int s2 = random.nextInt(max); gs.drawImage(img2[s2], i * pix + pixoff, j * pix + pixoff, pix * 2, pix, null); code[i+1][j] = false; } else { //隨機取圖片,畫50*50的圖 int s1 = random.nextInt(max); gs.drawImage(img1[s1], i * pix + pixoff, j * pix + pixoff, pix, pix, null); } } } } } /** * 繪製 演算法1 普通二維碼 素材有50*50 50*100 50*150 * @param gs 畫筆 * @param code 二維碼陣列 */ public static void drawQrcodeOrdi(Graphics2D gs,boolean[][] code){ //把圖片素材放進陣列 BufferedImage[] img1 = {image11,image12,image13}; BufferedImage[] img2 = {image21,image22,image23}; BufferedImage[] img3 = {image31,image32,image33}; //通用地繪製碼眼 gs.drawImage(image_eye, pix, pix, pix*7, pix*7, null); gs.drawImage(image_eye, (codeLength-7)*pix+pixoff, pix, pix*7, pix*7, null); gs.drawImage(image_eye, pix, (codeLength-7)*pix+pixoff, pix*7, pix*7, null); Random random = new Random(); for(int i = 0;i < codeLength;i++){ for(int j = 0;j < codeLength;j++){ //1*3 if(code[i][j]){ if(i+2 < codeLength && code[i+1][j] && code[i+2][j]){ //隨機取圖片 下標隨機[0,2],畫50*150的圖 int s3 = random.nextInt(max); gs.drawImage(img3[s3], j*25+pixoff, i*25+pixoff, 25, 75, null); code[i+2][j]=false; code[i+1][j]=false; }else if(i+1 < codeLength && code[i+1][j]){ //1*2 //隨機取圖片,畫50*100的圖 int s2 = random.nextInt(max); gs.drawImage(img2[s2], j*25+pixoff, i*25+pixoff, 25, 50, null); code[i+1][j]=false; } else { //隨機取圖片,畫50*50的圖 int s1 = random.nextInt(max); gs.drawImage(img1[s1], j*25+pixoff, i*25+pixoff, 25, 25, null); } } } } } }
專案截圖
相關地址
歡迎 start