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

今天小夥伴在羣裏問了這麼一個問題:

出現這種情況就是因爲內存不足,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

libvips/libvips

libvips/libvips readme

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章