自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java 代碼基于開源組件生成帶頭像的二維碼,推薦收藏!

開發(fā) 前端 開源
我們生成二維碼使用工具 zxing,合成圖片我們采用 thumbnailator,接下來(lái)我們實(shí)操一下吧。

二維碼在我們目前的生活工作中,隨處可見,日常開發(fā)中難免會(huì)遇到需要生成二維碼的場(chǎng)景,網(wǎng)上也有很多開源的平臺(tái)可以使用,不過這里我們可以通過幾個(gè)開源組件,自己來(lái)實(shí)現(xiàn)一下。

在動(dòng)手之前我們先思考一下需要進(jìn)行的操作,首先我們需要生成一個(gè)二維碼,其次我們需要在這里二維碼中間添加一個(gè)頭像。

這里我們生成二維碼使用工具 zxing,合成圖片我們采用 thumbnailator,接下來(lái)我們實(shí)操一下吧。

生成二維碼

首先我們先根據(jù)目標(biāo)地址,生成一個(gè)二維碼,這里我們使用的是組件 zxing,在 SpringBoot 的pom依賴中,我們加入下面的依賴。

<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.0</version>
</dependency>

然后編寫工具類 QRCodeGenerator.java

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.HashMap;


publicclass QRCodeGenerator {

/**
* 根據(jù)內(nèi)容,大小生成二維碼到指定路徑
*
* @param contents 跳轉(zhuǎn)的鏈接
* @param width 寬度
* @param height 高度
* @param filePath 路徑
* @throws WriterException
* @throws IOException
*/
public static void generateQrWithImage(String contents, int width, int height, String filePath) throws WriterException, IOException {
//構(gòu)造二維碼寫碼器
MultiFormatWriter mutiWriter = new com.google.zxing.MultiFormatWriter();
HashMap<EncodeHintType, Object> hint = new HashMap<>(16);
hint.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hint.put(EncodeHintType.ERROR_CORRECTION, com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.H);
hint.put(EncodeHintType.MARGIN, 1);
//生成二維碼
BitMatrix bitMatrix = mutiWriter.encode(contents, BarcodeFormat.QR_CODE, width, height, hint);
Path path = FileSystems.getDefault().getPath(filePath);
MatrixToImageWriter.writeToPath(bitMatrix, "jpeg", path);
}
}

這個(gè)靜態(tài)方法有四個(gè)參數(shù),分別是:

  • 跳轉(zhuǎn)的鏈接內(nèi)容;
  • 二維碼的寬度;
  • 二維碼的高度;
  • 生成的二維碼后的存放路徑;

代碼中還有幾個(gè)常量,EncodeHintType.CHARACTER_SET:表示編碼;EncodeHintType.ERROR_CORRECTION 表示二維碼的容錯(cuò)率;EncodeHintType.MARGIN 表示二維碼的邊框。

解釋一下什么是二維碼的容錯(cuò)率,大家在日常生活或者工作中應(yīng)該會(huì)發(fā)現(xiàn),有些二維碼輕輕一掃就掃成功了,有的二維碼卻很難掃成功,這背后就是二維碼的容錯(cuò)率的原因(對(duì),有時(shí)候并不是你的網(wǎng)絡(luò)問題!)。

不同密度的二維碼所包含的信息其編碼的字符、容錯(cuò)率均不同。密度越低,編碼的字符個(gè)數(shù)越少、容錯(cuò)率越低,二維碼容錯(cuò)率表示二維碼圖標(biāo)被遮擋多少后,仍可以被掃描出來(lái)的能力。目前,典型的二維碼的容錯(cuò)率分為 7%、15%、25%、30% 四個(gè)等級(jí),容錯(cuò)率越高,越容易被快速掃描?!暗?,容錯(cuò)率越高,二維碼里面的黑白格子也就越多。因此,對(duì)于目前主流手機(jī),在絕大多數(shù)掃描場(chǎng)景下,仍普遍應(yīng)用 7% 容錯(cuò)率的二維碼就能滿足需求。

