PHP Conference Japan 2024

imagecreatefromgif

(PHP 4、PHP 5、PHP 7、PHP 8)

imagecreatefromgif從檔案或 URL 建立新影像

描述

imagecreatefromgif(string $filename): GdImage|false

imagecreatefromgif() 會傳回一個影像識別符,表示從給定的檔案名稱取得的影像。

注意

將 GIF 檔案讀入記憶體時,影像物件中只會傳回第一個影格。影像的大小不一定與 getimagesize() 所報告的大小相同。

提示

如果已啟用 fopen 封裝器,則可以使用 URL 作為此函式的檔案名稱。請參閱 fopen(),以取得有關如何指定檔案名稱的詳細資訊。請參閱 支援的協定與封裝器,以取得各種封裝器所具有的功能、使用注意事項,以及任何它們可能提供的預定義變數等資訊連結。

參數

filename

GIF 影像的路徑。

傳回值

成功時傳回影像物件,錯誤時傳回 false

變更日誌

版本 描述
8.0.0 成功時,此函式現在會傳回 GDImage 實例;先前,傳回的是 resource

範例

範例 #1 在載入 GIF 期間處理錯誤的範例

<?php
function LoadGif($imgname)
{
/* 嘗試開啟 */
$im = @imagecreatefromgif($imgname);

/* 看看是否失敗 */
if(!$im)
{
/* 建立空白影像 */
$im = imagecreatetruecolor (150, 30);
$bgc = imagecolorallocate ($im, 255, 255, 255);
$tc = imagecolorallocate ($im, 0, 0, 0);

imagefilledrectangle ($im, 0, 0, 150, 30, $bgc);

/* 輸出錯誤訊息 */
imagestring ($im, 1, 5, 5, 'Error loading ' . $imgname, $tc);
}

return
$im;
}

header('Content-Type: image/gif');

$img = LoadGif('bogus.image');

imagegif($img);
imagedestroy($img);
?>

上面的範例將輸出類似以下的內容

Output of example : Example to handle an error during loading of a GIF
新增註解

使用者貢獻的註解 20 則註解

15
frank at huddler dot com
13 年前
根據這裡和其他地方回報的問題更新的 is_ani

<?php
function is_ani($filename) {
if(!(
$fh = @fopen($filename, 'rb')))
return
false;
$count = 0;
//動畫 GIF 包含多個「影格」,每個影格都有一個由以下內容組成的標頭:
// * 一個靜態的 4 位元組序列 (\x00\x21\xF9\x04)
// * 4 個可變位元組
// * 一個靜態的 2 位元組序列 (\x00\x2C) (有些變體可能會使用 \x00\x21?)

// 我們讀取檔案直到到達檔案末尾,或我們找到
// 至少 2 個影格標頭
while(!feof($fh) && $count < 2) {
$chunk = fread($fh, 1024 * 100); //一次讀取 100KB
$count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches);
}

fclose($fh);
return
$count > 1;
}
?>
2
moxley at moxleydata dot com
18 年前
我想要找出 GIF 是黑白還是彩色,但我不想等 imagecreatefromgif() 解析 200k 檔案(約 1 秒)來取得色彩對應,所以我寫了這個函式來取得 GIF 中所有色彩的清單。希望對您有所幫助。

<?php
function getGIFColorMap($file)
{
$fp = fopen($file, 'r');
$buf = fread($fp, 1024);
fclose($fp);

// 計算顏色數量
// buf[10] 是顏色資訊位元組
$color_byte = ord($buf[10]);
$has_color_map = ($color_byte >> 7) & 1;
$color_res = (($color_byte >> 4) & 7) + 1;
$bits_per_pixel = ($color_byte & 7) + 1;
$color_count = 1 << $bits_per_pixel;

if (!
$has_color_map) return null;

// buf[13] 是顏色映射表的開始位置
$color_map_index = 13;
$map = array();
for (
$i=0; $i < $color_count; $i++) {
$index = $color_map_index + $i*3;
$r = ord($buf[$index]);
$g = ord($buf[$index + 1]);
$b = ord($buf[$index + 2]);
$map[$i] = array($r, $g, $b);
}
return
$map;
}
?>
2
hdogan at gmail dot com
7 年前
剛剛發現一些動態 GIF 並不包含 GCE(圖形控制擴展)。以下是重構後的 is_ani() 函數

