Java 生成二维码

使用springboot,实现生成二维码功能,本案例相比之前版本,在外观上更美,在功能上更多,支持自定义logo,title,description内容

依赖

        <!--二维码-->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.4.1</version>
        </dependency>
xml

请求调用

  @GetMapping("/qr-code")
    public void qrCodeText(@RequestParam("text") String text,@RequestParam(value = "logo",required = false) String logo,@RequestParam(value = "title",required = false) String title ,@RequestParam(value = "description",required = false) String description, HttpServletResponse response, HttpServletRequest request) {
        try{
            byte[] bytes = QrCodeUtils.encodeQRCode(text,logo,title,description);
            response.setContentType(QrCodeUtils.RESPONSE_CONTENT_TYPE);
            OutputStream stream = response.getOutputStream();
            stream.write(bytes);
            stream.flush();
        }catch (Exception e){
	    log.info("出错了");
        }
    }
java

二维码生成工具类(已优化)

package com.lb.upload.fileupload.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;
import sun.font.FontDesignMetrics;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

@Slf4j
public class QrCodeUtils {

    public static int QRCODE_SIZE = 512;
    private static int rowHeight;
    public static int rowCount;
    public static final String format = "png";
    public static final String RESPONSE_CONTENT_TYPE = "image/png";
    //默认logo本地
    //public static final String LOGO_PATH = "src/main/resources/logo.jpg";
    //默认logo远程
    public static final String LOGO_PATH = "https://files.hyz.cool/files/qr-code-config/logo.jpg";
    //默认logo服务端
    //public static final String LOGO_PATH = "home/ubuntu/app/files/jar/logo.jpg";
    //背景
    public static final String BACKGROUND = "https://files.hyz.cool/files/qr-code-config/background.png";

