Laravel 10 – Optimize and Upload Image to Azure Blob Storage

Optimize image and save to Azure blob container using laravel

Last Updated On - February 14th, 2024 Published On - Jul 20, 2023

Introduction

When it comes to creating visually appealing websites, having well-optimized images is crucial. In this tutorial, we’ll walk you through a step-by-step guide on how to resize images in Laravel while maintaining the aspect ratio, and then create multiple copies of the images with different sizes like thumbnails, medium, and banner. We’ll also explore how to save all these images efficiently to an Azure Blob container, ensuring an outstanding user experience. Let’s dive in!


Understanding Laravel’s Image Resizing Workflow

In this section, we’ll break down the workflow of the image resizing process in Laravel. From loading the original image to calculating dimensions for different sizes, you’ll understand the inner workings of this powerful feature. We’ll also show you how to efficiently center the resized image on a white background for a professional look.

function resizeImage($file, $size)
    {
            [$width, $height] = explode('x', $size);
           
            $sourceImage = imagecreatefromstring(file_get_contents($file));

            // Get the original image dimensions
            $sourceWidth = imagesx($sourceImage);
            $sourceHeight = imagesy($sourceImage);
        
            // Calculate the aspect ratios of both images
            $sourceAspectRatio = $sourceWidth / $sourceHeight;
            $targetAspectRatio = $width / $height;
        
            // Calculate the new dimensions for the resized image
            if ($sourceAspectRatio > $targetAspectRatio) {
                $resizeWidth = $width;
                $resizeHeight = $width / $sourceAspectRatio;
            } else {
                $resizeHeight = $height;
                $resizeWidth = $height * $sourceAspectRatio;
            }

            // Creating white background
            $targetImage = imagecreatetruecolor($width, $height);
            $whiteColor = imagecolorallocate($targetImage, 255, 255, 255);
            imagefill($targetImage, 0, 0, $whiteColor);
        
            // Calculate the center position for the resized image on the new background
            $centerX = ($width - $resizeWidth) / 2;
            $centerY = ($height - $resizeHeight) / 2;

            // Resize the source image to the calculated dimensions
            imagecopyresampled(
                $targetImage,
                $sourceImage,
                $centerX,
                $centerY,
                0,
                0,
                $resizeWidth,
                $resizeHeight,
                $sourceWidth,
                $sourceHeight
            );
            $outputImagePath = 'resized_image.png';
            imagepng($targetImage, $outputImagePath);

            return $outputImagePath; // Return output image
    }

Also Read: Laravel Image Resize Project in 10 Minutes


Step-by-Step Implementation Guide

Create a Laravel project

composer create-project --prefer-dist laravel/laravel imageOptimization

Install laravel-azure-storage package via composer

composer require matthewbdaly/laravel-azure-storage

Add configuration variables in .env file (Values you’ll get from your azure account)

AZURE_STORAGE_CONTAINER=azure_container_name
AZURE_STORAGE_URL=https://azurestorageurl.blob.core.windows.net
AZURE_STORAGE_NAME=azureStorageName
AZURE_STORAGE_KEY=azureStorageKey

Add azure to the disk array in config/filesystems.php

'azure' => [
            'driver'    => 'azure', // As this is the name of the driver, this MUST be set to "azure"
            'name'      => env('AZURE_STORAGE_NAME'),
            'key'       => env('AZURE_STORAGE_KEY'),
            'container' => env('AZURE_STORAGE_CONTAINER'),
            'url'       => env('AZURE_STORAGE_URL')
            'prefix'    => null,
        ]

Create a controller to handle the Resize image logic

php artisan make:controller ImageOptimizeController
<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Request;

class ImageOptimizeController extends Controller
{
    
    public function index()
    {
        return view('resize-image');
    }

    public function store(Request $request)
    {
        // Get the uploaded image from the request
        $image = $request->file('image');

        // Validate the image for acceptable image formats and max upload size(Max upto 5MB)
        $this->validate($request, [
            'image' => 'required|image|mimes:jpg,jpeg,png,gif|max:5120',
        ]);

        // Generate a unique filename for the uploaded image
        $timestamp = time();
        $imageName= $timestamp.'.'.$image->getClientOriginalExtension();

        // Saving original image to azure container
        $disk = Storage::disk('azure');
        $disk->put($imageName,file_get_contents($image));

        // Creating Multiple Image Copies of different sizes and saving to Azure blob container
        $sizes = ['240x100', '300x200', '900x300'];
        $this->resizeAndSaveToAzureBlob($image,$sizes,$imageName);
        
        //Send the user back to the upload page with success message and image URL in session
        return back()
            ->with('success','Image has successfully uploaded.');
    }

