PHP - Compress Image to Meet File Size Limit

五迷三道 提交于 2020-01-11 07:55:27

问题


I have to upload image files that meet a max width dimension and max file size.

I have the code that checks width size and resizes the image to meet the max image width.

However, when I am saving the file I can set the quality

imagejpeg( $imgObject , 'resized/50.jpg' , 50 ); //save image and set quality

What I would like to do is avoid setting a standard quality, as the images being submitted vary highly from quality and may be low to begin with.

The quality of the image should be set as high as possible without going over the max file size limit.

The only solution I have is to save several versions of the image at varying qualities, check each file size and pick the best one. This works but is very slow and process intensive.

Any suggestions on how this could be done better?

Thanks


回答1:


Here is a way to achieve that. It does not save a file until it is satisfied that the file size will be lower than the specified maximum.

$original_file = 'original.jpg';
$resized_file = 'resized.jpg';
$max_file_size = '30000'; // maximum file size, in bytes

$original_image = imagecreatefromjpeg($original_file);

$image_quality = 100;

do {
    $temp_stream = fopen('php://temp', 'w+');
    $saved = imagejpeg($original_image, $temp_stream, $image_quality--);
    rewind($temp_stream);
    $fstat = fstat($temp_stream);
    fclose($temp_stream);

    $file_size = $fstat['size'];
}
while (($file_size > $max_file_size) && ($image_quality >= 0));

if (-1 == $image_quality) {
    echo "Unable to get the file that small. Best I could do was $file_size bytes at image quality 0.\n";
}
else {
    echo "Successfully resized $original_file to $file_size bytes using image quality $image_quality. Resized file saved as $resized_file.\n";
    imagejpeg($new_image, $resized_file, $image_quality + 1);
}

This requires no file to be written until you've successfully found the ideal compression ratio.

This loop starts with an $image_quality of 100, then counts downward trying each new value on a temporary in-memory buffer. If gets down to trying 0 and the file would still be too big, it returns an error message. Otherwise, if it gets to a value that works, it reports that and saves the new file using that image quality setting.

If you're feeling adventurous, you could implement a binary search algorithm to find the ideal compression ratio more quickly, but this quick-fix gives the same result, albeit possibly a tad slower.




回答2:


No. It's the optimum possible.




回答3:


Unfortunately, estimating final file size isn't something you can do as you have no access to the JPEG encoder's internal state.

One thing you can do is compress a smaller version of the image and extrapolate from there. Reducing the width and height by four means the computer has to deal with only one sixteenth of the pixels. The trick here is how to prepare a representative test image. Scaling the image down using imagecopyresampled() or imagecopyresized() won't work. It changes the compression characteristic too much. Instead, what you want to do is copy every fourth 8x8 tile from the original image:

$width1 = imagesx($img1);
$height1 = imagesy($img1);
$width2 = floor($width1 / 32) * 8;
$height2 = floor($height1 / 32) * 8;
$img2 = imagecreatetruecolor($width2, $height2);
for($x1 = 0, $x2 = 0; $x2 + 8 < $width2; $x1 += 32, $x2 += 8) {
    for($y1 = 0, $y2 = 0; $y2 + 8 < $height2; $y1 += 32, $y2 += 8) {
        imagecopy($img2, $img1, $x2, $y2, $x1, $y1, 8, 8);
    }
}

Compress the smaller image at various quality levels and get the respected file sizes. Multiplying them by 16 to should yield a reasonably good estimate of what you would get with the original image.



来源:https://stackoverflow.com/questions/24872013/php-compress-image-to-meet-file-size-limit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!