blog of faywong

备案号: 浙ICP备2025185971号

  menu
41 文章
0 浏览
0 当前访客
ღゝ◡╹)ノ❤️

ESP32 中压缩 gif 资源

通过 idf.py size-components 发现项目中有大量 gif 文件占据内部内存。导致 bt 协议栈都初始化失败。遂开始这一场 gif 压缩之旅。

首先是针对分辨率、有损编码做一定处理。macos 上如果是 macos 15(beta 版本)记得从源码安装 ImageMagick

#!/bin/bash

# ==============================================================================
# batch_optimize_gifs.sh
#
# 功能: 查找当前目录下的所有 .gif 文件, 将其分辨率宽高各减半,
#       并进行极限压缩,然后保存到 'output' 目录中。
#
# 依赖: Gifsicle, ImageMagick (用于获取原始尺寸)
# ==============================================================================

# --- 设置输出目录 ---
OUTPUT_DIR="output"

# --- 检查依赖工具是否存在 ---
if ! command -v gifsicle &> /dev/null; then
    echo "错误: 未找到 'gifsicle'。请先安装 Gifsicle。"
    echo "  - Ubuntu/Debian: sudo apt install gifsicle"
    echo "  - macOS (Homebrew): brew install gifsicle"
    exit 1
fi

if ! command -v magick &> /dev/null && ! command -v identify &> /dev/null; then
    echo "错误: 未找到 ImageMagick 命令 ('magick' 或 'identify')。"
    echo "请先安装 ImageMagick。"
    echo "  - Ubuntu/Debian: sudo apt install imagemagick"
    echo "  - macOS (Homebrew): brew install imagemagick"
    exit 1
fi


# --- 创建输出目录 ---
if [ ! -d "$OUTPUT_DIR" ]; then
    echo "创建输出目录: $OUTPUT_DIR"
    mkdir "$OUTPUT_DIR"
fi

# --- 启用 shell 选项 ---
# nullglob: 如果没有匹配的文件,循环就不会执行
# nocaseglob: 匹配文件名时不区分大小写 (.gif, .GIF, .GiF 等)
shopt -s nullglob nocaseglob

# --- 变量初始化 ---
file_count=0
total_original_size=0
total_compressed_size=0

echo "开始批量处理 GIF 文件..."
echo "----------------------------------------"

# --- 循环处理当前目录下的所有 .gif 文件 ---
for file in *.gif; do
    # 检查这确实是一个文件
    if [ -f "$file" ]; then
        ((file_count++))
        echo "($file_count) 正在处理: $file"

        # --- 计算目标尺寸 (宽高减半) ---
        target_width=360
        target_height=360

        # 确保尺寸至少为 1px
        [ "$target_width" -eq 0 ] && target_width=1
        [ "$target_height" -eq 0 ] && target_height=1
    
        echo "  - 原始尺寸: ${original_width}x${original_height}"
        echo "  - 目标尺寸: ${target_width}x${target_height}"

        # --- 定义输出文件路径 ---
        output_file="$OUTPUT_DIR/$file"

        num_colors=4

        # --- 核心压缩命令 ---
        gifsicle \
            --resize "${target_width}x${target_height}" \
            --colors "${num_colors}" \
            --dither \
            --optimize=3 \
            --lossy=80 \
            "$file" \
            -o "$output_file"

        # --- 统计文件大小 ---
        original_size=$(stat -f \"%z\" "$file")
        compressed_size=$(stat -f \"%z\" "$output_file")
        ((total_original_size+=original_size))
        ((total_compressed_size+=compressed_size))

        echo "  - 压缩完成 -> $output_file"
        echo "" # 添加空行以分隔
    fi
done

# 恢复 shell 默认行为
shopt -u nullglob nocaseglob

gifsicle \
--resize "360x360" --colors 64 --dither \
--optimize=3 \
--lossy=80 \
"network_setup.gif" \
-o output/network_setup_new.gif

# --- 输出总结报告 ---
echo "----------------------------------------"
if [ "$file_count" -eq 0 ]; then
    echo "未在当前目录找到任何 .gif 文件。"
else
    echo "批量处理完成!共处理了 $file_count 个 GIF 文件。"
    echo "所有优化后的文件已保存到 '$OUTPUT_DIR' 目录中。"
    echo ""
    echo "--- 压缩效果总结 ---"
  
    # 转换为 KB 或 MB 以方便阅读
    orig_kb=$((total_original_size / 1024))
    comp_kb=$((total_compressed_size / 1024))
  
    echo "总原始大小: $orig_kb KB"
    echo "总压缩后大小: $comp_kb KB"

    if [ "$total_original_size" -gt 0 ]; then
        reduction_percent=$(echo "scale=2; (1 - $total_compressed_size / $total_original_size) * 100" | bc)
        echo "总体积减小: $reduction_percent %"
    fi
fi

接下来通过在线工具 将其转为 c 语言数组格式,方便直接代码形式嵌入。

特别地,由于 network_setup.gif 文件颜色比较丰富,与普通的黑白色有不同,此时量化时应为其保留更多颜色:

gifsicle \
--resize "180x180" --colors 64 --dither \
--optimize=3 \
--lossy=90 \
"network_setup.gif" \
-o output/network_setup_new.gif


标题:ESP32 中压缩 gif 资源
作者:faywong8888
地址:https://blog.fay.wang/articles/2025/08/12/1754999048701.html