2008-11-11 5 views
39

현재 GD를 사용하여 이미지의 크기를 조정하는 데 문제가 있습니다.php 및 gd를 사용하여 애니메이션 GIF를 감지 할 수 있습니까?

검정색 배경의 첫 번째 프레임을 전달하는 애니메이션 GIF의 크기를 조정할 때까지 모든 것이 제대로 작동합니다.

나는 getimagesize을 사용해 보았습니다. 그러나 그것은 단지 어떤 크기와 어떤 gif와 애니메이션을 구별 할 수있는 것만 제공합니다.

실제 크기 조정은 애니메이션 GIF에는 필요하지 않습니다. 실제 크기 조정을 건너 뛰어도 우리의 목적에 충분할 것입니다.

실마리가 있습니까?

추신. 나는 imagemagick에 접근 할 수 없다.

종류와 관련,

크리스

+0

저자는 ImageMagick이 없다고 말했습니다. 하지만 모든 사람들이 gif가 애니메이션처럼 생겨서 Google 같은 곳에서 나처럼 발견되면 어떤 방법 으로든 검색 할 수 있습니다. ImageMagick은 매우 쉽게이 작업을 수행합니다. http://php.net/manual/en/imagick.getimageiterations .php – Lukas

답변

17

당신이 필요 있어야 imagecreatefromgif() 함수의 PHP 매뉴얼 페이지에 코드의 간단한 조각이있다 :

여기 imagecreatefromgif comment #59787 by ZeBadger

+0

내가 매뉴얼의 기본 미러에서 찾지 못했지만 링크를 위해 탱크가 많이 있습니다. 나는 함수를 수정하고 원래의 포스터와 주석을 모두 주석으로 보냈습니다. – Kris

+0

최적화 된 버전 [여기] (http://it1.php.net/manual/en/function.imagecreatefromgif.php#104473). –

+1

그 링크는 어떤 이유로 다운되었지만 여전히 여기에서 찾을 수 있습니다 : http://php.net/manual/en/function.imagecreatefromgif.PHP # 104473 – robjbrain

5

이의이 일 기능 :

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

동일한 문제에 대한 해결책을 찾고있는 동안 나는 php.net 사이트가 Davide와 Kris의 코드에 대한 후속 조치를 취하고 있음을 알아 차렸지만, 저자에 따르면 메모리 집약이 적고 디스크 - 강한.

관심이있을 수 있으므로 여기에서 설명하겠습니다.

소스 : 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의 수정을 추가했습니다. –

+7

최근 추가 된 메모는 포토샵이'\ x00 \ x2C '대신'\ x00 \ x21'을 사용할 수 있다고 언급했습니다. –

+6

프랭크 노트는 당연히 솔직한 말은 아닙니다. 이 페이지를 보는 다른 사용자는 [여기] (http://www.php.net/manual/en/function.imagecreatefromgif.php#104473) – billmalarky

-1

애니메이션 GIF의 필수가 다음 문자열

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

주어진 파일이 너무 큰 경우 너무 많은 메모리를 취할 수있다 file_get_contents에 전체 파일을 읽고 있습니다. 필자는 이전에 주어진 함수를 재구성하여 프레임을 검사하기에 충분한 바이트를 읽고 적어도 2 프레임을 찾자 마자 리턴합니다.

<?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은 절대적으로 사실입니다. 그 당시에는 파일이 작아서 전체를 읽는 것이 내가 연구하지 않았거나 연구를 기억하지 못하는 이유로 바이트 단위보다 빠릅니다. – Kris

+0

'fread ($ fp, 1) === "\ x2c"|| fread ($ fp, 2) === "\ x21 \ xf9"는 처음에 1 바이트 (A)를 읽습니다. 0x2C인지 확인합니다. 그렇지 않으면 ** 바이트 A 뒤에 2 바이트를 읽습니다. 0x00 바이트. 일치하는 바이트 문자열은 '00 2C' 또는'00 ** 21 F9'입니다. 여기서 **는 모든 바이트를 의미합니다. 이것이 의도 된 것인지 확실하지 않지만 코드에서 명확하지 않습니다. – Qtax

0

이것은 현재 최고 득표 답변의 개선이지만 아직 논평 할만한 평판이 충분하지 않습니다. 그 대답의 문제점은 파일을 100KB 청크로 읽고 프레임 마커의 끝 부분을 2 청크로 분할 할 수 있다는 것입니다. 이를 해결하려면 이전 프레임의 마지막 20b를 다음 프레임에 추가하십시오.

<?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; 
} 
관련 문제