Laravel 5.6: Create image thumbnails

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Migrating Legacy Image Processing: Creating Thumbnails in Laravel 5.6

As a senior developer, I’ve seen countless legacy systems built on older PHP versions where complex image manipulation—like creating thumbnails using the GD library—was handled directly within application logic. The approach you described, using raw GD functions to generate an image and then trying to serve it via Laravel's response methods (response()->file()), is a classic source of confusion when migrating to a modern framework like Laravel.

The issue you are encountering—seeing question marks or diamond icons instead of the actual image—stems from how PHP streams binary data to the HTTP client versus how Laravel expects file responses to be handled, especially concerning memory management and correct HTTP headers.

This post will walk you through the correct architectural approach for generating and serving image thumbnails in a Laravel 5.6 application, demonstrating how to properly bridge that legacy GD logic with modern framework conventions.

The Pitfall of Direct GD Output in Laravel

Your original function relies on manipulating image resources directly:

php
function imageThumbanail() {
    // ... GD operations create virtual images ...
    header('Content-Type: image/jpeg');
    imagejpeg($virtual_image, null, 100);
    imagedestroy($virtual_image);
}

When you use header() directly in a controller method, Laravel's response pipeline can sometimes interfere with the raw binary stream being sent. Furthermore, using response()->file($pathToFile) requires that the file already exists on the filesystem before the response is generated. If you try to pipe the GD output directly, the context shift between pure PHP execution and Laravel’s routing/response layer causes the corruption you observed.

The Correct Approach: Save, Then Serve

The most reliable way to handle binary data in a web application environment is to delegate the heavy lifting (the image generation) to a dedicated process that saves the result to a file, and then let the framework handle serving that static file.

Step 1: Implement Thumbnail Generation as a Service

Instead of trying to output the image directly, we should focus on saving the generated thumbnail to a temporary or public storage location. This separates the heavy processing from the HTTP request cycle.

Here is how you would refactor your GD logic into a controller method that saves the result:

php
<?php

namespace App\Http\Controllers;

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

class ImageController extends Controller
{
    public function createThumbnail(Request $request)
    {
        // 1. Define input path (assuming the original image is uploaded or known)
        $originalImagePath = 'path/to/your/source_image.jpg'; // Replace this logic with actual file handling

        // --- Legacy GD Logic Adaptation ---
        $thumbnail_width = 180;
        $image_width = imagesx($image_src);
        $image_height = imagesy($image_src);

        $thumbnail_height = floor($image_height * ($thumbnail_width / $image_width));
        $virtual_image = imagecreatetr