Heic文件转jpg纯java实现(亲测有效)

1.绪论

最近有个需求,需要Heic转jpg,对此做了调研,常见的解决方案主要有如下几种。

|---------------------------------------|---------------------------------------------------------------|
| 解决方案 | 特点 |
| ffmpeg | 可以直接在网上下载打包好的二进制包,拷贝到软件服务器里面就能运行 |
| ffmpeg(javacv-platform) | 可以直接纯java代码实现,通过maven依赖 |
| twelvemonkeys-imageio +imageio-heif插件 | 其中imageio-heif在maven中央仓库里面没有 |
| ImageMagic+libheif | 需要在服务器上面安装软件 |
| 其他 | 其他主要是提供一个客户端,本质上还是需要调用libheif这个库,可以说libheif是解决heic转jpg的唯一标准答案 |

由于系统是采用容器化部署,不好安装,所以我们想直接用javacv-platform来实现。

2.实现

2.1.安装依赖

引入javacv-platform,一定要1.5.12以上,不是可能报不支持heic格式。java-platfom底层其实也是ffmpeg的二进制源码包,通过jni实现java调用。

XML 复制代码
<dependency>
	<groupId>org.bytedeco</groupId>
	<artifactId>javacv-platform</artifactId>
	<version>1.5.12</version> <!-- 检查最新版本 -->
</dependency>

2.2.实现

java 复制代码
public static void main(String[] args) {
        try {
            FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("F:\\image\\IMG_1600.HEIC");
            grabber.start();

            // 获取第一帧
            Frame frame = grabber.grabImage();

            // 将帧转换为 BufferedImage
            Java2DFrameConverter converter = new Java2DFrameConverter();
            BufferedImage image = converter.convert(frame);

            // 保存为 JPEG 文件
            ImageIO.write(image, "jpg", new File("F:\\image\\out.jpg"));

            grabber.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

3.问题

ffmpeg是一个视频处理工具,所以还是把heic图片当成视频流来处理的,所以效果不是很好。

java 复制代码
Info: avformat_open_input rejected some options:	Option: pixel_format, value: bgr24
[mov,mp4,m4a,3gp,3g2,mj2 @ 0000025573ede680] Derived Image item of type tmap is not implemented. Update your FFmpeg version to the newest one from Git. If the problem still occurs, it means that your file has a feature which has not been implemented.
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'F:\image\IMG_1600.HEIC':
  Metadata:
    major_brand     : heic
    minor_version   : 0
    compatible_brands: mif1MiHBMiHAheixMiHEMiPrmiafheictmap
  Duration: N/A, start: 0.000000, bitrate: N/A
// tile grid 图像
  Stream group #0:0[0x31]: Tile Grid: hevc (Main Still Picture) (hvc1 / 0x31637668), yuvj420p(pc, smpte170m/smpte432/bt709), 4032x3024 (default)
  Stream group #0:1[0x53]: Tile Grid: hevc (Main 10) (hvc1 / 0x31637668), yuv420p10le(pc, smpte170m/smpte432/linear), 2880x2160
  Stream group #0:2[0x60]: Tile Grid: hevc (Rext) (hvc1 / 0x31637668), gray(pc), 2016x1512
  Stream #0:48[0x32]: Video: hevc (Rext) (hvc1 / 0x31637668), gray(pc), 2016x1512, 1 fps, 1 tbr, 1 tbn
  Stream #0:49[0x34]: Video: hevc (Main Still Picture) (hvc1 / 0x31637668), yuvj420p(pc, smpte170m/smpte432/bt709), 416x312, 1 fps, 1 tbr, 1 tbn
      Side data:
        ICC Profile
// 灰度图像
  Stream #0:92[0x61]: Video: hevc (Rext) (hvc1 / 0x31637668), gray(pc), 2016x1512, 1 fps, 1 tbr, 1 tbn
  Stream #0:93[0x63]: Video: hevc (Rext) (hvc1 / 0x31637668), gray(pc), 2016x1512, 1 fps, 1 tbr, 1 tbn
// 缩略图
  Stream #0:94[0x65]: Video: hevc (Main 10) (hvc1 / 0x31637668), yuv420p10le(pc), 1024x768, 1 fps, 1 tbr, 1 tbn

上面是一个heic图片的构成,可以看出heic里面是一个缩率图,灰度图,主图的集合。在苹果11过后,一些高级特性的图(比如HDR,live图)等会将元图分开存储到不同的tile grid中。而ffmpeg只能拿到灰度图形或者缩略图形。效果可能不是很好。并且有些高级特性的heic还可能解析失败。如果要获取到原图,据我所知,采用libheif是唯一的标准解决方案。参考Heic文件转jpg标准解决方案(libheif安装)

相关推荐
benbenAItalk1 小时前
数字人口播视频的批量生产实践:素材规范、任务编排与质量验收
java·前端·音视频
sunshine22 girl1 小时前
Java学习二 基本语法2, 算术运算符
java·学习
2601_966949651 小时前
为什么量化策略需要大量历史股票数据?从回测可信度理解数据规模
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
niucloud-admin1 小时前
JAVA V6 多商户商城 开发文档——插件目录结构
java·开发语言
2601_962885721 小时前
如何用 Python 扫描 A 股跳空缺口并统计缺口回补概率?
java·前端·python
anew___1 小时前
蜂鸣器播放音乐——让 Arduino 唱出旋律
c++·stm32·单片机·嵌入式硬件·c
滕州市燕猫虎计算机科技工作室个体工商户2 小时前
Java锁
java·开发语言
多加点辣也没关系2 小时前
JavaScript|第31章:表单与控件
开发语言·javascript·ecmascript
菜鸟~noob2332 小时前
【电子战】 第09篇:阵列信号处理——波束形成、MVDR、MUSIC【含matlab代码】
开发语言·matlab·信号处理
ocean21032 小时前
2025-2026年Python面试高频知识点洞察
开发语言·python·面试·python八股文