package com.scamel.mom.common.util; import cn.hutool.core.io.resource.ClassPathResource; import com.alibaba.nacos.common.utils.StringUtils; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import sun.font.FontDesignMetrics; import javax.imageio.ImageIO; import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; import java.awt.geom.AffineTransform; import java.awt.geom.RoundRectangle2D; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * QR code, barcode generation tool */ public class CodeUtils {<!-- --> /** * the width of the center image */ private static final int IMAGE_WIDTH = 80; private static final int IMAGE_HEIGHT = 80; private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH / 2; private static final int FRAME_WIDTH = 2; /** * Times New Roman */ private static Font fontSun; /* Statically load fonts (linux does not have Chinese fonts, it will display 口口口) */ static {<!-- --> try {<!-- --> ClassPathResource fontResource = new ClassPathResource("font/simsun.ttc"); Font font = Font.createFont(Font.TRUETYPE_FONT, fontResource.getStream()); fontSun = font. deriveFont(Font. BOLD, 15); } catch (Exception e) {<!-- --> e.printStackTrace(); } } /** * Generate QR code * * @param content QR code content * @return image * @throws WriterException exception */ public static BufferedImage createQRImage(String content) throws WriterException {<!-- --> // QR code parameter setting Map<EncodeHintType, Object> hints = new HashMap<>(); // security level, the highest h hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // encoding settings hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); // set margin=0-10 hints. put(EncodeHintType. MARGIN, 1); // create matrix container BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, 300, 300, hints); int width = bitMatrix. getWidth(); int height = bitMatrix. getHeight(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // matrix transform image for (int x = 0; x < width; x ++ ) {<!-- --> for (int y = 0; y < height; y ++ ) {<!-- --> image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); } } return image; } /** * Generate a QR code with text at the bottom of the picture inserted in the center * * @param content QR code content * @param description Bottom description text * @return the picture to be inserted * @throws WriterException exception */ public static BufferedImage createQRImageWithPic(String content, String description, String srcImagePath) throws WriterException, IOException {<!-- --> BufferedImage bufferedImage = genBarcode(content, description, 300, 300, srcImagePath); // Determine whether to add bottom text if (StringUtils. hasText(description)) {<!-- --> addText(bufferedImage, description, 300); } return bufferedImage; } /** * Add text at the bottom of the QR code * * @param source source QR code image * @param description Bottom description text */ private static void addText(BufferedImage source, String description, int qrWidth) {<!-- --> //Generate image int defineHeight = 20; BufferedImage textImage = new BufferedImage(qrWidth, defineHeight, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = (Graphics2D) textImage. getGraphics(); //Enable text anti-aliasing g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2.setBackground(Color.WHITE); g2. clearRect(0, 0, qrWidth, defineHeight); g2.setPaint(Color.BLACK); FontRenderContext context = g2. getFontRenderContext(); g2.setFont(fontSun); LineMetrics lineMetrics = fontSun. getLineMetrics(description, context); FontMetrics fontMetrics = FontDesignMetrics. getMetrics(fontSun); float offset = (qrWidth - fontMetrics. stringWidth(description)) / 2; float y = (defineHeight + lineMetrics.getAscent() - lineMetrics.getDescent() - lineMetrics.getLeading()) / 2; g2.drawString(description, (int) offset, (int) y); Graphics2D graph = source. createGraphics(); //Enable text anti-aliasing graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); //add image int width = textImage. getWidth(null); int height = textImage. getHeight(null); graph.drawImage(textImage, 0, qrWidth - 8, width, height, Color.WHITE, null); graph.dispose(); } /** * Generate a QR code and insert a picture in the center * * @param content QR code content * @param description Bottom description text * @param width QR code width * @param height QR code height * @param srcImagePath original image * @return * @throws WriterException * @throws IOException */ private static BufferedImage genBarcode(String content, String description, int width, int height, String srcImagePath) throws WriterException, IOException {<!-- --> // There is text, height + 12, otherwise the text at the bottom will not be fully displayed if (StringUtils. hasText(description)) {<!-- --> height = height + 12; } // read source image and scale BufferedImage scaleImage = scale(srcImagePath, IMAGE_WIDTH, IMAGE_HEIGHT, false); int[][] srcPixels = new int[IMAGE_WIDTH][IMAGE_HEIGHT]; for (int i = 0; i < scaleImage.getWidth(); i ++ ) {<!-- --> for (int j = 0; j < scaleImage.getHeight(); j ++ ) {<!-- --> srcPixels[i][j] = scaleImage.getRGB(i, j); } } // QR code parameter setting Map<EncodeHintType, Object> hints = new HashMap<>(); // security level, the highest h hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // encoding settings hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); // set margin=0-10 hints. put(EncodeHintType. MARGIN, 1); // create matrix container BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints); // Convert two-dimensional matrix to one-dimensional pixel array int halfW = bitMatrix. getWidth() / 2; int halfH = bitMatrix. getHeight() / 2; int[] pixels = new int[width * height]; for (int y = 0; y < bitMatrix. getHeight(); y ++ ) {<!-- --> for (int x = 0; x < bitMatrix.getWidth(); x ++ ) {<!-- --> // read the image if (x > halfW - IMAGE_HALF_WIDTH & amp; & amp; x < halfW + IMAGE_HALF_WIDTH & amp; & amp; y > halfH - IMAGE_HALF_WIDTH & amp; & amp; y < halfH + IMAGE_HALF_WIDTH) {<!-- --> pixels[y * width + x] = srcPixels[x - halfW + IMAGE_HALF_WIDTH][y - halfH + IMAGE_HALF_WIDTH]; } else if ( // Form a border around the image (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH & amp; & amp; x < halfW - IMAGE_HALF_WIDTH + FRAME_WIDTH & amp; & amp; y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH & amp; & amp; y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH) || (x > halfW + IMAGE_HALF_WIDTH - FRAME_WIDTH & amp; & amp; x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH & amp; & amp; y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH & amp; & amp; y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH) || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH & amp; & amp; x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH & amp; & amp; y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH & amp; & amp; y < halfH - IMAGE_HALF_WIDTH + FRAME_WIDTH) || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH & amp; & amp; x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH & amp; & amp; y > halfH + IMAGE_HALF_WIDTH - FRAME_WIDTH & amp; & amp; y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)) {<!-- --> pixels[y * width + x] = 0xfffffff; } else {<!-- --> // The color of the QR code can be modified here, and the color of the QR code and the background can be specified separately; pixels[y * width + x] = bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF; } } } BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); image.getRaster().setDataElements(0, 0, width, height, pixels); return image; } /** * Scale the incoming original image according to height and width to generate an icon that meets the requirements * * @param srcImageFile source file address * @param height target height * @param width target width * @param hasFiller Whether filling is required when the ratio is wrong: true is filling; false is not filling; * @throws IOException */ private static BufferedImage scale(String srcImageFile, int height, int width, boolean hasFiller) throws IOException {<!-- --> // scaling ratio double ratio; File file = new File(srcImageFile); BufferedImage srcImage = ImageIO. read(file); Image destImage = srcImage.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH); // calculate ratio if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {<!-- --> if (srcImage.getHeight() > srcImage.getWidth()) {<!-- --> ratio = (new Integer(height)). doubleValue() / srcImage.getHeight(); } else {<!-- --> ratio = (new Integer(width)). doubleValue() / srcImage.getWidth(); } AffineTransformOp op = new AffineTransformOp( AffineTransform. getScaleInstance(ratio, ratio), null); destImage = op. filter(srcImage, null); } if (hasFiller) {<!-- --> BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D graphic = image. createGraphics(); graphic.setColor(Color.PINK); graphic. fillRect(10, 10, width, height); graphic. drawRect(100, 360, width, height); if (width == destImage.getWidth(null)) {<!-- --> graphic.drawImage(destImage, 0, (height - destImage. getHeight(null)) / 2, destImage.getWidth(null), destImage.getHeight(null), Color. white, null); Shape shape = new RoundRectangle2D. Float(0, (height - destImage. getHeight(null)) / 2, width, width, 20, 20); graphic.setStroke(new BasicStroke(5f)); graphic. draw(shape); } else {<!-- --> graphic.drawImage(destImage, (width - destImage.getWidth(null)) / 2, 0, destImage.getWidth(null), destImage.getHeight(null), Color. white, null); Shape shape = new RoundRectangle2D. Float((width - destImage. getWidth(null)) / 2, 0, width, width, 20, 20); graphic.setStroke(new BasicStroke(5f)); graphic. draw(shape); } graphic.dispose(); destImage = image; } return (BufferedImage) destImage; } public static void main(String[] args) {<!-- --> try {<!-- --> String content = "Nintendo is the pig of the world"; BufferedImage image = genBarcode(content, content, 300, 300, "D://QR code//Nintendo is the world's piglet-s.jpg"); // Determine whether to add bottom text if (StringUtils.hasText(content)) {<!-- --> addText(image, content, 300); } if (!ImageIO.write(image, "jpg", new File("D://QR code//test.jpg"))) {<!-- --> throw new IOException("Could not write an image of format "); } } catch (WriterException | IOException e) {<!-- --> e.printStackTrace(); } } }