使用Zxing實(shí)現(xiàn)二維碼生成器內(nèi)嵌圖片
使用Zxing實(shí)現(xiàn)二維碼生成器內(nèi)嵌圖片,具有一定的參考價(jià)值,具體如下:
基本思路是先使用zxing生成的二維碼圖片,然后讀取圖片,在其中插入圖標(biāo),然后整個(gè)輸出圖片。
最近的項(xiàng)目中需要生成二維碼,找了幾個(gè)例子綜合下,做出了最后的效果,二維碼可以生成圖片格式(jpg等)或者在web頁面上顯示,此片文章僅作記錄,雷同之處多多,包涵。。。。
注:需要Zxing包裝的工具類,大概的流程是讀取內(nèi)嵌的圖片,將內(nèi)容轉(zhuǎn)化成二維碼,將圖片內(nèi)嵌到二維碼中,出圖。
下面是完整代碼:
import Java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
public class Zxing {
private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;
// 圖片寬度的一般
private static final int IMAGE_WIDTH = 80;
private static final int IMAGE_HEIGHT = 80;
private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH / 2;
private static final int FRAME_WIDTH = 2;
// 二維碼寫碼器
private static MultiFormatWriter mutiWriter = new MultiFormatWriter();
public static void main(String[] args) {
try {
//BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, 400, 400,hints);
String content="13400000000";//二維碼的內(nèi)容
BufferedImage image = genBarcode(content, 400, 400, "F:\\amazed.png");
if (!ImageIO.write(image, "jpg", new File("F:\\2122.jpg"))) {
throw new IOException("Could not write an image of format ");
}
/**
//將上面的代碼換成此處,使用流讀入到頁面即可
OutputStream os = response.getOutputStream();
if (!ImageIO.write(image, "jpg",os)) {
throw new IOException("Could not write an image of format ");
}
**/
} catch (WriterException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
}
}
return image;
}
private static BufferedImage genBarcode(String content, int width,
int height, String srcImagePath) throws WriterException,
IOException {
// 讀取源圖像
BufferedImage scaleImage = scale(srcImagePath, IMAGE_WIDTH,
IMAGE_HEIGHT, true);
int[][] srcPixels = new int[IMAGE_WIDTH][IMAGE_HEIGHT];
for (int i = 0; i < scaleImage.getWidth(); i++) {
for (int j = 0; j < scaleImage.getHeight(); j++) {
srcPixels[i][j] = scaleImage.getRGB(i, j);
}
}
Map<EncodeHintType, Object> hint = new HashMap<EncodeHintType, Object>();
hint.put(EncodeHintType.CHARACTER_SET, "utf-8"); //內(nèi)容編碼
hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//錯(cuò)誤等級
hint.put(EncodeHintType.MARGIN, 1); //設(shè)置二維碼外邊框的空白區(qū)域的寬度
// 生成二維碼
BitMatrix matrix = mutiWriter.encode(content, BarcodeFormat.QR_CODE,
width, height, hint);
// 二維矩陣轉(zhuǎn)為一維像素?cái)?shù)組
int halfW = matrix.getWidth() / 2;
int halfH = matrix.getHeight() / 2;
int[] pixels = new int[width * height];
for (int y = 0; y < matrix.getHeight(); y++) {
for (int x = 0; x < matrix.getWidth(); x++) {
// 讀取圖片
if (x > halfW - IMAGE_HALF_WIDTH
&& x < halfW + IMAGE_HALF_WIDTH
&& y > halfH - IMAGE_HALF_WIDTH
&& y < halfH + IMAGE_HALF_WIDTH) {
pixels[y * width + x] = srcPixels[x - halfW
+ IMAGE_HALF_WIDTH][y - halfH + IMAGE_HALF_WIDTH];
}
// 在圖片四周形成邊框
else if ((x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH
&& x < halfW - IMAGE_HALF_WIDTH + FRAME_WIDTH
&& y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH
+ IMAGE_HALF_WIDTH + FRAME_WIDTH)
|| (x > halfW + IMAGE_HALF_WIDTH - FRAME_WIDTH
&& x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
&& y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH
+ IMAGE_HALF_WIDTH + FRAME_WIDTH)
|| (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH
&& x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
&& y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH
- IMAGE_HALF_WIDTH + FRAME_WIDTH)
|| (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH
&& x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
&& y > halfH + IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH
+ IMAGE_HALF_WIDTH + FRAME_WIDTH)) {
pixels[y * width + x] = 0xfffffff;
} else {
// 此處可以修改二維碼的顏色,可以分別制定二維碼和背景的顏色;
pixels[y * width + x] = matrix.get(x, y) ? 0xff000000
: 0xfffffff;
}
}
}
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
image.getRaster().setDataElements(0, 0, width, height, pixels);
return image;
}
/**
* 把傳入的原始圖像按高度和寬度進(jìn)行縮放,生成符合要求的圖標(biāo)
*
* @param srcImageFile
* 源文件地址
* @param height
* 目標(biāo)高度
* @param width
* 目標(biāo)寬度
* @param hasFiller
* 比例不對時(shí)是否需要補(bǔ)白:true為補(bǔ)白; false為不補(bǔ)白;
* @throws IOException
*/
private static BufferedImage scale(String srcImageFile, int height,
int width, boolean hasFiller) throws IOException {
double ratio = 0.0; // 縮放比例
File file = new File(srcImageFile);
BufferedImage srcImage = ImageIO.read(file);
Image destImage = srcImage.getScaledInstance(width, height,
BufferedImage.SCALE_SMOOTH);
// 計(jì)算比例
if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {
if (srcImage.getHeight() > srcImage.getWidth()) {
ratio = (new Integer(height)).doubleValue()
/ srcImage.getHeight();
} else {
ratio = (new Integer(width)).doubleValue()
/ srcImage.getWidth();
}
AffineTransformOp op = new AffineTransformOp(
AffineTransform.getScaleInstance(ratio, ratio), null);
destImage = op.filter(srcImage, null);
}
if (hasFiller) {// 補(bǔ)白
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D graphic = image.createGraphics();
graphic.setColor(Color.PINK);
graphic.fillRect(10, 10, width, height);
graphic.drawRect(100, 360, width, height);
if (width == destImage.getWidth(null)) {
graphic.drawImage(destImage, 0,
(height - destImage.getHeight(null)) / 2,
destImage.getWidth(null), destImage.getHeight(null),
Color.white, null);
Shape shape = new RoundRectangle2D.Float(0, (height - destImage.getHeight(null)) / 2, width, width, 20, 20);
graphic.setStroke(new BasicStroke(5f));
graphic.draw(shape);
}
else {
graphic.drawImage(destImage,
(width - destImage.getWidth(null)) / 2, 0,
destImage.getWidth(null), destImage.getHeight(null),
Color.white, null);
Shape shape = new RoundRectangle2D.Float((width - destImage.getWidth(null)) / 2, 0, width, width, 20, 20);
graphic.setStroke(new BasicStroke(5f));
graphic.draw(shape);
}
graphic.dispose();
destImage = image;
}
return (BufferedImage) destImage;
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
淺談shiro的SecurityManager類結(jié)構(gòu)
下面小編就為大家?guī)硪黄獪\談shiro的SecurityManager類結(jié)構(gòu)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07
Spring MVC學(xué)習(xí)教程之視圖深入解析
這篇文章主要給大家介紹了關(guān)于Spring MVC學(xué)習(xí)教程之視圖解析的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或使用spring mvc具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧2018-11-11
詳解SpringBoot 多線程處理任務(wù) 無法@Autowired注入bean問題解決
這篇文章主要介紹了詳解SpringBoot 多線程處理任務(wù) 無法@Autowired注入bean問題解決,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-06-06
IDEA在SpringBoot項(xiàng)目使用Maven打包后jar包太小問題及解決
這篇文章主要介紹了IDEA在SpringBoot項(xiàng)目使用Maven打包后jar包太小問題及解決,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
JXLS根據(jù)模板導(dǎo)出Excel實(shí)例教程
這篇文章主要為大家詳細(xì)介紹了JXLS根據(jù)模板導(dǎo)出Excel實(shí)例教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
Java實(shí)現(xiàn)單向鏈表反轉(zhuǎn)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)單向鏈表反轉(zhuǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
mybatis查詢實(shí)現(xiàn)返回List<Map>類型數(shù)據(jù)操作
這篇文章主要介紹了mybatis查詢實(shí)現(xiàn)返回List<Map>類型數(shù)據(jù)操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11

