|
|
@@ -0,0 +1,122 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace app\common\service;
|
|
|
+
|
|
|
+use Exception;
|
|
|
+
|
|
|
+class ImageMagickCompressService
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * 使用ImageMagick压缩图片
|
|
|
+ */
|
|
|
+ public static function compress($sourcePath, $compressConfig = [])
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ // 检查ImageMagick扩展
|
|
|
+ if (!extension_loaded('imagick')) {
|
|
|
+ outFileLog('ImageMagick扩展未安装', 'upload_img', 'imagick_not_installed');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 默认配置
|
|
|
+ $config = array_merge([
|
|
|
+ 'max_width' => 1920,
|
|
|
+ 'max_height' => 1080,
|
|
|
+ 'quality' => 80,
|
|
|
+ 'format' => null // 保持原格式
|
|
|
+ ], $compressConfig);
|
|
|
+
|
|
|
+ // 检查源文件
|
|
|
+ if (!file_exists($sourcePath)) {
|
|
|
+ throw new Exception('源文件不存在: ' . $sourcePath);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取文件信息
|
|
|
+ $pathInfo = pathinfo($sourcePath);
|
|
|
+ $extension = strtolower($pathInfo['extension']);
|
|
|
+
|
|
|
+ // 支持的格式
|
|
|
+ $supportedFormats = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'];
|
|
|
+ if (!in_array($extension, $supportedFormats)) {
|
|
|
+ outFileLog('不支持的图片格式: ' . $extension, 'upload_img', 'unsupported_format');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建Imagick对象
|
|
|
+ $imagick = new \Imagick($sourcePath);
|
|
|
+
|
|
|
+ // 获取原始尺寸
|
|
|
+ $originalWidth = $imagick->getImageWidth();
|
|
|
+ $originalHeight = $imagick->getImageHeight();
|
|
|
+
|
|
|
+ outFileLog("原始尺寸: {$originalWidth}x{$originalHeight}", 'upload_img', 'original_size');
|
|
|
+
|
|
|
+ // 计算新尺寸
|
|
|
+ $newSize = self::calculateNewSize(
|
|
|
+ $originalWidth,
|
|
|
+ $originalHeight,
|
|
|
+ $config['max_width'],
|
|
|
+ $config['max_height']
|
|
|
+ );
|
|
|
+
|
|
|
+ // 如果需要缩放
|
|
|
+ if ($newSize['width'] < $originalWidth || $newSize['height'] < $originalHeight) {
|
|
|
+ $imagick->resizeImage(
|
|
|
+ $newSize['width'],
|
|
|
+ $newSize['height'],
|
|
|
+ \Imagick::FILTER_LANCZOS,
|
|
|
+ 1
|
|
|
+ );
|
|
|
+ outFileLog("压缩后尺寸: {$newSize['width']}x{$newSize['height']}", 'upload_img', 'compressed_size');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置压缩质量
|
|
|
+ $imagick->setImageCompressionQuality($config['quality']);
|
|
|
+
|
|
|
+ // 去除EXIF信息减小文件大小
|
|
|
+ $imagick->stripImage();
|
|
|
+
|
|
|
+ // 生成压缩后的文件路径
|
|
|
+ $compressedPath = self::generateCompressedPath($sourcePath);
|
|
|
+
|
|
|
+ // 保存压缩后的图片
|
|
|
+ $imagick->writeImage($compressedPath);
|
|
|
+ $imagick->clear();
|
|
|
+ $imagick->destroy();
|
|
|
+
|
|
|
+ // 检查压缩效果
|
|
|
+ $originalSize = filesize($sourcePath);
|
|
|
+ $compressedSize = filesize($compressedPath);
|
|
|
+ $compressionRatio = round((1 - $compressedSize / $originalSize) * 100, 2);
|
|
|
+
|
|
|
+ outFileLog("压缩完成,原大小: {$originalSize}字节,压缩后: {$compressedSize}字节,压缩率: {$compressionRatio}%", 'upload_img', 'compression_result');
|
|
|
+
|
|
|
+ return $compressedPath;
|
|
|
+
|
|
|
+ } catch (Exception $e) {
|
|
|
+ outFileLog('ImageMagick压缩失败: ' . $e->getMessage(), 'upload_img', 'imagick_compress_error');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算新尺寸(保持宽高比)
|
|
|
+ */
|
|
|
+ private static function calculateNewSize($width, $height, $maxWidth, $maxHeight)
|
|
|
+ {
|
|
|
+ $ratio = min($maxWidth / $width, $maxHeight / $height, 1);
|
|
|
+ return [
|
|
|
+ 'width' => intval($width * $ratio),
|
|
|
+ 'height' => intval($height * $ratio)
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成压缩后的文件路径
|
|
|
+ */
|
|
|
+ private static function generateCompressedPath($sourcePath)
|
|
|
+ {
|
|
|
+ $pathInfo = pathinfo($sourcePath);
|
|
|
+ return $pathInfo['dirname'] . '/' . $pathInfo['filename'] . '_compressed.' . $pathInfo['extension'];
|
|
|
+ }
|
|
|
+}
|