目标
使用谷歌zxing生成带有logo二维码 便捷地解决二维码中文乱码问题
过程
下载依赖:
maven坐标:
< dependency>
< groupId> com.google.zxing</ groupId>
< artifactId> core</ artifactId>
< version> 3.3.3</ version>
</ dependency>
编写java代码生成二维码,并绘制logo
public static void drawQrCode ( String qrUrl, String logoUrl, String outputPath, String note, int width, int height) throws Exception {
MultiFormatWriter multiFormatWriter = new MultiFormatWriter ( ) ;
BitMatrix bitMatrix = multiFormatWriter. encode ( qrUrl, BarcodeFormat . QR_CODE, width, height, new HashMap < EncodeHintType , Object > ( ) {
private static final long serialVersionUID = 1L ;
{
put ( EncodeHintType . ERROR_CORRECTION, ErrorCorrectionLevel. H ) ;
put ( EncodeHintType . CHARACTER_SET, "UTF-8" ) ;
put ( EncodeHintType . MARGIN, 0 ) ;
}
} ) ;
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, bitMatrix. get ( x, y) ? 0xFF000000 : 0xFFFFFFFF ) ;
}
}
if ( logoUrl != null && ! "" . equals ( logoUrl) ) {
Graphics2D graphics = image. createGraphics ( ) ;
BufferedImage logoImg = ImageIO . read ( new URL ( logoUrl) ) ;
graphics. drawImage ( logoImg, width * 2 / 6 , height * 2 / 6 , width * 3 / 10 , height * 3 / 10 , null ) ;
graphics. dispose ( ) ;
logoImg. flush ( ) ;
}
if ( note != null && ! "" . equals ( note) ) {
BufferedImage outImage = new BufferedImage ( width, height + 45 , BufferedImage . TYPE_4BYTE_ABGR) ;
Graphics2D outGraphics = outImage. createGraphics ( ) ;
outGraphics. drawImage ( image, 0 , 0 , image. getWidth ( ) , image. getHeight ( ) , null ) ;
outGraphics. setColor ( Color . BLACK) ;
outGraphics. setFont ( new Font ( "Arial" , Font . BOLD, 26 ) ) ;
int noteWidth = outGraphics. getFontMetrics ( ) . stringWidth ( note) ;
outGraphics. drawString ( new QrCodeAttributedCharacter ( note) , ( width - noteWidth) / 2 , image. getHeight ( ) + ( outImage. getHeight ( ) - image. getHeight ( ) ) / 2 + 12 ) ;
outGraphics. dispose ( ) ;
outImage. flush ( ) ;
image = outImage;
}
image. flush ( ) ;
ImageIO . write ( image, "png" , Paths . get ( outputPath) . toFile ( ) ) ;
}
编写QrCodeAttributedCharacter解决中文乱码问题
public class QrCodeAttributedCharacter implements AttributedCharacterIterator {
private int index;
private char [ ] textChars;
public QrCodeAttributedCharacter ( String text) {
this . textChars = text. toCharArray ( ) ;
}
@Override
public int getRunStart ( ) {
return 0 ;
}
@Override
public int getRunStart ( Attribute attribute) {
return 0 ;
}
@Override
public int getRunStart ( Set < ? extends Attribute > attributes) {
return 0 ;
}
@Override
public int getRunLimit ( ) {
return this . textChars. length;
}
@Override
public int getRunLimit ( Attribute attribute) {
return this . textChars. length;
}
@Override
public int getRunLimit ( Set < ? extends Attribute > attributes) {
return this . textChars. length;
}
@Override
public Map < Attribute , Object > getAttributes ( ) {
return Collections . EMPTY_MAP;
}
@Override
public Object getAttribute ( Attribute attribute) {
return Collections . EMPTY_MAP;
}
@Override
public Set < Attribute > getAllAttributeKeys ( ) {
return Collections . EMPTY_SET;
}
@Override
public char first ( ) {
this . index = 0 ;
return this . textChars[ 0 ] ;
}
@Override
public char last ( ) {
return this . textChars[ this . textChars. length - 1 ] ;
}
@Override
public char current ( ) {
return this . textChars[ this . index] ;
}
@Override
public char next ( ) {
if ( this . index == this . textChars. length - 1 ) {
return CharacterIterator . DONE;
}
return this . textChars[ ++ this . index ] ;
}
@Override
public char previous ( ) {
if ( this . index == 0 ) {
return CharacterIterator . DONE;
}
return this . textChars[ this . index - 1 ] ;
}
@Override
public char setIndex ( int position) {
this . index = position;
return textChars[ position] ;
}
@Override
public int getBeginIndex ( ) {
return 0 ;
}
@Override
public int getEndIndex ( ) {
return this . textChars. length;
}
@Override
public int getIndex ( ) {
return this . index;
}
@Override
public Object clone ( ) {
return new String ( textChars) ;
}
}
中文乱码问题分析与解决依据
乱码原因:
通过查看zxing的Encoder类可以发现默认编码方式是ISO-8859-1。
通过新建QrCodeAttributedCharacter类修复乱码问题原理.
进入Graphics2D的drawString(AttributedCharacterIterator iterator, int x, int y)方法找到其读取字符串内容逻辑如下:
从图中可以看出其是通过调用AttributedCharacterIterator的实现类的方法来获取字符串内容的,因此可以通过实现AttributedCharacterIterator接口来控制获取的字符串内容。
测试
测试代码:
public static void main ( String [ ] args) throws Exception {
String qrUrl = "https://blog.csdn.net/qq_41633199" ;
String logoUrl = "http://www.finac.site/logo.png" ;
String outputPath = "B:\\logo.jpg" ;
drawQrCode ( qrUrl, logoUrl, outputPath, "博文地址" , 400 , 400 ) ;
}
测试结果: