This commit is contained in:
gaofeng
2026-05-12 18:27:28 +08:00
commit 6d9aee81aa
3664 changed files with 274415 additions and 0 deletions

View File

@@ -0,0 +1,186 @@
<?php
namespace app\service;
/**
* 压缩二进制流图片
*/
class CompressImgService
{
/**
* 压缩通过表单上传的图片
*
* @param string $fileData 图片的二进制数据
* @param int $quality 压缩质量0-100仅适用于JPEG和WebP
* @param string|null $targetFormat 目标格式('jpeg', 'png', 'webp',默认使用原格式)
* @return array 包含压缩后图片信息的数组
*/
function compress($fileData, $quality = 80, $targetFormat = null)
{
// 读取上传的二进制数据
$imageData = file_get_contents($fileData);
if ($imageData === false) {
return [
'code' => 0,
'message' => '无法读取上传的文件',
];
}
// 获取图片信息
$imageInfo = getimagesizefromstring($imageData);
if (!$imageInfo) {
return [
'code' => 0,
'message' => '无法解析图片信息',
];
}
// 确定原始和目标格式
$originalMimeType = $imageInfo['mime'];
$originalExtension = image_type_to_extension($imageInfo[2], false);
if ($targetFormat === null) {
$targetFormat = $originalExtension;
}
// 创建图片资源
switch (strtolower($originalExtension)) {
case 'jpeg':
case 'jpg':
$image = imagecreatefromstring($imageData);
break;
case 'png':
$image = imagecreatefromstring($imageData);
break;
case 'webp':
$image = imagecreatefromstring($imageData);
break;
default:
return [
'code' => 0,
'message' => '不支持的图片格式',
];
}
if (!$image) {
return [
'code' => 0,
'message' => '无法创建图片资源',
];
}
// 压缩并转换图片
ob_start();
switch (strtolower($targetFormat)) {
case 'jpeg':
case 'jpg':
imagejpeg($image, null, $quality);
$compressedMimeType = 'image/jpeg';
break;
case 'png':
$pngQuality = 9 - floor($quality / 11);
imagepng($image, null, $pngQuality);
$compressedMimeType = 'image/png';
break;
case 'webp':
if (function_exists('imagewebp')) {
imagewebp($image, null, $quality);
$compressedMimeType = 'image/webp';
} else {
imagejpeg($image, null, $quality);
$compressedMimeType = 'image/jpeg';
}
break;
default:
imagedestroy($image);
ob_end_clean();
return [
'code' => 0,
'message' => "不支持的目标格式: {$targetFormat}",
];
}
$compressedData = ob_get_clean();
imagedestroy($image);
// 返回结果
return [
'code' => 1,
'compressed_data' => $compressedData,
'base64' => 'data:' . $compressedMimeType . ';base64,' . base64_encode($compressedData),
];
}
public function compressImage($filePath, $fileSize)
{
// 获取图片信息
$imageInfo = getimagesize($filePath);
if (!$imageInfo) {
return false;
}
$mime = $imageInfo['mime'];
// 根据MIME类型创建图像资源
switch ($mime) {
case 'image/jpeg':
$image = imagecreatefromjpeg($filePath);
break;
case 'image/png':
$image = imagecreatefrompng($filePath);
break;
case 'image/gif':
$image = imagecreatefromgif($filePath);
break;
default:
return false;
}
if (!$image) {
return false;
}
// 计算压缩质量(根据文件大小动态调整)
$originalQuality = 85; // 初始质量
$targetSize = 2.5 * 1024 * 1024; // 目标大小2.5MB
// 如果文件很大,降低初始质量
if ($fileSize > 5 * 1024 * 1024) {
$quality = 75;
} elseif ($fileSize > 10 * 1024 * 1024) {
$quality = 65;
} else {
$quality = $originalQuality;
}
// 创建临时文件
$tempFile = tempnam(sys_get_temp_dir(), 'compressed_');
// 保存压缩后的图片
switch ($mime) {
case 'image/jpeg':
imagejpeg($image, $tempFile, $quality);
break;
case 'image/png':
// PNG使用压缩级别0-9需要转换
$pngQuality = 9 - round(($quality / 100) * 9);
imagepng($image, $tempFile, $pngQuality);
break;
case 'image/gif':
imagegif($image, $tempFile);
break;
}
// 释放内存
imagedestroy($image);
// 检查压缩后文件大小如果仍然大于3MB继续压缩
$compressedSize = filesize($tempFile);
if ($compressedSize > 3 * 1024 * 1024) {
// 递归压缩直到满足要求
return $this->compressImage($tempFile, $compressedSize);
}
return $tempFile;
}
}