All formats

GD

LanguagePHP (bundled extension ext/gd)
LicensePHP License (bundled libgd: BSD-style GD license)
Repositorygithub.com/php/php-src (ext/gd)
Documentationphp.net/manual/en/book.image.php, exif_read_data
Depends onlibjpeg (usually libjpeg-turbo); the exif extension for metadata
Read / writeyes / yes; baseline and progressive output; no metadata on save

GD is PHP’s built-in image library. imagecreatefromjpeg decodes a file into a GdImage object (truecolor RGB), the image* functions draw and transform it, and imagejpeg encodes it with a quality from 0 to 100. Since PHP 8.0 images are objects and are freed automatically.

GD drops all metadata: Exif, ICC profiles and comments are not written to the output, and the Exif orientation is not applied on load. Read the orientation with the exif extension and rotate yourself. Resampling quality is good with imagecopyresampled or imagescale, but slower than Imagick or libvips for large photos.

Installation#

GD is compiled into most PHP packages. Otherwise:

Shell
# Debian / Ubuntu
sudo apt install php-gd
# Docker official image
docker-php-ext-configure gd --with-jpeg && docker-php-ext-install gd exif

Check with php -r 'var_dump(gd_info()["JPEG Support"]);'.

Basic usage: load, resize and save a JPEG#

PHP
<?php
$src = imagecreatefromjpeg('photo.jpg');
if ($src === false) {
    exit("not a valid JPEG\n");
}
printf("%d x %d\n", imagesx($src), imagesy($src));

$small = imagescale($src, 1200);   // width 1200, height in proportion
imageinterlace($small, true);      // progressive JPEG
if (!imagejpeg($small, 'out.jpg', 85)) {
    exit("write failed\n");
}

Pass null as the file name to send the JPEG to the output (with header('Content-Type: image/jpeg')).

How to get JPEG dimensions without decoding#

PHP
$info = getimagesize('photo.jpg');
if ($info !== false && $info[2] === IMAGETYPE_JPEG) {
    [$width, $height] = $info;
    echo "$width x $height, {$info['channels']} channels, {$info['mime']}\n";
}

How to fix photo rotation using Exif orientation#

PHP
<?php
function imagecreatefromjpeg_upright(string $path): GdImage|false
{
    $img = imagecreatefromjpeg($path);
    if ($img === false || !function_exists('exif_read_data')) {
        return $img;
    }
    $exif = @exif_read_data($path);
    $rotated = match ($exif['Orientation'] ?? 1) {
        3 => imagerotate($img, 180, 0),
        6 => imagerotate($img, -90, 0),   // imagerotate turns counter-clockwise
        8 => imagerotate($img, 90, 0),
        default => $img,
    };
    return $rotated;
}

How to read Exif data#

PHP
$exif = exif_read_data('photo.jpg', 'ANY_TAG', true);   // true = group by section
if ($exif !== false) {
    echo $exif['IFD0']['Model'] ?? '', "\n";
    echo $exif['EXIF']['DateTimeOriginal'] ?? '', "\n";
    print_r($exif['GPS'] ?? []);    // GPSLatitude is an array of "num/den" strings
}

How to convert PNG with transparency to JPEG#

PHP
$png = imagecreatefrompng('logo.png');
$w = imagesx($png);
$h = imagesy($png);
$jpg = imagecreatetruecolor($w, $h);
imagefill($jpg, 0, 0, imagecolorallocate($jpg, 255, 255, 255));  // white background
imagecopy($jpg, $png, 0, 0, 0, 0, $w, $h);
imagejpeg($jpg, 'logo.jpg', 90);

Tips#