    public static byte[] encodeQRCode(String text, String logoUrl, String title, String description) {

        try {
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            //容错率越高,可存储的信息越少;但是对二维码清晰对要求越小
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            // 生成二维码
            BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
            //删除白边
            bitMatrix = deleteBorder(bitMatrix);
            BufferedImage bufferedImage = toBufferedImage(bitMatrix);
            //获取二维码小块儿边长
            rowHeight = getRowHeight(bufferedImage);
            //获取二维码行数
            rowCount = bufferedImage.getWidth() / rowHeight;
            //二维码圆角
            bufferedImage = roundType1QrCode(bufferedImage);
            //美化二维码
            bufferedImage = beautifyQrCode(bufferedImage);
            //设置logo
            bufferedImage = addImgLogo(bufferedImage, logoUrl);
            //添加title
            bufferedImage = addQRCodeTitle(bufferedImage, title);
            //添加description
            bufferedImage = addQRCodeDescription(bufferedImage, description);
            //添加边框
            bufferedImage = addPadding(bufferedImage);
            //转为透明背景
//            bufferedImage = transparent(bufferedImage);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, format, out);
            return out.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public static final int BORDER_WIDTH = 0;

    public static BitMatrix deleteBorder(BitMatrix matrix) {
        int[] rec = matrix.getEnclosingRectangle();

        int resWidth = rec[2] + BORDER_WIDTH;
        int resHeight = rec[3] + BORDER_WIDTH;
        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
        resMatrix.clear();
        for (int i = BORDER_WIDTH; i < resWidth; i++) {
            for (int j = BORDER_WIDTH; j < resHeight; j++) {
                if (matrix.get(i + rec[0], j + rec[1])) resMatrix.set(i, j);
            }
        }
        return resMatrix;
    }

    public static BufferedImage toBufferedImage(BitMatrix matrix) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
        int onColor = 0xFF000000;
        int offColor = 0x00ffffff;
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? onColor : offColor);
            }
        }
        return image;
    }

    private static BufferedImage roundType1QrCode(BufferedImage qr_code) {
        BufferedImage result = null;
        try {
            result = qr_code;
            int qr_codeWidth = result.getWidth();
            int qr_codeHeight = result.getHeight();
            Graphics2D graphics = result.createGraphics();
            //消除文字锯齿
            graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            //消除画图锯齿
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            graphics.drawImage(qr_code, 0, 0, qr_codeWidth, qr_codeHeight, null);

            //圆角1:内外角圆心相同
            int[][] list = {
                    //(列,行,角度/90)
                    {0, 0, 1}, {3, 0, 0}, {rowCount - 7, 0, 1}, {rowCount - 4, 0, 0},//第一行
                    {0, 3, 2}, {3, 3, 3}, {rowCount - 7, 3, 2}, {rowCount - 4, 3, 3},//第七行
                    {0, rowCount - 7, 1}, {3, rowCount - 7, 0},//倒数第一列
                    {0, rowCount - 4, 2}, {3, rowCount - 4, 3},//倒数第七列
            };
            for (int i = 0; i < list.length; i++) {
                graphics.setColor(Color.WHITE);
                graphics.fillRect((list[i][0] + (list[i][2] != 1 && list[i][2] != 2 ? 2 : 0)) * rowHeight, (list[i][1] + +(list[i][2] !=0 && list[i][2] != 1 ? 2 : 0)) * rowHeight, rowHeight * 2, rowHeight * 2);
                graphics.setColor(Color.BLACK);
                graphics.fillArc(
                        list[i][0] * rowHeight,
                        list[i][1] * rowHeight,
                        rowHeight * 4, rowHeight * 4,
                        list[i][2] * 90, 90);
                graphics.setColor(Color.WHITE);
                graphics.fillArc(
                        (list[i][0] + 1) * rowHeight,
                        (list[i][1] + 1) * rowHeight,
                        rowHeight * 2, rowHeight * 2,
                        list[i][2] * 90, 90);
            }
            int[][] list1 = {
                    {2, 2, 1}, {4, 2, 0}, {rowCount - 5, 2, 1}, {rowCount - 3, 2, 0},
                    {2, 4, 2}, {4, 4, 3}, {rowCount - 5, 4, 2}, {rowCount - 3, 4, 3},
                    {2, rowCount - 5, 1}, {4, rowCount - 5, 0},
                    {2, rowCount - 3, 2}, {4, rowCount - 3, 3},
            };
            for (int i = 0; i < list1.length; i++) {
                graphics.setColor(Color.WHITE);
                graphics.fillRect(list1[i][0] * rowHeight, list1[i][1] * rowHeight, rowHeight, rowHeight);
                graphics.setColor(new Color(14, 149, 228));
                graphics.fillArc(
                        (list1[i][0] - (list1[i][2] == 0 || list1[i][2] == 3 ? 1 : 0)) * rowHeight,
                        (list1[i][1] - (list1[i][2] > 1 ? 1 : 0)) * rowHeight,
                        rowHeight * 2, rowHeight * 2,
                        list1[i][2] * 90, 90);
            }
            int[][] list2 = {
                    {3, 2}, {rowCount - 4, 2},
                    {2, 3}, {3, 3}, {4, 3}, {rowCount - 3, 3}, {rowCount - 4, 3}, {rowCount - 5, 3},
                    {3, 4}, {rowCount - 4, 4},
                    {3, rowCount - 5},
                    {2, rowCount - 4}, {3, rowCount - 4}, {4, rowCount - 4},
                    {3, rowCount - 3},
            };
            graphics.setColor(new Color(14, 149, 228));
            for (int i = 0; i < list2.length; i++) {
                graphics.fillRect(list2[i][0] * rowHeight, list2[i][1] * rowHeight, rowHeight, rowHeight);
            }

            graphics.dispose();
            result.flush();
        } catch (
                Exception e) {
            log.info("二维码美化失败");
        }
        return result;
    }


    private static BufferedImage roundType2QrCode(BufferedImage qr_code) {
        BufferedImage result = null;
        try {
            result = qr_code;
            int qr_codeWidth = result.getWidth();
            int qr_codeHeight = result.getHeight();
            Graphics2D graphics = result.createGraphics();
            //消除文字锯齿
            graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            //消除画图锯齿
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            graphics.drawImage(qr_code, 0, 0, qr_codeWidth, qr_codeHeight, null);

            //圆角2:内外角完全相同
            int[][] list0 = {
                    //(列,行,角度/90)
                    {0, 0, 1}, {6, 0, 0}, {rowCount - 7, 0, 1}, {rowCount - 1, 0, 0},//第一行
                    //   {2, 2, 1}, {4, 2, 0}, {rowCount - 5, 2, 1}, {rowCount - 3, 2, 0},//第三行
                    //   {2, 4, 2}, {4, 4, 3}, {rowCount - 5, 4, 2}, {rowCount - 3, 4, 3},//第五行
                    {0, 6, 2}, {6, 6, 3}, {rowCount - 7, 6, 2}, {rowCount - 1, 6, 3},//第七行
                    {0, rowCount - 7, 1}, {6, rowCount - 7, 0},//倒数第一列
                    //   {2, rowCount - 5, 1}, {4, rowCount - 5, 0},//倒数第三列
                    //   {2, rowCount - 3, 2}, {4, rowCount - 3, 3},//倒数第五列
                    {0, rowCount - 1, 2}, {6, rowCount - 1, 3},//倒数第七列
            };
            for (int i = 0; i < list0.length; i++) {
                graphics.setColor(Color.WHITE);
                graphics.fillRect(list0[i][0] * rowHeight, list0[i][1] * rowHeight, rowHeight, rowHeight);
                graphics.setColor(Color.BLACK);
                graphics.fillArc(
                        (list0[i][0] - (list0[i][2] == 0 || list0[i][2] == 3 ? 1 : 0)) * rowHeight,
                        (list0[i][1] - (list0[i][2] > 1 ? 1 : 0)) * rowHeight,
                        rowHeight * 2, rowHeight * 2,
                        list0[i][2] * 90, 90);
            }
            int[][] list1 = {
                    {2, 2, 1}, {4, 2, 0}, {rowCount - 5, 2, 1}, {rowCount - 3, 2, 0},
                    {2, 4, 2}, {4, 4, 3}, {rowCount - 5, 4, 2}, {rowCount - 3, 4, 3},
                    {2, rowCount - 5, 1}, {4, rowCount - 5, 0},
                    {2, rowCount - 3, 2}, {4, rowCount - 3, 3},
            };
            for (int i = 0; i < list1.length; i++) {
                graphics.setColor(Color.WHITE);
                graphics.fillRect(list1[i][0] * rowHeight, list1[i][1] * rowHeight, rowHeight, rowHeight);
                graphics.setColor(new Color(14, 149, 228));
                graphics.fillArc(
                        (list1[i][0] - (list1[i][2] == 0 || list1[i][2] == 3 ? 1 : 0)) * rowHeight,
                        (list1[i][1] - (list1[i][2] > 1 ? 1 : 0)) * rowHeight,
                        rowHeight * 2, rowHeight * 2,
                        list1[i][2] * 90, 90);
            }
            int[][] list2 = {
                    {3, 2}, {rowCount - 4, 2},
                    {2, 3}, {3, 3}, {4, 3}, {rowCount - 3, 3}, {rowCount - 4, 3}, {rowCount - 5, 3},
                    {3, 4}, {rowCount - 4, 4},
                    {3, rowCount - 5},
                    {2, rowCount - 4}, {3, rowCount - 4}, {4, rowCount - 4},
                    {3, rowCount - 3},
            };
            graphics.setColor(new Color(14, 149, 228));
            for (int i = 0; i < list2.length; i++) {
                graphics.fillRect(list2[i][0] * rowHeight, list2[i][1] * rowHeight, rowHeight, rowHeight);
            }

            int[][] list3 = {
                    {1, 1, 1}, {5, 1, 0}, {rowCount - 6, 1, 1}, {rowCount - 2, 1, 0},
                    {1, 5, 2}, {5, 5, 3}, {rowCount - 6, 5, 2}, {rowCount - 2, 5, 3},
                    {1, rowCount - 6, 1}, {5, rowCount - 6, 0},
                    {1, rowCount - 2, 2}, {5, rowCount - 2, 3},
            };
            for (int i = 0; i < list3.length; i++) {
                graphics.setColor(Color.BLACK);
                graphics.fillRect(list3[i][0] * rowHeight, list3[i][1] * rowHeight, rowHeight, rowHeight);
                graphics.setColor(Color.WHITE);
                graphics.fillArc(
                        (list3[i][0] - (list3[i][2] == 0 || list3[i][2] == 3 ? 1 : 0)) * rowHeight,
                        (list3[i][1] - (list3[i][2] > 1 ? 1 : 0)) * rowHeight,
                        rowHeight * 2, rowHeight * 2,
                        list3[i][2] * 90, 90);
            }
            graphics.dispose();
            result.flush();
        } catch (
                Exception e) {
            log.info("二维码美化失败");
        }
        return result;
    }


    private static BufferedImage beautifyQrCode(BufferedImage qr_code) {
        BufferedImage result = null;
        try {
            int qr_codeWidth = qr_code.getWidth();
            int qr_codeHeight = qr_code.getHeight();

            result = new BufferedImage(qr_codeWidth + rowHeight * 8, qr_codeHeight + rowHeight * 8, BufferedImage.TYPE_4BYTE_ABGR);
            Graphics2D graphics = result.createGraphics();
            //消除文字锯齿
            graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            //消除画图锯齿
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            graphics.setColor(Color.WHITE);
            graphics.fillRect(0, 0, qr_codeWidth + rowHeight * 8, qr_codeHeight + rowHeight * 8);
            graphics.drawImage(qr_code, rowHeight * 4, rowHeight * 4, qr_codeWidth, qr_codeHeight, null);

            graphics.setColor(new Color(14, 149, 228));
            int[][] list0 = {
                    {4, 5, 0},
                    {rowCount + 8 - 9, 5, 0},
                    {4, 5, rowCount + 8 - 1},
                    {rowCount + 8 - 9, 5, rowCount + 8 - 1}

            };
            for (int i = 0; i < list0.length; i++) {
                graphics.fillRect(
                        list0[i][0] * rowHeight,
                        list0[i][2] * rowHeight,
                        rowHeight * list0[i][1],
                        rowHeight);
                graphics.fillRect(
                        list0[i][2] * rowHeight,
                        list0[i][0] * rowHeight,
                        rowHeight,
                        rowHeight * list0[i][1]);
            }

            int[][] list1 = {
                    //(列,行,角度/90)
                    {0, 0, 1},//左上角
                    {rowCount, 0, 0},//右上角
                    {0, rowCount, 2},//左下角
                    {rowCount, rowCount, 3},
            };
            for (int i = 0; i < list1.length; i++) {
                graphics.setColor(new Color(14, 149, 228));
                graphics.fillArc(
                        list1[i][0] * rowHeight,
                        list1[i][1] * rowHeight,
                        rowHeight * 8, rowHeight * 8,
                        list1[i][2] * 90, 90);
                graphics.setColor(Color.WHITE);
                graphics.fillArc(
                        (list1[i][0] + 1) * rowHeight,
                        (list1[i][1] + 1) * rowHeight,
                        rowHeight * 6, rowHeight * 6,
                        list1[i][2] * 90, 90);
            }
            graphics.dispose();
            result.flush();
        } catch (
                Exception e) {
            log.info("二维码美化失败");
        }
        return result;
    }


    public static BufferedImage addImgLogo(BufferedImage qr_img, String logoUrl) {
        logoUrl = logoUrl != null && logoUrl != "" ? logoUrl : LOGO_PATH;
        BufferedImage result = null;
        try {
            //读取logo图片
            BufferedImage logo = ImageIO.read(new URL(logoUrl));
            //读取二维码图片
            result = qr_img;
            //获取画笔
            Graphics2D graphics = result.createGraphics();
            //消除文字锯齿
            graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            //消除画图锯齿
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            //设置二维码大小,太大,会覆盖二维码,此处1/6
            int logoWidth = logo.getWidth(null) > result.getWidth() / 6 ? (result.getWidth() / 6) : logo.getWidth(null);
            int logoHeight = logo.getHeight(null) > result.getHeight() / 6 ? (result.getHeight() / 6) : logo.getHeight(null);
            // 确定二维码的中心位置坐标,设置logo图片放置的位置
            int x = (result.getWidth() - logoWidth) / 2;
            int y = (result.getHeight() - logoHeight) / 2;
            //开始合并绘制图片
            //圆角logo
            //BufferedImage bufferedImage = setRadius(logo, logoWidth, 0, 0);
            //圆形logo
            BufferedImage bufferedImage = getRoundImg(logo);
            //绘制logo
            graphics.drawImage(bufferedImage, x, y, logoWidth, logoHeight, null);
            //设置logo边框大小
            //graphics.setStroke(new BasicStroke(5));
            //设置logo边框颜色
            //graphics.setColor(Color.WHITE);
            //graphics.drawRect(x, y, logoWidth, logoHeight);
            graphics.dispose();
            logo.flush();
            result.flush();

        } catch (Exception e) {
            log.info("二维码绘制logo失败");
        }
        return result;
    }

    public static BufferedImage addQRCodeTitle(BufferedImage qr_img, String title) {
        if (title == null || title.equals("")) return qr_img;
        BufferedImage result = null;
        try {
            result = drawTextLines(qr_img, title, 40, true);
        } catch (Exception e) {
            log.info("二维码绘制标题失败");
        }
        return result;
    }

    public static BufferedImage addQRCodeDescription(BufferedImage qr_img, String description) {
        if (description == null || description.equals("")) return qr_img;
        BufferedImage result = null;
        try {
            result = drawTextLines(qr_img, description, 25, false);
        } catch (Exception e) {
            log.info("二维码绘制描述失败");
        }
        return result;
    }


    private static BufferedImage addPadding(BufferedImage bufferedImage) {
        BufferedImage result = null;
        try {
            int border = 150;
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            result = new BufferedImage(width + border, height+border, BufferedImage.TYPE_4BYTE_ABGR);
            Graphics2D graphics = result.createGraphics();
            //消除文字锯齿
            graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            //消除画图锯齿
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            graphics.setColor(Color.WHITE);
            graphics.fillRect(0, 0, width + border, height+ border);
            graphics.drawImage(bufferedImage, border / 2, border / 2, width, height, null);
            graphics.dispose();
            result.flush();
        } catch (Exception e) {
            log.info("二维码绘制边框失败");
        }
        return result;
    }


    public static BufferedImage transparent(BufferedImage QrImg) {
        BufferedImage image = QrImg;
        ImageIcon imageIcon = new ImageIcon(image);
        BufferedImage bufferedImage = new BufferedImage(
                imageIcon.getIconWidth(), imageIcon.getIconHeight(),
                BufferedImage.TYPE_4BYTE_ABGR);

        Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics();
        //消除文字锯齿
        g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //消除画图锯齿
        g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2D.drawImage(imageIcon.getImage(), 0, 0,
                imageIcon.getImageObserver());
        int alpha = 0;
        for (int j1 = bufferedImage.getMinY(); j1 < bufferedImage
                .getHeight(); j1++) {
            for (int j2 = bufferedImage.getMinX(); j2 < bufferedImage
                    .getWidth(); j2++) {
                int rgb = bufferedImage.getRGB(j2, j1);
                if (colorInRange(rgb))
                    alpha = 0;
                else
                    alpha = 255;
                rgb = (alpha << 24) | (rgb & 0x00ffffff);
                bufferedImage.setRGB(j2, j1, rgb);
            }
        }
        g2D.drawImage(bufferedImage, 0, 0, imageIcon.getImageObserver());
        return bufferedImage;
    }

    public static boolean colorInRange(int color) {
        int red = (color & 0xff0000) >> 16;
        int green = (color & 0x00ff00) >> 8;
        int blue = (color & 0x0000ff);
        if (red >= color_range && green >= color_range && blue >= color_range)
            return true;
        return false;
    }

    public static int color_range = 210;
    public static Pattern pattern = Pattern.compile("[0-9]*");

    public static boolean isNo(String str) {
        return pattern.matcher(str).matches();
    }

    /**
     * 图片设置圆角
     *
     * @param srcImage
     * @param radius
     * @param border
     * @param padding
     * @return
     * @throws IOException
     */
    public static BufferedImage setRadius(BufferedImage srcImage, int radius, int border, int padding) throws IOException {
        int width = srcImage.getWidth();
        int height = srcImage.getHeight();
        int canvasWidth = width + padding * 2;
        int canvasHeight = height + padding * 2;

        BufferedImage image = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = image.createGraphics();
        //消除文字锯齿
        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //消除画图锯齿
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics.setComposite(AlphaComposite.Src);
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics.setColor(Color.WHITE);
        graphics.fill(new RoundRectangle2D.Float(0, 0, canvasWidth, canvasHeight, radius, radius));
        graphics.setComposite(AlphaComposite.SrcAtop);
        graphics.drawImage(setClip(srcImage, radius), padding, padding, null);
        if (border != 0) {
            graphics.setColor(Color.GRAY);
            graphics.setStroke(new BasicStroke(border));
            graphics.drawRoundRect(padding, padding, canvasWidth - 2 * padding, canvasHeight - 2 * padding, radius, radius);
        }
        graphics.dispose();
        return image;
    }

    /**
     * 图片设置圆角
     *
     * @param srcImage
     * @return
     * @throws IOException
     */
    public static BufferedImage setRadius(BufferedImage srcImage) throws IOException {
        int radius = (srcImage.getWidth() + srcImage.getHeight()) / 6;
        return setRadius(srcImage, radius, 2, 5);
    }

    /**
     * 图片切圆角
     *
     * @param srcImage
     * @param radius
     * @return
     */
    public static BufferedImage setClip(BufferedImage srcImage, int radius) {
        int width = srcImage.getWidth();
        int height = srcImage.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = image.createGraphics();
        //消除文字锯齿
        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //消除画图锯齿
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics.setClip(new RoundRectangle2D.Double(0, 0, width, height, radius, radius));
        graphics.drawImage(srcImage, 0, 0, null);
        graphics.dispose();
        return image;
    }

    public static BufferedImage getRoundImg(BufferedImage avatarImage) throws Exception {
        int width = avatarImage.getWidth();
        // 透明底的图片
        BufferedImage formatAvatarImage = new BufferedImage(width, width, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D graphics = formatAvatarImage.createGraphics();
        //消除画图锯齿
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        //把图片切成一个圓
        //留一个像素的空白区域,这个很重要,画圆的时候把这个覆盖
        int border = 10;
        //图片是一个圆型
        Ellipse2D.Double shape = new Ellipse2D.Double(border, border, width - border * 2, width - border * 2);
        //需要保留的区域
        graphics.setClip(shape);
        graphics.drawImage(avatarImage, border, border, width - border * 2, width - border * 2, null);
        graphics.dispose();
        //在圆图外面再画一个圆
        //新创建一个graphics,这样画的圆不会有锯齿
        graphics = formatAvatarImage.createGraphics();
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        //画笔是4.5个像素,BasicStroke的使用可以查看下面的参考文档
        //使画笔时基本会像外延伸一定像素,具体可以自己使用的时候测试
        Stroke s = new BasicStroke(4.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        graphics.setStroke(s);
        graphics.setColor(Color.WHITE);
        graphics.drawOval(border, border, width - border * 2, width - border * 2);
        graphics.dispose();
        return formatAvatarImage;
    }

    private static BufferedImage drawTextLines(BufferedImage qr_img, String content, int fontSize, boolean top) {
        //设置字体字号
        Font font = new Font("微软雅黑", Font.PLAIN, fontSize);
        FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
        int height = metrics.getHeight();//计算高
        int qr_imgWidth = qr_img.getWidth();
        int qr_imgHeight = qr_img.getHeight();
        java.util.List<String> textLines = getTextLines(qr_imgWidth, font, content);
        int textViewHeight = height * (2 + textLines.size());
        int graphics_height = qr_imgHeight + textViewHeight;
        BufferedImage result = new BufferedImage(qr_imgWidth, graphics_height, BufferedImage.TYPE_INT_BGR);
        Graphics2D graphics = result.createGraphics();
        //消除文字锯齿
        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //消除画图锯齿
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        //设置文字
        Color color = new Color(0, 0, 0);
        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
        //设置背影为白色
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, qr_imgWidth, graphics_height);
        graphics.setFont(font);
        graphics.setColor(color);
        for (int i = 0; i < textLines.size(); i++) {
            String text = textLines.get(i);
            int width = getWordWidth(font, text);//计算图片的宽
            graphics.drawString(text, (qr_imgWidth - width) / 2, (top ? 0 : qr_imgHeight) + height * (2 + i));//图片上写文字
        }
        graphics.drawImage(qr_img, 0, top ? textViewHeight : 0, qr_imgWidth, qr_imgHeight, null);
        graphics.dispose();
        result.flush();
        return result;
    }

    private static List<String> getTextLines(int qr_imgWidth, Font font, String content) {
        int contentWidth = getWordWidth(font, content);
        int size = contentWidth / qr_imgWidth + 1;
        int length = content.length() / size;
        java.util.List<String> textLines = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            if (i + 1 == size)
                textLines.add(content.substring(length * i));
            else
                textLines.add(content.substring(length * i, length * (i + 1)));
        }
        return textLines;
    }

    public static int getWordWidth(Font font, String content) {
        FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
        int width = 0;
        for (int i = 0; i < content.length(); i++) {
            width += metrics.charWidth(content.charAt(i));
        }
        return width;
    }

    private static int getRowHeight(BufferedImage result) {
        int RowHeight = 0;
        for (int pos = 0; pos < result.getWidth(); pos++) {
            int rgb = result.getRGB(pos, pos);
            String s = Integer.toHexString(rgb);
	    // log.info("rgb"+rgb);
	    // log.info(" Integer.toHexString(rgb);"+ Integer.toHexString(rgb));
            if (rgb > 0) {
                RowHeight = pos;
                break;
            }
        }
        return RowHeight;
    }

}
java

注:部分实现参考互联网分享,仅供学习

打赏
  • 微信
  • 支付宝
评论
来发评论吧~
···

歌手: