使用 LibreOffice 将 PPT 转换为 PNG 图片

序言

最近收到一个需求,要将 PPT 文件转换成 PNG 图片。起初使用 LibreOffice 测试时发现只能转换第一页,其他页面都无法生成。经过研究后,最终确定解决方案:先用 LibreOffice 将 PPT 转换为 PDF,再使用 pdftoppm 工具将 PDF 转换为 PNG。同时,我将这个过程封装成一个命令行工具,方便其他程序调用。

转换脚本:ppt2png.sh

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
#!/bin/sh

# 日志函数
log_info() {
echo "INFO: $1"
}

log_error() {
echo "ERROR: $1" >&2
}

# 清理函数 - 默认清理中间PDF文件
cleanup() {
if [ -f "$PDF_FILE" ]; then
log_info "Cleaning up temporary PDF file: $PDF_FILE"
rm -f "$PDF_FILE"
fi
}

# 错误处理
trap cleanup EXIT

# 检查输入参数
if [ "$#" -ne 2 ]; then
log_error "Invalid arguments. Usage: $0 <input_file_path> <output_dir>"
exit 1
fi

INPUT_PATH="$1"
OUTPUT_DIR="$2"

# 检查输入文件是否存在且可读
if [ ! -f "$INPUT_PATH" ] || [ ! -r "$INPUT_PATH" ]; then
log_error "Input file does not exist or is not readable: $INPUT_PATH"
exit 1
fi

# 确保输出目录存在
mkdir -p "$OUTPUT_DIR"

# 检查输出目录是否可写
if [ ! -w "$OUTPUT_DIR" ]; then
log_error "Output directory is not writable: $OUTPUT_DIR"
exit 1
fi

# 检查必要的命令是否存在
for cmd in libreoffice pdftoppm; do
if ! command -v $cmd &> /dev/null; then
log_error "Required command '$cmd' not found"
exit 1
fi
done

# 获取文件名和扩展名
FILE_NAME=$(basename "$INPUT_PATH")
BASE_NAME="${FILE_NAME%.*}"
EXTENSION="${FILE_NAME##*.}"
PDF_FILE="$OUTPUT_DIR/$BASE_NAME.pdf"

# 将扩展名转换为小写
EXTENSION=$(echo "$EXTENSION" | tr '[:upper:]' '[:lower:]')

# 检查文件扩展名
case "$EXTENSION" in
ppt|pptx)
log_info "Converting $INPUT_PATH to PDF..."
if ! libreoffice --headless --convert-to pdf:impress_pdf_Export --outdir "$OUTPUT_DIR" "$INPUT_PATH"; then
log_error "PPT to PDF conversion failed"
exit 2
fi

if [ ! -f "$PDF_FILE" ]; then
log_error "PDF file was not created"
exit 2
fi

log_info "PPT to PDF conversion succeeded: $PDF_FILE"
log_info "Converting $PDF_FILE to PNG..."

# 以basename为目录名,确保目录存在
OUTPUT_SUB_DIR="$OUTPUT_DIR/$BASE_NAME"
if ! mkdir -p "$OUTPUT_SUB_DIR"; then
log_error "Failed to create output directory: $OUTPUT_SUB_DIR"
exit 1
fi
# 以basename为目录名, 1为前缀
if ! pdftoppm -png "$PDF_FILE" "$OUTPUT_SUB_DIR/1"; then
log_error "PDF to PNG conversion failed"
exit 3
fi

log_info "PDF to PNG conversion completed successfully"
log_info "Output files are located in: $OUTPUT_DIR"

# 检查是否至少生成了一个PNG文件
if ! ls "$OUTPUT_DIR/${BASE_NAME}"*.png >/dev/null 2>&1; then
log_error "No PNG files were generated"
exit 3
fi
;;
*)
log_error "Unsupported file type: $EXTENSION. Only PPT and PPTX are supported."
exit 4
;;
esac

exit 0

Dockerfile 配置

基于 Alpine 镜像构建,安装所需的依赖项。

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
# 使用 Alpine 作为基础镜像
FROM alpine:3.21

# 安装 LibreOffice 所需的依赖包
RUN apk update && \
apk add --no-cache \
# 字体相关
# 字体配置工具,确保字体被正确识别
fontconfig \
# Noto CJK 字体,支持中文(简体、繁体)及其他东亚语言
font-noto-cjk \
# Noto Sans 和其他西文字体
font-noto \
# DejaVu 字体,补充西文字体支持
ttf-dejavu \
# LibreOffice 主程序
libreoffice \
# 解决: javaldx: Could not find a Java Runtime Environment!
openjdk8-jre \
# 用于将 pdf 文件转换为 png (libreoffice无法将ppt逐张转为png)
poppler-utils && \
# 清理 APK 缓存以减少镜像体积
rm -rf /var/cache/apk/* && \
# 删除日文、韩文字体,保留简体中文
rm -rf /usr/share/fonts/noto/{*JP*,*KR*} && \
# 刷新字体缓存,确保字体可用
fc-cache -fv

COPY ppt2png.sh /usr/local/bin/ppt2png
RUN chmod +x /usr/local/bin/ppt2png

CMD ["/bin/sh"]

使用方法

  1. 构建 Docker 镜像:

    1
    docker build -t ppt2png .
  2. 在容器中执行转换命令:

    1
    ppt2png /result/test.pptx /result

    参数说明:

  • 第一个参数:PPT 文件路径
  • 第二个参数:输出目录路径

常见问题及解决方案

  1. Shell 脚本兼容性问题:

    • Alpine Linux 使用 /bin/sh 作为默认 shell,而其他 Linux 发行版通常使用 /bin/bash
    • 在编写脚本时,请确保首行为 #!/bin/sh,否则直接执行脚本会提示 ppt2png: not found 错误
  2. 中文字体显示问题:

    • 必须安装适当的字体包,否则中文字符可能显示为方框
    • 本方案中已包含必要的中文字体支持(Noto CJK)

使用 LibreOffice 将 PPT 转换为 PNG 图片
https://blog.ishare.cool/2025/01/11/libreoffice-ppt-to-png/
作者
吴哥
发布于
2025年1月11日
许可协议