Skip to content

Instantly share code, notes, and snippets.

@AndisGrossteins
Last active June 30, 2018 17:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndisGrossteins/e6e4806013845edaf79a3e18231891f7 to your computer and use it in GitHub Desktop.
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.
<?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