Equilateral Triangle in Rectangle
Right, presuming that you want a maximum size equilateral triangle within a rectangle, with the flat side parallel to the horizontal axis, ie. the point uppermost, then there are two scenarios depending on the aspect ratio of the rectangle.
Landscape Rectangle (width > height)

In this case, the height of the rectangle is the limiting factor.
The task is to determine the length of the side of the triangle, and use it to find the position of the two bottom points of the triangle, by taking half the length away from the midpoint of the rectangle.
If we call the triangle length e
as it is marked on the diagram (also g
and f
), and the height of the rectangle is marked as a
, then a quick bit of trigonometry states that:
sin 60 = opp / hyp = a / e = sqrt(3) / 2
so
e = 2a / sqrt(3)
The horizontal side we can call b
as it is in the diagram, the midpoint is obviously at b / 2
, so the points of the base of the triangle are at [ (b / 2) ± (e / 2) , 0 ]
.
To perform the crop perform the following steps:
- create a new image the same size as the source
- fill the whole destination transparent
- copy a rectangle from the source between the two base points of the triangle, of the full height, to the same location in the
destination
- fill triangles with transparent on both sides from the two base points of the triangles, to the top of the rectangle parallel above
them to the midpoint of the top of the rectangle
Portrait Rectangle (width < height)

In this case the width is the limiting factor.
The length of the side of the triangle is therefore the width of the rectangle, so that is known. What needs calculating is the height of the triangle.
If we call the height H
, as marked on the diagram, and the width b
as previous, then simple trigonometry states that:
sin 60 = opp / hyp = H / b = sqrt(3) / 2
so
H = b x sqrt(3) / 2
The vertical side we can call a
as it is in the diagram, the midpoint is at a / 2
, so the points of the base of the triangle are at [ 0 , (a / 2) + (H / 2) ]
and [ b , (a / 2) + (H / 2) ]
and the tip of the triangle E
is at [ (b / 2) , (a / 2) - (H / 2) ]
.
To perform the crop perform the following steps, (initially the two
same steps as before):
- create a new image the same size as the source
- fill the whole destination transparent
- copy a rectangle from the source of full width, between the base and tip of the triangle
E
, to the same location in the destination
- fill triangles with transparent on both sides from the two base points of the triangles, to the triangle tip
E
to the point on the
edge at the same height as E
on the same side as the base point of
the triangle in question
NB. In the case where you have a square, either calculation should work, though the landscape calculation seems simpler to me, so I would use that.
Code
Adapted from your own, so not my usual style of coding, but it works. It took awhile as transparency is a bit of a pain in GD.
Original

Cropped (created with the code below)

<?php
// Acquire image
$src = imagecreatefromjpeg ('https://i.stack.imgur.com/YlnCJ.jpg');
// Get image width/height
$srcWidth = imagesx ($src);
$srcHeight = imagesy ($src);
// Get centre position
$centreX = floor ($srcWidth / 2);
$centreY = floor ($srcHeight / 2);
// Calculate triangle length (base) and points
if ( $srcWidth >= $srcHeight ) {
$base = (2 * $srcHeight) / sqrt(3);
$points = array( 'a' => array( 'x' => $centreX - ( $base / 2 ),
'y' => $srcHeight ),
'b' => array( 'x' => $centreX + ( $base / 2 ),
'y' => $srcHeight ),
'c' => array( 'x' => $centreX,
'y' => 0 ) );
} else {
$base = $srcWidth;
$height = $base * sqrt(3) / 2;
$points = array( 'a' => array( 'x' => 0,
'y' => $centreY + ( $height / 2 ) ),
'b' => array( 'x' => $srcWidth,
'y' => $centreY + ( $height / 2 ) ),
'c' => array( 'x' => $centreX,
'y' => $centreY - ( $height / 2 ) ) );
}
// Create destination, same size as source
$dest = imagecreatetruecolor ($srcWidth, $srcHeight);
// Setup full alpha handling for pngs (8-bit)
imagealphablending ($dest, false);
imagesavealpha ($dest, true);
// Define a transparent colour
$colTrans = imagecolorallocatealpha ($dest, 255, 255, 255, 127);
// If old png transparency was used, setting the transparency colour
// would be needed, with 8-bit it is not
// imagecolortransparent ($dest, $colTrans);
// Make the image transparent
imagefill ($dest, 0, 0, $colTrans);
// Copy from source just the rectangle flush with the triangle
imagecopy ($dest, $src, // Images
$points['a']['x'], $points['c']['y'], // Destination x,y
$points['a']['x'], $points['c']['y'], // Source x,y
$points['b']['x'] - $points['a']['x'], // Width
$points['a']['y'] - $points['c']['y']); // Height
// Fill out the triangles within that area not wanted with transparent
// Left side
imagefilledpolygon ($dest, array( $points['a']['x'], $points['a']['y'],
$points['c']['x'], $points['c']['y'],
$points['a']['x'], $points['c']['y'] ),
3, $colTrans);
// Right side
imagefilledpolygon ($dest, array( $points['b']['x'], $points['b']['y'],
$points['c']['x'], $points['c']['y'],
$points['b']['x'], $points['c']['y'] ),
3, $colTrans);
// Output new image
header ('Content-Type: image/png');
imagepng ($dest);
// Clean up
imagedestroy ($src);
imagedestroy ($dest);