眼下正在做的业务,需要在公众号关注二维码中嵌入品牌logo,网上查询资料踩了不少坑,分享一下悲惨经历希望能够帮助有需要的童鞋少走弯路!
1 添加依赖(笔者用的是Google的那套)
<!--Google生成二维码的依赖--> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.3.0</version> </dependency> </dependencies>
2 封装方法
/** *@param qrcodeUrl 二维码url * @param logo图片地址 这里用到的是七牛云图片地址 / public String getQrcodeWithLogo(String qrcodeUrl, String logo) { BufferedImage qrcodeImg = generateQrcode(qrcodeUrl); //单纯把二维码转换成图片返回 if (StringUtils.isEmpty(logo)) { return getQiniuImageUrl(qrcodeImg); } //添加logo try { //获取画笔 Graphics2D g = qrcodeImg.createGraphics(); BufferedImage logoImg =ImageIO.read(downloadImgToLocal(logo)); //设置二维码大小,太大,会覆盖二维码,此处20% int logoWidth = logoImg.getWidth() > qrcodeImg.getWidth() * 2 / 10 ? (qrcodeImg.getWidth() * 2 / 10) : logoImg.getWidth(); int logoHeight = logoImg.getHeight() > qrcodeImg.getHeight() * 2 / 10 ? (qrcodeImg.getHeight() * 2 / 10) : logoImg.getHeight(); //设置logo图片放置位置 居中 int x = (qrcodeImg.getWidth() - logoWidth) / 2; int y = (qrcodeImg.getHeight() - logoHeight) / 2; //开始合并绘制图片 g.drawImage(logoImg, x, y, logoWidth, logoHeight, null); g.dispose(); logoImg.flush(); qrcodeImg.flush(); return getQiniuImageUrl(qrcodeImg); } catch (IOException e) { e.printStackTrace(); } return null; }
private File downloadImgToLocal(String imgUrl){ File file = new File(Constants.LOCAL_BASE_DIR+Constants.LOGO_IMG_NAME); FileOutputStream fops = null; try { fops = new FileOutputStream(file); fops.write(getImageFromNetByUrl(imgUrl)); fops.flush(); fops.close(); } catch (Exception e) { e.printStackTrace(); } return file; } /** * 根据地址获得数据的字节流 * @param strUrl 网络连接地址 * @return */ public static byte[] getImageFromNetByUrl(String strUrl){ try { URL url = new URL(strUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(10 * 1000); InputStream inStream = conn.getInputStream();//通过输入流获取图片数据 byte[] btImg = readInputStream(inStream);//得到图片的二进制数据 return btImg; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 从输入流中获取数据 * @param inStream 输入流 * @return * @throws Exception */ public static byte[] readInputStream(InputStream inStream) throws Exception{ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while( (len=inStream.read(buffer)) != -1 ){ outStream.write(buffer, 0, len); } inStream.close(); return outStream.toByteArray(); } //生成二维码 private BufferedImage generateQrcode(String qrcodeUrl){ BufferedImage qrcodeImg = null; Hashtable hints = new Hashtable(); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//容错率,H最高 hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); //编码格式 hints.put(EncodeHintType.MARGIN, 1); //设置白边 try { BitMatrix bitMatrix = new MultiFormatWriter().encode(qrcodeUrl,BarcodeFormat.QR_CODE, Constants.QRCODE_WIDTH, Constants.QRCODE_HEIGHT, hints); String filePath=Constants.LOCAL_BASE_DIR+Constants.QRCODE_IMG_NAME; Path file = new File(filePath).toPath(); MatrixToImageWriter.writeToPath(bitMatrix, "jpeg", file); //读取二维码图片 qrcodeImg = ImageIO.read(new File(file.toString())); //通过这个api画出来的二维码logo是黑白的 //qrcodeImg = MatrixToImageWriter.toBufferedImage(bitMatrix); }catch (WriterException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return qrcodeImg; }
其中,getQiniuImageUrl方法未给出实现,是把传入的BufferedImage转换为字节数组,然后上传到七牛云服务器上返回图片路径,根据实际业务场景同样可以上传到自己服务器或者阿里OSS等。