<?php
/**
* 從給定的檔案指標資源或檔名中偵測動態 GIF。
*
* @param resource|string $file 檔案指標資源或檔名
* @return bool
*/
function is_animated_gif($file)
{
$fp = null;

if (
is_string($file)) {
$fp = fopen($file, "rb");
} else {
$fp = $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") {
/* 有些動態 GIF 不包含圖形控制擴展(以 21 f9 開始) */
if (fread($fp, 1) === "\x21" || fread($fp, 2) === "\x21\xf9") {
$frames++;
}
}
}

fclose($fp);

return
$frames > 1;
}
?>
2
ZeBadger
11 年前
以 100Kb 區塊讀取檔案的 is_ani 版本是有缺陷的,因為影格結束標記可能會在兩個區塊之間分割 - 所以要小心。
1
josh [ a t ] OnlineComics [ d o t ] net
21 年前
我剛剛在我的伺服器上安裝了 gif2png,並且我花了一點時間研究才發現這個...

passthru("$path/gif2png -O $image_path/image.gif")

如果安全模式開啟,將無法運作。 如果您使用共享伺服器,則很可能已經開啟。但是,您不需要關閉安全模式,只需在您的 php.ini 檔案中將 safe_mode_exec_dir 變數設定為您安裝 gif2png 的目錄。 然後您就可以從 PHP 腳本執行該程式。
1
unknown at hotmail dot com
22 年前
如果 GD 不支援 GIF,而且 gif2png 無法使用,而且您不是管理員,您可以像這樣在您的帳戶中安裝它

建立 do.php
<?
global $do;
passthru($do);
?>

然後上傳 gif2png-2.4.6.tar.gz,解壓縮並安裝它
do.php?do=tar+-xvzf+gif2png-2.4.6.tar.gz
do.php?do=gif2png-2.4.5/configure
do.php?do=make

然後移除除 gif2png 之外的所有檔案。 別忘了移除 do.php,因為它會是您系統中嚴重的安全漏洞。

Njoy!

Anze
4
ZeBadger
18 年前
我寫了這段程式碼來偵測 gif 檔案是否為動態。 我想我應該分享它 :-)

<?php

function is_ani($filename)
{
$filecontents=file_get_contents($filename);

$str_loc=0;
$count=0;
while (
$count < 2) # 找到第二個影格後就沒有繼續的意義了
{

$where1=strpos($filecontents,"\x00\x21\xF9\x04",$str_loc);
if (
$where1 === FALSE)
{
break;
}
else
{
$str_loc=$where1+1;
$where2=strpos($filecontents,"\x00\x2C",$str_loc);
if (
$where2 === FALSE)
{
break;
}
else
{
if (
$where1+8 == $where2)
{
$count++;
}
$str_loc=$where2+1;
}
}
}

if (
$count > 1)
{
return(
true);

}
else
{
return(
false);
}
}

exec("ls *gif" ,$allfiles);
foreach (
$allfiles as $thisfile)
{
if (
is_ani($thisfile))
{
echo
"$thisfile 是動態 <BR>\n";
}
else
{
echo
"$thisfile 不是動態 <BR>\n";
}
}
?>

如果您需要,可以很容易地修改它來計算影格的數量。
1
marianbucur17 at yahoo dot com
8 年前
我討厭建立一個改良版本的 frank at huddler dot com 的 is_ani 函數,它甚至在區塊之間也會保持分數。 希望這對您有幫助!

/**
* 檢查提供的檔案是否為動態 gif。
*
* @param string $fileName
* @return bool
*/
function isAnimatedGif($fileName)
{
$fh = fopen($fileName, 'rb');

if (!$fh) {
return false;
}

$totalCount = 0;
$chunk = '';

// 動態 gif 包含多個「影格」,每個影格都有一個由以下組成的標頭
// * 一個靜態的 4 位元組序列 (\x00\x21\xF9\x04)
// * 4 個可變位元組
// * 一個靜態的 2 位元組序列 (\x00\x2C)(有些變體可能會使用 \x00\x21 ?)

// 我們讀取檔案直到到達檔案結尾,或者我們已經找到至少 2 個影格標頭。
while (!feof($fh) && $totalCount < 2) {
// 一次讀取 100kb 並將其附加到剩餘的區塊中。
$chunk .= fread($fh, 1024 * 100);
$count = preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches);
$totalCount += $count;

// 只有在我們找到至少一個匹配項時,才執行此區塊,
// 且如果我們沒有達到所需的最大匹配數量。
if ($count > 0 && $totalCount < 2) {
// 取得最後一個完整表達式匹配項。
$lastMatch = end($matches[0]);
// 取得最後一個匹配項之後的字串。
$end = strrpos($chunk, $lastMatch) + strlen($lastMatch);
$chunk = substr($chunk, $end);
}
}

fclose($fh);

