海报生成方案一 Java Graphics2D 海报生成 设置图片切圆 ,图片生成工具

本文介绍了一个用于生成海报图片的工具类,包括圆形和圆角图片处理、海报合成等功能,适用于活动宣传海报的自动化制作。
部署运行你感兴趣的模型镜像
package com.hkb.soulaud.tools;

import com.hkb.soulaud.pojo.ActivityPlayerPoster;
import com.hkb.soulaud.pojo.ActivityPoster;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author lime
 * @Description
 * @Date 10:41 2020/3/31
 * @Modified by 海报图片生成工具
 */
@Slf4j
public class PosterImageTools {
    public static BufferedImage circle(BufferedImage avatarImage) throws IOException {
        int width = 90;
        // 透明底的图片
        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 = 1;
            //图片是一个圆型
            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);
            int border = 3;
            //画笔是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;
    }


    /**
     * 传入的图像必须是正方形的 才会 圆形 如果是长方形的比例则会变成椭圆的
     * <p>
     * 用户头像地址
     *
     * @return
     * @throws IOException
     */
    public static BufferedImage convertCircular(BufferedImage bi1) throws IOException {
        BufferedImage formatAvatarImage = new BufferedImage(bi1.getWidth() + 10, bi1.getHeight() + 10, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D graphics = formatAvatarImage.createGraphics();

        BufferedImage bi2 = new BufferedImage(bi1.getWidth(), bi1.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
        Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, bi1.getWidth(), bi1.getHeight());
        Graphics2D g2 = bi2.createGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.setClip(shape);
        // 使用 setRenderingHint 设置抗锯齿
        g2.drawImage(bi1, 0, 0, null);
        // 设置颜色
        g2.setBackground(Color.green);
        g2.dispose();

        int border = 3;
        //画笔是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, (bi1.getWidth() + 10) - border * 2, (bi1.getWidth() + 10) - border * 2);
        graphics.dispose();

        return bi2;
    }

    public static void playerPoster(ActivityPlayerPoster poster) throws IOException {
        BufferedImage bgImage = fileToBufferedImage(poster.getBgPath());
        BufferedImage qrImage = fileToBufferedImage(poster.getQrUrl());
        BufferedImage playerImage = fileToBufferedImage(poster.getCoverPath());
        playerImage = circle(playerImage);

        Graphics2D graphics2D = bgImage.createGraphics();
        //消除锯齿
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //在背景上绘制二维码
        graphics2D.drawImage(qrImage, 36, 294, 56, 56, null);
        //在背景上绘制选手头像
        graphics2D.drawImage(playerImage, 90, 115, 90, 90, null);

        Font font = new Font("SourceHanSerifCN-Bold", Font.PLAIN, 10);
        //绘制编号
        graphics2D.setFont(font);


        //正文颜色
        graphics2D.setPaint(new Color(255, 255, 255));
        graphics2D.drawString("编号:" + poster.getNumber(), 197, 32);
        //绘制活动标题
        Font title1Font = new Font("SourceHanSerifCN-Bold", Font.PLAIN, 14);
        graphics2D.setFont(title1Font);
        graphics2D.setPaint(new Color(255, 191, 0));
        //计算居中
        FontMetrics fm = graphics2D.getFontMetrics(title1Font);
        int title1Center = (bgImage.getWidth() - fm.stringWidth(poster.getTitle1())) / 2;
        graphics2D.drawString(poster.getTitle1(), title1Center, 70);
        graphics2D.setPaint(new Color(255, 191, 0));
        int title2Center = (bgImage.getWidth() - fm.stringWidth(poster.getTitle2())) / 2;
        graphics2D.drawString(poster.getTitle2(), title2Center, 90);
        //绘制选手名称
        graphics2D.setPaint(new Color(255, 255, 255));
        Font playerNameFont = new Font("SourceHanSerifCN-Bold", Font.PLAIN, 12);
        graphics2D.setFont(playerNameFont);
        graphics2D.drawString("选手名称:" + poster.getPlayerName(), 36, 240);
        graphics2D.setPaint(new Color(255, 255, 255));
        //绘制机构名称
        graphics2D.drawString("单位机构:" + poster.getMechanismName(), 36, 260);
        graphics2D.setPaint(new Color(255, 255, 255));
        //绘制二维码右边的文字
        graphics2D.setPaint(new Color(255, 191, 0));
        graphics2D.drawString("长按识别二维码", 100, 310);
        graphics2D.setPaint(new Color(255, 191, 0));

        graphics2D.drawString("为支持的选手打CALL!", 100, 330);
        graphics2D.setPaint(new Color(255, 191, 0));

        //释放图形上下文
        graphics2D.dispose();
        File posterFile = new File(poster.getUploadPath() + poster.getPosterName());
        log.debug(posterFile + "");
        ImageIO.write(bgImage, "png", posterFile);

    }

    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 gs = image.createGraphics();

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

    /**
     * 设置圆角
     *
     * @param srcImage 图片
     * @param radius   圆角
     * @param border   边框
     * @param padding  内边距
     */
    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 gs = image.createGraphics();
        gs.setComposite(AlphaComposite.Src);
        gs.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        gs.setColor(Color.WHITE);
        gs.fill(new RoundRectangle2D.Float(0, 0, canvasWidth, canvasHeight, radius, radius));
        gs.setComposite(AlphaComposite.SrcAtop);
        gs.drawImage(setClip(srcImage, radius), padding, padding, null);
        if (border != 0) {
            gs.setColor(Color.GRAY);
            gs.setStroke(new BasicStroke(border));
            gs.drawRoundRect(padding, padding, canvasWidth - 2 * padding, canvasHeight - 2 * padding, radius, radius);
        }
        gs.dispose();
        return image;
    }

    /**
     * 圆角
     */
    public static BufferedImage setRadius(BufferedImage srcImage) throws IOException {
        int radius = (srcImage.getWidth() + srcImage.getHeight()) / 25;
        return setRadius(srcImage, radius, 0, 0);
    }

    /**
     * 圆形
     */
    public static BufferedImage setRadius2(BufferedImage srcImage) throws IOException {
        int radius = (srcImage.getWidth() + srcImage.getHeight()) / 2;
        return setRadius(srcImage, radius, 0, 0);
    }

    public static BufferedImage fileToBufferedImage(String filePath) throws IOException {
        File file = new File(filePath);
        FileInputStream fis = new FileInputStream(file);
        BufferedImage image = ImageIO.read(fis);
        fis.close();
        return image;
    }

    public static void activityPoster(ActivityPoster poster) throws Exception {
        BufferedImage bgImage = fileToBufferedImage(poster.getBgPath());
        BufferedImage acImage = fileToBufferedImage(poster.getCoverPath());
        //等宽高缩放图片
        acImage = ImageTools.zoomImage(acImage, 440, 200);
        acImage = setRadius(acImage);
        BufferedImage qrImage = fileToBufferedImage(poster.getQrUrl());
        qrImage = setRadius(qrImage);
        Graphics2D graphics2D = bgImage.createGraphics();
        //消除锯齿
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        //在背景上绘制活动封面
        graphics2D.drawImage(acImage, 24 * 2, 80 * 2, 221 * 2, 99 * 2, null);
        //在背景上绘制二维码
        graphics2D.drawImage(qrImage, 200, 505, 140, 140, null);
        //绘制活动标题
        Font title1Font = new Font("SourceHanSerifCN-Bold", 1, 14 * 2);
        graphics2D.setFont(title1Font);
        graphics2D.setPaint(new Color(255, 191, 0));
        //计算居中
        FontMetrics fm = graphics2D.getFontMetrics(title1Font);
        int title1Center = (bgImage.getWidth() - fm.stringWidth(poster.getTitle1())) / 2;
        graphics2D.drawString(poster.getTitle1(), title1Center, 50 * 2);
        graphics2D.setPaint(new Color(255, 191, 0));
        int title2Center = (bgImage.getWidth() - fm.stringWidth(poster.getTitle())) / 2;
        graphics2D.drawString(poster.getTitle2(), title2Center, 70 * 2);
        //绘制二维码右边的文字
        Font qrTopInfoFont = new Font("SourceHanSerifCN-Bold", 1, 12 * 2);
        FontMetrics fm2 = graphics2D.getFontMetrics(qrTopInfoFont);
        int qrTopInfoCenter = (bgImage.getWidth() - fm2.stringWidth(poster.getQrInfo1())) / 2;
        graphics2D.setFont(qrTopInfoFont);
        graphics2D.drawString(poster.getQrInfo1(), qrTopInfoCenter, 210 * 2);
        graphics2D.setPaint(new Color(255, 191, 0));
        int qrTopInfo2Center = (bgImage.getWidth() - fm2.stringWidth(poster.getQrInfo2())) / 2;
        graphics2D.drawString(poster.getQrInfo2(), qrTopInfo2Center, 230 * 2);
        graphics2D.setPaint(new Color(255, 191, 0));
        //释放图形上下文
        graphics2D.dispose();
        File posterFile = new File(poster.getUploadPath() + poster.getPosterName());
        log.debug(posterFile + "");
        ImageIO.write(bgImage, "png", posterFile);
    }


}