感興趣的小伙伴也可以自己嘗試幾個(gè)不同的容錯(cuò)率,看看掃碼的難度有沒有變化。

接下來(lái),我們編寫一個(gè) main 方法來(lái)生成一個(gè)二維碼

public static void main(String[] args) {
try {
QRCodeGenerator.generateQrWithImage("https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzkzODE3OTI0Ng==&scene=124#wechat_redirect", 500, 500, "./QRCode.jpeg");
} catch (Exception e) {
}
}

運(yùn)行完上面的 main 方法,我們可以得到一個(gè)二維碼,到這里我們第一步已經(jīng)完成了,接下來(lái)就是給這個(gè)二維碼加上我們的頭像。

添加頭像

添加頭像我們需要準(zhǔn)備一個(gè)頭像的照片,阿粉這里就用阿粉的頭像了,如果這里有現(xiàn)成大小的頭像就直接拿來(lái)使用就行,如果沒有也沒有關(guān)系,我們可以自己裁剪,這里我們就需要用來(lái)圖片處理工具 thumbnailator 了。

阿粉

先將頭像處理成 100 x 100 的大小,然后再合成上去就行,代碼如下:

public static void main(String[] args) {
try {
// 將大圖片縮小到指定大小
// ThumbnailsImageUtils.size("./阿粉.jpeg", 100, 100, 1, "./阿粉100.png");
// 通過水印的形式,將頭像加到生成的二維碼上面
ThumbnailsImageUtils.watermark("./QRCode.jpeg",
500, 500, Positions.CENTER, "./阿粉100.png",
1f, 1f, "./result.png");
} catch (Exception e) {
}
}

這個(gè)就是最終生成的帶頭像的二維碼啦,友情提示,掃碼可以看到更多優(yōu)質(zhì)文章。

通過上面的代碼可以看到,ThumbnailsImageUtils 是真的很多強(qiáng)大,一行代碼就能搞定圖片縮小和圖片合成,更多關(guān)于 ThumbnailsImageUtils 工具類的完整代碼如下,趕緊收藏起來(lái)。


