Skip to content

Instantly share code, notes, and snippets.

@HedicGuibert
Last active May 3, 2023 11:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HedicGuibert/3ff3c99c90329448a7f7dd5b18a433b9 to your computer and use it in GitHub Desktop.
Save HedicGuibert/3ff3c99c90329448a7f7dd5b18a433b9 to your computer and use it in GitHub Desktop.
The ArticlePreviewRenderer class showcased in an article describing how to use Imagine to create article preview images
<?php
namespace App;
use Imagine\Gd\Font;
use Imagine\Image\Box;
use Imagine\Image\Point;
use Imagine\Image\Palette\RGB;
use Imagine\Image\Point\Center;
use Imagine\Draw\DrawerInterface;
use Imagine\Image\ImageInterface;
use Imagine\Image\ImagineInterface;
use Imagine\Image\Fill\Gradient\Vertical;
class ArticlePreviewRenderer
{
public function __construct(
private readonly ImagineInterface $imagine,
private readonly string $publicDir,
private readonly RGB $rgb = new RGB(),
private readonly int $imageHeight = 600,
private readonly int $imageWidth = 1200,
private readonly int $marginSize = 35,
private ?Font $footerFont = null,
) {
$this->footerFont = new Font(
$this->publicDir . '/font/alatsi/Alatsi-Regular.ttf',
22,
$this->rgb->color('#FFF')
);
}
public function generatePreviewImage(): void
{
$image = $this->imagine->create(
new Box($this->imageWidth, $this->imageHeight),
);
$drawer = $image->draw();
$this->drawBackgroundImage($image);
$this->drawTitle($drawer);
$this->drawLogo($drawer);
$this->drawFooter($drawer);
$image->save($this->publicDir . '/img/shinyPreviewImage.png');
}
private function drawFooter(DrawerInterface $drawer): void
{
$leftTop = new Point(0, $this->imageHeight - 100);
$rightBottom = new Point($this->imageWidth, $this->imageHeight);
$drawer->rectangle(
$leftTop,
$rightBottom,
$this->rgb->color('#9900FF'),
true,
);
$this->drawAuthorName($drawer);
$this->drawDate($drawer);
}
private function drawTitle(DrawerInterface $drawer): void
{
$titleText = 'Create your own shiny preview images with Imagine PHP';
$titleFont = new Font(
$this->publicDir . '/font/Butler/Butler_Medium.otf',
32,
$this->rgb->color('#2b2b2a')
);
if (\strlen($titleText) > 90) {
$titleText = substr($titleText, 0, 87) . '...';
}
$drawer->text(
$titleText,
$titleFont,
new Point($this->marginSize, $this->marginSize),
0,
$this->imageWidth / 1.5
);
}
private function drawLogo(DrawerInterface $drawer): void
{
$squareSideWidth = 100;
$squareLeftStart = $this->imageWidth - $this->marginSize - $squareSideWidth;
$squareBottomEnd = $this->marginSize + $squareSideWidth;
$leftTop = new Point($squareLeftStart, $this->marginSize);
$rightBottom = new Point($this->imageWidth - $this->marginSize, $squareBottomEnd);
$drawer->rectangle(
$leftTop,
$rightBottom,
$this->rgb->color('#9900FF'),
true,
);
$logoFont = new Font(
$this->publicDir . '/font/alatsi/Alatsi-Regular.ttf',
22,
$this->rgb->color('#9900FF')
);
$drawer->text(
'SQUARE',
$logoFont,
new Point($squareLeftStart - 30, $this->marginSize - 23),
90
);
$drawer->text(
'CORP',
$logoFont,
new Point($squareLeftStart + 16, $this->marginSize + $squareSideWidth + 5),
);
}
private function drawAuthorName(DrawerInterface $drawer): void
{
$drawer->text(
'HÉDIC GUIBERT',
$this->footerFont,
new Point($this->marginSize, $this->imageHeight - 60)
);
}
private function drawDate(DrawerInterface $drawer): void
{
$date = new \DateTime();
$drawer->text(
date('j F Y', strtotime($date->format('m/d/Y'))),
$this->footerFont,
new Point($this->imageWidth - 200, $this->imageHeight - 60)
);
}
private function drawBackgroundImage(ImageInterface $image): void
{
$backgroundImage = $this->imagine->open($this->publicDir . '/img/nicolas_cage.jpg');
$aspectRatio = $backgroundImage->getSize()->getHeight() / $backgroundImage->getSize()->getWidth();
$resizedHeight = $aspectRatio * $this->imageWidth;
if ($resizedHeight >= $this->imageHeight) {
// The image has sufficient height. We need to resize it horizontally and to center it vertically.
$backgroundImage->resize($backgroundImage->getSize()->widen($this->imageWidth));
$center = new Center(new Box($this->imageWidth, $backgroundImage->getSize()->getHeight() / 2));
// Some images don't crop well because their height, once resized, is too short. These will render with some white space at the bottom.
// To prevent this, we don't center them vertically. It will not really be noticeable since their new height will be very close to the box height.
if ($center->getY() >= 200) {
$backgroundImage->crop(
new Point(0, $center->getY()),
$image->getSize()
);
}
} else {
// The image has insufficient height. We need to resize it vertically and to center it horizontally.
$backgroundImage->resize($backgroundImage->getSize()->heighten($this->imageHeight));
$center = new Center(new Box($backgroundImage->getSize()->getWidth() / 2, $backgroundImage->getSize()->getHeight()));
// Some images don't crop well because their width, once resized, is too narrow. These will render with some white space on the right.
// To prevent this, we don't center them horizontally. It will not really be noticeable since their new width will be very close to the box width.
if ($center->getX() >= 390) {
$backgroundImage->crop(
new Point($center->getX(), 0),
$image->getSize()
);
}
}
$white = $backgroundImage->palette()->color('fff');
$fill = new Vertical(
$backgroundImage->getSize()->getHeight(),
$white->dissolve(-30),
$white->dissolve(-30),
);
$transparentImage = $this->imagine->create($backgroundImage->getSize())
->fill($fill);
$backgroundImage->paste($transparentImage, new Point(0, 0));
$image->paste($backgroundImage, new Point(0, 0));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment