世界上25%的人都有拖延症——但我觉得这统计肯定少了,至少我就是一名拖延症患者。一直想把“Java生成名片式(带有背景图片、用户网络头像、用户昵称)的二维码”这篇博客分享出来,但一直拖啊拖,拖到现在,真应了苏格兰的那句谚语——“什么时候都能做的事,往往什么时候都不会去做。”
零、效果图
- 左上角为微信头像。
- 沉默王二是文字昵称。
- 附带URL为http://blog.youkuaiyun.com/qing_gee的二维码
- 还有指定的背景图。
使用场景:
点公众号的微信菜单“我的二维码”,然后展示一张名片式的二维码给用户。
一、源码下载
可以通过GitHub直接下载https://github.com/qinggee/qrcode-utils.
二、源码介绍
你肯定在网络上见到过不少Java生成带有logo的二维码的源码,这些都是生成二维码的初级应用。相对来说,生成“名片式(带有背景图片、用户网络头像、用户名称的二维码图片)的二维码”可能更高级一点,但内在的原理其实是相似的——在一张指定的图片对象Graphics2D利用drawImage()方法绘制上层图像,利用drawString绘制文字。
2.1 使用接口
文件位置: /qrcode-utils/src/test/QrcodeUtilsTest.java
MatrixToBgImageConfig config = new MatrixToBgImageConfig();
// 网络头像地址 config.setHeadimgUrl("https://avatars2.githubusercontent.com/u/6011374?v=4&u=7672049c1213f7663b79583d727e95ee739010ec&s=400");
// 二维码地址,扫描二维码跳转的地址
config.setQrcode_url("http://blog.youkuaiyun.com/qing_gee");
// 二维码名片上的名字 config.setRealname("沉默王二"); // 通过QrcodeUtils.createQrcode()生成二维码的字节码 byte[] bytes = QrcodeUtils.createQrcode(config); // 二维码生成路径 Path path = Files.createTempFile("qrcode_with_bg_", ".jpg"); // 写入到文件 Files.write(path, bytes);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
如果你从GitHub上下载到源码后,可直接通过eclipse把工程导入到你的工作库,运行/qrcode-utils/src/test/QrcodeUtilsTest.java 即可生成二维码。
2.2 目录文件介绍
- 核心类为QrcodeUtils.java(用来生成二维码)
- 名片式二维码的参数类MatrixToBgImageConfig.java
- 测试用例QrcodeUtilsTest.java
- res资源包下有两张图片,bg.jpg为指定的背景图、default_headimg.jpg为默认的头像图
- /qrcode-utils/lib为所需的jar包
2.3 QrcodeUtils.java
2.3.1 获取背景
注意以下代码中的第一行代码。
InputStream inputStream = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(config.getBgFile());
File bgFile = Files.createTempFile("bg_", ".jpg").toFile();
FileUtils.copyInputStreamToFile(inputStream, bgFile);
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
2.3.2 获取微信头像
通过建立HttpGet请求来获取微信头像。
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
HttpGet httpget = new HttpGet(config.getHeadimgUrl());
httpget.addHeader("Content-Type", "text/html;charset=UTF-8");
// 配置请求的超时设置
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(500) .setConnectTimeout(500).setSocketTimeout(500).build(); httpget.setConfig(requestConfig); try (CloseableHttpResponse response = httpclient.execute(httpget); InputStream headimgStream = handleResponse(response);) { Header[] contentTypeHeader = response.getHeaders("Content-Type"); if (contentTypeHeader != null && contentTypeHeader.length > 0) { if (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) { // application/json; encoding=utf-8 下载媒体文件出错 String responseContent = handleUTF8Response(response); logger.warn("下载网络头像出错{}", responseContent); } } headimgFile = createTmpFile(headimgStream, "headimg_" + UUID.randomUUID(), "jpg"); } catch (Exception e) { logger.error(e.getMessage(), e); throw new Exception("头像文件读取有误!", e); } finally { httpget.releaseConnection(); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
通过createTmpFile方法将图像下载到本地。
public static File createTmpFile(InputStream inputStream, String name, String ext) throws IOException {
File tmpFile = File.createTempFile(name, '.' + ext); tmpFile.deleteOnExit(); try (FileOutputStream fos = new FileOutputStream(tmpFile)) { int read = 0; byte[] bytes = new byte[1024 * 100]; while ((read = inputStream.read(bytes)) != -1) { fos.write(bytes, 0, read); } fos.flush(); return tmpFile; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
2.3.3 在背景图上绘制二维码、头像、昵称
private static void increasingImage(BufferedImage image, String format, String imagePath, File bgFile,
MatrixToBgImageConfig config, File headimgFile) throws Exception { try { BufferedImage bg = ImageIO.read(bgFile); Graphics2D g = bg.createGraphics(); // 二维码的高度和宽度如何定义 int width = config.getQrcode_height(); int height = config.getQrcode_height(); // logo起始位置,此目的是为logo居中显示 int x = config.getQrcode_x(); int y = config.getQrcode_y(); // 绘制图 g.drawImage(image, x, y, width, height, null); BufferedImage headimg = ImageIO.read(headimgFile); int headimg_width = config.getHeadimg_height(); int headimg_height = config.getHeadimg_height(); int headimg_x = config.getHeadimg_x(); int headimg_y = config.getHeadimg_y(); // 绘制头像 g.drawImage(headimg, headimg_x, headimg_y, headimg_width, headimg_height, null); // 绘制文字 g.setColor(Color.GRAY);// 文字颜色 Font font = new Font("宋体", Font.BOLD, 28); g.setFont(font); g.drawString(config.getRealname(), config.getRealname_x(), config.getRealname_y()); g.dispose(); // 写入二维码到bg图片 ImageIO.write(bg, format, new File(imagePath)); } catch (Exception e) { throw new Exception("二维码添加bg时发生异常!", e); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
好了,源码就先介绍到这喽。
http://blog.youkuaiyun.com/qing_gee/article/details/77341821