Resize and Watermark

Resizing, Cropping and Watermarking

Square product thumbnails take three steps: crop the largest centered square with imagecrop(), scale it with imagescale() (bicubic is sharper than the bilinear default), and draw a watermark with imagettftext(), measured first by imagettfbbox() and made translucent by an alpha color (0 opaque, 127 clear). For a logo, use imagecopy() or imagecopymerge().

thumbs.php: centered crop, resize and a translucent watermarkPHP
<?php
declare(strict_types=1);
function thumbnail(GdImage $src, int $size, string $mark): GdImage
{
    $font = '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf';
    $side = min($w = imagesx($src), $h = imagesy($src));
    $thumb = imagescale(imagecrop($src, ['x' => intdiv($w - $side, 2),
        'y' => intdiv($h - $side, 2), 'width' => $side, 'height' => $side]),
        $size, $size, IMG_BICUBIC);
    $box = imagettfbbox($pt = $size / 16, 0, $font, $mark);  // 8 ints: the text's corners
    imagettftext($thumb, $pt, 0, $size - ($box[2] - $box[0]) - (int) $pt, $size - (int) $pt,
        imagecolorallocatealpha($thumb, 255, 255, 255, 50), $font, $mark);
    return $thumb;
}
$src = imagecreatefromjpeg('books.jpg');
imagewebp(thumbnail($src, 300, '© Bookshop'), 't300.webp');        // 11,620 bytes
imagewebp(thumbnail($src, 120, '© Bookshop'), 't120.webp');
The source photo with its crop square marked, and the 300 px and 120 px thumbnails
The source photo with its crop square marked, and the 300 px and 120 px thumbnails

Always scale from the original. Imagick 623 crops and resizes in one call, $im->cropThumbnailImage(300, 300), and Intervention Image 14,373 (github.com/Intervention/image (https://github.com/Intervention/image 14,373 ), Comparison and Logic) puts GD and Imagick behind one fluent API.