Image compression without changing content format (png, jpeg, gif, webp)

Asked

Viewed 554 times

2

The difference from this question to duplicates: keep the content format (png, jpeg, gif, webp), in order not to harm images with layers, transparency, etc. The others do not have.


I have a file upload script, where I save the file to a folder, and write the address to the database:

if (!empty($_FILES['anexo']['name']) && ($fass[0]['status'] != 'C' && $fass[0]['status'] != 'F'))
{
        $arqNome = $_FILES['anexo']['name'];
        $extpat  = pathinfo($_FILES['anexo']['name']);
        $ext     = $extpat['extension'];

        $uploaddir  = $_SERVER['DOCUMENT_ROOT'].'/sys/files/';
        $uploadfile = $tId . '-' . time();
        $uploadatt  = $uploaddir . $uploadfile . '.' . $ext;

        if (move_uploaded_file($_FILES['anx']['tmp_name'], $uploadatt)) 
        {
            $dir = str_replace('\\', '\\\\', $uploaddir);
            $arq = $uploadfile;
            $att = $arq . '.' . $ext; // $dir

            if ($attc -> attachments($tId,$arqNome,$att,$solicitante))
            {
                header('location:../t_vis.php?id='. $tId);
            }
        }
}

I’ve been checking, and there are attachments images who are very large.

I would like to "compress/decrease" the image, as for example Whatsapp does, but of course, without losing the image quality, maintaining file type (jpg, png, etc), so does not "spoil" the original image with the loss of layers, transparency, etc.

  • There are native functions for this purpose?
  • There are libraries?
  • There are other ways?
  • compress/decrease the image without losing image quality and without changing the type is impossible... some information needs to be removed or decreased, such as file metadata information (photo location, comments, etc), resolution and number of colors, for example.

1 answer

4


Just use for each image the functions for each format:

For PNG

For JPEG

To GIF

For WEBP (requires PHP 5.4+)


There are other clear formats, such as BMP and WBMP, but they are not good formats to work with WEB, since it usually has no compression which makes a simple image very heavy.


Working without losing transparency

Use imagecreatefrompng can cause loss of transparence, so to avoid loss use:

imagealphablending (resource $image , true);
imagesavealpha (resource $image , true);

An example of code to reduce images with PHP in different formats

Following the example of calculating the @Bacchus:

<?php
function image_resize($path, $width = 200, $height = 200, $save = null, $quality = 100)
{
    $details = getimagesize($path);

    if (!$details) {
        trigger_error('Imagem inválida');
        return false;
    }

    $width_orig = $details[0];
    $height_orig = $details[1];

    // Calculando a proporção
    $ratio_orig = $width_orig / $height_orig;

    if ($width / $height > $ratio_orig) {
        $width = $height * $ratio_orig;
    } else {
        $height = $width / $ratio_orig;
    }

    if (is_string($save) === false) {
        $save = null;
        header('Content-Type: ' . $details['mime']);
    }

    $image_p = imagecreatetruecolor($width, $height);

    switch ($details['mime']) {
        case 'image/jpeg':
            $image = imagecreatefromjpeg($path);
            break; 
        case 'image/gif': 
            $image = imagecreatefromgif($path);
            break; 
        case 'image/png': 
            $image = imagecreatefrompng($path);
            break;
        case 'image/webp': 
            $image = imagecreatefromwebp($path);
            break;
        default:
            trigger_error('Formato não suportado');
            $image_p = null;
            return false;
    }

    imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);

    if ( in_array($details['mime'], array('image/png', 'image/webp')) ) {
        imagealphablending($image_p, true);
        imagesavealpha($image_p, true);
    }

    switch ($details['mime']) {
        case 'image/jpeg':
            imagejpeg($image_p, $save, $quality);
            break; 
        case 'image/gif': 
            imagegif($image_p, $save);
            break; 
        case 'image/png': 
            imagepng($image_p, $save, $quality);
            break;
        case 'image/webp': 
            imagewebp($image_p, $save, $quality);
            break;
    }
}

Example of using to copy a JPEG image to a new smaller one:

image_resize('bar.jpg', 200, 200, 'bar_1.jpg');

To overwrite an image just use the same name:

image_resize('bar.jpg', 200, 200, 'bar.jpg');

The first 200 would be the maximum width, and the second is the maximum height.

  • In the case of the resize, could you maintain the image ratio instead of setting height and width and risk distorting? In the "quality" property, he references what? Because, for example, I have an image that would already be in low quality, so I could not reduce more. Would that be in pixels (resolution)? What he considers?

  • @RBZ is just what $width and $height do, they are the maximum sizes, that is to say when decreasing keeps the ratio (ratio), unless the code is with some BUG, the $quality can be kept at 100 if the image is already bad, the PHP GD is not so good to work with checking the current quality, there are specialized software for this, but no longer would be with PHP, would be with terminal + exec(); PHP

  • Jeez, I’m sorry, I don’t understand... Let’s assume that the image is 800x600, but I "don’t know" that, because they will upload various formats and sizes right!? If I catch a width and height it will distort because they are not all equal. Or am I not obliged to set them? As for quality, the same thing. I’ll have pictures, ex. , UHD and HD, if the quality is 90, will reduce them or the quality recognizes a standard, type, quality 90 is HD resolution, 95 Fullhd, etc

  • Or it would be proportional quality. For example, 90 would be 90% of the current quality. Then considering the way he works with quality, I could also work with the tamanho file, so up to 1mb file, use 90 quality, above that, use 85, and so on...

  • @RBZ yes, the current one, but the GD compression system is not smart, it doesn’t have much to do, I recommend using between 92 and 95 for JPEG, for other formats it can vary a lot, even more PNG.

  • @RBZ what is the maximum width and height you want the image to have?

  • My focus would be on file size, so I wouldn’t even have to mess with the ratio. I am seeing that the idea would be to check the size first, and see the need for reduction, then the type (extension) to maintain in an acceptable quality range. But to understand the ratio... if I set only one measure (width or height), the other it will make proportional?

  • @RBZ use getimagesize and see if it is smaller or larger, if it is larger runs, although it can be implemented in code.

  • @RBZ will change the code so that when the image is equal to or less than the height and width mentioned in the arguments it does only the imagecopyresampled, there are no guarantees that GD will decrease the size of the photo, as I have said before, but in the case of digital camera images maybe wipes a lot of things

  • My fear is to lose proportion and distort. Have you ever tested whether it maintains proportion? If inform only the width or height it will make the other proportional?

Show 5 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.