imageResource($srcPath); if ($resource === false) { appNotice("could not get image resource: $srcPath"); return $dbPath; } [$image, $saveMethod, $quality] = $resource; $width = imagesx($image); $height = imagesy($image); $cropWidth ??= $width; $cropHeight ??= $height; if (($width > $cropWidth || $height > $cropHeight) === false) { $destPath = $this->destPath($srcPath, $dbPath, $width, $height); appInfo(self::$counter++ . ". skip cropping ($width x $height): " . basename($destPath[0]) . " saved"); return File::move($srcPath, $destPath[0]) ? $destPath[1] : $dbPath; } $horizontalAlignPixels = $this->calculatePixelsForAlign($width, $cropWidth, $horizontalAlign); $verticalAlignPixels = $this->calculatePixelsForAlign($height, $cropHeight, $verticalAlign); $destPath = $this->destPath($srcPath, $dbPath, $horizontalAlignPixels[1], $verticalAlignPixels[1]); $croppedImage = imagecrop($image, [ 'x' => $horizontalAlignPixels[0], 'y' => $verticalAlignPixels[0], 'width' => $horizontalAlignPixels[1], 'height' => $verticalAlignPixels[1], ]); if ($croppedImage !== false) { $saveMethod($croppedImage, $destPath[0], $quality); imagedestroy($croppedImage); appSuccess( self::$counter++ . ". cropped successfully from $width x $height: " . basename($destPath[0]) . " saved" ); } imagedestroy($image); if (File::delete($srcPath) === false) { $e = new RuntimeException("could not delete image: $srcPath"); appWarning($e); return $dbPath; } return $destPath[1]; } /** * @param string $srcPath * * @return false|array */ private function imageResource(string $srcPath): false|array { return match (mime_content_type($srcPath)) { 'image/jpeg' => [imagecreatefromjpeg($srcPath), 'imagejpeg', 84], 'image/png' => [imagecreatefrompng($srcPath), 'imagepng', 7], 'image/gif' => [imagecreatefromgif($srcPath), 'imagegif', null], default => false, }; } /** * @param string $srcPath * @param string $dbPath * @param int $width * @param int $height * * @return string[] */ private function destPath(string $srcPath, string $dbPath, int $width, int $height): array { $pi = pathinfo($srcPath); $fs_path = sprintf( "%s\%s-%dx%d.%s", $pi['dirname'], $pi['filename'], $width, $height, $pi['extension'] ); $db_path = sprintf( "%s/%s-%dx%d.%s", dirname($dbPath), $pi['filename'], $width, $height, $pi['extension'] ); return [$fs_path, $db_path]; } /** * @param int $imageSize * @param int $cropSize * @param string $align * * @return array|int[] */ private function calculatePixelsForAlign(int $imageSize, int $cropSize, string $align): array { return match ($align) { 'left', 'top' => [0, min($cropSize, $imageSize)], 'right', 'bottom' => [max(0, $imageSize - $cropSize), min($cropSize, $imageSize)], 'center', 'middle' => [ max(0, floor(($imageSize / 2) - ($cropSize / 2))), min($cropSize, $imageSize), ], default => [0, $imageSize], }; } }