对于如何转换 HEIC 图片,目前主要是两类,五种方法。
Contents
使用系统级别的编码器
使用 Windows HEVC Video Extensions
这个方案依赖于 Windows 商店中的 或者 。 你需要从制造商获得兑换码,或者支付 1 美元来安装这个扩展,我这里另外提供一下 HEVC Video Extensions from Device Manufacturer 的下载,可以通过 appx 文件部署,该插件已在 Windows 1809/1903/1909/2004 版本上测试过。
https://cloud.ezapi.net/s/JaXjLjejdacJep8
Add-AppxPackage -Path Microsoft.HEVCVideoExtension_1.0.40203.0_x64__8wekyb3d8bbwe.Appx
在安装好上述扩展后,即可使用 / 进行转换。以 XnConvert 为例:
将文件或者文件夹拖拽到输入窗口
在输出中选择 HEIC - HEIF
,如果需要修改编码的质量,还可以通过下方的 Settings
按钮设置
接下来点击 Convert
即可生成文件。
这里提供了一个 PowerShell脚本:https://github.com/DavidAnson/ConvertTo-Heic/blob/master/ConvertTo-Heic.ps1
你可以在安装完 Windows HEVC Video Extensions 后使用。
优缺点
这种方法在基本只需要通过 GUI (XnView/XnConvert) 即可完成转换,而且转换出来的图片没有色彩问题,兼容性也较好。但它需要 1 美元安装扩展,同时很难灵活的控制编码参数(例如位深度,deblock 等设置)。在 Linux 平台上也不支持转换为 HEIC 。另外在图片的尺寸不能被 2 整除时,还有额外的 artifact。目前使用该 API 的方法都会遇到这样的问题。
使用预览.app
macOS 自带预览.app,你可以通过它的导出功能转换到 HEIC 文件。
优缺点
这种方法在基本只需要通过 GUI 即可完成转换,而且转换出来的图片没有色彩问题,兼容性也较好。但是编码参数也和 Windows 一样不可控制。
使用 x265
由于 HEIC 实际上是 HEVC 的帧内编码在图片编码领域的应用,因此这个操作是可以通过 x265 完成的,下述两种方法在核心的编码方面均使用 x265,因此归为一类。
使用 FFmpeg 和 GPAC
安装环境
这里需要两个软件
你可以从这里获取 ,Windows 用户还可以使用
choco install ffmpeg
只需要安装 MP4box 部分。
转换代码
最核心的的代码是 x265 编码以及 MP4box 封装,示例如下
ffmpeg -hide_banner -r 1 -i "example.png" -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2,zscale=m=170m:r=pc" -pix_fmt yuv420p -frames 1 -c:v libx265 -preset veryslow -crf 20 -x265-params range=full:colorprim=smpte170m "example.hevc" mp4box -add-image "example.hevc:primary" -brand heic -new "example.heic"
这里首先是使用 trunc 保证输入给 x265 的图片尺寸满足能够被 2 整除,并且强制使用 smpte170m (bt601) 以保证 Windows 平台正确解码。
ffmpeg -hide_banner -r 1 -i "example.png" -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2,zscale=m=170m:r=pc" -pix_fmt yuv420p -frames 1 -c:v libx265 -preset veryslow -crf 20 -x265-params range=full:colorprim=smpte170m:aq-strength=1.2 -deblock -2:-2 "example.hevc"
对于一些需要批量处理图像的使用情况,可以使用如下方法:
在 我的文档\WindowsPowerShell
文件夹下新建一个名为: Microsoft.PowerShell_profile.ps1
的空文件,使用记事本打开,粘贴下面的函数保存。
function mdel($tpath, $tformat){ dir -recurse -path $tpath -include *.$tformat |%{ $_.Delete(); } } function imgconv($tpath, $quality,$sformat ,$tformat) { If($tformat -eq "heic") { dir -recurse -path $tpath -include *.$sformat |%{ $extentmark = 0; $imwidth=magick identify -ping -format "%w" $_.FullName $imwidth=[int]$imwidth; If(($imwidth)%2 -ne 0) { $imwidth=$imwidth+1; $extentmark=1; } $imheight=magick identify -ping -format "%h" $_.FullName; $imheight=[int]$imheight; If(($imheight)%2 -ne 0) { $imheight=$imheight+1; $extentmark=1; } If($extentmark) { magick $_.FullName -gravity center -strip -extent "($imwidth)x($imheight)" -quality 100% $_.FullName; } } dir -recurse -path $tpath -include *.$sformat |%{ $crfoffset = $quality * 10; $crfval= 30 - $crfoffset; ffmpeg -i "$($_.Directory)\$($_.Basename).$sformat" -crf $crfval -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2,zscale=m=170m:r=pc" -pix_fmt yuv420p -frames 1 -c:v libx265 -preset veryslow -x265-params range=full:colorprim=smpte170m -f hevc "$($_.Directory)\$($_.Basename).hvc" 2>&1 | Out-Null; mp4box -add-image "$($_.Directory)\$($_.Basename).hvc:primary" -ab heic -new "$($_.Directory)\$($_.Basename).heic" 2>&1 | Out-Null; } mdel $tpath hvc } Else { dir -recurse -path $tpath -include *.$sformat |%{ $quality=[int]$quality; $magickquality=$quality * 100; #$magickquality="$magickquality"+"%"; magick $_.FullName -quality $magickquality -interlace Plane -sampling-factor 4:2:0 -strip "$($_.Directory)\$($_.Basename).$tformat"; } } }
管理员身份
set-executionpolicy remotesigned
则可以在 PowerShell 中批量转换图片
imgconv "图片所在的目标文件夹" 质量参数 原图格式 目标格式 #例子一 jpg转heic #这里用的函数是最上方的那个 crf基础为30 质量参数设为1时crf为20 crf设置为3时进行无损转换 imgconv "D:\Download\manga\Akira" 3 jpg heic #例子二 jpg和png之间互相转换 #当目标格式不是heic的时候 转换仅仅使用imagemagick进行 #这是质量参数会映射为百分比 #即1=100%质量 0.75=75%质量 #在目标格式heic的时候 质量参数是对基础crf的改变 #这里则是直接的百分比映射 imgconv "D:\Download\Manga\bababababa" 1 jpg png
获取
choco install imagemagick
这种方法可以最大限度的控制编码参数,并且也是跨平台的。但是它需要使用一些代码,并且在少数的移动设备上会有无法识别的问题。
使用 libheif
这里需要一个软件
-
libheif
在 Linux/MacOS 中你可以直接用包管理器安装,而在 Windows 中你需要下载编译好的。
转换代码
最简单的生成方式如下
heif-enc -q 90 -p x265:colorprim=smpte170m example.jpg -o example.heic
这里仅指定了色彩空间,如果需要使用更高级的算法编码参数则可以如下操作
heif-enc -p x265:crf=20.5 -p x265:colorprim=smpte170m -p x265:rdoq-level=1 -p x265:aq-strength=1.2 -p x265:deblock=-2:-2 example.jpg -o example.heic
批量处理
对于一些需要批量处理图像的使用情况,可以使用如下方法:
在 我的文档\WindowsPowerShell
文件夹下新建一个名为: Microsoft.PowerShell_profile.ps1
的空文件,使用记事本打开,粘贴下面的函数保存。
然后管理员身份打开 PowerShell 运行
function imgconv($tpath, $quality,$sformat ,$tformat) { If($tformat -eq "heic") { dir -recurse -path $tpath -include *.$sformat |%{ $extentmark = 0; $imwidth=magick identify -ping -format "%w" $_.FullName $imwidth=[int]$imwidth; If(($imwidth)%2 -ne 0) { $imwidth=$imwidth+1; $extentmark=1; } $imheight=magick identify -ping -format "%h" $_.FullName; $imheight=[int]$imheight; If(($imheight)%2 -ne 0) { $imheight=$imheight+1; $extentmark=1; } If($extentmark) { magick $_.FullName -gravity center -strip -extent "($imwidth)x($imheight)" -quality 100% $_.FullName; } } dir -recurse -path $tpath -include *.$sformat |%{ $crfoffset = $quality * 10; $crfval= 30 - $crfoffset; Write-Output "Encoding $($_.Directory)\$($_.Basename).heic" heif-enc -p x265:crf=$crfval -p x265:colorprim=smpte170m -p x265:rdoq-level=1 -p x265:aq-strength=1.2 -p x265:deblock=-2:-2 "$($_.Directory)\$($_.Basename).$sformat"-o "$($_.Directory)\$($_.Basename).heic"; } } Else { dir -recurse -path $tpath -include *.$sformat |%{ $quality=[int]$quality; $magickquality=$quality * 100; #$magickquality="$magickquality"+"%"; magick $_.FullName -quality $magickquality -interlace Plane -sampling-factor 4:2:0 -strip "$($_.Directory)\$($_.Basename).$tformat"; } } }
管理员身份
set-executionpolicy remotesigned
则可以在 PowerShell 中批量转换图片
imgconv "图片所在的目标文件夹" 质量参数 原图格式 目标格式 #例子一 jpg转heic #这里用的函数是最上方的那个 crf基础为30 质量参数设为1时crf为20 crf设置为3时进行无损转换 imgconv "D:\Download\manga\Akira" 3 jpg heic #例子二 jpg和png之间互相转换 #当目标格式不是heic的时候 转换仅仅使用imagemagick进行 #这是质量参数会映射为百分比 #即1=100%质量 0.75=75%质量 #在目标格式heic的时候 质量参数是对基础crf的改变 #这里则是直接的百分比映射 imgconv "D:\Download\Manga\bababababa" 1 jpg png
该函数依赖于 ImageMagick,也可以使用 获取
choco install imagemagick
优缺点
这种方法可以最大限度的控制编码参数,并且也是跨平台的,兼容性较好。但是它需要使用一些代码。
简单总结
作为新一代的图片编码技术,HEIC 的优势不言而喻,目前由于桌面平台上可以用来编码的软件并不是很多,因此提供了上述几种思路。目前我认为比较好的方法是 libheif 或者 macOS 下的预览.app。目前上述方法考虑到兼容性默认使用 YUV420p 8bit 编码,但你也可以通过修改代码兼容 10bit编码提高还原度。
你可以通过如下代码查看生成的 HEIC 文件,确保生成的文件可用。
magick identify output.heic
参考文档
https://nokiatech.github.io/heif/technical.html
https://bbs.saraba1st.com/2b/thread-1931974-1-1.html
https://www.itu.int/rec/T-REC-H.273/en
https://github.com/Mr-Z-2697/awkward_win_batches/blob/main/makeheic-z.bat