storeOriginalImage($imageFile); // 2. 无损压缩图片 $compressedPath = $this->compressToWebp($originalPath); // 3. 添加水印 $watermarkedPath = $this->addWatermark($compressedPath); ImagesModel::create([ 'photo_album_id' => $pid, 'title' => date('Y-m-d H:i:s'), 'original' => $originalPath, 'compressed' => $compressedPath, 'watermarked' => $watermarkedPath, 'created_at' => time() ]); return [ 'original' => $originalPath, 'compressed' => $compressedPath, 'watermarked' => $watermarkedPath ]; } /** * 保存原始图片 */ protected function storeOriginalImage($imageFile) { $path = 'images/original/cc_'. date('Ymdhis') . Str::random(40) . '.' . $imageFile->getClientOriginalExtension(); Storage::put($path, file_get_contents($imageFile)); return $path; } /** * 使用WebP格式高效压缩图片 * * @param string $originalPath 原始图片路径 * @param int $quality WebP压缩质量(1-100) * @param int|null $maxWidth 最大宽度(可选) * @param int|null $maxHeight 最大高度(可选) * @return string 压缩后的图片路径 */ protected function compressToWebp($originalPath, $quality = 85, $maxWidth = null, $maxHeight = null) { // 获取原始图片内容 $imageContent = Storage::get($originalPath); $image = imagecreatefromstring($imageContent); // 获取图片信息 $info = getimagesizefromstring($imageContent); $width = $info[0]; $height = $info[1]; $mime = $info['mime']; // 调整图片尺寸(如果指定了最大宽高) if ($maxWidth || $maxHeight) { // 计算新尺寸,保持宽高比 $originalRatio = $width / $height; // 如果只指定了一个维度,自动计算另一个 if (!$maxWidth) { $maxWidth = (int)($maxHeight * $originalRatio); } elseif (!$maxHeight) { $maxHeight = (int)($maxWidth / $originalRatio); } // 计算最终尺寸(不超过原始尺寸) $newWidth = min($width, $maxWidth); $newHeight = min($height, $maxHeight); // 创建新尺寸的画布 $resizedImage = imagecreatetruecolor($newWidth, $newHeight); // 保留透明度 (PNG/GIF) if ($mime == 'image/png' || $mime == 'image/gif') { imagealphablending($resizedImage, false); imagesavealpha($resizedImage, true); $transparent = imagecolorallocatealpha($resizedImage, 255, 255, 255, 127); imagefilledrectangle($resizedImage, 0, 0, $newWidth, $newHeight, $transparent); } // 调整图片大小 imagecopyresampled($resizedImage, $image, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height); // 替换原始图片资源 imagedestroy($image); $image = $resizedImage; $width = $newWidth; $height = $newHeight; } // 生成压缩后的WebP图片 $compressedPath = 'images/compressed/' . Str::random(40) . '.webp'; // 保存WebP图片 ob_start(); imagewebp($image, null, $quality); $compressedContent = ob_get_clean(); Storage::put($compressedPath, $compressedContent); // 释放内存 imagedestroy($image); return $compressedPath; } /** * 添加水印 */ protected function addWatermark($imagePath) { $imageContent = Storage::get($imagePath); $image = imagecreatefromstring($imageContent); // 获取图片信息 $info = getimagesizefromstring($imageContent); $width = $info[0]; $height = $info[1]; $mime = $info['mime']; // 水印文字设置 $text = '@ Li Qi'; $fontSize = 20; $fontFile = public_path('fonts/arial.ttf'); // 确保字体文件存在 // $fontFile = ''; // 确保字体文件存在 $textColor = imagecolorallocatealpha($image, 255, 255, 255, 50); // 计算文字位置 (右下角) $textBox = imagettfbbox($fontSize, 0, $fontFile, $text); $textWidth = $textBox[2] - $textBox[0]; $textHeight = $textBox[7] - $textBox[1]; $x = $width - $textWidth - 40; $y = $height - $textHeight - 40; // 添加文字水印 imagettftext($image, $fontSize, 0, $x, $y, $textColor, $fontFile, $text); // 生成带水印的路径 $extension = pathinfo($imagePath, PATHINFO_EXTENSION); $watermarkedPath = 'images/watermarked/' . Str::random(40) . '.' . $extension; // 保存带水印的图片 ob_start(); switch ($mime) { case 'image/jpeg': imagejpeg($image, null, 100); break; case 'image/png': imagepng($image, null, 9); break; case 'image/gif': imagegif($image); break; case 'image/webp': imagewebp($image, null, 100); break; } $watermarkedContent = ob_get_clean(); Storage::put($watermarkedPath, $watermarkedContent); // 释放内存 imagedestroy($image); return $watermarkedPath; } }