建设一个怎样的自己的网站首页,全国企业信用信息公示系统河南,wordpress栏目文章自定义标题,福州seo关键词排名之前星之音乐下载器有需要生成二维码功能,当时用的是一个开源库来实现的,但是没过多久,发现那个库依赖太多,有个http-client的依赖,把软件都搞大了一倍,而且有时候开发的时候下载依赖还报错,就想换个方案
于是在网上找了下解决方案,最终只需要依赖两个zxing的两个依赖即可实现…之前星之音乐下载器有需要生成二维码功能,当时用的是一个开源库来实现的,但是没过多久,发现那个库依赖太多,有个http-client的依赖,把软件都搞大了一倍,而且有时候开发的时候下载依赖还报错,就想换个方案
于是在网上找了下解决方案,最终只需要依赖两个zxing的两个依赖即可实现功能
本文基于TornadoFx框架进行编写,封装工具代码是kotlin版本,工具类已经封装在common-controls库中
工具支持带logo图标,带底部文本的二维码生成
代码封装
1.引入依赖
dependencygroupIdcom.google.zxing/groupIdartifactIdcore/artifactIdversion3.5.0/version
/dependency
dependencygroupIdcom.google.zxing/groupIdartifactIdjavase/artifactIdversion3.5.0/version
/dependency2.使用
由于工具代码过多不便阅读,就先讲些使用,工具代码就放下面了
比较核心的就两个方法,如下面代码所示,其他的方法是带Swing关键字,就是生成Swing包中的Image对象
getQRcodeFxImg()方法就是直接生成Fx的Image对象,可以JavaFx中直接使用
/*** 初始化设置** param qrcodeSize 二维码尺寸默认为320(即320*320)* param logoSize logo图标尺寸,默认为80(即80*80)* param bottomTextSize 底部文字大小,默认20px* param qrcodeType 二维码图片格式,默认为png*/
fun initConfig(qrcodeSize: Int 320, logoSize: Int 80, bottomTextSize: Int 20, qrcodeType: String PNG)/*** 生成二维码图片** param data 二维码文本内容* param logoPath 图标图片的路径* param bottomText 底部文字* return fx的img对象*/
fun getQRcodeFxImg(data: String?, logoPath: String?null, bottomText: String?null): WritableImage使用的话也比较简单:
//得到的swing的image对象
val buImg QRCodeUtil.getQRcodeFxImg(这是测试文本)
val buImg1 QRCodeUtil.getQRcodeFxImg(这是测试文本, null, 底部文字)
val buImg2 QRCodeUtil.getQRcodeFxImg(这是测试文本, /x5.jpg, 底部文字)val list listOf(buImg, buImg1, buImg2)hbox(20.0) {list.forEach {imageview(it) {fitWidth 200.0fitHeight 200.0}}
}3.工具库代码
/*** 二维码生成工具类* Created by stars-one*/
object QRCodeUtil {private var QRCODE_SIZE 320 // 二维码尺寸宽度和高度均是320private var LOGO_SIZE 80 // 二维码里logo的尺寸宽高一致 80*80private var BOTTOM_TEXT_SIZE 20 // 底部文本的文字大小private var FORMAT_TYPE PNG // 二维码图片类型/*** 初始化设置** param qrcodeSize 二维码尺寸默认为320(即320*320)* param logoSize logo图标尺寸,默认为80(即80*80)* param bottomTextSize 底部文字大小,默认20px* param qrcodeType 二维码图片格式,默认为png*/fun initConfig(qrcodeSize: Int 320, logoSize: Int 80, bottomTextSize: Int 20, qrcodeType: String PNG) {QRCODE_SIZE qrcodeSizeLOGO_SIZE logoSizeBOTTOM_TEXT_SIZE bottomTextSizeFORMAT_TYPE qrcodeType}/*** 生成二维码图片** param data 二维码文本内容* param logoPath 图标图片的路径* param bottomText 底部文字* return*/fun getQRcodeFxImg(data: String?, logoPath: String?null, bottomText: String?null): WritableImage {val resources ResourceLookup(this)val url if (logoPath null) {null} else {resources.url(logoPath)}val swingImg getQRCodeSwingImg(data, url, bottomText)return SwingFXUtils.toFXImage(swingImg,null)}/*** 默认需要logo,无底部文字* 返回 BufferedImage 可以使用ImageIO.write(BufferedImage, png, outputStream);输出** param dataStr* return 返回 BufferedImage 可以使用ImageIO.write(BufferedImage, png, outputStream);输出*/Throws(Exception::class)fun getQRCodeSwingImg(dataStr: String?): BufferedImage {return getQRCodeSwingImg(dataStr, null, null)}/*** 默认需要logo,无底部文字** param dataStr* return 返回字节数组*/Throws(Exception::class)fun getQRCodeByte(dataStr: String?): ByteArray {val bufferedImage getQRCodeSwingImg(dataStr, null, null)val outputStream ByteArrayOutputStream()ImageIO.write(bufferedImage, FORMAT_TYPE, outputStream)return outputStream.toByteArray()}/*** 默认需要logo包含底部文字 文字为空则不显示文字* 返回 BufferedImage 可以使用ImageIO.write(BufferedImage, png, outputStream);输出** param dataStr* return*/Throws(Exception::class)fun getQRCodeSwingImg(dataStr: String?, bottomText: String?): BufferedImage {return getQRCodeSwingImg(dataStr, null, bottomText)}/*** 默认需要logo包含底部文字 文字为空则不显示文字** param dataStr* return 返回字节数组*/Throws(Exception::class)fun getQRCodeByte(dataStr: String?, bottomText: String?): ByteArray {val bufferedImage getQRCodeSwingImg(dataStr, null, bottomText)val outputStream ByteArrayOutputStream()ImageIO.write(bufferedImage, FORMAT_TYPE, outputStream)return outputStream.toByteArray()}/*** 获取二维码图片** param dataStr 二维码内容* param needLogo 是否需要添加logo* param bottomText 底部文字 为空则不显示* return*/Throws(Exception::class)fun getQRCodeSwingImg(dataStr: String?, url: URL?, bottomText: String?): BufferedImage {if (dataStr null) {throw RuntimeException(未包含任何信息)}val hints HashMapEncodeHintType, Any?()hints[EncodeHintType.CHARACTER_SET] utf-8 //定义内容字符集的编码hints[EncodeHintType.ERROR_CORRECTION] ErrorCorrectionLevel.L //定义纠错等级hints[EncodeHintType.MARGIN] 1val qrCodeWriter QRCodeWriter()val bitMatrix qrCodeWriter.encode(dataStr, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints)val width bitMatrix.widthval height bitMatrix.heightvar tempHeight heightif (StringUtils.isNotBlank(bottomText)) {tempHeight tempHeight 12}val image BufferedImage(width, tempHeight, BufferedImage.TYPE_INT_RGB)for (x in 0 until width) {for (y in 0 until height) {image.setRGB(x, y, if (bitMatrix[x, y]) -0x1000000 else -0x1)}}// 判断是否添加logoif (url ! null) {insertLogoImage(image, url)}// 判断是否添加底部文字if (StringUtils.isNotBlank(bottomText)) {addFontImage(image, bottomText)}return image}/*** 插入logo图片** param source 二维码图片* throws Exception*/Throws(Exception::class)private fun insertLogoImage(source: BufferedImage, url: URL) {var src: Image ImageIO.read(url)val width LOGO_SIZEval height LOGO_SIZEval image src.getScaledInstance(width, height, Image.SCALE_SMOOTH)val tag BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)val g tag.graphicsg.drawImage(image, 0, 0, null) // 绘制缩小后的图g.dispose()src image// 插入LOGOval graph source.createGraphics()val x (QRCODE_SIZE - width) / 2val y (QRCODE_SIZE - height) / 2graph.drawImage(src, x, y, width, height, null)val shape: Shape RoundRectangle2D.Float(x.toFloat(), y.toFloat(), width.toFloat(), width.toFloat(), 6f, 6f)graph.stroke BasicStroke(3f)graph.draw(shape)graph.dispose()}private fun addFontImage(source: BufferedImage, declareText: String?) {//生成imageval defineWidth QRCODE_SIZEval defineHeight 20val textImage BufferedImage(defineWidth, defineHeight, BufferedImage.TYPE_INT_RGB)val g2 textImage.graphics as Graphics2D//开启文字抗锯齿g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)g2.background Color.WHITEg2.clearRect(0, 0, defineWidth, defineHeight)g2.paint Color.BLACKval context g2.fontRenderContext//部署linux需要注意 linux无此字体会显示方块val font Font(宋体, Font.BOLD, BOTTOM_TEXT_SIZE)g2.font fontval lineMetrics font.getLineMetrics(declareText, context)val fontMetrics: FontMetrics FontDesignMetrics.getMetrics(font)val offset ((defineWidth - fontMetrics.stringWidth(declareText)) / 2).toFloat()val y (defineHeight lineMetrics.ascent - lineMetrics.descent - lineMetrics.leading) / 2g2.drawString(declareText, offset.toInt(), y.toInt())val graph source.createGraphics()//开启文字抗锯齿graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)//添加imageval width textImage.getWidth(null)val height textImage.getHeight(null)val src: Image textImagegraph.drawImage(src, 0, QRCODE_SIZE - 8, width, height, Color.WHITE, null)graph.dispose()}
}