애니메이션 GIF에서 매 초마다 프레임을 제거하는 방법은 무엇입니까?


22

애니메이션 GIF로 변환하려는 비디오로 가득 찬 폴더가 있습니다. ffmpeg / avconv는 직접 수행하는 나쁜 작업을 수행하므로 먼저 각 프레임을 png로 출력 한 다음 imagemagick을 사용하여 gif로 다시 변환하여 비디오를 gif로 변환합니다. 문제는 파일 크기 측면에서 큰 gif가 발생한다는 것입니다. 이 문제를 해결하기 위해 GIF로 변환 할 때 모든 이미지 파일을 건너 뛰거나 GIF에서 프레임을 제거하여 GIF에서 초 또는 n 번째 프레임마다 "드롭"하고 싶습니다. imagemagick 또는 다른 명령 줄 유틸리티를 사용하여 Ubuntu (13.04)에서이 작업을 수행하려면 어떻게해야합니까?

답변:


14

bash 스크립트 사용

명령 행에서이를 수행하기 위해 Gifsicle 이라는 유틸리티를 사용할 수 있습니다 . 다른 모든 프레임을 삭제하는 기본 제공 방법이 없으므로 스크립팅으로 손을 더럽힐 필요가 있습니다.

다음은 하나의 GIF를 만들기 위해 작성한 간단한 스크립트입니다.

#!/bin/bash
# This script will take an animated GIF and delete every other frame
# Accepts two parameters: input file and output file
# Usage: ./<scriptfilename> input.gif output.gif

# Make a copy of the file
cp $1 $2

# Get the number of frames
numframes=`gifsicle $1 -I | grep -P "\d+ images" --only-matching | grep -P "\d+" --only-matching`

# Deletion
let i=0
while [[ $i -lt $numframes  ]]; do
    rem=$(( $i % 2 ))

    if [ $rem -eq 0 ]
    then
        gifsicle $2 --delete "#"$(($i/2)) -o $2 
    fi

    let i=i+1 
done

간단한 카운트 다운 GIF로 테스트했습니다.

여기에 이미지 설명을 입력하십시오

다음은 스크립트를 통해 실행 한 결과입니다.

여기에 이미지 설명을 입력하십시오

이 스크립트는 물론 방탄은 아니지만 올바른 방향으로 안내해야합니다.


삭제 루프를 간단히 단순화 할 수 있습니다.let i=0; while [[ $i -lt $(($numframes / 2)) ]]; do gifsicle $2 --delete "#$i" -o $2; let i=i+1; done
Ilmari Karonen

1
실제로 루프가 전혀 필요하지 않습니다 gifsicle "$1" --unoptimize $(seq -f "#%g" 0 2 $numframes) -O2 -o "$2". 한 번의 호출로 수행합니다.
Ilmari Karonen

실제로 명령 줄 에서이 스크립트를 실행하는 방법을 모르겠습니다. 나는 그것을 gifdrop.sh 파일로 저장하고 in.gif라는 gif의 사용법 (./gifdrop.sh in.gif out.gif)에 지시 된대로 실행하려고 시도했으며 알 수없는 명령 gifdrop
mheavers

@mheavers 파일을 실행 가능하게 했습니까? chmod +x gifdrop.sh
JohnB

1
macOS에서 더 잘 작동합니다 : github.com/colindean/hejmo/blob/master/scripts/…-grep 대신 perl을 사용하여 기본적으로 GNU grep이 설치되어 있지 않은 macOS에서 작동하도록 내 버전입니다. 또한 파일 이름에서 공백을 처리합니다.
콜린 딘

27

JohnB의 스크립트보다 gifsicle 을 사용하는 간단한 솔루션은 다음과 같습니다 .

gifsicle -U input.gif `seq -f "#%g" 0 2 99` -O2 -o output.gif

이 명령은 대부분의 유닉스 쉘에서 작동합니다. 나는 그것을 bash에서 테스트했다. 교체 input.gifoutput.gif입력 및 출력 파일 이름 및 99애니메이션의 프레임의 수. (더 큰 숫자를 사용하는 것은 좋지만 gifsicle이 이에 대해 불평합니다.)

몇 가지 참고 사항 :

  • -U스위치는 각 프레임이 혼자 의미하고 다른 사람에 의존하지 않는 그래서, 앞의 사람과 입력 애니메이션 프레임을 병합합니다. 애니메이션으로 거의 모든 작업을 수행하기 전에이 작업을 수행하려고합니다. 그렇지 않으면 지저분한 결과가 발생할 수 있습니다. 입력 애니메이션이 이미 최적화되지 않은 경우 gifsicle에 대한 경고가 표시 될 수 있지만이 역시 완전히 무해합니다.

  • 반대로, -O2스위치는 출력 애니메이션을 다시 최적화하여 파일 크기를 최소화합니다. JohnB의 샘플 애니메이션을 사용하면 출력 크기가 27 % 줄어 듭니다.

  • seq명령은 0에서 99까지의 일련의 숫자를 2 단계로 계산하여 -f "#%g"출력합니다. #각 숫자 앞에 a 를 인쇄하여 gifsicle이 파일 이름 대신 프레임 선택으로 인식하도록합니다. `seq 명령 주위 의 백틱 ( )으로 인해 출력이 gifsicle 명령 행에 매개 변수로 포함됩니다.

gif 속도를 높이고 싶지 않으면 gifsicle -I input.gif현재 프레임 지연을 가져 와서 2를 곱한 다음을 사용할 수 있습니다 gifsicle -d ${delay} ....


