Create Thumbnail in Laravel Using Intervention Image Library

On the website, we always deal with images. Based on the website’s structure, we use different versions of images. It’s always a good practice to create distinct versions aka thumbnails of a single image. These thumbnails can be displayed depending on the container size. Showing an image that fits the container size saves bandwidth and improves page load time. Putting a large-size image in a small container is a bad practice and compromises page speed. So, it’s beneficial to create multiple thumbnails of an image and use the appropriate version wherever necessary.

The Intervention Image is a free and popular package for image manipulation. It’s used to generate thumbnails from the image. In this article, we study how to create a thumbnail in Laravel using the Intervention Image library. Under the hood, this package uses the GD library and Imagick for image manipulation.

For this tutorial, I will create 3 thumbnails – small, medium, and large with sizes 150*93, 300*185, and 550*340 respectively. You may change these sizes as per your requirement.

Getting Started

To get started, you first need to install the Intervention Image library. Open the terminal in your project root directory and run the command below:

composer require intervention/image

After installing the library, go to the config/app.php file and add the following lines to it.

Include the service providers of the package in the $providers array.

Intervention\Image\ImageServiceProvider::class

Add the package’s facade to the $aliases array.

'Image' => Intervention\Image\Facades\Image::class

Next, to store the images we require a directory. Head over to the terminal and run the command:

php artisan storage:link

This command creates a symbolic link from public/storage to storage/app/public. Inside this public/storage folder, I’ll upload the original image and its thumbnails.

Create a Thumbnail in Laravel

We are done with the basic setup and can now write the actual code. Let’s create the HTML form in the image.blade file.

@if (session('success'))
    <strong>{{ session('success') }}</strong>
@endif

<form action="{{ url('store') }}" method="post" enctype="multipart/form-data">
    @csrf
    <p>
       Upload Image: <input type="file" name="profile_image" />
    </p>
    <button type="submit" name="submit">Submit</button>
</form>

Here I set form action to store route. I’ll map this route with the ImageController. Run the command to create ImageController.

php artisan make:controller ImageController

Next, define the following routes in the routes/web.php file.

Route::get('image', 'ImageController@index');
Route::post('store', 'ImageController@store');

In the ImageController, add the Image facade and call the view from the index() method.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Image;

class ImageController extends Controller
{
    public function index()
    {        
        return view('image');
    }
}

By adding the facade, we are able to use methods of the Intervention Image library.

In the below code, I will upload the image in two places. The original image goes directly inside the storage/profile_images folder and the thumbnails will be stored under the storage/profile_images/thumbnail directory. We first upload the original image in the thumbnail folder and then resize it on the fly.

public function store(Request $request)
{
    if($request->hasFile('profile_image')) {
        //get filename with extension
        $filenamewithextension = $request->file('profile_image')->getClientOriginalName();

        //get filename without extension
        $filename = pathinfo($filenamewithextension, PATHINFO_FILENAME);

        //get file extension
        $extension = $request->file('profile_image')->getClientOriginalExtension();

        $time = time();

        //filename to store
        $filenametostore = $filename.'_'.$time.'.'.$extension;

        //small thumbnail name
        $smallthumbnail = $filename.'_small_'.$time.'.'.$extension;

        //medium thumbnail name
        $mediumthumbnail = $filename.'_medium_'.$time.'.'.$extension;

        //large thumbnail name
        $largethumbnail = $filename.'_large_'.$time.'.'.$extension;

        //Upload File
        $request->file('profile_image')->storeAs('public/profile_images', $filenametostore);
        $request->file('profile_image')->storeAs('public/profile_images/thumbnail', $smallthumbnail);
        $request->file('profile_image')->storeAs('public/profile_images/thumbnail', $mediumthumbnail);
        $request->file('profile_image')->storeAs('public/profile_images/thumbnail', $largethumbnail);

        //create small thumbnail
        $smallthumbnailpath = public_path('storage/profile_images/thumbnail/'.$smallthumbnail);
        $this->createThumbnail($smallthumbnailpath, 150, 93);

        //create medium thumbnail
        $mediumthumbnailpath = public_path('storage/profile_images/thumbnail/'.$mediumthumbnail);
        $this->createThumbnail($mediumthumbnailpath, 300, 185);

        //create large thumbnail
        $largethumbnailpath = public_path('storage/profile_images/thumbnail/'.$largethumbnail);
        $this->createThumbnail($largethumbnailpath, 550, 340);

        return redirect('image')->with('success', "Image uploaded successfully.");
    }
}

The above code stores the image in 3 versions – small, medium, and large. After storing them we are calling the method createThumbnail() along with the width and height.

This createThumbnail() function will generate a thumbnail using the values provided and replace the image with the thumbnail. Let’s define this function in the ImageController.

/**
 * Create a thumbnail of specified size
 *
 * @param string $path path of thumbnail
 * @param int $width
 * @param int $height
 */
public function createThumbnail($path, $width, $height)
{
    $img = Image::make($path)->resize($width, $height, function ($constraint) {
        $constraint->aspectRatio();
    });
    $img->save($path);
}

Here I am resizing the images proportionally. It will keep the aspect ratio so the image will not cut off.

If you are looking for a hard crop then replace the below lines

$img = Image::make($path)->resize($width, $height, function ($constraint) {
    $constraint->aspectRatio();
});
$img->save($path);

With

$img = Image::make($path)->resize($width, $height)->save($path);

That’s it! Go ahead and give it a try and you should see you’ve successfully created your thumbnails.

I hope you understand how to create a thumbnail in Laravel using the Intervention Image library. I would like to hear your thoughts and suggestions in the comment section below.

Related Articles

If you liked this article, then please subscribe to our YouTube Channel for video tutorials.

7 thoughts on “Create Thumbnail in Laravel Using Intervention Image Library

  1. I have face this issue.

    Argument 1 passed to Illuminate\Database\Eloquent\Builder::make() must be of the type array, string given, called in C:\laragon\www\hed-web\vendor\laravel\framework\src\Illuminate\Support\Traits\ForwardsCalls.php on line 23

  2. thank you sir this nice post , but i have one question how to use these thumbnails in img src path.

    Sorry I am new in laravel so plzzz kindly help me

  3. Also can you explain the bit bit where you upload the files…
    //Upload File
    $request->file(‘uploaded_file’)->storeAs(‘public/uploaded_files’, $filenametostore);
    $request->file(‘uploaded_file’)->storeAs(‘public/uploaded_files/thumbnail’, $smallthumbnail);
    $request->file(‘uploaded_file’)->storeAs(‘public/uploaded_files/thumbnail’, $mediumthumbnail);
    $request->file(‘uploaded_file’)->storeAs(‘public/uploaded_files/thumbnail’, $largethumbnail);

    But then you create the thumbnail?

    $smallthumbnailpath = public_path(‘storage/uploaded_files/thumbnail/’.$smallthumbnail);
    $this->createThumbnail($smallthumbnailpath, 150, 93);

    Seems backwards?

    Thanks

    1. This library only works with the image. For video, you may want to try another solution like FFmpeg.

Leave a Reply

Your email address will not be published. Required fields are marked *