Her ikinci kareyi animasyonlu bir gif'ten nasıl kaldırırım?


22

Animasyonlu bir gif'e dönüştürmek istediğim videolarla dolu bir klasörüm var. ffmpeg / avconv doğrudan bunu yapmakta zorlanıyor, bu yüzden önce her kareyi png olarak çıkarıp sonra da imagemagick'i kullanarak gif'e geri dönüştürerek videoyu bir gif'e dönüştürüyorum. Sorun, bunun dosya boyutu açısından büyük bir gif ile sonuçlanmasıdır. Bunu çözmek için, ya bir gif'e dönüştürürken her görüntü dosyasını atlayarak ya da bir gifden kareleri kaldırarak, her saniye ya da her kareyi giften "düşürmek" istiyorum. İmagemagick veya başka bir komut satırı yardımcı programını kullanarak bunu Ubuntu'da (13.04) nasıl yapabilirim?

Yanıtlar:


14

Bir bash betiği kullanmak

Bunu komut satırından yapmak için Gifsicle adlı bir yardımcı program kullanabilirsiniz . Diğer tüm kareleri silmek için yerleşik bir yöntem yoktur, bu nedenle bazı komut dosyasıyla ellerinizi kirletmeniz gerekir.

İşte sadece bir GIF yapmak için yaptığım hızlı bir script:

#!/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

Basit bir geri sayım GIF ile test ettim:

görüntü tanımını buraya girin

Ve işte senaryoyu çalıştırdıktan sonra sonuç:

görüntü tanımını buraya girin

Bu senaryo elbette kurşun geçirmez değildir, ancak sizi doğru yöne yönlendirmelidir.


Silme let i=0; while [[ $i -lt $(($numframes / 2)) ]]; do gifsicle $2 --delete "#$i" -o $2; let i=i+1; done
döngünüzün

1
Aslında, hiç bir döngüye ihtiyaç duymazsınız: gifsicle "$1" --unoptimize $(seq -f "#%g" 0 2 $numframes) -O2 -o "$2"tek bir çağrıda yapacaktır.
Ilmari Karonen

Aslında bu betiği komut satırından nasıl çalıştıracağımı bilmiyorum. Ben gifdrop.sh dosyası olarak kaydetmeye çalıştım ve kullanımında (./gifdrop.sh in.gif out.gif) belirtilen şekilde çalıştırıp in.gif adında bir gif olarak kullandım ve bilinmeyen komut gifdrop dedi
mheavers

@mheavers dosyayı çalıştırılabilir hale getirdiniz mi? chmod +x gifdrop.sh
JohnB

1
MacOS'ta daha iyi çalışır: github.com/colindean/hejmo/blob/master/scripts/… - grep yerine perl kullanan sürümüm, varsayılan olarak GNU grep yüklü olmayan macOS'ta çalışacak şekilde çalışır. Ayrıca, dosya adlarındaki boşlukları işler.
Colin Dean

27

İşte gifsicle kullanarak JohnB'nin senaryosundan daha basit bir çözüm :

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

Bu komut çoğu Unix kabuğunda çalışmalıdır; Bunu bash olarak test ettim. Değiştir input.gifve output.gifgiriş ve çıkış dosya adları ile ve 99animasyonunuzdaki kare sayısı ile. (Daha büyük bir sayı kullanmanız uygundur, ancak gifsicle bundan şikayet edecektir.)

Bazı notlar:

  • -UAnahtar, her kare tek başına duran ve herhangi bir diğer olarak bağlı değildir, böylece, daha öncekiler ile giriş animasyon kareleri birleştirme. Bunu animasyonlarla çok fazla bir şey yapmadan önce yapmak istersiniz, aksi takdirde karışık sonuçlar elde edersiniz. (Giriş animasyonunuz zaten korumasızsa, gifesicle bunun hakkında bir uyarı yazdırabilir, ancak bu tamamen zararsızdır.)

  • Buna karşılık, -O2anahtar, dosya boyutunu en aza indirmek için çıktı animasyonunu yeniden optimize eder. JohnB'nin örnek animasyonu ile çıktı boyutunu% 27 oranında küçültür.

  • Bu seqkomut sadece 0'dan 99'a kadar olan bir sayı dizisi verir, 2 adımda sayılır. Bu -f "#%g", #her sayının önüne bir sayı yazılmasını sağlar, bu da gifsicle'ın bir dosya adı yerine çerçeve seçimi olarak anlamasını sağlar. `Seq komutunun etrafındaki backticks ( ) çıktısının gifsicle komut satırına parametre olarak dahil edilmesine neden olur.

