2008-11-11 19 views
39

Şu anda GD'yi kullanarak görüntüleri yeniden boyutlandırma ile ilgili bazı sorunlara göz atıyorum.Animasyonlu gifleri php ve gd kullanarak tespit edebilir miyim?

Siyah bir arka plan üzerinde ilk çerçeveyi sunan animasyonlu bir gif'i yeniden boyutlandırmak istediğim sürece her şey iyi çalışıyor.

getimagesize kullanmayı denedim, ancak yalnızca herhangi bir gif ve animasyonlu birini ayırt etmek için bana boyutlar ve hiçbir şey vermiyor.

Animasyonlu gifler için gerçek boyutlandırma gerekli değildir, sadece onları atlayabilmek, bizim amacımız için yeterli olacaktır.

Herhangi bir ipuçları?

PS. Imagemagick'e erişimim yok.

Saygılarımızla

Kris

+0

Yazar, ImageMagick içermediğini söyledi. Ancak, tüm insanlar için bir gifin animasyonlu olup olmadığını ve Google'dan buraya gelip gelmediğini öğrenmek için herhangi bir yol arar. (Benim gibi): ImageMagick bunu kolayca yapar: http://php.net/manual/en/imagick.getimageiterations .php – Lukas

cevap

17

neye ihtiyacınız olmalı imagecreatefromgif() fonksiyonun PHP manuel sayfasında kod kısa bir pasajı vardır:

İşte imagecreatefromgif comment #59787 by ZeBadger

+0

Bunu, kılavuzun varsayılan aynasında bulamadığım garip ama bağlantı için çok şey var. Fonksiyonu değiştirdim ve hem orijinal posteri hem de sizlere yorumda kredi verdim. – Kris

+0

