feiyu02
2024-08-15 196bb14112448857a885e32dc4149e308e00b01a
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package cn.flightfeather.supervision.common.creditcode
 
import cn.flightfeather.supervision.infrastructure.utils.QRCodeUtil
import java.awt.Color
import java.awt.Font
import java.awt.image.BufferedImage
import java.io.*
import javax.imageio.IIOImage
import javax.imageio.ImageIO
import javax.imageio.ImageTypeSpecifier
import javax.imageio.metadata.IIOInvalidTreeException
import javax.imageio.metadata.IIOMetadata
import javax.imageio.metadata.IIOMetadataNode
import javax.imageio.stream.ImageOutputStream
 
/**
 * 环信码生成工具
 */
object EnvCreditCode {
 
    val templatePath =
        (Thread.currentThread().contextClassLoader?.getResource("/")?.path ?: "src/main/resources") + "/templates/"
    val templateName = "qr_code_bg.png"
 
    fun createImage(userId: String, userName: String, company: String?, supply: String?, os: OutputStream) {
        // 确定图片宽高以及二维码的宽度
        val bgWidth = 1181
        val bgHeight = 1654
        val qrCodeWidth = 440
 
        // 生成二维码图片
        val baseUrl = "http://47.100.191.150/ledger/page/qrcode.html"
        val url = "$baseUrl?id=${userId}"
        val qrCode = QRCodeUtil.createQRCodeBitmap2(url, userName, qrCodeWidth, qrCodeWidth)
 
        // 生成画布
        val bg = ImageIO.read(FileInputStream(templatePath + templateName))
        val source = BufferedImage(bgWidth, bgHeight, BufferedImage.TYPE_INT_RGB)
 
 
//        val f1 = Font("思源黑体 CN Medium", Font.PLAIN, 40)
        val font = Font("微软雅黑", Font.PLAIN, 40)
 
        val graphics2D = source.graphics
 
        // 绘制二维码底图
        graphics2D.drawImage(bg, 0, 0) { _, _, _, _, _, _ ->
            true
        }
 
        // 绘制顶部居中的场景名称(x坐标根据文本长度动态计算,y坐标根据设计方案直接定位)
        graphics2D.font = font
        graphics2D.color = Color.BLACK
        val w1 = graphics2D.fontMetrics.stringWidth(userName)
        val x1 = (bgWidth - w1) / 2
        graphics2D.drawString(userName, x1, 160 + graphics2D.fontMetrics.ascent)
 
        // 绘制场景名称下方居中的所属企业名称(x坐标根据文本长度动态计算,y坐标根据设计方案直接定位)
        val c = company ?: ""
        graphics2D.font = font
        val w2 = graphics2D.fontMetrics.stringWidth(c)
        val x2 = (bgWidth - w2) / 2
        graphics2D.drawString(c, x2, 250 + graphics2D.fontMetrics.ascent)
 
        // 绘制中心的二维码图片(x坐标根据文本长度动态计算,y坐标根据设计方案直接定位)
        val x3 = (bgWidth - qrCodeWidth) / 2
        graphics2D.drawImage(qrCode, x3, 410) { img, infoflags, x, y, width, height ->
            true
        }
 
        // 绘制支持提供方
        val s = supply ?: ""
        graphics2D.font = Font("微软雅黑", Font.PLAIN, 30)
        val w4 = graphics2D.fontMetrics.stringWidth(s)
        val x4 = (bgWidth - w4) / 2
        graphics2D.drawString(s, x4, 753 + graphics2D.fontMetrics.ascent)
 
        val a = ImageIO.getImageWritersByFormatName("png")
        while (a.hasNext()) {
            val iw = a.next()
            val writeParam = iw.defaultWriteParam
            val typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB)
            val metadata = iw.getDefaultImageMetadata(typeSpecifier, writeParam)
            if (metadata.isReadOnly || !metadata.isStandardMetadataFormatSupported) {
                continue
            }
 
            setDPI(metadata)
 
            val stream = ImageIO.createImageOutputStream(os)
//            val stream = ImageIO.createImageOutputStream(output)
//            val stream = ImageIO.createImageOutputStream(File("C:/tools/${userName}.png"))
            stream.use {
                iw.output = it
                iw.write(metadata, IIOImage(source, null, metadata), writeParam)
            }
            break
        }
//        ImageIO.write(source, "png", File("E:/qrcode/${it.second}.png"))
    }
 
    @Throws(IIOInvalidTreeException::class)
    private fun setDPI(metadata: IIOMetadata) {
 
        // for PMG, it's dots per millimeter
        val dotsPerMilli = 1.0 * 300 / 10 / 2.54
 
        val horiz = IIOMetadataNode("HorizontalPixelSize")
        horiz.setAttribute("value", java.lang.Double.toString(dotsPerMilli))
 
        val vert = IIOMetadataNode("VerticalPixelSize")
        vert.setAttribute("value", java.lang.Double.toString(dotsPerMilli))
 
        val dim = IIOMetadataNode("Dimension")
        dim.appendChild(horiz)
        dim.appendChild(vert)
 
        val root = IIOMetadataNode("javax_imageio_1.0")
        root.appendChild(dim)
 
        metadata.mergeTree("javax_imageio_1.0", root)
    }
}