PHP處理高分辨率圖片的問題

PHP技術大全 / 2019-03-15 14:53:47

今天小伙伴在群里問了這么一個問題:

出現這種情況就是因為內存不足, PHP 程序直接退出了,報錯大概如下:

上圖的意思就是說,我們能使用的內存最大是8M,但是處理這個圖片還需要額外的41bytes,就會導致內存不足,這是一個很嚴重的錯誤。在對圖片進行操作前需要將圖片的所有信息讀入內存中,同時還會使用另一部分內存同于處理計算并緩存輸出,所以內存大小的使用還是和圖片的大小有關。

PHP 中圖片的處理都是使用了 GD 庫,這個庫提供了很多方法讓 PHP 可以更方便地對圖片進行操作,支持的圖片格式如下:

回到一開始的問題,那個小伙伴需要處理高分辨的圖片,圖片大小必然很大,所以就會出現內存不夠的情況,解決方法還是有很多的。

1. 設置圖片最大可上傳的大小

前端上傳前可以先檢測下大小,如果超過最大值直接就不請求接口,同時為安全起見,后端接收到請求后也要檢測大小,防止程序異常退出。

2. 壓縮圖片

3. 關閉 memory_limit

群里的小伙伴最后使用了一種 簡單粗暴的方式 解決了該問題,直接在PHP中關閉 memory_limit :

set_time_limit(0);
@ini_set('memory_limit','-1');

這樣雖然解決了問題,但不優雅也不安全,同樣在 php.ini 配置文件中將 memory_limit 的值設置很大也能解決:

memory_limit = 256M

PHP代碼中也可以這樣設置:

ini_set('memory_limit', '256M');

上面我們將 memory_limit 參數固定了,這就帶來一個弊端,因為大多數情況下不需要這么大的內存,有點浪費資源,最好的做法就是根據需要來設置 memory_limit ,我寫了一個如下方法可供參考:

public function setMemoryLimit($filename){
// 控制執行時間
set_time_limit(50);

$maxMemoryUsage = 256M;
$width = 0;
$height = 0;
$size = ini_get('memory_limit');

// 獲取圖片大小
list($width, $height) = getimagesize($filename);

// 計算需要的內存,并轉換成'M'單位
// 4 因為png圖片一個像素有4字節
// 1.5 是一個調整因子,因為memory_limit不是那么精確
// 詳細可以查看: http://php.net/imagecreatefromjpeg#76968
$size = $size + floor(($width * $height * 4 * 1.5 + 1048576) / 1048576);

if ($size > $maxMemoryUsage){
$size = $maxMemoryUsage;
}

// 更新
ini_set('memory_limit',$size.'M');
}

最后說一下,網上說 GD 庫是比較耗內存的,但我這里沒有做過測試。Github上有個 C 的項目叫 libvips/libvips :

可以在不占用很多內存的情況下提高圖片處理的速度,這是地址:http://github.com/libvips/libvips,有時間可以學習下。

更多精彩

敬請關注“PHP技術大全”微信公眾號


4399小游戏上海麻将连连看 天津时时20180806开奖结果 2018最新白小姐 内快三开奖结果 3d试机号走势图大全 内蒙快三开奖历史查询 550678香港开奖结果天线宝宝 新疆时时开走势图 北京时时彩开奖结果查询结果 河北福利彩票快三开奖结果走势图 公式规律开奖结果历史纪录