Cloudinary Blog

Compressing, Resizing, and Optimizing Images in Laravel

Compressing, Resizing, and Optimizing Images in Laravel

Since performance is by and large the holy grail of software development, tools abound for building fast software, notably those for optimizing online media, most of which are images and videos. Optimization in this context means downsizing the media files but maintaining a satisfactory level of visual quality for delivery. The smaller those files are, the faster your website loads.

This article shows you how to optimize images in Laravel.

Set Up a Laravel Project

  1. Install Composer and PHP on your development or production machine and then run this command:

    Copy to clipboard
    composer create-project --prefer-dist laravel/laravel performance
  2. Go to the performance directory and rename the env.example file to .env.

  3. Run the project with the command php artisan serve.

Your Laravel project is now up and running.

Set Up Cloudinary’s Laravel SDK

With Cloudinary, you can efficiently optimize media assets—regardless of programming language. One reason is that, by default, Cloudinary automatically performs certain optimization steps on all transformed images. Plus, its integrated, fast-delivery capability through content delivery networks (CDNs) ensures that your images are seamlessly displayed on your viewers’ devices.

To enable file uploads and optimization with Cloudinary:

  1. Sign up for a free Cloudinary account, log in, and note your cloud name and API keys from the dashboard.

    media library

  2. Install Cloudinary’s Laravel SDK:

    Copy to clipboard
    composer require cloudinary-labs/cloudinary-laravel

Important: Be sure to follow the steps in the #Installation section. Publish the configuration file and add your Cloudinary credentials to the .env file of your app.

Set Up the Mechanics for File Uploads

  1. Create a file-upload controller (FileUpload Controller) in your project:

    Copy to clipboard
    php artisan make:controller FileUploadController
  2. Open the FileUploadController.php file and add a method for displaying the upload form:

    Copy to clipboard
    <?php
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    
    class FileUploadController extends Controller
    {
        public function showUploadForm()
        {
            return view('upload');
        }
    }
  3. Create an upload.blade.php file in the resources/views directory and populate the file with the code below:

    Copy to clipboard
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    
        <title>Laravel File Upload</title>
    
        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
    
        <!-- Styles -->
        <style>
            html, body {
                background-color: #fff;
                color: #636b6f;
                font-family: 'Nunito', sans-serif;
                font-weight: 200;
                height: 100vh;
                margin: 0;
            }
    
            .full-height {
                height: 100vh;
            }
    
            .flex-center {
                align-items: center;
                display: flex;
                justify-content: center;
            }
    
            .position-ref {
                position: relative;
            }
    
            .top-right {
                position: absolute;
                right: 10px;
                top: 18px;
            }
    
            .content {
                text-align: center;
            }
    
            .title {
                font-size: 84px;
            }
    
            .links > a {
                color: #636b6f;
                padding: 0 25px;
                font-size: 13px;
                font-weight: 600;
                letter-spacing: .1rem;
                text-decoration: none;
                text-transform: uppercase;
            }
    
            .m-b-md {
                margin-bottom: 30px;
            }
        </style>
    </head>
    <body>
        <div class="flex-center position-ref full-height">
            <div class="content">
                <div class="title m-b-md">
                    Laravel File Upload
                </div>
    
                @if ($message = Session::get('success'))
                    <div class="alert alert-success alert-block">
                        <button type="button" class="close" data-dismiss="alert">×</button>
                            <strong>{{ $message }}</strong>
                    </div>
                @endif
    
                <div class="links">
                     <form action="/upload" method="POST" enctype="multipart/form-data">
                        @csrf
                        <div class="row">
    
                            <div class="col-md-6">
                                <input type="file" name="image" class="form-control">
                            </div>
    
                            <div class="col-md-6">
                                <button type="submit" class="btn btn-success">Upload a File</button>
                            </div>
    
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </body>
    </html>

    On a successful upload, the code above displays the form along with a confirmation message. Concurrently, the code posts the form data to an /upload route in the routes/web.php file.

    Note: You'll see the related code later in this post.

  4. Go to the routes/web.php directory and add two routes: one to display the form and the other to process the file upload:

    Copy to clipboard
    Route::get('/upload', 'FileUploadController@showUploadForm');
    Route::post('/upload', 'FileUploadController@storeUploads');

Now reload the app and go to the /upload route. This page is then displayed:

Laravel File upload

Compress and Resize Images On Upload

Create an upload method in the FileUploadController.php file to ensure that compression and resizing of user-uploaded images occur by default on upload.

The code below resizes an image to 100 pixels in both width and height:

Copy to clipboard
public function upload(Request $request)
{
     $resizedImage = cloudinary()->upload($request->file('image')->getRealPath(), [
            'folder' => 'uploads',
            'transformation' => [
                      'width' => 100,
                      'height' => 100
             ]
])->getSecurePath();

    dd($resizedImage);
}

The code below resizes an image through smart cropping:

Copy to clipboard
public function upload(Request $request)
{
     $resizedImage = cloudinary()->upload($request->file('image')->getRealPath(), [
            'folder' => 'uploads',
            'transformation' => [
                      'width' => 100,
                      'height' => 100,
              ‘crop’ => ‘limit’
             ]
])->getSecurePath();

dd($resizedImage);
}

The code below, slated for images with people, focuses on those people through cropping and resizing:

