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
- Resize Image in Laravel Using Intervention Image Library
- A Guide to Upload and Compress Images in Laravel
- Upload and Resize Multiple Images in Laravel
If you liked this article, then please subscribe to our YouTube Channel for video tutorials.
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
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
echo asset(‘storage/profile_images/thumbnail/image_name_here’);
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
I have been struggling with this for the last few days. I’m uploading to the cloud. Hopefully this wil work! Works great locally. Thanks!
Nice job but please how can i implement this for video files with laravel
This library only works with the image. For video, you may want to try another solution like FFmpeg.