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 notes

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;
}
?>
moxley at moxleydata dot com
17 年前
我想找出 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;
}
?>
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;
}
ZeBadger
11 年前
以 100Kb 块读取文件的 is_ani 版本存在缺陷,因为帧结束标记可能被拆分到两个块之间 - 所以要小心。
josh [ a t ] OnlineComics [ d o t ] net
20 年前
我刚刚在我的服务器上安装了 gif2png,并且花了一点时间研究才发现...

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

如果安全模式开启则无法工作。如果您使用的是共享服务器,它很可能已经开启。但是,您不需要关闭安全模式,只需在 php.ini 文件中将 safe_mode_exec_dir 变量设置为安装 gif2png 的目录。然后您就可以从 PHP 脚本中执行该程序了。
unknown at hotmail dot com
21 年前
如果 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,因为它会导致系统存在严重的安全性漏洞。

享受!

Anze
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 is animated<BR>\n";
}
else
{
echo
"$thisfile is NOT animated<BR>\n";
}
}
?>

如果您需要,可以很容易地修改它来计算帧数。
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;
}
steve at stevedix dot de
18 年前
如果有人正在寻找 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
simon at shortpixel dot com
6 年前
解决当前 is_ani 函数问题的办法是将前一帧的最后 20b 添加到下一帧中

<?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;
}
?>
Malcolm Murphy
13 年前
希望这可以帮助使用函数检查动画 GIF 的人避免头疼。

我遇到了一些 GIF 使用不同的帧分隔符序列,\x00\x21,而不是官方标准 \x00\x2C。这似乎发生在使用 Photoshop CS5 保存的动画 GIF 中,虽然我不确定问题是否来自那里。

无论如何,我一直使用以下模式
"#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s"
它似乎涵盖了所有 GIF,希望不会误解。

干杯。
Anonymous
21 年前
回复:09-May-2002 11:31

似乎 gif2png 不再位于 http://www.tuxedo.org/~esr/gif2png/
我在 http://www.r1ch.net/stuff/gif2png/ 找到了一个 Win32 版本
(有关 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,大部分为空白)
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
Ady at freebsd dot ady dot ro
21 年前
FreeBSD 用户很幸运,可以通过 ports 系统在 GD2.x 中编译 GIF 支持。
您只需在编译 graphics/gd2 端口时导出“WITH_LZW=yes”全局变量,例如:

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

然后重新编译并(重新)安装 www/mod_php4 端口,您就可以开始使用了... :)

祝好!
senbei at terra dot es
22 年前
由于 gif 支持已从最新的 GD 库中删除,您仍然可以通过外部程序使用它。
我在某处读到关于使用 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,以便您对它执行任何操作。
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
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, "Error loading $imgname", $tc);
}
return $im;
}
geoffrey at poulet dot org
21 年前
经过几个小时的搜索,我终于找到一个可以将 JPG 转换为 GIF 的程序。
IJG - 独立 JPEG 组的 JPEG 软件
版本 6 支持 GIF(使用 LZW 读取和写入)
以及支持 GIF(仅写入,不使用 LZW)的版本 6b

文件名:jpegsrc.v6.tar.gz
Anonymous
10 年前
使用以下脚本生成(保留)动画 GIF,它修复了 GD 库动画问题。
http://www.gdenhancer.com/
anthony dot atkins at vt dot edu
24 年前
<?php

function myImageCreateFromGif($file_or_url) {

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

# 如果这是一个 URL,使用 fopen 获取文件数据,然后
# 保存到一个临时文件
if (preg_match("/(http|ftp):\/\//i", $file_or_url)) {
# 使用 fopen 打开文件,支持远程 URL
$input = fopen($file_or_url, "rb");

# 读取文件内容
# 将接受最多 10Mb 的文件,但可能会在之前得到
# EOF,我们必须以这种方式进行,因为
# filesize 不适用于 URL。唉。
$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);

}

# 如果不是 URL,我们可以直接打开图像
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