잘 했어요! 정말로 원한다면 내 스크립트에서 grep을 사용하여 프레임 수를 정확하게 제공하고 명령을 크게 만들 수 있습니다. 또는 애니메이션 GIF에서 프레임 수를 반환하는 간단한 방법이 있습니까?
JohnB

3
내가 명령의 괴수를 만들어 결국, @JohnB -gifsicle input.gif `seq -f "#%g" 0 2 $(identify input.gif | tail -1 | cut -d "[" -f2 - | cut -d "]" -f1 -)` --unoptimize -O2 -o output.gif
Kasra Rahjerdi

버전 1.71의 Windows 7 x64에서는 다음이 useless unoptimization-related input option있습니다.. 나는 (힘내 배쉬 내에서) 두 단계로 그것을했다 그래서 : 1. gifsicle -U -o unoptimized.gif input.gif2.gifsicle unoptimized.gif `seq -f "#%g" 0 2 99` -O2 -o output.gif
feklee

11

참고 : 이 답변은 명령 줄 / 오픈 소스 요구 사항이 있기 전에 게시되었지만 향후 다른 사람을 도울 수 있으므로 남겨 두겠습니다.


Photoshop 사용

이것은 오픈 소스 또는 명령 줄 솔루션이 아니지만 Photoshop에서 수행 할 수 있습니다.

파일가져 오기비디오 프레임을 레이어로 ...

비디오 가져 오기

" 모든 __ 프레임으로 제한 "은 트릭을 수행합니다.


0

배치 스크립트 처리를 사용하는 솔루션은 다음과 같습니다.

먼저 캡처 한 원래 애니메이션 gif를 input.gif 파일로 복사 한 다음 명령 인터프리터를 시작하고 다음을 입력하십시오.

gifsicle input.gif -I "# -1"> input.txt

input.txt를 살펴보고 애니메이션 길이를 확인하십시오-얼마나 많은 프레임이 포함되어 있는지 ...

input.txt :

* input.gif 166 images
  logical screen 1366x768
  global color table [256]
  background 15
  loop forever
  + image #165 1x1 at 1365,767 transparent 15
    disposal asis delay 0.07s

그런 다음 test.bat를 편집하고 작성하고 변수 len = specify_length_number_from_input.txt의 값을 변경하고 test.bat를 저장하십시오 ...

test.bat :

@echo off
set /A len=166
set /A i=1
set /A ii=0
:loop
if %i%==%len% goto :eof
if %ii%==0 (set /A ii=1) else (set /A ii=0)
set /A iii=%ii%*%i%
if %i%==%iii% echo gifsicle -b input.gif --delete "#1" --done
set /A i=%i%+1
goto :loop

마지막으로 process1.bat 및 process2.bat를 시작하면 모든 홀수 프레임으로 자른 애니메이션이 파일 input.gif로 처리됩니다.

process1.bat :

gifsicle -b -U input.gif
test.bat > input.bat

process2.bat :

call "input.bat"
gifsicle -b -O2 input.gif
erase "input.bat"

0

더 정교한 설명이 필요하다고 생각합니다 (프레임 지연도 고려해야 할 중요한 사항입니다) ...이 새로운 프로세스를 위해서는 다음 링크에서 JREPL.BAT를 다운로드해야합니다. http://www.dostips.com /forum/viewtopic.php?t=6044

먼저 캡처 된 gif를 input.gif 파일로 복사 한 다음 명령 인터프리터를 시작하고 다음을 입력하십시오.

gifsicle input.gif -I "# -1"> input.txt

input.txt를보고 애니메이션 길이가 무엇인지 확인하십시오-얼마나 많은 프레임이 포함되어 있는지 ... 프레임 지연을보고 0.07 인 경우 -d14 (7msec * 2) 옵션을이 줄에 넣어야합니다 process.cmd에서 : gifsicle -b -U -d14 input.gif, 편집 저장 후 process.cmd

그런 다음 test.bat를 편집하고 애니메이션의 프레임 수와 일치하도록 변수 166의 값을이 줄에서 변경하십시오. for / L %% i IN (1,2,166) DO echo "# %% i">> input.bat, test.bat 저장 저장 ...

그런 다음 process.cmd를 시작하고 모든 홀수 프레임마다 자른 애니메이션이 파일 input.gif로 처리됩니다.

추신 :이 방법의 장점은 gif (두 번째 프레임 (1,2,166) 또는 모든 세 번째 (1,3,166))에서 삭제할 항목을 완전히 제어 할 수 있다는 것입니다. 배치 라인이지만 (1,3,166)을 지정하면 process.cmd에서 -d14 (지연 옵션)를 변경하여 (7msec * 2 대신 변경 (7msec * 3 / 2 = 10)을 반영해야합니다. / 1 = 14), 지연 옵션은 -d10 ...이어야합니다.

다른 파일 (예 : 매 초마다 프레임 제거) : test.bat :

@echo off
echo gifsicle -b input.gif --delete>> input.bat
for /L %%i IN (1,2,166) DO echo  "#%%i">> input.bat
echo  --done>> input.bat
call jrepl.bat "\n" "" /x /m /f input.bat /o -

process.cmd :

gifsicle -b -U -d14 input.gif
call "test.bat"
call "input.bat"
gifsicle -b -O3 input.gif
erase "input.bat"

그리고 도우미 readme 파일 input.txt :

* input.gif 166 images
  logical screen 1366x768
  global color table [256]
  background 15
  loop forever
  + image #165 1x1 at 1365,767 transparent 15
    disposal asis delay 0.07s
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.