從網際網路下載影像時,最簡單的方式是讓 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 會解壓縮影像,這可能會導致您的腳本耗盡記憶體。
如果您下載 rawimage 並將其以 jpeg 格式儲存在電腦上,以便縮減檔案大小,GD 會自動將其轉換為原始格式,而您可能會耗盡記憶體。
我知道很多人在使用來自 Sprint PPC6700 的影像時遇到 GD 問題。jpeg 程式庫總是會拋出一個關於 16 個位元組的額外資料的錯誤。我決定在十六進位編輯器中研究一下,發現這些額外的位元組正好出現在 exif 資料的末尾。
透過移除這些額外的資料,GD 和 EXIF 擴充功能可以像處理正常影像一樣輕鬆地處理影像。這也解決了使用必須依賴相同 jpeg 程式庫的 GIMP 處理影像的任何問題。
以下是一個函數,會檢查影像是否來自 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。
我經營一個部落格網站,允許使用者從他們的手機發佈圖片。由於某些原因,Nokia 3220 生產的 jpeg 檔案在 EOF 0xFFF9 之前會有額外的資料。
我寫了這個類別,讓你可以修復圖片,以便它們可以使用 GD 調整大小和處理。如果不進行修復,GD 和 gimp 都會回報檔案錯誤。它基本上會從垃圾部分不斷吞噬位元組,直到檔案成為有效的 jpeg。這裡有一個 Nokia 3220 寫入的垃圾圖片範例,你可以用它來測試:http://www.shawnrider.com/moblog/cache/0854747001121624103.jpg
/*
作者:Paul Visco
首頁:http://www.elmwoodstrip.com?u=paul
AIM:paulsidekick
筆記:這個檔案可以讓你修復 Nokia 3220 圖片手機產生的 jpeg,以便它們可以使用 PHP 的 GD 函式庫來處理。
用法:只需實例化這個類別,然後為每個圖片呼叫 fix 方法。
例如:
$nokia = new nokia;
$nokia->debug ="y";
$nokia->fix("yourpic.jpg");
*/
class 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);
//測試看看是否為 Nokia 圖片,或者之前是否已損壞
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." 不是損壞的 Nokia 圖片";
}
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);
};
?>
在外部程式(在此例中為 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);