PHP: Changing the image quality when condition is met?
Asked Answered
T

2

2

I have a php script where the user can upload images. I want to make the script lower the image quality (jpeg) if the file size is bigger than 'X' kbytes.

Something like this:

if( $_FILES['uploaded_img']['size'] > $file_size_limit ){
     // code that lowers the quality of the uploaded image but keeps the image width and height
}

What is the best approach for this?

ps: I don't want to change image width and height.

Telephotography answered 23/9, 2012 at 23:55 Comment(2)
Read up on the image functions: php.net/manual/en/ref.image.php You could use imagejpeg to save the image in another quality, but you wouldn't know the original quality though.Crocidolite
yeah, i figured i couldn't tell the image quality. That's why I will only run this code when the file size exceeds a certain limit.Telephotography
A
4

Sure you can. Do something like this.

$upload = $_FILES['uploaded_img'];
$uploadPath = 'new/path/for/upload/';
$uploadName = pathinfo($upload['name'], PATHINFO_FILENAME);
$restrainedQuality = 75; //0 = lowest, 100 = highest. ~75 = default
$sizeLimit = 2000;

if($upload['size'] > $sizeLimit) {
    //open a stream for the uploaded image
    $streamHandle = @fopen($upload['tmp_name'], 'r');
    //create a image resource from the contents of the uploaded image
    $resource = imagecreatefromstring(stream_get_contents($streamHandle));

    if(!$resource)
        die('Something wrong with the upload!');

    //close our file stream
    @fclose($streamHandle);

    //move the uploaded file with a lesser quality
    imagejpeg($resource, $uploadPath . $uploadName . '.jpg', $restrainedQuality); 
    //delete the temporary upload
    @unlink($upload['tmp_name']);
} else {
    //the file size is less than the limit, just move the temp file into its appropriate directory
    move_uploaded_file($upload['tmp_name'], $uploadPath . $upload['name']);
}

This will accept any image format supported by PHP GD (Assuming that it's installed on your server. Most likely is). If the image is less than the limit, it will just upload the original image to the path you specify.

Angarsk answered 24/9, 2012 at 0:20 Comment(4)
WOW never thought this could be so simple in PHP. Thanks.Telephotography
I know this isn't directly related to my question, but is it necessary to 'unlink' the temporary file??? Wont the server do it automatically for me?Telephotography
Yes, the server will do it automatically. But why have two instances of the image on the server at once when you have the option to that script execution?Angarsk
This script seems OK except that it doesn't address the problem it tries to solve. The original may be too big simply because the image is large, in which case the resampling doesn't solve the problem and may even worsen it. In the very least, after the resampling, the new byte size should be compared to the original, and only used if it is better.Redskin
I
4

Your basic approach (which is implemented in Austin's answer) will work some of the time, but it's important to keep in mind that quality != file size. While they are generally correlated, it is perfectly possible (even common) that reducing the quality of a jpeg file will actually result in a LARGER file. This is because any JPEG uploaded to your system has already been run through the JPEG compression formula (often with a quality of 79 or 80). Depending on the original image, this process will create artifacts/alter the resulting image. When you run this already optimized image through the jpeg compression algorithm a second time it doesn't "know" what the original image looked like... so it treats the incoming jpeg as if it's a brand new lossless file and tries to copy it as closely as possible... including any artifacts created in the original process. Couple this with the fact that the original jpeg compression already took advantage of most of the "easy" compression tricks, it ends up being quite likely that compressing a second time results in a crappier looking image (copy of a copy problem) but not smaller file.

I did a few tests to see where the cutoff was, and unsurprisingly if the original image had a low compression ratio (q=99) a lot of space was saved re-compressing to q=75. If the original was compressed at q=75 (pretty common for graphic program defaults) then the secondary q=75 compression looked worse but resulted in virtually the same file-size as the original. If the original had a lower compression level (q=50) then the secondary q=75 compression resulted in a significantly larger file (for these tests I used three complex photos... obviously images with specific palates/compositions will have different performances going through these compressions). Note: I'm using Fireworks cs4 for this test... I realize that these quality indicators have no standardization between platforms

As noted in the comments below, moving from file formats like PNG to JPEG will usually end up significantly smaller (though without any transparency), but from JPEG -> JPEG (or GIF->JPEG, especially for simple or small-palate images) will often not help.

Regardless, you can still try using the compression method described by Austin, but make sure you compare the file-sizes of the two images when you're done. If there is only a small incremental gain or the new file is larger, then default back to the original image.

Inquisitionist answered 24/9, 2012 at 1:8 Comment(4)
Well, my only objective here is to prevent the user from uploading heavy image files, and this is the only solution I found for this so farTelephotography
You are right about instances of JPEGs, but converting a png -> jpg will generally yield a lot of difference in size.Angarsk
True. Not only that but I tried using this code with a png that has transparent background, the new jpeg came all messed up. But yet this is still better than simply telling the user they will have to compress the image and not doing anything.Telephotography
Yeah, jpegs can't support transparency, but moving from PNG->jpeg will generally result in savings... Just make sure that you're checking the compressed result to make sure it gives you significant enough savings to justify the lossiness.Inquisitionist

© 2022 - 2024 — McMap. All rights reserved.