return $totalCount > 1;
}
1
steve at stevedix dot de
19 年前
如果有人正在尋找 Yamasoft gif 轉換工具

雖然 Yamasoft 的網站早已消失,但可以在以下網站找到程式碼
http://www.fpdf.org/phorum/read.php?f=1&i=9418&t=7568#9418

http://www.fpdf.org/download/php-gif.zip

http://phpthumb.sourceforge.net/index.php?source=phpthumb.gif.php
0
simon at shortpixel dot com
6 年前
針對目前 is_ani 函式的問題,一個解決方案是將前一個影格的最後 20 個位元組添加到下一個影格中

<?php
function is_ani($filename) {
if(!(
$fh = @fopen($filename, 'rb')))
return
false;
$count = 0;
//一個動畫 GIF 包含多個「影格」,每個影格都有一個
//由以下組成的標頭:
// * 一個靜態的 4 位元組序列 (\x00\x21\xF9\x04)
// * 4 個可變位元組
// * 一個靜態的 2 位元組序列 (\x00\x2C)(某些變體可能會使用 \x00\x21?)

// 我們讀取檔案直到檔案結尾,或者我們找到了
// 至少 2 個影格標頭
$chunk = false;
while(!
feof($fh) && $count < 2) {
//從前一個字串添加最後 20 個字元,以確保搜尋的模式不會被分割。
$chunk = ($chunk ? substr($chunk, -20) : "") . fread($fh, 1024 * 100); //一次讀取 100kb
$count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches);
}

fclose($fh);
return
$count > 1;
}
?>
0
Malcolm Murphy
13 年前
希望這能幫助使用函式檢查動畫 GIF 的人省去一些麻煩。

我遇到一些 GIF 使用不同的影格分隔符序列 \x00\x21,而不是官方標準的 \x00\x2C。這似乎發生在 Photoshop CS5 中儲存的動畫 GIF 中,儘管我不確定問題是否源自於此。

無論如何,我一直在使用這個模式
"#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s"
這似乎涵蓋了所有 GIF,希望不會產生誤判。

感謝。
0
Anonymous
21 年前
回覆:2002 年 5 月 9 日 11:31

gif2png 似乎不再位於 http://www.tuxedo.org/~esr/gif2png/
我找到了 Win32 版本,位於 http://www.r1ch.net/stuff/gif2png/
(對於 Unix 和原始碼,請參閱 http://catb.org/~esr/gif2png/

在 Win32 中,
passthru("gif2png $filename");
如果 gif2png.exe 在路徑中,則可以正常運作。
它將覆蓋帶有 .png 擴展名的檔案,因此請小心,或者像上面引用的文章中那樣使用臨時檔案(不帶 -O;在命令列輸入 "gif2png" 以取得選項)。

我在 PHP 中遇到超過預設的 30 秒執行時間限制的問題,所以我加入了這行
set_time_limit(0); // 一些奇怪的 GIF 需要很長時間(例如,一個 25K GIF,700x700,大部分空白)
0
fezber at yamasoft dot com
21 年前
對於只想支援 GIF 讀取(而非寫入)的使用者,但是
1) 不想修補 GD 函式庫
2) 不想重新編譯任何東西
3) 沒有權限安裝轉換套件
4) 任何其他原因...

我建立了一個小型 php 腳本(約 25KB),可讓您從檔案載入 GIF(您甚至可以在動畫 GIF 上指定影像索引),然後將其轉換為 PNG 或 BMP 檔案。

如果我舉一個例子

<?
include("gif.php");

$gif = gif_loadFile("./test.gif");

if($gif) {
// GIF 檔案已成功開啟
if(gif_outputAsPNG($gif, "./test.png")) {
// 現在,只需使用 ImageCreateFromPng...
$img = ImageCreateFromPng("./test.png");

if($img) {
header("Content-Type: image/jpeg");
ImageJPEG($img);
ImageDestroy($img);
}
else {
// 無法開啟 PNG
}
}
else {
// 無法將 GIF 轉換為 PNG...
}
}
else {
// GIF 未載入...
}
?>

當然,它比使用適當的軟體和/或函式庫慢,但對於偶爾讀取一些 GIF 檔案非常有用。

您可以在以下位置找到 gif.php 原始碼: http://www.yamasoft.com/php-gif.zip

Fabien
0
Ady at freebsd dot ady dot ro
21 年前
FreeBSD 使用者很幸運可以選擇通過 ports 系統在 GD2.x 中編譯 GIF 支援。
您所需要做的就是在編譯 graphics/gd2 port 時匯出 "WITH_LZW=yes" 全域變數,例如