import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
* <br>
* <b>功能:</b><br>
* <b>作者:</b>@author ziyou<br>
* <b>日期:</b>2018-05-25 16:17<br>
* <b>詳細(xì)說(shuō)明:</b>使用google開源工具Thumbnailator實(shí)現(xiàn)圖片的一系列處理<br>
*/
publicclass ThumbnailsImageUtils {

privatefinalstatic Logger logger = LoggerFactory.getLogger(ThumbnailsImageUtils.class);

/**
* 將原圖根據(jù)指定大小生產(chǎn)新圖
*
* @param sourceFilePath 原始圖片路徑
* @param width 指定圖片寬度
* @param height 指定圖片高度
* @param targetFilePath 目標(biāo)圖片路徑
* @return 目標(biāo)圖片路徑
* @throws IOException
*/
public static String thumb(String sourceFilePath, Integer width, Integer height, String targetFilePath) throws IOException {
Thumbnails.of(sourceFilePath)
.forceSize(width, height)
.toFile(targetFilePath);
return targetFilePath;
}


/**
* 按照比例進(jìn)行縮放
*
* @param sourceFilePath 原始圖片路徑
* @param scale scale(比例)
* @param targetFilePath 目標(biāo)圖片路徑
* @return 目標(biāo)圖片路徑
* @throws IOException
*/
public static String scale(String sourceFilePath, Double scale, String targetFilePath) throws IOException {
Thumbnails.of(sourceFilePath)
.scale(scale)
.toFile(targetFilePath);
return targetFilePath;
}


/**
* 不按照比例,指定大小進(jìn)行縮放
*
* @param sourceFilePath 原始圖片路徑
* @param width 指定圖片寬度
* @param height 指定圖片高度
* @param targetFilePath 目標(biāo)圖片路徑
* keepAspectRatio(false) 默認(rèn)是按照比例縮放的
* @return 目標(biāo)圖片路徑
* @throws IOException
*/
public static String size(String sourceFilePath, Integer width, Integer height, float quality, String targetFilePath) throws IOException {
Thumbnails.of(sourceFilePath)
.size(width, height)
.outputQuality(quality)
.keepAspectRatio(false)
.toFile(targetFilePath);
return targetFilePath;
}


/**
* 指定大小和角度旋轉(zhuǎn)
*
* @param sourceFilePath 原始圖片路徑
* @param width 指定圖片寬度
* @param height 指定圖片高度
* @param rotate rotate(角度),正數(shù):順時(shí)針 負(fù)數(shù):逆時(shí)針
* @param targetFilePath 目標(biāo)圖片路徑
* @return 目標(biāo)圖片路徑
* @throws IOException
*/
public static String rotate(String sourceFilePath, Integer width, Integer height, Double rotate, String targetFilePath) throws IOException {
Thumbnails.of(sourceFilePath)
.size(width, height)
.rotate(rotate)
.toFile(targetFilePath);
return targetFilePath;
}


/**
* 指定角度旋轉(zhuǎn)
*
* @param sourceFilePath 原始圖片路徑
* @param rotate rotate(角度),正數(shù):順時(shí)針 負(fù)數(shù):逆時(shí)針
* @param targetFilePath 目標(biāo)圖片路徑
* @return 目標(biāo)圖片路徑
* @throws IOException
*/
public static String rotate(String sourceFilePath, Double rotate, String targetFilePath) throws IOException {
Thumbnails.of(sourceFilePath)
.rotate(rotate)
.toFile(targetFilePath);
return targetFilePath;
}


/**
* @param sourceFilePath 原始圖片路徑
* @param width 指定圖片寬度
* @param height 指定圖片高度
* @param position 水印位置
* @param waterFile 水印文件
* @param opacity 水印透明度
* @param quality 輸出文件的質(zhì)量
* @param targetFilePath 目標(biāo)圖片路徑
* @return 目標(biāo)圖片路徑
* @throws IOException
*/
public static String watermark(String sourceFilePath, Integer width, Integer height, Positions position, String waterFile, float opacity, float quality, String targetFilePath) throws IOException {
Thumbnails.of(sourceFilePath)
.size(width, height)
.watermark(position, ImageIO.read(new File(waterFile)), opacity)
.outputQuality(quality)
.toFile(targetFilePath);
return targetFilePath;
}


public static BufferedImage watermarkList(BufferedImage buffImg, int length, File[] waterFileArray) throws IOException {
int x = 0;
int y = 0;
if (buffImg == null) {
// 獲取底圖
buffImg = new BufferedImage(1200, 1200, BufferedImage.SCALE_SMOOTH);
} else {
x = (length % 30) * 40;
y = (length / 30) * 40;
}
// 創(chuàng)建Graphics2D對(duì)象,用在底圖對(duì)象上繪圖
Graphics2D g2d = buffImg.createGraphics();
// 將圖像填充為白色
g2d.setColor(Color.WHITE);
g2d.fillRect(x, y, 1200, 40 * (waterFileArray.length + length));
for (int i = 0; i < waterFileArray.length; i++) {
// 獲取層圖
BufferedImage waterImg = ImageIO.read(waterFileArray[i]);
// 獲取層圖的寬度
int waterImgWidth = waterImg.getWidth();
// 獲取層圖的高度
int waterImgHeight = waterImg.getHeight();
// 在圖形和圖像中實(shí)現(xiàn)混合和透明效果
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
// 繪制
Integer j = i / 30;
Integer index = i - j * 30;
g2d.drawImage(waterImg, waterImgWidth * index + 1, waterImgHeight * j, waterImgWidth, waterImgHeight, null);

}

// 釋放圖形上下文使用的系統(tǒng)資源
g2d.dispose();
return buffImg;
}

/**
* @param sourceFilePath 原始圖片路徑
* @param waterFile 水印文件
* @param targetFilePath 目標(biāo)圖片路徑
* 透明度默認(rèn)值0.5f,質(zhì)量默認(rèn)0.8f
* @return 目標(biāo)圖片路徑
* @throws IOException
*/
public static String watermark(String sourceFilePath, String waterFile, String targetFilePath) throws IOException {
Image image = ImageIO.read(new File(waterFile));
Integer width = image.getWidth(null);
Integer height = image.getHeight(null);
return watermark(sourceFilePath, width, height,
Positions.BOTTOM_RIGHT, waterFile, 0.5f, 0.8f, targetFilePath);
}


/**
* 將圖片轉(zhuǎn)化為指定大小和格式的圖片
*
* @param sourceFilePath
* @param width
* @param height
* @param format
* @param targetFilePath
* @return
* @throws IOException
*/
public static String changeFormat(String sourceFilePath, Integer width, Integer height, String format, String targetFilePath) throws IOException {
Thumbnails.of(sourceFilePath)
.size(width, height)
.outputQuality(0.8f)
.outputFormat(format)
.toFile(targetFilePath);
return targetFilePath;
}


/**
* 根據(jù)原大小轉(zhuǎn)化指定格式
*
* @param sourceFilePath
* @param format
* @param targetFilePath
* @return
* @throws IOException
*/
public static String changeFormat(String sourceFilePath, String format, String targetFilePath) throws IOException {
Image image = ImageIO.read(new File(sourceFilePath));
Integer width = image.getWidth(null);
Integer height = image.getHeight(null);
Thumbnails.of(sourceFilePath)
.size(width, height)
.outputFormat(format)
.toFile(targetFilePath);
return targetFilePath;
}

/**
* 輸出到輸出流
*
* @param sourceFilePath
* @param targetFilePath
* @return
* @throws IOException
*/
public static String toOutputStream(String sourceFilePath, String targetFilePath) throws IOException {
OutputStream os = new FileOutputStream(targetFilePath);
Thumbnails.of(sourceFilePath).toOutputStream(os);
return targetFilePath;
}


/**
* 輸出到BufferedImage
*
* @param sourceFilePath
* @param format
* @param targetFilePath
* @return
* @throws IOException
*/
public static String asBufferedImage(String sourceFilePath, String format, String targetFilePath) throws IOException {
/**
* asBufferedImage() 返回BufferedImage
*/
BufferedImage thumbnail = Thumbnails.of(sourceFilePath).size(1280, 1024).asBufferedImage();
ImageIO.write(thumbnail, format, new File(targetFilePath));
return targetFilePath;
}
}

