Summary

一次用 Java 处理 heif 格式文件的碎碎念

背景

在维护我司的一个文档处理服务,主要是功能是把各种类型的文件,统一转成 pdf 添加水印,然后前端通过通过 pdfview 统一渲染 pdf ,实现各种文件在线预览的功能

底层用到的服务比较多,大部分文档是通过 openoffice 来实现,各种类型的图片资源是通过 itext 来支持的,但是 itextImageData 没法支持 heif 格式。需要单独支持一下 heif 转 pdf 功能

过程

先测试了下 openoffice 跟 itext ,发现确实不能直接支持那剩下的方案优先考虑社区开源的 java 方案

但是看下来,也没有 pure java 的实现

TwelveMonkeys 是一个 Java 图片类型处理库,但是现在没有支持 heif 类型的图片

haraldk/TwelveMonkeys#440 HEIF support

看起来除非有人愿意实现或者资金支持,否则作者自己应该不会进行 HEIF 的支持了

然后 issue 里提到的 NightMonkeys 是基于 libheif 实现的,但是要求 Java22+ , 线上代码还停留在祖传的 Java8 ,这个库也没法直接用

GitHub - gotson/NightMonkeys: Additional plug-ins and extensions for Java’s I…

那么基本就剩下 JNI 跟 调用命令两个方案了,相比之下,调用命令可能实现更简单一些,问题就只剩下怎么把 libheif 打入镜像了

libheif 底层依赖 libde265

由于各种网络环境的限制,已经一些其他,打镜像可谓是一波三折

基础镜像是一个基于 centos7

构建机器访问外网也有限制,没法直接通过 yum 安装

转而尝试自己编译,编译的时候,发现 yum 安装的 cmake 是 2.x ,编译 libheif 需要 cmake 3.21 以上

又需要手动安装 cmake 好在 cmake 有提供现成的 .sh 脚本,直接加入到镜像里执行即可

FROM baseimage
MAINTAINER xxx
USER root

COPY repo.sh /root/repo.sh

RUN sh /root/repo.sh

RUN yum-config-manager --disable updates
RUN yum makecache
RUN yum groupinstall "Development Tools" -y
RUN yum install libjpeg-turbo-devel libpng-devel libtiff-devel -y

COPY cmake-3.29.8-linux-x86_64.sh /root/cmake-3.29.8-linux-x86_64.sh
RUN chmod +x /root/cmake-3.29.8-linux-x86_64.sh
RUN /root/cmake-3.29.8-linux-x86_64.sh --prefix=/usr/local --skip-license


RUN mkdir "/root/heif/"
COPY heif.sh /root/heif/heif.sh
COPY libde265-1.0.15.tar.gz /root/heif
COPY libheif-1.18.2.tar.gz /root/heif
RUN sh /root/heif/heif.sh

然后就是编译安装 libde265 以及 libheif

比较坑的是 ld 部分,不知道为啥这个镜像没法加载 /usr/local/lib 以及 /usr/local/lib64 下的动态库,导致命令安装成功,但是执行会报错,提示动态库加载不到

后来单独设置了一下,把 /usr/local/lib 以及 /usr/local/lib64 都加入到 ld 的文件夹下

base=/root/heif/
cd $base

tar zxvf libde265-1.0.15.tar.gz
tar zxvf libheif-1.18.2.tar.gz

cd $base/libde265-1.0.15
./autogen.sh
./configure
make && make install
echo "/usr/local/lib" > /etc/ld.so.conf.d/lib256.conf

cd $base/libheif-1.18.2
mkdir build
cd build
cmake --preset=release ..
make && make install

echo "/usr/local/lib64" > /etc/ld.so.conf.d/libheif.conf

ldconfig

构建好的镜像就加入了 heif-convert 命令,在 java 程序中,直接使用 ProcessBuilder 调用 heif-convert 即可

思考

这种方案并不能说是一个好方案,依赖底层环境,这种方案,换个环境就是个坑,但是在 docker 的加持下,这种方案可能算是一种比较快速的解决方案

整个过程中,确实没少问 GPT ,技术类问题, GPT 也不是真全知全能,也会睁着眼睛说瞎话,这个在使用的过程中,是需要自己去甄别测试的,但是确实能节约一些搜索时间。现在 GPT 对我来说差不多能替代 70% 在搜索引擎上的使用场景