从互联网下载图像时,最简单的方法是让 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 '发生错误。';
}
?>
以上示例将输出类似以下内容
从互联网下载图像时,最简单的方法是让 php 决定文件类型。因此,忘记使用 imagecreatefromjpg、imagecreatefromgif 和 imagecreatefrompng。相反,这是要走的路
<?php
$src = "http://www.varuste.net/tiedostot/l_ylabanneri.jpg";
$image = imagecreatefromstring(file_get_contents($src));
?>
(编者注:从 PHP 7.2.0 开始将支持 BMP。)
如果从 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 上的图像与 GD 时遇到了麻烦。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 函数将返回错误 "Data is not in a recognized format in"。
如果你遇到这种情况
$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 生成的 jpeg 文件在 EOF 0xFFF9 之前包含额外的數據。
我编写了这个类,允许你修复这些图片,以便可以使用 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 位),而 resample 函数需要真彩色,我猜……这就是为什么它适用于 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);
};
?>
在外部程序(在本例中为 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);