Creating a Virtual Photo Booth Gallery

Banner for a MediaJam post

Eugene Musebe


Physical events are often packed with several brand activation activities and photo booths are always a must. We can make our space exciting and engaging to our audience by creating a photo booth. The virtual photo booth will take user images apply cool effect transformations and display them in a gallery.

PHPSandbox and Github

All the code is available on Github and PHPSandbox for a live demonstration of the Virtual Photo Booth Gallery.


To be able to follow this article, you need to have experience issuing commands through a terminal. You should also have some knowledge of Git version control and PHP specifically with the Laravel framework.

Getting Started

We will need Composer to initiate a Laravel project and install our dependencies. Follow the steps below diligently. In step 1 we will install PHP and Composer.

  1. Install Composer and PHP on your machine. Be sure to follow the steps for your respective operating system.

  2. There are two ways to install Laravel:

    1. Via Composer:

      composer create-project --prefer-dist laravel/laravel cloudinary-photobooth

    2. Via Laravel Installer (Recommended):

      composer global require laravel/installer

      laravel new cloudinary-photobooth

  3. Following the Laravel installation steps above will create a new application in the folder cloudinary-photobooth. Now we need to start the server and test our new application to ensure everything is okay. Change the directory to the project folder and run the local development server by typing the following commands:

    cd cloudinary-photobooth

    php artisan serve

The Laravel server should be up and running and when you open http://localhost:8000 on your computer, you should see the application default page shown in the image below:

Laravel Server Running

Setting up Cloudinary’s Laravel SDK

Cloudinary has made integration easy for different programming languages with their Programmable Media SDK libraries and with a vibrant community, there are community libraries available as well. In this article, we will use Cloudinary's Laravel SDK.

  1. First things first, we will need a Cloudinary account. You can sign up for one here. Don't worry it's free. Log in with your details and you will be redirected to the Dashboard. Take note of your Account details, the Cloud Name, API Key, API Secret and the API Environment variable, we will need them later.

    Cloudinary Dashboard

  2. Back at our terminal, we need to install Cloudinary’s Laravel SDK. Run the following command:

    composer require cloudinary-labs/cloudinary-laravel

    Note: Follow the link to the SDK and ensure you follow all the steps in the #Installation section.

  3. To complete the setup we will need to add the Account details to our .env file as shown below:


Image Manipulation

Cloudinary is a great platform for media management and manipulation. It is perfect for our current use case since we will need to apply some transformations to the images our users will be uploading and return a URL that we will use to populate our gallery.

To return their desired photo booth effect we will manipulate the photos as follows:

  1. Change the aspect ratio 0.75 which is a 3x4.
  2. Adjust the height to 1600px
  3. Apply an overlay of the respective effect chosen by the user

Before we can start image manipulation, you'll have to upload the overlay effects to your Cloudinary media library. You can find them below:

  1. Cloudinary Rocks
  2. Rose Flowers
  3. Abstract
  4. Flower Petals Effect

As you can see we will have four overlays in this project. You can download the above overlay effects and upload them to your Cloudinary Media library and name them as follows:

  1. effect_one
  2. effect_two
  3. effect_three
  4. effect_four

Rename Overlay Effect

Uploading the Photos

With the overlay effects uploaded, we will need a user interface to allow the user to upload images, for this, we will use the Laravel package Livewire.

  1. Install Livewire Package by running the following command in your Laravel project:

    composer require livewire/livewire

  2. Include Livewire scripts and styles on every page that will be using Livewire. In our case welcome.blade.php:

2 @livewireStyles
5 ...
7 @livewireScripts
  1. We will then create a Livewire Component to handle our image uploads:

    php artisan make:livewire PhotoBooth

    This will create two files, first app/Http/Livewire/PhotoBooth.php and the other one in resources/views/livewire/photo-booth.blade.php.

    We can then use this component anywhere in our code using the following snippet:




  2. Open resources/views/welcome.blade.php and add the following code within the <body></body> tags as shown below:

1<body class="antialiased">
2 <div>
3 @livewire('photo-booth')
4 </div>

This includes the Livewire component we created earlier in our welcome.blade.php.

Note: Please ensure you go through the Livewire documentation, to learn how to install and set it up.

  1. Open the file resources/views/livewire/photo-booth.blade.php and populate it with the following code:
