2017-10-17 73 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);