GIF'in hızlanmasını istemiyorsanız, gifsicle -I input.gifgeçerli kare gecikmesini elde etmek için kullanabilirsiniz , 2 ile çarpın ve kullanın gifsicle -d ${delay} ....


Güzel bitti! Gerçekten istersen, betiğimin grep'ini kare sayısını tam olarak vermek için kullanabilirsin (ve komutun bir tanesini yap). Veya belki de bir animasyonlu GIF'teki kare sayısını döndürmenin daha basit bir yolu var mı?
JohnB

3
Komutanlıktan vazgeçtim, 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

Sürümü 1.71 ile, Windows 7 x64, ben var: useless unoptimization-related input option. Bu yüzden iki adımda yaptım (Git Bash'in içinden): 1. gifsicle -U -o unoptimized.gif input.gif2.gifsicle unoptimized.gif `seq -f "#%g" 0 2 99` -O2 -o output.gif
feklee

11

NOT : Bu cevap bir komut satırı / açık kaynak gereksinimi olmadan önce gönderildi, ancak ileride bir başkasına yardım edebileceğinden dolayı ayrılıyorum


Photoshop'u kullanma

Bu açık kaynak kodlu bir komut satırı çözümü değildir, ancak bunu Photoshop ile yapabilirsiniz:

Dosyaİçe AktarKatmanlara Video Kareleri ...

Video içe aktar

" Her __ Çerçeveleri Sınırla " sizin için hile yapacak


0

Toplu komut dosyası işleme kullanarak benim çözümüm ...

Öncelikle yakalanan orijinal animasyonlu gif'i input.gif dosyasına kopyalayın, sonra komut yorumlayıcısını başlatın ve şunu yazın:

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

input.txt dosyasına bakın ve animasyonun uzunluğunun ne olduğunu görün - kaç tane kare içerdiğini ...

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

daha sonra edit-create test.bat ve len = değişken_değiflik_sayısı_from_input.txt değişkeninin değerini değiştirin ve test.bat dosyasını kaydedin ...

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

daha sonra nihayet process1.bat ve process2.bat komutlarını başlatın ve her garip kareyle birlikte kırpılmış animasyon input.gif dosyasına dönüştürülür.

işlem1.bat:

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

process2.bat:

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

0

Daha sofistike bir açıklamaya ihtiyacım olduğunu düşünüyorum (kare gecikmesi de dikkate alınması gereken önemli bir şey) ... Bu yeni işlem için bu bağlantıdan JREPL.BAT dosyasını indirmeniz gerekecek: http://www.dostips.com /forum/viewtopic.php?t=6044

Öncelikle yakalanan gif'i input.gif dosyasına kopyalayın, sonra komut yorumlayıcısını başlatın ve şunu yazın:

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

input.txt dosyasına bakın ve animasyonun uzunluğunun ne olduğunu görün - kaç tane kareler içeriyorsa ... karenin gecikmesine de bakın ve eğer 0.07s ise -d14 (7msec * 2) seçeneğini bu satıra koymanız gerektiği anlamına gelir. process.cmd içinde: gifsicle -b -U -d14 input.gif, edit save işleminden sonra.

daha sonra test.bat dosyasını düzenleyin ve 166 değişkeninin değerini bu satırdaki animasyon karelerinin sayısına göre değiştirin: for / L %% i IN (1,2,166) DO echo "# %% i" >> input.bat düzenle save test.bat ...

daha sonra process.cmd'yi başlatın ve her bir tek kareyle birlikte kırpılmış animasyon input.gif dosyasına işlenir.

PS Bu yöntemin avantajı ayrıca, gif'ten ne silmek istediğinizi (her ikinci karede (1,2,166) veya her üçte bir (1,3,166)) tam olarak kontrol edebilmenizdir; toplu iş hattı, ancak (1,3,166) belirtirseniz, buna göre (7msec * 2 yerine -d14 (gecikme seçeneği) 'yi process.cmd öğesinden değiştirmelisiniz (7msn * 3/2 = 10). / 1 = 14), gecikme seçeneği -d10 ... olmalıdır

Diğer dosyalar (örneğin, her ikinci kareyi kaldırma): 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 -

süreç.cmd:

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

Ve yardımcı benioku dosyası 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.