You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PDFBox绘制彩色表情符号?

用PDFBox绘制彩色表情符号的解决方案

你当前的代码通过showText绘制表情符号时,只会渲染字形的单色轮廓——因为PDFBox默认文本绘制不处理字体中的COLR/CPAL彩色表(seguiemj.ttf属于这类彩色字体)。要实现彩色效果,有两种可行方案:

方案一:利用PDFBox的彩色字体渲染支持(需2.0.27+版本)

PDFBox从2.0.27版本开始支持带有COLR/CPAL表的彩色字体,需要启用彩色渲染选项并使用showGlyphs方法替代showText。

修改后的代码示例:

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.PDVectorFont;
import java.io.File;
import java.io.IOException;
import java.util.List;

public class ColoredEmojiPDF {
    public static void main(String[] args) throws IOException {
        try (PDDocument doc = new PDDocument()) {
            PDPage page = new PDPage();
            doc.addPage(page);

            // 加载Segoe UI Emoji字体
            PDType0Font emojiFont = PDType0Font.load(doc, new File("C:/Windows/Fonts/seguiemj.ttf"));
            
            // 验证字体是否支持COLR彩色表
            if (!(emojiFont.getDescendantFont() instanceof PDVectorFont vectorFont) || !vectorFont.hasCOLRTable()) {
                System.err.println("该字体不支持彩色COLR表");
                return;
            }

            try (PDPageContentStream cs = new PDPageContentStream(doc, page)) {
                float fontSize = 24;
                float x = 100;
                float y = 700;

                cs.beginText();
                cs.setFont(emojiFont, fontSize);
                cs.newLineAtOffset(x, y);
                
                // 将表情文本转换为字形ID列表
                String emojiText = "🎯💡📢✅";
                List<Integer> glyphIds = emojiFont.encode(emojiText);
                
                // 启用彩色渲染绘制字形
                cs.showGlyphs(glyphIds, emojiFont, fontSize, true);
                
                cs.endText();
            }

            doc.save("colored_emoji.pdf");
        }
    }
}

注意事项:

  • 必须使用PDFBox 2.0.27或更高版本,旧版本无此功能
  • 确保字体路径正确,非Windows系统可替换为对应彩色Emoji字体(如Noto Color Emoji)

方案二:将Emoji渲染为图像后插入PDF

如果无法升级PDFBox版本,可通过Java AWT将Emoji渲染为图像,再插入PDF文档:

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class EmojiImagePDF {
    public static void main(String[] args) throws IOException {
        try (PDDocument doc = new PDDocument()) {
            PDPage page = new PDPage();
            doc.addPage(page);

            String emojiText = "🎯💡📢✅";
            float fontSize = 24;
            float startX = 100;
            float startY = 700;
            float spacing = 30; // 表情间的间距

            // 加载系统彩色Emoji字体
            Font emojiFont = new Font("Segoe UI Emoji", Font.PLAIN, (int) fontSize);
            
            try (PDPageContentStream cs = new PDPageContentStream(doc, page)) {
                float currentX = startX;
                for (char c : emojiText.toCharArray()) {
                    // 创建图像并绘制单个Emoji
                    BufferedImage image = new BufferedImage((int) fontSize, (int) fontSize, BufferedImage.TYPE_INT_ARGB);
                    Graphics2D g2d = image.createGraphics();
                    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    g2d.setFont(emojiFont);
                    g2d.drawString(String.valueOf(c), 0, fontSize - 2); // 调整基线位置保证显示完整
                    g2d.dispose();

                    // 将图像插入PDF
                    PDImageXObject pdImage = PDImageXObject.createFromByteArray(doc, imageToBytes(image), "emoji");
                    cs.drawImage(pdImage, currentX, startY - fontSize, fontSize, fontSize);
                    
                    currentX += spacing;
                }
            }

            doc.save("colored_emoji_image.pdf");
        }
    }

    // 将BufferedImage转为字节数组
    private static byte[] imageToBytes(BufferedImage image) throws IOException {
        java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
        javax.imageio.ImageIO.write(image, "PNG", baos);
        return baos.toByteArray();
    }
}

这种方法依赖系统的字体渲染能力,生成的是图像格式的Emoji,无需依赖PDFBox的高版本特性。

内容的提问来源于stack exchange,提问作者bai yuan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 16:45:21