Reputation: 603
I built a quick recursive image scaling function. I need to have images under 1mb.
Trying to figure out how I'm using 128mb by using this method of scaling down a 6mb image.
Note that I've tried unset($image) in the while loop, no luck. Not sure how I'm causing a memory leak here. Even with jpeg compression ratio of 10:1 it's only half of the available memory.
function downsize($file, $max = 1048576) {
$deg = 0;
$scale = 0.10;
while(filesize($file) > $max) {
$info = getimagesize($file);
$exif = exif_read_data($file);
// var_dump($info);
// var_dump($exif);
if($info['mime'] == 'image/jpeg')
$image = imagecreatefromjpeg($file);
else if($info['mime'] == 'image/png')
$image = imagecreatefrompng($file);
if($exif['Orientation'] != 1) {
switch ($exif['Orientation']) {
case 3:
$deg = 180;
break;
case 6:
$deg = 270;
break;
case 8:
$deg = 90;
break;
}
}
$width = $info[0] - ($info[0] * $scale);
$image = imagescale($image, $width);
$image = imagerotate($image, $deg, 0);
if($info['mime'] == 'image/jpeg')
imagejpeg($image, $file);
else if($info['mime'] == 'image/png')
imagepng($image, $file);
clearstatcache();
}
return filesize($file);
}
The error I'm getting with PHP 7.3.6 is:
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted
Thanks for any insight or advice!
Upvotes: 1
Views: 229
Reputation: 2841
Lawrence Cherone's answer is correct, but let me give a little more information in mine as to why so much memory is being used.
Think of a pixel as an array with three values; R, G, and B values, each of which can be an integer between 0 and 255. That means each is an eight-bit value, so each pixel in the image takes up 24 bits. Now imagine you have an image which is at 4K HDTV resolution: 3840 x 2160 or 8,294,400 pixels, with each pixel taking up 24 bits, and you have 199,065,600 bits of data, or 24,883,200 bytes. If the image has transparency, that's another 8 bits per pixel…
Now the reason the file won't actually be that large is because of the JPEG or PNG compression applied to it. But image libraries can't do tasks like scaling to compressed images, so it has to uncompress the image into memory first so it can operate upon that uncompressed data. This is why doing operations on images which might only take up a few dozen kilobytes of disk space can easily eat up many megabytes of memory. And since we don't otherwise have fine-grained control over PHP's garbage collection - that is, when it frees up the memory of variables we're not using anymore - you should use imagedestroy()
to do so manually when working with images as Lawrence Cherone suggested.
Upvotes: 2
Reputation: 46602
You should call imagedestroy() between iterations so it clears the image resource from memory.
Upvotes: 4