Optimize edilmiş bir sürüm [burada] (http://it1.php.net/manual/en/function.imagecreatefromgif.php#104473). –

+1

Bu bağlantı bir sebepten ötürü, hala burada bulunabilir: http://php.net/manual/en/function.imagecreatefromgif.php # 104473 – robjbrain

5

var çalışma işlevi:

/** 
* Thanks to ZeBadger for original example, and Davide Gualano for pointing me to it 
* Original at http://it.php.net/manual/en/function.imagecreatefromgif.php#59787 
**/ 
function is_animated_gif($filename) 
{ 
    $raw = file_get_contents($filename); 

    $offset = 0; 
    $frames = 0; 
    while ($frames < 2) 
    { 
     $where1 = strpos($raw, "\x00\x21\xF9\x04", $offset); 
     if ($where1 === false) 
     { 
      break; 
     } 
     else 
     { 
      $offset = $where1 + 1; 
      $where2 = strpos($raw, "\x00\x2C", $offset); 
      if ($where2 === false) 
      { 
       break; 
      } 
      else 
      { 
       if ($where1 + 8 == $where2) 
       { 
        $frames ++; 
       } 
       $offset = $where2 + 1; 
      } 
     } 
    } 

    return $frames > 1; 
} 
37

Aynı soruna bir çözüm ararken, php.net sitesinin Davide ve Kris kodunun bir izine sahip olduğunu fark ettim, ancak yazara göre daha az bellek yoğunluğu ve muhtemelen daha az disk yoğun.

Burada çoğaltıcım, çünkü ilginizi çekebilir.

kaynak: http://www.php.net/manual/en/function.imagecreatefromgif.php#88005

function is_ani($filename) { 
    if(!($fh = @fopen($filename, 'rb'))) 
     return false; 
    $count = 0; 
    //an animated gif contains multiple "frames", with each frame having a 
    //header made up of: 
    // * a static 4-byte sequence (\x00\x21\xF9\x04) 
    // * 4 variable bytes 
    // * a static 2-byte sequence (\x00\x2C) 

    // We read through the file til we reach the end of the file, or we've found 
    // at least 2 frame headers 
    while(!feof($fh) && $count < 2) { 
     $chunk = fread($fh, 1024 * 100); //read 100kb at a time 
     $count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00[\x2C\x21]#s', $chunk, $matches); 
    } 

    fclose($fh); 
    return $count > 1; 
} 
+0

Stevio düzeltmesi aşağıda verilmiştir. –

+7

Yakın zamanda eklenen bir not, photoshop'un '\ x00 \ x2C' yerine' \ x00 \ x2'' kullanabileceğinden bahsediyor. –

+6

Frank’ın notu olması gerektiği kadar açık değil. Bu sayfayı inceleyen diğer kişilere, lütfen şu adresteki açıklamalarına bakın: http://www.php.net/manual/en/function.imagecreatefromgif.php#104473) – billmalarky

-1

Hareketli GIF zorunluluk aşağıdaki dizeyi

"\x21\xFF\x0B\x4E\x45\x54\x53\x43\x41\x50\x45\x32\x2E\x30" 
2

verilen dosya çok büyükse çok fazla bellek sürebilir file_get_contents ile tüm dosyasını okuma vardır. Çerçeveleri kontrol etmek için yalnızca yeterli bayt okuyan ve en az 2 kare bulduğu anda döndüren, daha önce verilen işlevi yeniden belirledim.

<?php 
/** 
* Detects animated GIF from given file pointer resource or filename. 
* 
* @param resource|string $file File pointer resource or filename 
* @return bool 
*/ 
function is_animated_gif($file) 
{ 
    $fp = null; 

    if (is_string($file)) { 
     $fp = fopen($file, "rb"); 
    } else { 
     $fp = $file; 

     /* Make sure that we are at the beginning of the file */ 
     fseek($fp, 0); 
    } 

    if (fread($fp, 3) !== "GIF") { 
     fclose($fp); 

     return false; 
    } 

    $frames = 0; 

    while (!feof($fp) && $frames < 2) { 
     if (fread($fp, 1) === "\x00") { 
      /* Some of the animated GIFs do not contain graphic control extension (starts with 21 f9) */ 
      if (fread($fp, 1) === "\x2c" || fread($fp, 2) === "\x21\xf9") { 
       $frames++; 
      } 
     } 
    } 

    fclose($fp); 

    return $frames > 1; 
} 
+0

+1. Ancak o zamanlar, dosyalar küçüktü ve onları bütünüyle okumak, araştırma yapmadığım veya araştırmayı hatırlamadığım nedenlerden dolayı bayt tarafından bayttan daha hızlıydı. – Kris

+0

Dikkat: “fread ($ fp, 1) ===" \ x2c "|| fread ($ fp, 2) === "\ x21 \ xf9" 'önce bir bayt (A) okuyacaktır, eğer 0x2C olduğunu kontrol edin, eğer değilse, iki bayt ** sonra da ** byte A'dan sonra okuyacaktır. 0x00 bayt. Böylece eşleşen bayt dizeleri '00 2C' veya' 'F **' '' '' '' '' '' '' '' '' herhangi bir bayt anlamına gelir. Bunun amaçlanmış olup olmadığından emin değilim, ancak koddan çok net değil. – Qtax

0

Bu, geçerli en çok okunan yanıtın bir gelişmesidir, ancak henüz yorum yapabilmek için yeterli itibarım yok. Bu yanıtla ilgili sorun, dosyayı 100Kb boyutlarında okuyup çerçeve işaretinin sonunun 2 parça arasında bölünebileceğidir. Bunun için bir düzeltme, önceki karenin son 20b'sini bir sonrakine eklemektir:

<?php 
function is_ani($filename) { 
    if(!($fh = @fopen($filename, 'rb'))) 
    return false; 
    $count = 0; 
    //an animated gif contains multiple "frames", with each frame having a 
    //header made up of: 
    // * a static 4-byte sequence (\x00\x21\xF9\x04) 
    // * 4 variable bytes 
    // * a static 2-byte sequence (\x00\x2C) (some variants may use \x00\x21 ?) 

    // We read through the file til we reach the end of the file, or we've found 
    // at least 2 frame headers 
    $chunk = false; 
    while(!feof($fh) && $count < 2) { 
    //add the last 20 characters from the previous string, to make sure the searched pattern is not split. 
    $chunk = ($chunk ? substr($chunk, -20) : "") . fread($fh, 1024 * 100); //read 100kb at a time 
    $count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches); 
    } 

    fclose($fh); 
    return $count > 1; 
} 
İlgili konular