總結(jié)

今天阿粉通過兩個(gè)組件帶大家實(shí)踐了一個(gè)二維碼的生成和圖片的合成,這兩個(gè)技巧在工作中難免會(huì)使用到,趕緊保存使用起來(lái)吧。

責(zé)任編輯:武曉燕 來(lái)源: Java極客技術(shù)
相關(guān)推薦

2024-06-26 08:46:45

2021-02-08 08:40:00

Zint二維碼開源

2023-11-17 15:44:06

C++庫(kù)生成二維碼

2023-11-17 09:07:51

.NET生成二維碼識(shí)別二維碼

2015-09-24 09:56:19

.NET二維碼

2013-10-29 09:46:05

二維碼

2020-12-30 10:55:01

代碼Java二維碼

2013-03-27 16:13:17

Android開發(fā)Android二維碼生QR生成

2013-01-30 12:16:49

二維碼NFC近場(chǎng)通訊

2021-01-14 06:19:45

QRCanvas開源二維碼

2023-10-31 08:16:16

Go語(yǔ)言二維碼

2014-12-31 15:37:16

二維碼生成掃描

2020-08-07 14:18:03

二維碼Go語(yǔ)言編程

2017-11-21 09:00:15

PHP二維碼LOGO圖像

2017-02-21 09:17:46

二維碼漏洞

2012-04-01 09:53:13

二維碼

2011-12-06 16:40:45

二維碼快拍二維碼靈動(dòng)快拍

2015-11-09 13:03:47

JavaServlet創(chuàng)建二維碼

2011-11-24 16:00:23

信息圖QR碼二維碼

2022-03-24 09:43:29

二維碼二維碼修改器github
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)