Last active
June 30, 2018 17:44
-
-
Save AndisGrossteins/e6e4806013845edaf79a3e18231891f7 to your computer and use it in GitHub Desktop.
Function to allocate memory for image processing with PHP in a smart way.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Dynamically allocate memory based on image dimensions, bit-depth and channels | |
* Shamelessly stolen somewhere online years ago. | |
* Probably from https://alvarotrigo.com/blog/allocate-memory-on-the-fly-PHP-image-resizing/ | |
* | |
* @param string $filename Full path to a file supported by getimagesize() function | |
* @param int $tweak_factor Multiplier for tweaking required memory. 1.8 seems fine. More info: http://php.net/imagecreatefromjpeg#76968 | |
* @param string $original_name Used purely for reporting actual file name instead of uploaded temp file (e.g. /tmp/RaNd0m.tmp) | |
* | |
* @return bool true on success or if no memory increase required, false if required memory amount is too large | |
*/ | |
function setMemoryLimit($filename, $tweak_factor = 1.8, $original_name = null) { | |
$maxMemoryUsage = 512 * 1024 * 1024; // 512MB | |
$width = 0; | |
$height = 0; | |
$memory_limit = return_bytes(ini_get('memory_limit')); | |
$memory_baseline_usage = memory_get_usage(true); | |
// Getting the image info | |
$info = @getimagesize($filename); | |
if( empty($info) ) { | |
throw new Exception( sprintf('ERROR: getimagesize("%s") returned: %s', $filename, print_r($info, true)) ); | |
return false; | |
} | |
!empty($original_name) ? $filename = $original_name : $original_name; | |
$channels = isset($info['channels']) ? $info['channels'] : 3; | |
$width = $info[0]; | |
$height = $info[1]; | |
if($info['mime'] == 'image/png') { | |
$channels = 4; | |
} | |
if(!isset($info['bits'])) { | |
$info['bits'] = 16; | |
} | |
$bytes_per_channel = ( ($info['bits'] / 8) * $channels ); | |
// Calculating the needed memory | |
$new_limit = $memory_baseline_usage + ($width * $height * $bytes_per_channel * $tweak_factor + 1048576); | |
if( $new_limit <= $memory_limit ) { | |
return true; | |
} | |
/* We don't want to allocate an extremely large amount of memory | |
so it's a good practice to define a limit and bail out if new limit is more than that */ | |
if ($new_limit > $maxMemoryUsage) { | |
throw new Exception( sprintf( "Failed increasing memory limit to %dMB (max=%dMB) for file '%s' (%d x %d)", ceil( $new_limit / 1048576 ), ceil( $maxMemoryUsage / 1048576 ), $filename, $width, $height ) ); | |
return false; | |
} | |
$new_limit = ceil( $new_limit / 1048576 ); | |
// Updating the default value | |
ini_set('memory_limit', $new_limit.'M'); | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment