返回

不依赖第三方工具判断 AVIF 动画的技巧

java

不借助第三方工具判断 AVIF 文件是否为动画

在处理图像文件时,判断一个 AVIF 文件是否包含动画,而又不依赖任何第三方库或程序,是一个有些挑战但有趣的问题。AVIF 格式的灵活性带来了一些识别上的复杂性。下面介绍几种方法,直接利用文件结构来判断其是否为动画。

一、理解 AVIF 文件结构

AVIF 文件格式基于 HEIF(High Efficiency Image File Format)。它使用“boxes”(也称为“atoms”)的结构来组织数据。每个 box 都有一个类型和大小。 要确定 AVIF 文件是否是动画,需要深入查看特定的 box。

二、检测方法

1. 检查 'meta' Box 中的 'iprp' 和 'ipco'

静态 AVIF 通常只有一个图像项,而动画 AVIF 往往有多个。关键在于 'meta' box 内的 'iprp' (Image Properties) 和 'ipco' (Image Property Container) boxes。动画 AVIF 可能会包含多个与图像项关联的属性,指示多个帧。

原理:

  • meta box 包含了关于图像的元数据。
  • iprp 包含了图像属性。
  • ipco 包含属性容器。
    动画AVIF文件中,多个帧的信息会体现在这里。

步骤与代码示例 (使用 hexdump 和 shell 脚本):

  1. 使用 hexdump 查看文件头部信息。 观察 'meta' box 的位置和大小。

    hexdump -C <your_avif_file> | head -n 50
    

    从输出中定位meta box。

  2. 使用脚本解析,统计相关的 boxes:
    这只一个思路,真实环境下要通过meta box大小计算偏移,再读取对应的内容:

    #!/bin/bash
    
    file="$1"
    
    #  查找 'meta' box 的起始位置 (简化示例,假设 'meta' 总是在开头附近)
    meta_start=$(hexdump -v -e '8/1 "%02X ""\n"' "$file" | grep -n "6D 65 74 61" | head -n 1 | cut -d: -f1)
      # 简单的计算偏移示例,不保证通用。  
      # echo $meta_start;
      if [ -z "$meta_start" ]; then
         echo "Meta box not found"
         exit 1
      fi;
    
      meta_start_decimal=$((16#${meta_start// /})) # 转10进制。
    # echo "Meta box 10: $meta_start_decimal"
    
    # 注意,这只是一个*非常简化*的示例, 用来显示大致思路,不能直接用于生产!
     is_animated=$(hexdump -v  -s $meta_start_decimal -n 512 -e '8/1 "%02X ""\n"'  "$file" | grep "69 70 72 70"| wc -l);  #查找 iprp. 69 70 72 70 是iprp 的hex
    
    if (( is_animated > 1 ));
    then
       echo "Likely an animated AVIF (iprp count: $is_animated)"
    else
      echo "Likely a static AVIF (iprp count: $is_animated)"
    fi
    
    

    运行脚本:

      ./check_avif.sh your_avif_file.avif
    

    注意: 上面的脚本非常初级,仅仅为了展示思路。 真实的解析需要处理更多边界情况,如'meta' box 大小、嵌套 box 结构等。 上面的代码仅用于学习理解 ,真实情况下需要写更完整的解析代码,正确地解析出所有BOX的起始和结束。

  3. 观察:多个 'iprp'/'ipco' 的关联暗示动画。

2. 使用 'ispe' (Image Spatial Extents) box

'ispe' box 定义了图像的空间尺寸。在动画 AVIF 中,尽管所有帧通常具有相同的尺寸,但检查每个关键帧或显著变化帧的 'ispe' box 是否存在并一致,可以作为辅助判断。

原理:
每一个关键帧,都可能有自己的信息。通过比较可以佐证。

步骤与代码示例(思路):
类似于上述方法, 使用 hexdump 查找 'ispe' box, 提取宽度和高度信息。 然后需要一个循环,去分析可能的每一个关键帧数据。 如果宽度高度信息出现不一致,可能就不是动画。反之,如果宽度高度数量多,而且一样,可以佐证是动画的可能性增加。 这里不做代码演示,因为它和方法一类似, 需要较为复杂的BOX结构解析代码,仅仅用脚本较难完成.

3. "逐步加载"特征

一些 AVIF 动画可能被配置为“逐步加载”,类似于渐进式 JPEG。虽然这不是动画的直接指标,但这种配置有时与动画一起使用,以便在加载时提供视觉反馈。逐步加载通常涉及到多个具有不同质量级别的图像数据项。这个判断不能作为独立的判断条件。

安全建议

在解析任何外部文件格式时,始终要进行安全检查。不要假定文件的结构完全符合规范。处理文件时,应该:

  • 验证大小和偏移量 : 确保读取的 box 大小和计算的偏移量在文件范围内,避免越界读取。
  • 限制内存使用 : 解析大型文件或复杂结构时,注意控制内存占用,避免潜在的拒绝服务攻击。
  • 输入验证 : 在使用文件名或路径时,请仔细进行安全验证。

判断 AVIF 是否是动画,没有单一、绝对可靠、又不使用第三方工具的方法。最好的方法是结合多种线索进行综合判断, 也就是组合使用上面介绍的各种技术,通过综合的得分进行判断。上面提到的解析meta信息等,可以提供很强的判断依据。

重要说明: 以上代码示例主要是概念性的,用于说明判断逻辑。在生产环境中,更建议使用专门的二进制文件解析工具(如 xxd 或自定义解析程序, 而不是纯粹使用 hexdump)来精确解析 AVIF 的 box 结构,这样才可靠,且具有工业应用价值.