| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- <?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'];
- }
- }
|