# cd /usr/ports/graphics/gd2
# export WITH_LZW=yes
# make && make install

然後重新編譯並(重新)安裝 www/mod_php4 port,您就可以開始使用了... :)

祝您好運!
0
senbei at terra dot es
22 年前
由於較新的 GD 函式庫已移除 GIF 支援,您仍然可以通過外部程式使用它。
我曾在某處讀到關於使用 ImageMagick 的資訊,我自己也嘗試過,但它是一個相當大的套件,需要一些伺服器上沒有的 X11 函式庫。
我找到的另一個選擇是使用一個小程式 "gif2png" http://www.tuxedo.org/~esr/gif2png/
將 GIF 檔案轉換為 PNG 檔案。它可以在 Unix 和 dos/win32/winnt 下運作,並且非常簡單。
如果您需要修改使用者上傳的 GIF 檔案以將其儲存到您的網站中,只需使用此程式碼

$path=$_FILES["photo"]["tmp_name"];
passthru("/usr/bin/gif2png -d -O ".$path);
$src_img=imagecreatefrompng( dirname($path)."/".basename($path, ".gif").".png");

這會將 GIF 轉換為 PNG 並刪除 GIF 檔案,然後它會使用 GDlib 開啟 PNG,以便您可以對其執行任何操作。
-1
jason at null dot zzz
20 年前
感謝 yamasoft 的 GIF 轉 PNG 函式庫。它可以使用!但是,有一個錯誤。我將第 1003 行更改為

if(isset($this->m_img->m_bTrans) && $this->m_img->m_bTrans && ($nColors > 0)) {

因為我收到 m_bTrans 未定義的錯誤。我認為這是因為我的 GIF 沒有透明度。在我更新這行之後,就沒有問題了。

謝謝!

-j
-1
Anonymous
21 年前
function LoadGif ($imgname) {
$im = @ImageCreateFromGIF ($imgname); /* 嘗試開啟 */
if (!$im) { /* 看看是否失敗 */
$im = ImageCreate (150, 30); /* 建立一個空白影像 */
$bgc = ImageColorAllocate ($im, 255, 255, 255);
$tc = ImageColorAllocate ($im, 0, 0, 0);
ImageFilledRectangle ($im, 0, 0, 150, 30, $bgc);
/* 輸出錯誤訊息 */
ImageString($im, 1, 5, 5, "載入 $imgname 時發生錯誤", $tc);
}
return $im;
}
-1
geoffrey at poulet dot org
21 年前
經過數小時的搜尋,我終於找到一個可以將 JPG 轉換為 GIF 的程式。
IJG - 獨立 JPEG 小組的 JPEG 軟體
支援 GIF 的版本 6(讀取和寫入,帶有 LZW)
以及支援 GIF 的版本 6b(僅寫入,沒有 LZW)

檔案名稱是:jpegsrc.v6.tar.gz
-1
Anonymous
11 年前
使用以下腳本產生(保留)動畫 GIF,它可以修復 GD 函式庫的動畫問題。
http://www.gdenhancer.com/
-2
anthony dot atkins at vt dot edu
24 年前
<?php

function myImageCreateFromGif($file_or_url) {

$dummy_file = "/tmp/dummy.gif";

# 如果這是一個網址,使用 fopen 取得檔案資料,然後
# 儲存到一個虛擬檔案
if (preg_match("/(http|ftp):\/\//i", $file_or_url)) {
# 使用 fopen 開啟檔案,支援遠端網址
$input = fopen($file_or_url, "rb");

# 讀取檔案內容
# 將接受最大 10Mb 的檔案,但可能會在之前收到
# EOF,我們必須這樣做,因為
# filesize 不適用於網址。唉。
$image_data = fread($input, 10000000);

fclose($input);

# 將內容寫入虛擬檔案
$output = fopen("$dummy_file", "wb");
fwrite($output, $image_data);
fclose($output);

# 從虛擬檔案建立 gif 圖片
$image = ImageCreateFromGif($dummy_file);

# 移除虛擬檔案
unlink($dummy_file);

}

# 如果不是網址,我們可以簡單地直接開啟圖片
else {
$image = ImageCreateFromGif($file_or_url);
}

if (
$image) { return $image; }
else { return
0; }
}


if (!
$url) { $url = "http://scholar.lib.vt.edu/images/cornholio.gif";}
$image = myImageCreateFromGif($url);

if (
$image == "" || $image == 0) {
print
"<p>沒有圖片資料被回傳...</p>\n";
}
else {
header("Content-Type: image/gif\n\n");
ImageGif($image);
}

?>
To Top