phplaravelamazon-s3

Laravel lowers the quality of the image by uploading amazon s3


I'm uploading images from the right to amazon s3, and when uploading the image loses quality. The images I want to save directly in my amazon s3 bucket, to optimize the disk space of my virtual machine I attach the source code.

public static function uploadToAmazon($photos, $ad_id)
{

    // Start Uploading to Amazon Cloud
    try {

        // Set loop couter
        $counter = 0;

        // Count photos
        $count_photos      = count($photos);

        // Manage each image
        foreach ($photos as $photo) {

            $preview_name   = 'preview_'   . $counter . '.jpg';
            $thumbnail_name = 'thumbnail_' . $counter . '.jpg';

            $image = Image::make($photo->getRealPath());

            // Get Ration
            $ratio        = $image->width() / $image->height();

            /**
            * Upload first thumbnails
            */
            $targetThumbWidth  = 270 * $ratio;
            $targetThumbHeight = $targetThumbWidth / $ratio;

            // Resize Thumbnail
            $thumbNewSize      = $image->fit($targetThumbWidth, $targetThumbHeight)->stream();

            Storage::disk('s3')->put('photos/'.$ad_id.'/thumbnails/'.$thumbnail_name, $thumbNewSize->__toString());
            Storage::disk('s3')->setVisibility('photos/'.$ad_id.'/thumbnails/'.$thumbnail_name, 'public');

            /**
            * Now upload Preview images
            */
            $resposniveSize = Uploader::resposniveSize($image->width(), $image->height());

            // Resize Thumbnail
            $previewNewSize      = $image->fit($resposniveSize[0], $resposniveSize[1])->stream();

            // Check if Watermark enabled or not
            $is_watermark   = Uploader::is_watermark();

            if ($is_watermark) {

                // Get Watermark Options
                $watermark = $is_watermark['watermark'];
                $position  = $is_watermark['position'];

                // Insert Watermark
                $image->insert($watermark, $position);

            }

            Storage::disk('s3')->put('photos/'.$ad_id.'/previews/'.$preview_name, $previewNewSize->__toString());
            Storage::disk('s3')->setVisibility('photos/'.$ad_id.'/previews/'.$preview_name, 'public');

            // New Counter
            $counter ++;

        }

        if($counter == $count_photos){

            // Return Previews Array
            $previews_array   = array();

            // Return Thumbnails Array
            $thumbnails_array = array();

            for ($i = 0 ; $i <= $count_photos - 1 ; $i++) { 

                array_push($previews_array, '/'.$ad_id.'/previews/preview_'.$i.'.jpg');
                array_push($thumbnails_array, '/'.$ad_id.'/thumbnails/thumbnail_'.$i.'.jpg');

            }

            // Return Data
            $data  = array(
                'previews_array'   => $previews_array, 
                'thumbnails_array' => $thumbnails_array, 
            );

            return $data;

        }else{

            return false;

        }

    } catch (\Exception $e) {

        /*echo $e->getMessage();
        die();*/
        return false;

    }

}

The truth that I can not find the moment in which the image loses quality, will be to resize?

This is the original picture enter image description here

This is the image that is in amazon s3 enter image description here

public static function resposniveSize($originalWidth, $originalHeight)
{
    // Get Ration
    $ratio        = $originalWidth / $originalHeight;

    // New Width
    $targetWidth  = intval(500 * $ratio);

    // New Height
    $targetHeight = intval($targetWidth / $ratio);

    return array($targetWidth, $targetHeight);
}

Solution

  • The problem you're having here is that you resize the Image to thumbnail size first. After which you scale it up to your preview size. This results in a loss of quality.

    So instead of using:

    $thumbNewSize = $image->fit($targetThumbWidth, $targetThumbHeight)->stream();

    Try to use this:

    $thumbNewSize = $image;
    $thumbNewSize->fit($targetThumbWidth, $targetThumbHeight)->stream();
    

    Same goes for $previewNewSize.

    You could also try to use ->resize($targetThumbWidth, $targetThumbHeight) instead of ->fit()