2008-11-11 23 views
39

Tôi hiện đang gặp phải một số sự cố khi đổi kích thước hình ảnh bằng GD.Tôi có thể phát hiện các hình động bằng php và gd không?

Mọi thứ hoạt động tốt cho đến khi tôi muốn đổi kích thước hình động gif, cung cấp khung hình đầu tiên trên nền đen.

Tôi đã thử sử dụng getimagesize nhưng chỉ cung cấp cho tôi thứ nguyên và không có gì để phân biệt giữa bất kỳ hình gif nào và hình động.

Không cần phải thay đổi kích thước thực tế cho các hình động, chỉ có thể bỏ qua chúng là đủ cho mục đích của chúng tôi.

Bất kỳ manh mối nào?

PS. Tôi không có quyền truy cập vào imagemagick.

Trân trọng!

Kris

+0

Tác giả cho biết anh không có ImageMagick. Nhưng đối với tất cả mọi người tìm kiếm bất kỳ cách nào để tìm hiểu xem một gif là hoạt hình và tìm thấy con đường của họ ở đây từ Google (như tôi): ImageMagick thực hiện điều này khá dễ dàng: http://php.net/manual/en/imagick.getimageiterations .php – Lukas

Trả lời

17

Có một đoạn ngắn gọn về mã trong PHP trang hướng dẫn của imagecreatefromgif() chức năng đó nên được những gì bạn cần:

imagecreatefromgif comment #59787 by ZeBadger

+0

Thật kỳ lạ khi tôi không tìm thấy nó trong gương mặc định của hướng dẫn sử dụng, nhưng xe tăng rất nhiều cho liên kết. Tôi đã sửa đổi chức năng và cung cấp cả áp phích gốc và bạn ghi nhận quyền tác giả trong nhận xét. – Kris

+0

Phiên bản được tối ưu hóa [ở đây] (http://it1.php.net/manual/en/function.imagecreatefromgif.php#104473). –

+1

Liên kết đó bị lỗi vì lý do nào đó, vẫn có thể tìm thấy ở đây mặc dù: http://php.net/manual/en/function.imagecreatefromgif.php # 104473 – robjbrain

5

Đây là chức năng làm việc:

/** 
* 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

Trong khi tìm kiếm một giải pháp cho cùng một vấn đề, tôi nhận thấy rằng trang php.net có theo dõi mã Davide và Kris đang đề cập đến, nhưng, theo tác giả, ít tốn nhiều bộ nhớ hơn và có thể ít đĩa hơn chuyên sâu.

Tôi sẽ nhân rộng nó ở đây, vì nó có thể được quan tâm.

nguồn: 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

Đã thêm hiệu chỉnh của Stevio bên dưới. –

+7

Một ghi chú mới được thêm vào đề cập rằng photoshop có thể sử dụng '\ x00 \ x21' thay vì' \ x00 \ x2C' –

+6

Ghi chú của Frank không thẳng thắn như trước. Để những người khác xem trang này, vui lòng xem giải thích đầy đủ của anh ấy tại [here] (http://www.php.net/manual/en/function.imagecreatefromgif.php#104473) – billmalarky

-1

Animated GIF phải có chuỗi sau

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

Đọc toàn bộ tập tin với file_get_contents thể mất quá nhiều bộ nhớ nếu các tập tin nhất định là quá lớn. Tôi đã tái xác định chức năng trước đó được đưa ra mà chỉ đọc đủ byte để kiểm tra khung và trả về ngay sau khi nó tìm thấy ít nhất 2 khung hình.

<?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 là hoàn toàn đúng sự thật. Quay lại sau đó mặc dù, các tập tin đã được nhỏ và đọc chúng trong toàn bộ của họ đã được nhanh hơn byte byte vì lý do mà tôi đã không nghiên cứu, hoặc không nhớ nghiên cứu. – Kris

+0

Lưu ý rằng 'fread ($ fp, 1) ===" \ x2c "|| fread ($ fp, 2) === "\ x21 \ xf9" 'trước tiên sẽ đọc một byte (A), kiểm tra nó là 0x2C, nếu không thì nó sẽ đọc hai byte ** sau ** byte A, không phải sau byte 0x00. Vì vậy, các chuỗi byte phù hợp là '00 2C' hoặc' 00 ** 21 F9' trong đó '**' có nghĩa là bất kỳ byte nào. Tôi không chắc chắn nếu điều này là có ý định hay không, nhưng nó không phải là rất rõ ràng từ mã. – Qtax

0

Đây là một cải tiến của câu trả lời bình chọn hàng đầu hiện tại nhưng tôi chưa có đủ nhận xét để nhận xét. Vấn đề với câu trả lời đó là nó đọc tệp trong các khối 100Kb và phần cuối của điểm đánh dấu khung có thể được chia thành 2 phần. Khắc phục cho điều đó là thêm 20b cuối cùng của khung hình trước vào khung tiếp theo:

<?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; 
} 
Các vấn đề liên quan