    function resizeAndSaveToAzureBlob($file, $sizes, $imgName)
    {
        foreach ($sizes as $size) {
            [$width, $height] = explode('x', $size);
           
            $sourceImage = imagecreatefromstring(file_get_contents($file));

            // Get the original image dimensions
            $sourceWidth = imagesx($sourceImage);
            $sourceHeight = imagesy($sourceImage);
        
            // Calculate the aspect ratios of both images
            $sourceAspectRatio = $sourceWidth / $sourceHeight;
            $targetAspectRatio = $width / $height;
        
            // Calculate the new dimensions for the resized image
            if ($sourceAspectRatio > $targetAspectRatio) {
                $resizeWidth = $width;
                $resizeHeight = $width / $sourceAspectRatio;
            } else {
                $resizeHeight = $height;
                $resizeWidth = $height * $sourceAspectRatio;
            }

            // Creating white background
            $targetImage = imagecreatetruecolor($width, $height);
            $whiteColor = imagecolorallocate($targetImage, 255, 255, 255);
            imagefill($targetImage, 0, 0, $whiteColor);
        
            // Calculate the center position for the resized image on the new background
            $centerX = ($width - $resizeWidth) / 2;
            $centerY = ($height - $resizeHeight) / 2;
            // Resize the source image to the calculated dimensions
            imagecopyresampled(
                $targetImage,
                $sourceImage,
                $centerX,
                $centerY,
                0,
                0,
                $resizeWidth,
                $resizeHeight,
                $sourceWidth,
                $sourceHeight
            );
            $outputImagePath = 'resized_image.png';
            imagepng($targetImage, $outputImagePath);
    
            // Generate a unique filename for the resized image
            $resizedFilename = $width . 'x' . $height . $imgName;
    
            // Save the resized image to Azure Blob Storage
            Storage::disk('azure')->put($resizedFilename, file_get_contents($outputImagePath));
        }
    }
}

Create a form to upload the image

Create resize-image.blade.php file in resources/views directory

<div class="container mt-5" style="max-width: 550px">
    <h2 class="mb-5">Image Resize Demo</h2>
    <form action="{{route('resizeImage')}}" method="post" enctype="multipart/form-data">
        @csrf
        @if ($message = Session::get('success'))
            <div class="alert alert-success">
                <strong>{{ $message }}</strong>
            </div>
        @endif

        @if (count($errors) > 0)
            <div class="alert alert-danger">
                <ul>
                    @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
        @endif
        <div class="custom-file">
            <input type="file" name="image" class="custom-file-input" id="chooseFile">
            <label class="custom-file-label" for="chooseFile">Select Image</label>
        </div>
        <button type="submit" name="submit" class="btn btn-outline-danger btn-block mt-4">
            Upload
        </button>
    </form>
</div>

Create routes to handle requests

Add the following routes in routes/web.php

// Show image upload form
Route::get('/image-resize', [ImageOptimizeController::class, 'index']);
// Resize and save image in folder
Route::post('/resize', [ImageOptimizeController::class, 'store'])->name('resizeImage');

Run the project

Now it’s time to see the output. Execute php artisan serve in your terminal and upload your resized copies of the uploaded image to the Azure blob container.


Also Read: Sending messages to Microsoft Teams Channel by using Laravel


FAQs

Why is there a need for image resizing?

To create visually appealing websites by optimizing images for different purposes such as thumbnails, medium views, and banners.

Why are well-optimized images crucial for websites?

Well-optimized images improve page loading times, overall website performance, and provide a better user experience.

Why does the tutorial emphasize maintaining aspect ratio during image resizing?

Maintaining aspect ratio ensures that resized images do not appear distorted, preserving the visual integrity of the original content.

Why is efficient storage to an Azure Blob container highlighted in the tutorial?

Efficient storage in Azure Blob ensures that the resized images are readily accessible, scalable, and can be delivered with low latency, contributing to an outstanding user experience.

Why is it important to integrate Azure Blob storage specifically for saving resized images in Laravel?

Integrating Azure Blob storage provides a scalable, reliable, and cloud-based solution for saving resized images. It ensures accessibility, durability, and efficient management of image assets in a production environment, aligning with modern web development practices.



Summary of Findings

The root cause of the problem lies in the necessity for efficient image resizing and storage in Laravel to enhance website visual appeal and user experience. The need for well-optimized images, the importance of maintaining aspect ratio, the requirement for efficient storage on Azure Blob, the complexity of the process, and the importance of integrating Azure Blob storage contribute to the demand for a comprehensive tutorial and tooling. The tutorial systematically addresses these aspects, providing a solution that is accessible, error-resistant, and aligns with contemporary cloud-based storage practices for developers. By implementing these techniques, your website will stand out with stunning visuals, improved performance, and enhanced user experience. So go ahead, implement what you’ve learned, and watch your website’s images captivate your audience and outrank your competition!