在这里插入图片描述

 public static String generateCover(UploadConfig uploadConfig, InputStream coverTemplateInputStream, String city, String title) throws IOException {
        BufferedImage bg = ImageIO.read(coverTemplateInputStream);
        Graphics2D graphics2D = bg.createGraphics();
        int cityFontW = 50;
        //绘制城市
        Font cityFont = new Font("黑体", Font.PLAIN, cityFontW);
        graphics2D.setFont(cityFont);
        graphics2D.setPaint(new Color(250, 252, 255));
        graphics2D.drawString(city, 50, 300);

        //绘制活动标题
        int fontW = 100;
        //所有字总宽度
        int allFontW = 100 * title.length();
        Font title1Font = new Font("华康黑体W9(P)", Font.PLAIN, fontW);
        graphics2D.setFont(title1Font);
        graphics2D.setPaint(new Color(250, 252, 255));
        //消除锯齿
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        //计算居中 x
        int title1Center = (bg.getWidth() - allFontW) / 2;
        graphics2D.drawString(title, title1Center, 441);
        graphics2D.shear(0.1, -0.4);

        //释放图形上下文
        graphics2D.dispose();

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(bg, "jpg", byteArrayOutputStream);
        byteArrayOutputStream.flush();
        InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        return AliOssTools.upload(inputStream, "jpg", uploadConfig);
    }

您可能感兴趣的与本文相关的镜像

Qwen-Image

Qwen-Image

图片生成
Qwen

Qwen-Image是阿里云通义千问团队于2025年8月发布的亿参数图像生成基础模型,其最大亮点是强大的复杂文本渲染和精确图像编辑能力,能够生成包含多行、段落级中英文文本的高保真图像

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十方来财

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值