How to Create Thumbnail Images in PHP with GD

Last updated: August 25, 2026.

PHP’s GD extension can create proportional thumbnails for JPEG, PNG, and WebP images. The function below fits an image inside a maximum width and height, preserves transparency where supported, and avoids enlarging small images.

Requirements

  • PHP with the GD extension enabled.
  • A readable source file and a writable thumbnail directory.
  • Enough memory for the decoded image, which can be much larger than the compressed upload.

Create a proportional thumbnail

<?php
function createThumbnail(
    string $sourcePath,
    string $destinationPath,
    int $maxWidth,
    int $maxHeight
): void {
    if ($maxWidth < 1 || $maxHeight < 1) {
        throw new InvalidArgumentException('Thumbnail dimensions must be positive.');
    }

    if (!is_file($sourcePath) || !is_readable($sourcePath)) {
        throw new RuntimeException('Source image is not readable.');
    }

    if (filesize($sourcePath) > 20 * 1024 * 1024) {
        throw new RuntimeException('Source image is too large.');
    }

    $data = file_get_contents($sourcePath);
    $source = $data === false ? false : @imagecreatefromstring($data);

    if ($source === false) {
        throw new RuntimeException('Unsupported or invalid image.');
    }

    $sourceWidth = imagesx($source);
    $sourceHeight = imagesy($source);

    if ($sourceWidth * $sourceHeight > 40_000_000) {
        imagedestroy($source);
        throw new RuntimeException('Image dimensions are too large.');
    }

    $scale = min(
        $maxWidth / $sourceWidth,
        $maxHeight / $sourceHeight,
        1
    );

    $thumbWidth = max(1, (int) floor($sourceWidth * $scale));
    $thumbHeight = max(1, (int) floor($sourceHeight * $scale));
    $thumbnail = imagecreatetruecolor($thumbWidth, $thumbHeight);

    $format = strtolower(pathinfo($destinationPath, PATHINFO_EXTENSION));
    if (!in_array($format, ['jpg', 'jpeg', 'png', 'webp'], true)) {
        imagedestroy($source);
        imagedestroy($thumbnail);
        throw new InvalidArgumentException('Use JPG, PNG, or WebP output.');
    }

    if ($format === 'png' || $format === 'webp') {
        imagealphablending($thumbnail, false);
        imagesavealpha($thumbnail, true);
        $transparent = imagecolorallocatealpha($thumbnail, 0, 0, 0, 127);
        imagefill($thumbnail, 0, 0, $transparent);
    } else {
        $white = imagecolorallocate($thumbnail, 255, 255, 255);
        imagefill($thumbnail, 0, 0, $white);
    }

    imagecopyresampled(
        $thumbnail,
        $source,
        0,
        0,
        0,
        0,
        $thumbWidth,
        $thumbHeight,
        $sourceWidth,
        $sourceHeight
    );

    $saved = match ($format) {
        'jpg', 'jpeg' => imagejpeg($thumbnail, $destinationPath, 85),
        'png' => imagepng($thumbnail, $destinationPath, 6),
        'webp' => imagewebp($thumbnail, $destinationPath, 82),
    };

    imagedestroy($source);
    imagedestroy($thumbnail);

    if (!$saved) {
        throw new RuntimeException('The thumbnail could not be saved.');
    }
}

imagecopyresampled() performs smooth resampling, which produces better reduced images than a simple pixel resize. The destination file extension selects JPG, PNG, or WebP output.

Call the function

<?php
$source = __DIR__ . '/uploads/photo.jpg';
$destination = __DIR__ . '/thumbnails/photo.webp';

createThumbnail($source, $destination, 480, 320);

The result fits inside 480 × 320 pixels while retaining its aspect ratio. Create the destination directory before calling the function and give the PHP process permission to write there.

Handling uploaded images safely

  • Enforce both compressed file-size and decoded pixel limits.
  • Use Fileinfo and an actual image decoder; do not trust the browser-provided MIME type or filename extension.
  • Generate destination filenames on the server.
  • Store uploads where PHP files cannot execute.
  • Reject unreadable, unsupported, or corrupt files without displaying internal paths to visitors.

Phone-photo orientation

JPEG photos may store rotation in EXIF metadata. If phone uploads appear sideways, read the orientation with exif_read_data() and rotate the source before calculating the thumbnail dimensions.

Useful GD references

admin

admin

One thought on “How to Create Thumbnail Images in PHP with GD

  1. This works great thanks.
    It does create very low quality thumbnails though. How would I go about creating better quality ones? It seems the resizing algorithm here is a basic pixel resize one rather than the ones that give smoother results.

Leave a Reply

Your email address will not be published.