Skip to content

Commit 06ed38c

Browse files
dasGOLEandi34
authored andcommitted
feat(polaroid): Refactor Polaroid effect for aspect ratio integrity and performance
Refactored the Polaroid effect generation to prioritize aspect ratio preservation and optimize performance.
1 parent bb4959f commit 06ed38c

File tree

1 file changed

+67
-109
lines changed

1 file changed

+67
-109
lines changed

src/Image.php

Lines changed: 67 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,119 +1152,77 @@ public function effectPolaroid(GdImage $resource): GdImage
11521152
try {
11531153
// Get resolution of the input image
11541154
$resourceWidth = imagesx($resource);
1155-
$resourceHight = imagesy($resource);
1156-
1157-
// Reference dimensions of the original demo images, for which the polaroid effect was optimized
1158-
$referenceDemoWidth = 1024;
1159-
// $referenceDemoHeight = 682; // Not strictly needed for width-based scaling
1160-
1161-
// Calculate scaling factor based on the current image's width relative to the reference width
1162-
$scalingFactor = $resourceWidth / $referenceDemoWidth;
1163-
1164-
// --- SCALE ORIGINAL FIXED PIXEL VALUES ---
1165-
// Original fixed values (from initial implementation), scaled for the current image
1166-
$scaledBorderWidthAdd = (int) round(25 * $scalingFactor); // +25 for overall width
1167-
$scaledBorderHeightAdd = (int) round(80 * $scalingFactor); // +80 for overall height
1168-
1169-
$scaledImageOffsetX = (int) round(11 * $scalingFactor); // X-offset for copying the image
1170-
$scaledImageOffsetY = (int) round(11 * $scalingFactor); // Y-offset for copying the image
1171-
1172-
// Define minimum pixel values for borders/offsets to prevent them from disappearing
1173-
$minBorderPx = 5;
1174-
$scaledBorderWidthAdd = max($minBorderPx * 2, $scaledBorderWidthAdd); // Min 10px for both side borders combined
1175-
$scaledBorderHeightAdd = max($minBorderPx * 2, $scaledBorderHeightAdd); // Min 10px for top and bottom borders combined
1176-
$scaledImageOffsetX = max($minBorderPx, $scaledImageOffsetX); // Min 5px for image X-offset
1177-
$scaledImageOffsetY = max($minBorderPx, $scaledImageOffsetY); // Min 5px for image Y-offset
1178-
1179-
// We create a new image
1180-
$img = imagecreatetruecolor($resourceWidth + $scaledBorderWidthAdd, $resourceHight + $scaledBorderHeightAdd);
1181-
if (!$img) {
1182-
throw new \Exception('Cannot create new image.');
1155+
$resourceHeight = imagesy($resource);
1156+
1157+
// Determine the shorter side of the original image, used as a reference for border thickness
1158+
$resourceShortSide = min($resourceWidth, $resourceHeight);
1159+
1160+
// Define base border thickness parameters. These could eventually be configurable in the Admin Panel.
1161+
$borderThinPercentage = 2; // Percentage of the original short side for thin borders (left, right, top)
1162+
$factorBottomBorder = 6; // Multiplier for the bottom border thickness relative to the thin borders
1163+
1164+
// Calculate actual pixel thickness
1165+
$borderThinPx = (int) round($borderThinPercentage * $resourceShortSide / 100); // for the thin borders
1166+
$borderBottomPx = $factorBottomBorder * $borderThinPx; // for the thick bottom border
1167+
1168+
// Calculate dimensions for the final Polaroid image.
1169+
$finalPolaroidWidth = $resourceWidth + (2 * $borderThinPx);
1170+
// The final Polaroid height is calculated to maintain the original image's aspect ratio (width/height).
1171+
$finalPolaroidHeight = (int) round($finalPolaroidWidth / ($resourceWidth / $resourceHeight));
1172+
1173+
// Calculate the target height for the image *content* within the Polaroid frame.
1174+
$targetImageContentHeight = $finalPolaroidHeight - $borderThinPx - $borderBottomPx;
1175+
1176+
// Error handling: Ensure there is enough vertical space for the image content after borders.
1177+
if ($targetImageContentHeight <= 0) {
1178+
throw new \Exception('Polaroid borders are too large, no space left for image content. Please adjust border settings.');
1179+
}
1180+
1181+
// Calculate the amount of pixels to be cropped from the original image's height.
1182+
// This 'cropAmount' is distributed evenly on the top and bottom of the original image.
1183+
$cropAmountTotal = $resourceHeight - $targetImageContentHeight;
1184+
// Calculate the offset from the top (and bottom) of the original image for the crop.
1185+
$cropYOffset = (int) round($cropAmountTotal / 2);
1186+
1187+
// Create a new GD image resource for the final Polaroid output.
1188+
// This canvas will have the calculated final dimensions and serve as the base for the Polaroid.
1189+
$polaroidCanvas = imagecreatetruecolor($finalPolaroidWidth, $finalPolaroidHeight);
1190+
if (!$polaroidCanvas) {
1191+
throw new \Exception('Failed to create new image canvas for Polaroid effect.');
1192+
}
1193+
$white = intval(imagecolorallocate($polaroidCanvas, 255, 255, 255));
1194+
1195+
// Fill the entire canvas with white. This forms the base for all white borders.
1196+
if (!imagefill($polaroidCanvas, 0, 0, $white)) {
1197+
throw new \Exception('Failed to fill Polaroid canvas with white color.');
1198+
}
1199+
1200+
// Copy the original image onto the Polaroid canvas.
1201+
// The image is copied without scaling. Vertical cropping is achieved by specifying
1202+
// the source's Y-offset ($cropYOffset) and the source's effective height ($targetImageContentHeight).
1203+
// The destination X/Y positions ($borderThinPx, $borderThinPx) define the top-left
1204+
// corner of where the (cropped) image content starts within the Polaroid canvas.
1205+
if (!imagecopy(
1206+
$polaroidCanvas, // Destination image resource
1207+
$resource, // Source image resource
1208+
$borderThinPx, // Destination X-coordinate (left border)
1209+
$borderThinPx, // Destination Y-coordinate (top border)
1210+
0, // Source X-coordinate (start from left of original image)
1211+
$cropYOffset, // Source Y-coordinate (start from Y-offset within original image for cropping)
1212+
$resourceWidth, // Width of the source rectangle to copy (full original width)
1213+
$targetImageContentHeight // Height of the source rectangle to copy (cropped height from original)
1214+
)) {
1215+
unset($polaroidCanvas);
1216+
throw new \Exception('Failed to copy image onto Polaroid canvas.');
11831217
}
1184-
$white = intval(imagecolorallocate($img, 255, 255, 255));
11851218

1186-
// We fill in the new white image
1187-
if (!imagefill($img, 0, 0, $white)) {
1188-
throw new \Exception('Cannot fill image.');
1189-
}
1190-
1191-
// We copy the image to which we want to apply the polariod effect in our new image.
1192-
if (!imagecopy($img, $resource, $scaledImageOffsetX, $scaledImageOffsetY, 0, 0, $resourceWidth, $resourceHight)) {
1193-
unset($img);
1194-
throw new \Exception('Cannot copy image.');
1195-
}
1196-
1197-
// --- Removed Inner Gray Border ---
1198-
// The subtle gray border around the image itself (inside the white polaroid frame) has been commented out.
1199-
// Reasoning:
1200-
// 1. **Minimal visual impact:** Similar to the shadow effect, this thin border (originally 4 pixels wide)
1201-
// is often barely noticeable on larger, high-resolution images relative to the overall composition.
1202-
// 2. **Design simplification:** Removing it contributes to a cleaner, less cluttered aesthetic,
1203-
// putting full focus on the main image and the white polaroid frame.
1204-
//
1205-
// If an inner border is desired in the future, it might require a more distinct implementation.
1206-
/*
1207-
// Border color
1208-
$color = intval(imagecolorallocate($img, 192, 192, 192));
1209-
1210-
// We put a gray border to our image.
1211-
// Scaling original -4px offset from the image edge
1212-
$scaledOuterBorderOffset = max(2, (int) round(4 * $scalingFactor)); // Min 2px border offset
1213-
if (!imagerectangle($img, 0, 0, imagesx($img) - $scaledOuterBorderOffset, imagesy($img) - $scaledOuterBorderOffset, $color)) {
1214-
unset($img); // Clean up on failure
1215-
throw new \Exception('Cannot add border.');
1216-
}*/
1217-
1218-
// --- Removed Shadow Effect ---
1219-
// The shadow effect (originally consisting of multiple gray lines) has been commented out.
1220-
// Reasoning:
1221-
// 1. **Perceptibility on larger images:** When images are scaled up, the subtle shadow lines (originally 1-6 pixels wide)
1222-
// become proportionally larger but are often still too thin relative to the overall image size to be
1223-
// noticeable or to add significant visual depth.
1224-
// 2. **Performance optimization:** Removing these `imageline()` calls slightly improves performance,
1225-
// especially when processing many images.
1226-
//
1227-
// If a shadow effect is desired in the future, it might require a different, more pronounced implementation.
1228-
/*
1229-
// Shade Colors
1230-
$gris1 = intval(imagecolorallocate($img, 208, 208, 208));
1231-
$gris2 = intval(imagecolorallocate($img, 224, 224, 224));
1232-
$gris3 = intval(imagecolorallocate($img, 240, 240, 240));
1233-
1234-
// We add a small shadow
1235-
// Scaling original shadow line offsets based on their pixel values
1236-
$scaledOffset_1px = max(1, (int) round(1 * $scalingFactor)); // for imagesy($img) - 1, imagesx($img) - 1
1237-
$scaledOffset_2px = max(1, (int) round(2 * $scalingFactor)); // for x1=2, y1=2, imagesy($img) - 2, imagesx($img) - 2
1238-
$scaledOffset_3px = max(1, (int) round(3 * $scalingFactor)); // for imagesy($img) - 3, imagesx($img) - 3
1239-
$scaledOffset_4px = max(2, (int) round(4 * $scalingFactor)); // for x1=4, y1=4, imagesy($img) - 4, imagesx($img) - 4
1240-
$scaledOffset_6px = max(3, (int) round(6 * $scalingFactor)); // for x1=6, y1=6
1241-
if (
1242-
// Line 1: $gris1, original (2, imagesy($img) - 3) to (imagesx($img) - 1, imagesy($img) - 3)
1243-
!imageline($img, $scaledOffset_2px, imagesy($img) - $scaledOffset_3px, imagesx($img) - $scaledOffset_1px, imagesy($img) - $scaledOffset_3px, $gris1) ||
1244-
// Line 2: $gris2, original (4, imagesy($img) - 2) to (imagesx($img) - 1, imagesy($img) - 2)
1245-
!imageline($img, $scaledOffset_4px, imagesy($img) - $scaledOffset_2px, imagesx($img) - $scaledOffset_1px, imagesy($img) - $scaledOffset_2px, $gris2) ||
1246-
// Line 3: $gris3, original (6, imagesy($img) - 1) to (imagesx($img) - 1, imagesy($img) - 1)
1247-
!imageline($img, $scaledOffset_6px, imagesy($img) - $scaledOffset_1px, imagesx($img) - $scaledOffset_1px, imagesy($img) - $scaledOffset_1px, $gris3) ||
1248-
1249-
// Right shadow lines (vertical lines near the right edge)
1250-
// Line 1: $gris1, original (imagesx($img) - 3, 2) to (imagesx($img) - 3, imagesy($img) - 4)
1251-
!imageline($img, imagesx($img) - $scaledOffset_3px, $scaledOffset_2px, imagesx($img) - $scaledOffset_3px, imagesy($img) - $scaledOffset_4px, $gris1) ||
1252-
// Line 2: $gris2, original (imagesx($img) - 2, 4) to (imagesx($img) - 2, imagesy($img) - 4)
1253-
!imageline($img, imagesx($img) - $scaledOffset_2px, $scaledOffset_4px, imagesx($img) - $scaledOffset_2px, imagesy($img) - $scaledOffset_4px, $gris2) ||
1254-
// Line 3: $gris3, original (imagesx($img) - 1, 6) to (imagesx($img) - 1, imagesy($img) - 4)
1255-
!imageline($img, imagesx($img) - $scaledOffset_1px, $scaledOffset_6px, imagesx($img) - $scaledOffset_1px, imagesy($img) - $scaledOffset_4px, $gris3)
1256-
) {
1257-
unset($img);
1258-
throw new \Exception('Cannot add shadow.');
1259-
}
1260-
*/
12611219
// Convert hex color string to RGB values
12621220
$colorComponents = self::getColorComponents($this->polaroidBgColor);
12631221
list($rbcc, $gbcc, $bbcc) = $colorComponents;
12641222

12651223
// We rotate the image
1266-
$background = intval(imagecolorallocate($img, $rbcc, $gbcc, $bbcc));
1267-
$rotatedImg = imagerotate($img, $this->polaroidRotation, $background);
1224+
$rotationBackgroundColor = intval(imagecolorallocate($polaroidCanvas, $rbcc, $gbcc, $bbcc));
1225+
$rotatedImg = imagerotate($polaroidCanvas, $this->polaroidRotation, $rotationBackgroundColor);
12681226

12691227
if (!$rotatedImg) {
12701228
throw new \Exception('Cannot rotate image.');
@@ -1273,8 +1231,8 @@ public function effectPolaroid(GdImage $resource): GdImage
12731231
$this->addErrorData($e->getMessage());
12741232

12751233
// Try to clear cache
1276-
if (isset($img) && $img instanceof GdImage) {
1277-
unset($img);
1234+
if (isset($polaroidCanvas) && $polaroidCanvas instanceof GdImage) {
1235+
unset($polaroidCanvas);
12781236
}
12791237

12801238
// Re-throw exception on loglevel > 1
@@ -1287,7 +1245,7 @@ public function effectPolaroid(GdImage $resource): GdImage
12871245
}
12881246
$this->imageModified = true;
12891247
// We destroy the image we have been working with
1290-
unset($img);
1248+
unset($polaroidCanvas);
12911249

12921250
// We return the rotated image
12931251
return $rotatedImg;

0 commit comments

Comments
 (0)