2017-10-17 95 views
4

使用imagecreatefromjpeg打開JPEG圖像很容易導致致命錯誤,因爲需要的內存不能使用memory_limit如何檢查jpeg是否適合內存?

A .jpg大小小於100Kb的文件很容易超過2000x2000像素 - 打開時大約需要20-25MB的內存。 「使用不同的壓縮級別,相同的」2000x2000px圖像可能會佔用磁盤5MB。

所以我顯然不能使用文件大小來確定它是否可以安全地打開。

如何確定文件是否適合內存打開之前,這樣我就可以避免致命錯誤?

+0

注:Q &A張貼部分回答這個:https://stackoverflow.com/questions/46797422/php-fatal-error-is-any-way-to-not-stop-script這是(正確)標記爲重複 - 它做了提出這個有趣的問題,但我無法在SO上找到答案。 – Mikk3lRo

+1

非常好的問題和答案 – Machavity

回答

4

根據幾種不同的來源,所需的存儲器最多爲每個像素5個字節,具體取決於比特深度等幾個不同的因素。我自己的測試證實這大致是正確的。

最重要的是有一些開銷需要考慮。

,通過檢查圖像尺寸 - 這很容易,而無需加載圖像做 - 我們可以大致估算所需的內存,它與(的估算)的可用內存這樣的比較:

$filename = 'black.jpg'; 

//Get image dimensions 
$info = getimagesize($filename); 

//Each pixel needs 5 bytes, and there will obviously be some overhead - In a 
//real implementation I'd probably reserve at least 10B/px just in case. 
$mem_needed = $info[0] * $info[1] * 6; 

//Find out (roughly!) how much is available 
// - this can easily be refined, but that's not really the point here 
$mem_total = intval(str_replace(array('G', 'M', 'K'), array('000000000', '000000', '000'), ini_get('memory_limit'))); 

//Find current usage - AFAIK this is _not_ directly related to 
//the memory_limit... but it's the best we have! 
$mem_available = $mem_total - memory_get_usage(); 

if ($mem_needed > $mem_available) { 
    die('That image is too large!'); 
} 

//Do your thing 
$img = imagecreatefromjpeg('black.jpg'); 

這只是表面上進行測試,所以我建議用不同圖像的很多進一步的測試和使用這些功能來檢查計算是在特定環境中相當正確的:

//Set some low limit to make sure you will run out 
ini_set('memory_limit', '10M'); 

//Use this to check the peak memory at different points during execution 
$mem_1 = memory_get_peak_usage(true);