I've played this around for you.
First of all, GD (and even Imagick in its default operations) doesn't support perspective transformations - which is what you need to make the banner look like it's part of a 3D surface.
You cannot realistically get perspective distortion with GD, unless you manually do it with polygon fills which I would skip for sure, too complex...
However with Imagick I used distortImage()
as in the comment Chris Haas mentioned with Imagick::DISTORTION_PERSPECTIVE.
I've created this code:
function mergeWithPerspective(string $basePath, string $bannerPath, string $outputPath): void {
$imagick = new Imagick(realpath($basePath));
$banner = new Imagick(realpath($bannerPath));
// Resize banner to fixed dimensions for consistent perspective mapping
$banner->resizeImage(230, 300, Imagick::FILTER_LANCZOS, 1);
// Map corners of the banner to positions on the truck's black panel
$controlPoints = [
0, 0, 496, 145,
230, 0, 715, 163,
0, 300, 495, 407,
230, 300, 712, 375
];
$banner->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_TRANSPARENT);
$banner->distortImage(Imagick::DISTORTION_PERSPECTIVE, $controlPoints, true);
// Composite the distorted banner onto the truck image at a specific offset
$imagick->compositeImage($banner, Imagick::COMPOSITE_OVER, 507, 110);
$imagick->writeImage($outputPath);
$imagick->clear();
}
I applied a perspective distortion on the banner and tried to placed it realistically.
The downside of this as you can see that you have to define a starting X and Y coordinate with compositeImage() as well as creating the necessary control points with $controlPoints.
I've created a github repository for this:
https://github.com/marktaborosi/stackoverflow-79562669
The source images are in:
src/source-images
The processed image is in:
src/processed
Hope this helps!