Введение
В этой статье приведены: паттерны команд Bash в формате скрипта make_window_icon_txt.sh, а также добавление alpha канала с помощью Bash‑скрипта утилитами imagemagick (convert) и ffmpeg. Скрипт имеет размер 290 строк. Эти команды bash отвечают на вопросы:
Как удалить фон из анимированных форматов gif, webp, mov?
Как добавить alpha канал в форматы gif, webp, mov, mp4 и png?
Как конвертировать форматы gif, webp, mov, mp4 в отдельные png изображения?
Как собрать форматы gif, webp, mov, mp4 из отдельных png изображений?
Как конвертировать изображения в формат ARGB иконок оконных менеджеров?
Как попиксельно обрабатывать форматы gif, webp, mov, mp4 и png?
Также в статье приведены оптимальные параметры команд imagemagick (convert) и ffmpeg для обработки форматов gif, webp, mov, mp4 и png.
Установка
Установку можно выполнить с помощью команды git clone. Скрипт make_window_icon_txt.sh будет в директории xdotool_xseticon
git clone https://github.com/PVE-Vladimir/xdotool_xseticon.git cd ./xdotool_xseticon
Обзор функциональности
Каждый запрос создаёт файл.txt — текстовый массив Bash с пикселями ARGB. Если сделать запрос на одно изображение.png, скрипт вернёт массив с одним элементом — списком пикселей, записанным в файл.txt, содержащий declare -a arr_txt=([0]="2 2 0xffff0000 0x0000ffff 0xcccc0b09 0x10101010"), а также продублирует этот список пикселей прямо в терминале.
txt_off — Параметр, который позволяет не создавать при каждом запросе файл.txt. Создание этого файла очень ресурсоёмкий процесс для больших файлов. Если требуется только конвертация одного формата в другой, используйте txt_off. Пример вызова
./make_window_icon_txt.sh webp 30 txt_off './simplescreenrecorder-2026-08-26_03.07.26(1)(2).mp4'
Параметры по умолчанию: 20 кадров в секунду и сохранение в формате GIF. Если не указать количество кадров или тип, в который конвертировать, то форматы gif, webp, mov, mp4 разделятся на отдельные кадры. Для директории с png создастся формат GIF 20 кадров в секунду. Пример вызова
./make_window_icon_txt.sh '/home/vladimirpve/Desktop/WebDesktopGL/Images/Image 6'
Дополнительные параметры указываются в произвольном порядке перед обрабатываемым файлом.
Любое число задаёт частоту кадров в gif, webp, mov, mp4
Параметр alpha заменяет указанные в скрипте пиксели на альфа‑канал через | sed 's/0xffffffff/0x00000000/g'. Этот параметр ресурсозатратный, так как обрабатывается каждый кадр.
Если в качестве формата указать gif, webp, mov, mp4, файл будет сохранён именно в выбранном формате. Однако можно указывать только один формат за раз. Тем не менее, скрипт make_window_icon_txt.sh позволяет обрабатывать несколько файлов в одном запросе. Пример:
./make_window_icon_txt.sh 15 webp './Images/Image 5' \ 15 gif './Images/Image 5' 15 mov './Images/Image 5' \ 15 mp4 './Images/Image 5'
Скрипт распознаёт тип обрабатываемого файла и местоположение по относительным путям. Пример:
./make_window_icon_txt.sh 15 alpha webp './Images/Image 2'
Скрипт сохраняет полученный результат в ту же директорию, в которой находился обрабатываемый файл, не заменяя и не изменяя исходный файл. Названия файлов соответствуют запросам и выбранным параметрам. Пример:
./make_window_icon_txt.sh 15 alpha webp /home/vladimirpve/Desktop/WebDesktopGL/Images/tenor2.gif
Команда создаст директорию /home/vladimirpve/Desktop/WebDesktopGL/Images/tenor2, в которой будут:
tenor2.txt — текстовый Bash‑массив ARGB‑пикселей;
все исходные кадры файла tenor2.gif;
директория tenor2_alpha_channel, в которой будут все кадры файла tenor2.gif с добавлением альфа‑канала;
tenor2_alpha_channel_frame_15.webp — анимированный файл tenor2.gif, конвертированный в WebP с добавлением альфа‑канала и частотой кадров 15 кадров в секунду.

