GD
| Language | PHP (bundled extension ext/gd) |
|---|---|
| License | PHP License (bundled libgd: BSD-style GD license) |
| Repository | github.com/php/php-src (ext/gd) |
| Documentation | php.net/manual/en/book.image.php, exif_read_data |
| Depends on | libjpeg (usually libjpeg-turbo); the exif extension for metadata |
| Read / write | yes / 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:
# 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
$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#
$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
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#
$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#
$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#
- The default quality (
-1) is 75. - Large photos need memory for width × height × 4 bytes or more; a 24-megapixel JPEG needs about 100 MB. Raise
memory_limitor checkgetimagesizefirst. imagecreatefromjpegemits a warning and returnsfalsefor corrupt files; setini_set('gd.jpeg_ignore_warning', '1')to load slightly broken files.