Search code examples
phpimagegdcron-taskimage-compression

PHP: scan directory, compress & overwrite images - script fails on production, produces just warnings on local


I have this code that is run as a cron task. Basically what it does (should) is go through a folder, find images that are larger than the specified size, rezise them and overwrite them.

When testing it locally (using same 1300+ images) it works. If I remove the @ error supressant on imagecreatefromjpeg and imagecreatefrom_png I get the following warnings:

    Warning: imagecreatefromjpeg(): gd-jpeg, libjpeg: recoverable error: 
    Invalid SOS parameters for sequential JPEG in 
    C:\xampp56\htdocs\svamz\static\uploaded\image_compress.php on line 70

    Warning: imagecreatefromjpeg(): './certificate/POCAJT4.jpg' is not a 
    valid JPEG file in 
    C:\xampp56\htdocs\svamz\static\uploaded\image_compress.php on line 70
   POCAJT4.jpg resize Failed!

This warning is output for some images, but mostly the images are compressed and these images with warnings are skipped.

The problem is that on a server (Apache2, PHP 5.6.40) the execution of the same code produces just a 500 HTTP error. No errors, no warnings (that's making this a pain in the ass to debug)

Source/Target directories are writable. I have also tested the code by changing the if statement to include only a portion of images by using filesize($imagePath) > 8000000 && filesize($imagePath) < 9000000 and that works fine on the server. But as soon I try a range of filesize that contains these problematic images it breaks back to 500.

I tried to get to the problem with try catch, I also used set_error_handler() to try and catch E_WARNING messages on server but with no results.

gd_info() is the same locally and on server.

I think it is unrelated but php -v (also error.log) along with it's normal output gives this: Failed loading /usr/local/lib/ZendGuardLoader5.6.so: /usr/local/lib/ZendGuardLoader5.6.so: cannot open shared object file: No such file or directory

ini_set('error_reporting', E_ALL);
ini_set('max_execution_time', 0);

$imagesDirectory = './certificate/'; //Source directory
$destinationDirectory = './certificate/'; //Destination directory
$newImageWidth = 1600;
$newImageHeight = 1200;
$quality = 80;

// Source image directory, loop through each Image and resize it.
if($dir = opendir($imagesDirectory)){        
    while(($file = readdir($dir))!== false){
        $imagePath = $imagesDirectory.$file;
        $destPath = $destinationDirectory.$file;
        $checkValidImage = @getimagesize($imagePath);
        //image exists, is valid & larger than X
        if(file_exists($imagePath) && $checkValidImage && filesize($imagePath) > 800000)
        {      
                // resize
                if(resizeImage($imagePath,$destPath,$newImageWidth,$newImageHeight,$quality))
                {                                        
                    echo $file.' resized<br>';                    
                } else{
                    echo $file.' resize Failed!<br>';
                }                
        }
    }
    closedir($dir);
}
}
//Function that resizes image.
function resizeImage($srcImage,$destImage, $maxWidth,$maxHeight,$quality)
{

// Get dimensions of source image.
list($origWidth, $origHeight, $type) = getimagesize($srcImage);

if ($maxWidth == 0) {
    $maxWidth  = $origWidth;
}

if ($maxHeight == 0) {
    $maxHeight = $origHeight;
}

// Calculate ratio of desired maximum sizes and original sizes.
$widthRatio = $maxWidth / $origWidth;
$heightRatio = $maxHeight / $origHeight;

// Ratio used for calculating new image dimensions.
$ratio = min($widthRatio, $heightRatio);

// Calculate new image dimensions.
$newWidth  = (int)$origWidth  * $ratio;
$newHeight = (int)$origHeight * $ratio;

$newCanvas = imagecreatetruecolor($newWidth, $newHeight);

switch(strtolower(image_type_to_mime_type($type)))
{
    case 'image/jpeg':                      
        $newImage = @imagecreatefromjpeg($srcImage);

        if (!$newImage) {
            return false;
        }

    // copy file
    if(imagejpeg($newCanvas,$destImage,$quality)) {
        imagedestroy($newCanvas);
        return true;
    }            
    break;

    case 'image/png':
        $newImage = @imagecreatefrompng($srcImage);

        if (!$newImage) {
            return false;
        }

        // copy file
        if(imagepng($newCanvas,$destImage, floor($quality / 10))) {
            imagedestroy($newCanvas);
            return true;
        }             
    break;

    default:
        return false;
    }

    try
    {
        // Resize Image
        imagecopyresampled($newCanvas, $newImage,0, 0, 0, 0, $newWidth, $newHeight, $origWidth, $origHeight);
    }
    catch (Exception $e)
    {
        print $e->getMessage();
        return false;
    }    
}

The goal is to compress & overwrite if it's possible and skip if it's not. I have no control over what images the end users are uploading. Any kind of help would be appreciated.


Solution

  • @misorude Could not do that at this time because the person with write permissions is away at this time.

    Turn out setting just ini_set('error_reporting', E_ALL); is not enough.

    This worked for me:

    ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
    error_reporting(E_ALL);
    

    The error was out of memory.