Copy to clipboard
public function upload(Request $request)
{
     $resizedImage = cloudinary()->upload($request->file('image')->getRealPath(), [
            'folder' => 'avatar',
            'transformation' => [
                      'width' => 250,
                      'height' => 250,
              ‘gravity’ => ‘faces’,
              ‘crop’ => ‘fill’
             ]
])->getSecurePath();

    dd($resizedImage);
}

Optimize Images On Upload

The code below compresses and optimizes an image:

Copy to clipboard
public function upload(Request $request)
{
     $compressedImage = cloudinary()->upload($request->file('image')->getRealPath(), [
            'folder' => 'uploads',
            'transformation' => [
                      'quality' => auto,
                      'fetch_format' => auto
     ]
])->getSecurePath();
dd($resizedImage);
}

Setting the auto value for the fetch_format and quality attributes automatically compresses and optimizes the image in the best way, balancing its visual quality.

Note: As a rule, with fetch_format and quality set to auto, Cloudinary picks WebP or JPEG-XR as the display format for Chrome or IE, respectively. However, if the quality algorithm determines that PNG-8 or PNG-24 is optimal, Cloudinary might pick either of them for display.

Here’s the original, uncompressed picture with a size of 2.58 MB:

Ruby:
Copy to clipboard
cl_image_tag("eden_group.jpg")
PHP:
Copy to clipboard
cl_image_tag("eden_group.jpg")
Python:
Copy to clipboard
CloudinaryImage("eden_group.jpg").image()
Node.js:
Copy to clipboard
cloudinary.image("eden_group.jpg")
Java:
Copy to clipboard
cloudinary.url().imageTag("eden_group.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('eden_group.jpg').toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("eden_group.jpg")
React:
Copy to clipboard
<Image publicId="eden_group.jpg" >

</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="eden_group.jpg" >

</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="eden_group.jpg" >

</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.BuildImageTag("eden_group.jpg")
Android:
Copy to clipboard
MediaManager.get().url().generate("eden_group.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().generate("eden_group.jpg")!, cloudinary: cloudinary)
Eden group

Here’s the compressed version with a size of 918 KB:

Ruby:
Copy to clipboard
cl_image_tag("eden_group.jpg", :quality=>"auto")
PHP:
Copy to clipboard
cl_image_tag("eden_group.jpg", array("quality"=>"auto"))
Python:
Copy to clipboard
CloudinaryImage("eden_group.jpg").image(quality="auto")
Node.js:
Copy to clipboard
cloudinary.image("eden_group.jpg", {quality: "auto"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().quality("auto")).imageTag("eden_group.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('eden_group.jpg', {quality: "auto"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("eden_group.jpg", {quality: "auto"})
React:
Copy to clipboard
<Image publicId="eden_group.jpg" >
  <Transformation quality="auto" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="eden_group.jpg" >
  <cld-transformation quality="auto" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="eden_group.jpg" >
  <cl-transformation quality="auto">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Quality("auto")).BuildImageTag("eden_group.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().quality("auto")).generate("eden_group.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setQuality("auto")).generate("eden_group.jpg")!, cloudinary: cloudinary)
Eden Group Compressed

The two pictures look the same even though the second one has undergone compression that reduced its size by almost 2 MB.

Leverage More Cloudinary Capabilities

Cloudinary helps you administer the entire spectrum of your media’s lifecycle, end to end, from upload and transformation to optimization and delivery. Do check it out.

Recent Blog Posts

Automation Frees Up PetRescue’s Staff to Help Pets Find Their Forever Homes

As we spend more time at home, many of us are adopting pets for the joy, companionship and a surprising range of health benefits. In Australia, where our nonprofit customer PetRescue is located, there’s a shortage of pets to adopt. Last August, the Guardian reported that dog shelters in Australia emptied and adoption fees for puppies were running as high as $AUS1800.

Read more
Cloudinary and Contentful Make Modern Content Management Easier

I am pleased to share that Cloudinary and Contentful have joined forces to further streamline the creation, processing, and delivery of online content through Cloudinary’s digital asset management (DAM) solution and advanced transformation and delivery capabilities for images and video. What’s more, the partnership delivers a headless approach to DAM. By leveraging APIs for media management tasks, marketers and developers alike benefit from an integrated stack of optimized assets for optimization and automation. As a result, page loads are fast and beautiful, and at scale—with less overhead and effort.

Read more
Introducing Cloudinary's Nuxt Module

Since its initial release in October 2016 by the Chopin brothers as a server-side framework that runs on top of Vue.js, Nuxt (aka Nuxt.js) has gained prominence in both intuitiveness and performance. The framework offers numerous built-in features based on a modular architecture, bringing ease and simplicity to web development. Not surprisingly, Nuxt.js has seen remarkable growth in adoption by the developer community along with accolades galore. At this writing, Nuxt has earned over 30K stars on GitHub and 96 active modules with over a million downloads per month. And the upward trend is ongoing.

Read more
How Quality and Quantity can go Hand in Hand

When it comes to quality versus quantity, you’ll often hear people say, “It’s the quality that counts, not the quantity”. While that’s true in many situations, there are also cases where you want both quality and quantity. You may have thousands of images on your website and you want them all to look great. This is especially important if your website allows users to upload their own content, for example, to sell their own products or services. You don't want their poor quality images to reflect badly on your brand.

Read more
Product Videos 101: What Makes Them Great?

A product’s benefits and usage, including its value proposition, features, and instructive details, are best demonstrated through video. Product-video types vary, depending on the funnel, channel, and audience, the most popular ones being demos, reviews, installation, and how-tos.

Read more