Procházet zdrojové kódy

创建基于ImageMagick的压缩服务

moonsflyer před 4 měsíci
rodič
revize
2ea54fcbd2
1 změnil soubory, kde provedl 122 přidání a 0 odebrání
  1. 122 0
      app/common/service/ImageMagickCompressService.php

+ 122 - 0
app/common/service/ImageMagickCompressService.php

@@ -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'];
+    }
+}