从互联网下载图像时,最简单的方法是让 PHP 决定文件类型。因此,忘记使用 imagecreatefromjpg、imagecreatefromgif 和 imagecreatefrompng。相反,这是要走的路
<?php
$src = "http://www.varuste.net/tiedostot/l_ylabanneri.jpg";
$image = imagecreatefromstring(file_get_contents($src));
?>
(PHP 4 >= 4.0.4, PHP 5, PHP 7, PHP 8)
imagecreatefromstring — 从字符串中的图像流创建一个新图像
imagecreatefromstring() 返回一个图像标识符,表示从给定的 data
中获得的图像。如果您的 PHP 版本支持,这些类型将自动检测:JPEG、PNG、GIF、BMP、WBMP、GD2、WEBP 和 AVIF。
data
包含图像数据的字符串。
成功时将返回一个图像对象。如果图像类型不受支持、数据不在可识别的格式中,或者图像已损坏且无法加载,则返回 false
。
imagecreatefromstring() 如果数据不在可识别的格式中,则会引发 E_WARNING 级别的错误。
示例 #1 imagecreatefromstring() 示例
<?php
$data = 'iVBORw0KGgoAAAANSUhEUgAAABwAAAASCAMAAAB/2U7WAAAABl'
. 'BMVEUAAAD///+l2Z/dAAAASUlEQVR4XqWQUQoAIAxC2/0vXZDr'
. 'EX4IJTRkb7lobNUStXsB0jIXIAMSsQnWlsV+wULF4Avk9fLq2r'
. '8a5HSE35Q3eO2XP1A1wQkZSgETvDtKdQAAAABJRU5ErkJggg==';
$data = base64_decode($data);
$im = imagecreatefromstring($data);
if ($im !== false) {
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
}
else {
echo 'An error occurred.';
}
?>
以上示例将输出类似于
从互联网下载图像时,最简单的方法是让 PHP 决定文件类型。因此,忘记使用 imagecreatefromjpg、imagecreatefromgif 和 imagecreatefrompng。相反,这是要走的路
<?php
$src = "http://www.varuste.net/tiedostot/l_ylabanneri.jpg";
$image = imagecreatefromstring(file_get_contents($src));
?>
[编辑说明:BMP 将从 PHP 7.2.0 开始支持。]
如果从 GD 中没有 “imagecreatefrombmp()” 不明显,那么此函数也不能处理普通的 BMP 文件。
我的网站允许匿名上传到网络可访问的位置(如果找到脚本,该位置将执行脚本)。
当然,我需要验证只接受无害的内容。我期望只有图像,所以我使用
<?php
$im = $imagecreatefromstring($USERFILE);
$valid = ($im != FALSE);
imagedestroy($im);
return $valid;
?>
imagecreatefromstring 似乎不支持 WebP 图像(在 PHP 7.2.10 上测试,GD 2.1.0 和 GD WebP 支持已启用)。
所以你们不要花一个小时试图弄清楚为什么当你们使用这个或其他 imagecreatefrom 函数时,你们的脚本总是会内存不足。当你们使用这些函数时,GD 会解压缩图像,这会导致你们的脚本内存不足。
如果你们下载原始图像并将其保存到计算机上的 jpeg 中,这样文件大小就会减小,GD 会自动将其转换为原始图像,并且你们可能会内存不足。
我知道很多人在使用来自 Sprint PPC6700 的图像时遇到了问题。jpeg 库总是会抛出一个关于 16 字节额外数据的错误。我决定在十六进制编辑器中查看一下,发现这些额外字节出现在 EXIF 数据的末尾。
通过删除这些额外数据,图像可以像普通图像一样被 GD 和 EXIF 扩展轻松操作。这也消除了使用 GIMP 时遇到的任何问题,GIMP 必须依赖于相同的 jpeg 库。
这里有一个函数可以检查图像是否来自 PPC6700,然后为你们删除额外数据。结果可以成功地与 imagecreatefromstring 一起使用
作者:Paul Visco
IM: paulsidekick
创建日期:2-12-06
function checkFixPPC6700($orig){
//获取文件内容
$data = file_get_contents($orig);
//如果它是一个 PPC 6700 图像,请删除多余的 16 位
if(strstr($data, "\x41\x70\x61\x63\x68\x65\x00\x48")){
//下一行可以是单个字符串,我将它拆分开,以便 php.net 上的表单可以接受它
$bad_data ="\x00\x10\x4A\x46" . "\x49\x46\x00\x01\x01" . "\x00\x00\x01\x00\x01\x00\x00";
return substr_replace($data, "", strpos($data, $bad_data),
strlen($bad_data));
} else {
//如果不是来自 PPC 6700,请返回未经修改的数据
return $data;
}
}
我使用动态生成的图像,这些图像需要在显示之前进行一些调整。因此,我做了一些基础工作,然后将图像存储在内存缓存(APC)中,稍后从缓存中再次加载图像“进入”GD,进行最终处理,然后显示图像。
由于我想避免大量的磁盘访问,我使用了输出缓冲函数
<?php
// 执行图像处理操作
// 开始缓冲
ob_start ( );
ImageGD ( $hImage );
$sImage = ob_get_contents ( );
ob_end_clean ( );
// 将内容放入缓存
// 从缓存中重新加载并重新创建图像
$hImage = imagecreatefromstring ( $sImage );
// 执行最终编辑操作并输出图像
?>
当然,这是一个简化的示例,但我只想分享这个想法。
从文件创建图像资源,无需知道图像类型
<?php
function imagecreatefromfile($imagepath=false) {
if(!$imagepath || !$is_readable($imagepath) return false;
return @imagecreatefromstring(file_get_contents($imagepath));
}
$img_resource=imagecreatefromfile($imagepath);
?>
许多网站在将 .jpg / .png 转换为 base64 时,会在 base64 字符串之前添加一些文字:"data:image/png;base64,"
如果你放任它们,PHP 函数会返回一个错误 "数据不是已识别的格式"。
如果你遇到这种情况
$image_string=str_replace("data:image/png;base64,","",$image_string);
$image_string = base64_decode($image_string);
$img = imagecreatefromstring($image_string);
一个简单的例子,有助于理解这个函数...
<?
$loadFile = "http://static.php.net/images/php.gif";
$im = imagecreatefromstring(file_get_contents($loadFile));
// 等同于 imagecreatefromgif($loadFile);
imagegif($im);
?>
该函数会尝试自动确定文件格式(jpg、gif、png....),如果失败则返回 false。
我运营着一个博客网站,允许用户从手机发布图片。出于某种原因,诺基亚 3220 在 EOF 0xFFF9 之前会生成带有额外数据的 JPEG 图片。
我编写了这个类,允许你修复这些图片,以便它们可以使用 GD 进行调整大小和操作。如果不应用修复,GD 和 GIMP 都会报告文件错误。它基本上会一直从垃圾部分中读取字节,直到文件成为有效的 JPEG 图片。以下是一个由诺基亚 3220 生成的坏图片示例,你可以用它来测试:http://www.shawnrider.com/moblog/cache/0854747001121624103.jpg
/*
作者:Paul Visco
主页:http://www.elmwoodstrip.com?u=paul
AIM: paulsidekick
备注:该文件允许你修复诺基亚 3220 图片手机生成的 JPEG 图片,以便可以使用 PHP 的 GD 库对其进行操作。
用法:只需实例化类,然后为每个图片调用 fix 方法。
例如:
$nokia = new nokia;
$nokia->debug ="y";
$nokia->fix("yourpic.jpg");
*/
类 nokia
{
public $file;
public $debug = "n";
public $dir_name = "";
private $img; // 从字符串创建的图片
private $str;
function fix($file)
{
// 设置要修复的文件
$this->file = $file;
// 将文件加载到字符串中
$this->str = file_get_contents($this->file);
// 测试它是否为诺基亚图片,或者是否之前已损坏
if (substr_count($this->str, chr(0x28).chr(0x36).chr(0x28).chr(0x2B)) == 0 || @imagecreatefromstring($this->str))
{
if ($this->debug =="y")
{
echo "\n<br />".$this->file." 不是损坏的诺基亚图片";
}
return true;
}
// 如果不存在且已指定,则为修复后的图片创建一个目录
if(!empty($this->dir_name) && !is_dir($this->dir_name))
{
@mkdir($this->dir_name, 0777);
}
// 从文件中删除垃圾数据
$this->eat($this->str);
// 将文件写回自身
file_put_contents($this->dir_name.$this->file, $this->str);
// 返回 true 表示已修复
return true;
}
function eat()
{
// 检查图片
$this->img = @imagecreatefromstring($this->str);
// 如果图片无法正常显示,则继续删除垃圾数据
while(!$this->img)
{
// 逐个删除错误字节
$this->str= substr_replace($this->str, "", -3, -2);
// 再次检查图片
$this->img = @imagecreatefromstring($this->str);
}
if ($this->debug =="y")
{
// 通知用户已修复
echo "\n<br />已删除垃圾数据! ".$this->file." 现在已修复,感谢 p:labs!";
}
return true;
}
}
关于上一个问题的说明(如果你还不知道的话):
GIF 是 256 色(或 8 位),而重新采样函数似乎需要真彩色... 这就是它对 JPG 起作用而对 GIF 不起作用的原因。
接下来... 你将一个字符串写入文件,打开文件(imagecreatefromgif),然后再次删除文件。
如果你使用 imagecreatefromstring($string),则可以跳过临时文件部分。
我解决从文件数据加载图片文件(无论是在本地站点还是从非本地协议)的唯一方法如下。我希望这能节省其他人调试和寻找良好示例的两个小时。
[PHP]
<?php
$sFile = "http://www.justgreatwine.co.uk/img/vineyard.jpg";
$imagedata = GetFileData($sFile); // 以 4k 块加载文件
/*=======输出=========*/
ob_start();
// 假设你已经在 $imagedata 中拥有图片数据
$length = strlen($imagedata);
header('Last-Modified: '.date('r'));
header('Accept-Ranges: bytes');
header('Content-Length: '.$length);
header('Content-Type: image/jpeg');
print($imagedata);
ob_end_flush();
/*======使用的函数======*/
function GetFileData($sFilePath){
$fp = fopen($sFilePath, 'rb') or die('404! 无法打开文件!');
$buf = '';
while(!feof($fp)){
$buf .= fgets($fp, 4096);
}
fclose($fp);
return $buf; // 如果失败则返回 False,否则返回最多 FileSize 字节的内容。
}
?>
[/PHP]
这是我用来从数据库 blob 字段创建缩略图的代码。诀窍是使用 "imagecreatefromstring()" 创建图片文件。
Jack Shieh
<?php
require("dbconfig.inc");
$id = $_GET['id'];
if($id) {
$link = @mysql_connect($host, $user, $password) or die("无法连接: " . mysql_error());
@mysql_select_db($dbname, $link);
$query = "select filetype, image from pictures where id = $id";
$result = @mysql_query($query);
$data = @mysql_result($result,0,"image");
$type = @mysql_result($result,0,"filetype");
Header( "Content-type: $type");
$size = 150; // 新图片宽度
$src = imagecreatefromstring($data);
$width = imagesx($src);
$height = imagesy($src);
$aspect_ratio = $height/$width;
if ($width <= $size) {
$new_w = $width;
$new_h = $height;
} else {
$new_w = $size;
$new_h = abs($new_w * $aspect_ratio);
}
$img = imagecreatetruecolor($new_w,$new_h);
imagecopyresized($img,$src,0,0,0,0,$new_w,$new_h,$width,$height);
// 确定图片类型并发送给客户端
if ($type == "image/pjpeg") {
imagejpeg($img);
} else if ($type == "image/x-png") {
imagepng($img);
} else if ($type == "image/gif") {
imagegif($img);
}
imagedestroy($img);
mysql_close($link);
};
?>
我发现,在 PHP 4.3.2 和 4.3.4 中,`imagecreatefromstring` 函数在处理大图片时会占用大量内存…
尝试使用这段代码处理一张大图片(比如 1MB 或更大)
<?php
$loadFile = "http://bigimage.jpg";//尝试使用一张大图片
$im = imagecreatefromstring(file_get_contents($loadFile));
imagejpeg($im);
?>
对于一张 400KB 的图片,我运行时设置了 16MB 的 `Mem_limit`,但对于一张 1.4MB 的图片,所需的 `mem_limit` 则需要超过 32MB
在外部程序(本例中为 gnuplot)中生成图形可能会导致问题。这是在深夜匆忙拼凑出来的解决方案。
<?php
// 从数据库中获取值,比如:
$vals = "1 2\\\\n4 8\\\\n"; # 等等
// 构建 `gnuplot_call` 变量,类似于:
$gnuplot_call = "echo \"set term png; plot '<echo -e \\\"$vals\\\" ' ti 'Updated with' with line ; \" | gnuplot";
ob_start();
passthru($gnuplot_call, $gnuplot_call_output);
$image = imagecreatefromstring(ob_get_contents());
ob_end_clean();
imagepng($image); # 显示
?>
我正在尝试让 `imagecreatefromstring` 函数支持 GIF 图片。当然,它是不行的。
我已经阅读了一些提示,但是无法使它们正常工作。
以下是根据以上提示尝试的代码:
---
header('Content-Type: image/gif');
header('Content-Disposition: inline; filename=file.gif');
$temp = tmpfile();
fwrite($temp, $line['image']);
$src_img = imagecreatefromgif($temp);
fclose($temp); // 这会删除文件
$dst_img = imagecreatetruecolor(100, 100);
imagecopyresampled($dst_img, $src_img, 0,0,0,0, 100,100, imagesx($src_img), imagesy($src_img));
imagegif($dst_img);
---
其中 `$line['image']` 是从我的 MySQL 数据库中获取的 GIF 图片…
如果有人能够让类似的代码正常工作,请提供一段可运行的代码,我将不胜感激!
如果可以排除临时文件,那就更好了…
以下是一段针对 JPEG 图片的可运行代码:
---
header('Content-Type: image/jpeg');
header('Content-Disposition: inline; filename=file.jpg');
$src_img = imagecreatefromstring($line['image']);
$dst_img = imagecreatetruecolor(100, 100);
imagecopyresampled($dst_img, $src_img, 0,0,0,0, 100,100, imagesx($src_img), imagesy($src_img));
imagejpeg($dst_img);