1<form class="mb-5" wire:submit.prevent="photoBooth">
2 <div class="form-group row mt-5 mb-3">
3 <div class="input-group mb-5">
4 <select id="effect" type="file" class="form-select @error('effect') is-invalid @enderror"
5 wire:model="effect">
6 <option selected>Choose Photo Effect ...</option>
7 <option selected value="effect_one">Cloudinary Rocks</option>
8 <option value="effect_two">Rose Flower</option>
9 <option value="effect_three">Abstract</option>
10 <option value="effect_four">Flower Petals</option>
11 </select>
12 @error('effect')
13 <div class="invalid-feedback">{{ $message }}</div>
14 @enderror
15 </div>
16 <div class="input-group">
17 <input id="photo" type="file" class="form-control @error('photo') is-invalid @enderror"
18 placeholder="Choose photo..." wire:model="photo">
20 @error('photo')
21 <div class="invalid-feedback">{{ $message }}</div>
22 @enderror
23 </div>
24 <small class="text-muted text-center mt-2" wire:loading wire:target="photo">
25 {{ __('Uploading') }}…
26 </small>
27 </div>
28 <div class="text-center">
29 <button type="submit" class="btn btn-sm btn-primary w-25">
30 <i class="fas fa-check mr-1"></i> {{ __('Lights, Camera, Action') }}
31 <i class="spinner-border spinner-border-sm ml-1 mt-1" wire:loading wire:target="photoBooth"></i>
32 </button>
33 </div>

This is a form with a select field, file input field and a button. You can refer to the code on Github for the full implementation.

Implementation in Code

Open the file app/Http/Livewire/PhotoBooth.php and update it with the following code:

  1. First, we use Livewire's WithFileUploads to help us with file uploads, then create the variables $photo, $effect, effectTransformations, $tag, $folder and $gallery an array which will contain the transformed image URLs we get back from Cloudinary.

    1use WithFileUploads;
    3public $photo;
    4public $effect;
    5public $gallery = [];
    6public $effectTransformations;
    7public $folder = "photo-booth";
    8public $tag = "photo-booth";
  2. Next, create the photoBooth function which will apply upload and apply transformations to create the respective effect.

    1public function photoBooth() {
    2 ...
  3. Let's populate our method in step 2 above:

    1public function photoBooth() {
    2 $this->validate([
    3 'effect' => 'required|string',
    4 'photo' => ['required', 'image', 'max:10240'
    5 ]);
    7 $photo = cloudinary()->upload($this->photo->getRealPath(), [
    8 'folder' => $this->folder,
    9 'aspect_ratio' => 0.75,
    10 'crop' => 'fill',
    11 'height' => 1600,
    12 'gravity' => 'faces'
    13 ])->getSecurePath();
    15 $this->effectTransformations = [
    16 'overlay' => [
    17 'public_id' => "$this->folder/assets/$this->effect",
    18 'flags' => 'layer_apply',
    19 'width' => 1.0,
    20 'height' => 1.0,
    21 ]
    22 ];
    24 $transformed = cloudinary()->upload($photo, [
    25 'folder' => $this->folder,
    26 'tags' => $this->tag,
    27 'transformation' => $this->effectTransformations
    28 ])->getSecurePath();
    30 $this->gallery = Arr::prepend($this->gallery, $transformed);

    Let's talk about the code.

  • Overlay Transformation

    First, we create the effect transformations based on user input and assign them to the variable $effectTransformations.

1$this->effectTransformations = [
2 ['crop' => 'crop', 'aspect_ratio' => 0.75, 'gravity' => 'faces', 'height' => 1600],
3 [
4 'overlay' => [
5 'public_id' => "$this->folder/assets/$this->effect",
6 'flags' => 'layer_apply',
7 'width' => 1.0,
8 'height' => 1.0,
9 ]
10 ]
11 ];
  • Upload Photo with Transformations

    First, we upload the user image to Cloudinary, with an aspect_ratio of 0.75, crop of fill, gravity set to faces and get the secure_url which we save in the variable $photo. The last line just prepends the transformed $photo to our $this->gallery array which we use to display the gallery.

1$photo = cloudinary()->upload($this->photo->getRealPath(), [
2 'folder' => $this->folder,
3 'tags' => $this->tag,
4 'transformation' => $this->effectTransformations
7$this->gallery = Arr::prepend($this->gallery, $photo);

Update our Livewire component view and add the following code beneath the form:

1<div class="row mt-4">
2 @foreach($this->gallery as $galleryItem)
3 @if ($galleryItem)
4 <div class="col-sm-3 col-md-3 mb-3">
5 <img class="card-img-top img-thumbnail img-fluid" src="{{ $galleryItem }}" alt="Virtual Photo Booth"/>
6 </div>
7 @endif
8 @endforeach

This will display our gallery.

With our code implementation complete, you should be able to see the following when you navigate to http://localhost:8000:

Cloudinary Virtual Photo Booth Demo


Cloudinary Virtual Photo

Congratulations, we have built our own virtual photo booth powered by Cloudinary and Laravel. This is just the beginning, with Cloudinary you can create wonderful image management and manipulation products.

Keep discovering more with Cloudinary, all you have to do is create a free account.

Eugene Musebe

Software Developer

I’m a full-stack software developer, content creator, and tech community builder based in Nairobi, Kenya. I am addicted to learning new technologies and loves working with like-minded people.