Если сделалать команду «alpha txt_off» для одного файла frame_00000014.png то результат сохранится рядом с названием frame_00000014_alpha_channel.png
./make_window_icon_txt.sh alpha txt_off './Images/tenor2/frame_00000014.png' # Или для .txt создаст frame_00000014_alpha_channel_txt_frame_1.gif # и frame_00000014_0_alpha_channel_txt.png # в директории frame_00000014_alpha_channel_txt ./make_window_icon_txt.sh alpha txt_off './Images/tenor2/frame_00000014.txt'

Основные функции
Функция check_deps() проверяет установлены ли ImageMagick и FFmpeg, и предлагает их установить если не установлены.
check_deps() { local missing_packages=() if ! command -v convert >/dev/null 2>&1; then missing_packages+=("ImageMagick (sudo apt install imagemagick or sudo pacman -S imagemagick)") fi if ! command -v ffmpeg >/dev/null 2>&1; then missing_packages+=("FFmpeg (sudo apt install ffmpeg or sudo pacman -S ffmpeg)") fi if [ ${#missing_packages[@]} -gt 0 ]; then for package in "${missing_packages[@]}"; do echo "Error: Install $package" done exit 1 fi }
Функция zero_default() инициализирует начальные значения переменных, для логики работы, и сбрасывает их на изначальные для обработки следующего файла
process_png_files_in_directory() — функция, которая обрабатывает все файлы png в директории и, в зависимости от того, какие параметры были заданы для файлов gif, webp, mov, mp4, решает, нужно ли создавать файл.txt. Во время работы показывает прогресс обработки изображений: printf “\rNumber png_file:%d ” $count.
process_gif_files_in_directory() — Функция собирает отдельные кадры из директории в указанный формат gif, webp, mov, mp4
make_icon_gif() — функция разбивает форматы gif, webp, mov, mp4 на отдельные кадры
make_window_icon_txt() — Функция разбивает изображение на ARGB‑значения цветов, записывает их в переменную array, добавляет alpha канал, формирует директорию и создаёт изображения с alpha каналом, выводит в консоль ARGB значения цветов для png файла, формирует файл ARGB.txt. но не до конца, последний символ ')', закрывающий массив, ставится в process_png_files_in_directory(),
make_window_txt_icon() — Функция создаёт из ARGB.txt заданный формат конвертации
make_window_icon_png() — Функция make_window_icon_png собирает из пикселей ARGB изображение в формате PNG. Параметры ‑depth 8 ‑define png:color‑type=6 rgba:‑ являются оптимальными для сохранения всех изображений в одной кодировке. Если кодировка будет задана по умолчанию, то в некоторых случаях PNG будут созданы неправильно, и FFmpeg не будет обрабатывать такие кадры и последующие. ‑define png:color‑type=6 — это самый важный параметр здесь. Он напрямую говорит библиотеке libpng: «Запиши файл именно как 32-битный RGBA (тип 6), не смотри на количество цветов». Это отключает внутреннюю логику оптимизации ImageMagick.
Алгоритм работы функций конвертации
Полный код Bash‑скрипта make_window_icon_txt.sh
Функция make_window_icon_png()
Обработка входных данных: Функция make_window_icon_png() принимает массив шестнадцатеричных цветовых кодов (0xRRGGBBAA). Каждый цвет разбивается на компоненты R (красный), G (зеленый), B (синий), A (альфа‑канал). Каждая компонента преобразуется в байт (2 символа в шестнадцатеричном формате).
Генерация изображения: Из байтов формируется бинарный поток (stdin), который передается утилите convert из пакета ImageMagick. Утилита convert создает изображение заданного размера (width × height) с глубиной цвета 8 бит на канал. Изображение сохраняется в формате PNG с поддержкой альфа‑канала (‑define png:color‑type=6).
Комментарии к коду: В закомментированных строках присутствуют экспериментальные варианты с применением фильтров (например, размытие Gaussian (по Гауссу) или уменьшение палитры до 256 цветов). Эти строки можно использовать для альтернативной обработки изображения.
make_window_icon_png() { local PNG_DIR=$1 local width=$2 local height=$3 shift 3 local array=("$@") for ((i=0; i<${#array[@]}; i++)); do hex=${array[i]#0x} A=${hex:0:2} R=${hex:2:2} G=${hex:4:2} B=${hex:6:2} printf '%b' "\x$R\x$G\x$B\x$A" done | convert -size "${width}x$height" -depth 8 -define png:color-type=6 rgba:- "$PNG_DIR" # | convert -size "${width}x$height" -depth 8 rgba:- \ # -filter Gaussian -define filter:support=5 -blur 0x1 \ # "$PNG_DIR" # | convert -size "${width}x$height" -define png:transparency-palette=1 -colors 256 -depth 8 rgba:- "$PNG_DIR" }
Функция make_window_icon_txt()
Функция make_window_icon_txt() содержит логику разбиения файла.png на пиксели формата RGBA. Это основной способ получения пикселей из изображения для работы с отдельными пикселями.
convert "$input_png" -alpha on -channel RGBA rgba:- | od -t x1 -v -An | tr -d '\n' | sed 's/ //g' | sed 's/*//g' | fold -w8 | awk '{ # Extract bytes: rr gg bb aa (in hex for RGBA) rr = substr($0, 1, 2); gg = substr($0, 3, 2); bb = substr($0, 5, 2); aa = substr($0, 7, 2); # Convert to ARGB: aa rr gg bb pixel = "0x" aa rr gg bb; if (NR > 1) printf " %s", pixel; else printf "%s", pixel; } END { printf "\n" }' | tr -d '\n'
Этот запрос записывается в переменную argb_pixels, и затем внутри скрипта формируется общий массив пикселей.
Блок логики array добавление альфа‑канала
Этот блок используется в двух методах make_window_icon_txt() и make_window_txt_icon(). В Adobe Photoshop или другом редакторе можно попиксельно узнать цвет, например f2fefe, и заменить его на прозрачный фон или любой другой цвет. Также, меняя этот блок, можно обрабатывать сразу целые группы пикселей и менять цвета на анимированных изображениях.
array=$(echo "$array" | sed 's/0xffffffff/0x00000000/g' \ | sed 's/0xfffafeff/0x00000000/g' | sed 's/0xfffefaff/0x00000000/g'\ | sed 's/0xfff2fefe/0x00000000/g' | sed 's/0xffe9fefe/0x00000000/g' )
Также можно менять содержимое файла.txt, а затем создать из него файл любого формата.
./make_window_icon_txt.sh 15 webp './Images/Image.txt'
Функция make_icon_gif()
Функция make_icon_gif разделяет форматы gif, webp, mov, mp4 на отдельные кадры.
make_icon_gif() { local output_dir=$1 local type=$2 mkdir -p "$output_dir" if [[ "$type" == "gif" ]]; then ffmpeg -i "$output_dir.gif" "$output_dir/frame_%08d.png" elif [[ "$type" == "webp" ]]; then convert "$output_dir.webp" \ -background none \ -virtual-pixel transparent \ -filter point -depth 8 -define png:color-type=6 \ -distort SRT "0,0 1 0 %[fx:page.x],%[fx:page.y]" \ -extent "$(identify -format "%[page]" "$output_dir.webp[0]")" \ "$output_dir/frame_%08d.png" elif [[ "$type" == "mp4" ]]; then ffmpeg -i "$output_dir.mp4" -vf "format=rgb32,scale=trunc(iw/2)*2:trunc(ih/2)*2" -q:v 0 -vsync vfr "$output_dir/frame_%08d.png" elif [[ "$type" == "mov" ]]; then ffmpeg -i "$output_dir.mov" -vf "format=rgb32,scale=trunc(iw/2)*2:trunc(ih/2)*2" -q:v 0 -vsync vfr "$output_dir/frame_%08d.png" fi process_png_files_in_directory "$output_dir" echo "Frames extracted to '$output_dir/'" }
Запросы для.mov и.mp4
ffmpeg -i "$output_dir.mov" -vf "format=rgb32,scale=trunc(iw/2)*2:trunc(ih/2)*2" \ -q:v 0 -vsync vfr "$output_dir/frame_%08d.png" ffmpeg -i "$output_dir.mp4" -vf "format=rgb32,scale=trunc(iw/2)*2:trunc(ih/2)*2" \ -q:v 0 -vsync vfr "$output_dir/frame_%08d.png"
Входной файл: mov, mp4, расположенный в $output_dir.mov.
Видеофильтр (‑vf):
format=rgb32: конвертация видео в формат RGB32 (32-битный, с альфа‑каналом).
scale=trunc(iw/2)*2:trunc(ih/2)*2: изменение разрешения видео на чётное число пикселей (ширина и высота округляются вниз до ближайшего чётного числа).
Качество (‑q:v 0): максимальное качество для выходных изображений (0 — лучшее, 31 — худшее).
Синхронизация кадров (‑vsync vfr): переменный FPS (видео будет разбито на кадры без привязки к временной шкале).
Выходной формат: последовательность изображений в формате.png, сохранённых в директории $output_dir/ с именами frame_%08d.png (например, frame_00000001.png).
Запрос для.gif по умолчанию работает без дополнительных свойств.
ffmpeg -i "$output_dir.gif" "$output_dir/frame_%08d.png"
Запрос.webp
Запрос через ffmpeg не работает с.webp, поэтому используется convert с параметрами, чтобы извлечённое изображение избавилось от сжатия.
convert "$output_dir.webp" \ -background none \ -virtual-pixel transparent \ -filter point -depth 8 -define png:color-type=6 \ -distort SRT "0,0 1 0 %[fx:page.x],%[fx:page.y]" \ -extent "$(identify -format "%[page]" "$output_dir.webp[0]")" \ "$output_dir/frame_%08d.png"
Для того чтобы избавиться от обрезки кадра и других искажений Искажение (‑distort SRT):
SRT — это аффинное преобразование (Scale, Rotate, Translate).
Параметры «0,0 1 0%[fx:page.x],%[fx:page.y]» означают:
0,0 — точка привязки (координаты x=0, y=0).
1 — масштаб (1 = без изменений).
0 — угол поворота (0 = без поворота).
[fx:page.x],%[fx:page.y] — смещение (перемещение изображения на координаты x и y текущей страницы).
Обрезка (‑extent):
$(identify -format "%[page]" "$output_dir.webp[0]")
Использует identify (часть ImageMagick) для получения размеров первой страницы (кадра) WebP‑файла.
‑background none Устанавливает прозрачный фон для изображений (важно для изображений с альфа‑каналом).
‑virtual‑pixel transparent Использует прозрачный пиксель для заполнения краёв при искажениях (например, при ‑distort).
‑filter point Использует ближайший сосед (без интерполяции) при масштабировании/искажении. Это предотвращает размытие и сохраняет пиксели «как есть».
‑depth 8 Устанавливает битность цвета 8 бит на канал (стандартный формат PNG).
‑define png:color‑type=6 Принудительно задаёт тип цвета PNG-6 (RGBA, с альфа‑каналом). Это гарантирует, что выходной файл будет содержать прозрачность.
Функция process_gif_files_in_directory()
Функция process_gif_files_in_directory это более простая операция сборки отдельных кадров из директории в форматы gif, webp, mov, mp4.
process_gif_files_in_directory() { local output_dir="$1" local frame=$flag_frame if [[ "$flag_webp" == "1" ]]; then ffmpeg -y -framerate "$frame" -pattern_type glob -i "$output_dir/*.png" -loop 0 -quality 100 "$output_dir/$(basename "$output_dir")_frame_$frame.webp" #The .apng format is too rare, but it is possible to use it #ffmpeg -y -framerate "$frame" -pattern_type glob -i "$output_dir/*.png" -plays 0 "$output_dir/$(basename "$output_dir")_frame_$frame.apng" elif [[ "$flag_mp4" == "1" ]]; then ffmpeg -y -framerate "$frame" -pattern_type glob -i "$output_dir/*.png" \ -c:v libx265 \ -crf 12 \ -preset veryslow \ -pix_fmt yuv444p \ -x265-params "keyint=1:scenecut=0" \ -movflags +faststart \ "$output_dir/$(basename "$output_dir")_frame_$frame.mp4" elif [[ "$flag_mov" == "1" ]]; then ffmpeg -y -framerate "$frame" -pattern_type glob -i "$output_dir/*.png" \ -c:v prores_ks -profile:v 4444 \ "$output_dir/$(basename "$output_dir")_frame_$frame.mov" else ffmpeg -y -framerate "$frame" -pattern_type glob -i "$output_dir/*.png" \ -filter_complex "[0:v] split [a][b];[a] palettegen [p];[b][p] paletteuse" -loop 0 \ "${output_dir}/$(basename "$output_dir")_frame_$frame.gif" fi }
Запрос для.webp
ffmpeg -y -framerate "$frame" -pattern_type glob -i "$output_dir/*.png" \ -loop 0 -quality 100 "$output_dir/$(basename "$output_dir")_frame_$frame.webp"
‑y Автоматически перезаписывает выходной файл, если он уже существует (без запроса подтверждения).
‑framerate “$frame” Устанавливает частоту кадров (FPS) для анимации. Значение переменной $frame (например, 24, 30, 60).
‑pattern_type glob Включает поддержку glob‑шаблонов для указания входных файлов (например, *.png).
‑i “$output_dir/*.png” Указывает входные файлы — все PNG‑изображения в папке $output_dir.
‑loop 0 Задаёт бесконечный цикл для анимации (0 = без ограничений). Если указать число (например, ‑loop 5), анимация будет повторяться 5 раз.
‑quality 100 Устанавливает максимальное качество (100 = без сжатия). WebP поддерживает сжатие с потерями и без потерь, и 100 — это максимальное качество (без потерь).
"$output_dir/$(basename "$output_dir")_frame_$frame.webp" Задаёт выходной файл
Сделал запрос для формата.apng но формат мёртв оставил закоментированным в коде
ffmpeg -y -framerate "$frame" -pattern_type glob -i "$output_dir/*.png" \ -plays 0 "$output_dir/$(basename "$output_dir")_frame_$frame.apng"
Запрос для.gif
ffmpeg -y -framerate "$frame" -pattern_type glob -i "$output_dir/*.png" \ -filter_complex "[0:v] split [a][b];[a] palettegen [p];[b][p] paletteuse" -loop 0 \ "${output_dir}/$(basename "$output_dir")_frame_$frame.gif"
‑y Перезаписывает выходной файл без запроса подтверждения. Полезно для автоматизации.
‑framerate “$frame” Устанавливает частоту кадров (FPS) для входной последовательности. Например, 24, 30, 60.
‑pattern_type glob Включает glob‑шаблоны для указания входных файлов. Позволяет использовать *.png.
‑i “$output_dir/*.png” Указывает входные файлы — все PNG‑изображения в папке $output_dir.
‑filter_complex:
split [a][b] — разделяем поток на две части.
[a] palettegen [p] — генерируем оптимальную палитру по первым кадрам.
[b][p] paletteuse — применяем палитру ко всем кадрам для единообразия цвета.
‑loop 0 Задаёт бесконечный цикл для анимации (0 = без ограничений). Если указать число (например, ‑loop 5), анимация будет повторяться 5 раз.
Запрос для.mov
ffmpeg -y -framerate "$frame" -pattern_type glob -i "$output_dir/*.png" \ -c:v prores_ks -profile:v 4444 \ "$output_dir/$(basename "$output_dir")_frame_$frame.mov"
‑y Перезаписывает выходной файл без запроса подтверждения. Полезно для автоматизации.
‑framerate “$frame” Устанавливает частоту кадров (FPS) для входной последовательности. Например, 24, 30, 60.
‑pattern_type glob Включает glob‑шаблоны для указания входных файлов. Позволяет использовать *.png.
‑i “$output_dir/*.png” Указывает входные файлы — все PNG‑изображения в папке $output_dir.
‑c:v pror‑y Перезаписывает выходной файл без запроса подтверждения. Полезно для автоматизации.
‑framerate “$frame” Устанавливает частоту кадров (FPS) для входной последовательности. Например, 24, 30, 60.
‑pattern_type glob Включает glob‑шаблоны для указания входных файлов. Позволяет использовать *.png.
‑i “$output_dir/*.png” Указывает входные файлы — все PNG‑изображения в папке $output_dir.
es_ks Устанавливает кодек видео как Apple ProRes 4444 (prores_ks). Высококачественный кодек с поддержкой 4:4:4 и альфа‑канала.
‑profile:v 4444 Устанавливает профиль кодека ProRes как 4444 (максимальное качество). Поддерживает 10-битную глубину цвета и прозрачность (альфа‑канал).
Запрос для.mp4
ffmpeg -y -framerate "$frame" -pattern_type glob -i "$output_dir/*.png" \ -c:v libx265 \ -crf 12 \ -preset veryslow \ -pix_fmt yuv444p \ -x265-params "keyint=1:scenecut=0" \ -movflags +faststart \ "$output_dir/$(basename "$output_dir")_frame_$frame.mp4"
‑y Автоматически перезаписывает выходной файл, если он уже существует. Без запроса подтверждения.
‑framerate “$frame” Устанавливает частоту кадров (FPS) для входной последовательности. Например, 24, 30, 60.
‑pattern_type glob Включает поддержку glob‑шаблонов для указания входных файлов. Позволяет использовать *.png.
‑i “$output_dir/*.png” Указывает входные файлы — все PNG‑изображения в папке $output_dir. Должны быть одного размера.
‑c:v libx265 Устанавливает кодек видео как H.265 (HEVC). Высокоэффективный кодек с поддержкой 10/12 бит.
‑crf 12 Устанавливает качество квантования (Constant Rate Factor). 12 — очень высокое качество (малое сжатие), диапазон 0–51.
‑preset veryslow Устанавливает профиль сжатия для кодека x265. veryslow — максимальное сжатие, но долгое время кодирования.
‑pix_fmt yuv444p Задаёт цветовой формат пикселей как 4:4:4. Сохраняет чёткость изображения, но увеличивает размер файла.
‑x265-params “keyint=1:scenecut=0” Настраивает параметры кодека x265: <br> — keyint=1 — каждый кадр становится ключевым (I‑кадр). <br> — scenecut=0 — отключает автоматическое определение сцен. Подходит для анимации или слайд‑шоу.
‑movflags +faststart Оптимизирует MP4-файл для потоковой передачи. Ускоряет начало воспроизведения в браузере/медиаплеере.
Заключение
Данный скрипт прежде всего предназначен для создания файлов формата.txt (текстовых bash‑массивов ARGB‑пикселей). Данный формат нужен для установки иконок окна (анимированных иконок окна) в оконных менеджерах. Однако в процессе обработки различных форматов получился bash‑скрипт для работы с основными форматами изображений и анимации.
max-daniels
Градиент можно конвертировать в альфу? Точнее объект на картинке плавно становится прозрачнее по краям(например дым или полупрозрачное свечение). Я так и не понял как в таких картинках добавлять альфу.
PVE-Vladimir Автор
Я просто посчитал, что предложенного алгоритма удаления диапазона пикселей через | sed 's/Z/X/g' | sed 's/Y/X/g' достаточно. Возможно, действительно требуется в этой части усложнить алгоритм и сделать функцию с циклом for, которая принимала бы именно диапазон пикселей, а также дополнительную опцию, которая удаляла бы пиксели только по бокам изображения.