使用 LibreOffice 将 PPT 转换为 PNG 图片

序言

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

转换脚本:ppt2png.sh

#!/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 镜像构建,安装所需的依赖项。

# 使用 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 镜像:
docker build -t ppt2png .
  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)
评论 (0)

暂无评论,来抢沙发吧~

登录 后发表评论