|
|
|
@ -422,80 +422,47 @@ class Upload extends BaseController |
|
|
|
// 处理图地址 |
|
|
|
$target = root_path().'public/' .ltrim($compress_path,'/'); |
|
|
|
// 图片模糊处理 |
|
|
|
if (class_exists('Imagick')) { |
|
|
|
$compress_res = $this->slightBlurImagick($filePath, $target, 1); |
|
|
|
} else { |
|
|
|
$compress_res = $this->slightBlurGD($filePath, $target, 1); |
|
|
|
} |
|
|
|
$compress_res = $this->slightBlurGD($filePath, $target); |
|
|
|
if (!$compress_res) { |
|
|
|
return ''; |
|
|
|
} |
|
|
|
return $compress_path; |
|
|
|
} |
|
|
|
|
|
|
|
// 使用Imagick添加轻微模糊 |
|
|
|
protected function slightBlurImagick($source, $target, $blurLevel) |
|
|
|
{ |
|
|
|
try { |
|
|
|
$imagick = new \Imagick($source); |
|
|
|
|
|
|
|
// 轻微模糊 (半径0.5-2.0) |
|
|
|
$radius = min(2.0, max(0.5, $blurLevel * 0.5)); |
|
|
|
$imagick->gaussianBlurImage($radius, 1); |
|
|
|
|
|
|
|
// 保存时降低质量 |
|
|
|
$extension = strtolower(pathinfo($target, PATHINFO_EXTENSION)); |
|
|
|
|
|
|
|
switch ($extension) { |
|
|
|
case 'jpg': |
|
|
|
case 'jpeg': |
|
|
|
$imagick->setImageCompressionQuality(85); |
|
|
|
$imagick->setImageFormat('jpeg'); |
|
|
|
break; |
|
|
|
case 'webp': |
|
|
|
case 'png': |
|
|
|
$imagick->setImageCompressionQuality(85); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return $imagick->writeImage($target); |
|
|
|
} catch (\Exception $e) { |
|
|
|
\think\facade\Log::error('Imagick模糊处理失败: ' . $e->getMessage()); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 使用GD库添加轻微模糊 |
|
|
|
protected function slightBlurGD($source, $target, $blurLevel) |
|
|
|
protected function slightBlurGD($imageFile, $target) |
|
|
|
{ |
|
|
|
$info = getimagesize($source); |
|
|
|
$type = $info[2]; |
|
|
|
|
|
|
|
// 创建图像资源 |
|
|
|
switch ($type) { |
|
|
|
// 获取图片信息 |
|
|
|
list($imgWidth, $imgHeight, $imageType) = getimagesize($imageFile); |
|
|
|
// 根据图片类型创建图像资源 |
|
|
|
switch ($imageType) { |
|
|
|
case IMAGETYPE_JPEG: |
|
|
|
$image = imagecreatefromjpeg($source); |
|
|
|
$image = imagecreatefromjpeg($imageFile); |
|
|
|
break; |
|
|
|
case IMAGETYPE_PNG: |
|
|
|
$image = imagecreatefrompng($source); |
|
|
|
$image = imagecreatefrompng($imageFile); |
|
|
|
// 保留透明通道 |
|
|
|
imagealphablending($image, true); |
|
|
|
imagesavealpha($image, true); |
|
|
|
break; |
|
|
|
case IMAGETYPE_GIF: |
|
|
|
$image = imagecreatefromgif($source); |
|
|
|
break; |
|
|
|
case IMAGETYPE_WEBP: |
|
|
|
$image = imagecreatefromwebp($source); |
|
|
|
$image = imagecreatefromgif($imageFile); |
|
|
|
break; |
|
|
|
default: |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// 应用轻微模糊 |
|
|
|
for ($i = 0; $i < $blurLevel; $i++) { |
|
|
|
imagefilter($image, IMG_FILTER_GAUSSIAN_BLUR); |
|
|
|
} |
|
|
|
// 获取图片尺寸 |
|
|
|
|
|
|
|
// 调整选择区域确保在图片范围内 |
|
|
|
$x = 0; |
|
|
|
$y = 0; |
|
|
|
|
|
|
|
// 应用马赛克效果 |
|
|
|
$this->applyMosaic($image, $x, $y, $imgWidth, $imgHeight, 5, 2); |
|
|
|
|
|
|
|
// 保存图片 |
|
|
|
switch ($type) { |
|
|
|
switch ($imageType) { |
|
|
|
case IMAGETYPE_JPEG: |
|
|
|
imagejpeg($image, $target, 85); |
|
|
|
break; |
|
|
|
@ -510,7 +477,119 @@ class Upload extends BaseController |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
imagedestroy($image); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 应用马赛克效果 |
|
|
|
* |
|
|
|
* @param resource $image 图像资源 |
|
|
|
* @param int $x 起始X坐标 |
|
|
|
* @param int $y 起始Y坐标 |
|
|
|
* @param int $width 区域宽度 |
|
|
|
* @param int $height 区域高度 |
|
|
|
* @param int $blockSize 马赛克块大小 |
|
|
|
* @param int $blurStrength 模糊强度 (1-3) |
|
|
|
*/ |
|
|
|
protected function applyMosaic($image, $x, $y, $width, $height, $blockSize, $blurStrength) { |
|
|
|
// 调整马赛克块大小 |
|
|
|
$adjustedBlockSize = $blockSize * $blurStrength; |
|
|
|
|
|
|
|
// 计算马赛克网格 |
|
|
|
$cols = ceil($width / $adjustedBlockSize); |
|
|
|
$rows = ceil($height / $adjustedBlockSize); |
|
|
|
|
|
|
|
// 处理每个马赛克块 |
|
|
|
for ($row = 0; $row < $rows; $row++) { |
|
|
|
for ($col = 0; $col < $cols; $col++) { |
|
|
|
// 计算当前块的区域 |
|
|
|
$blockX = $x + $col * $adjustedBlockSize; |
|
|
|
$blockY = $y + $row * $adjustedBlockSize; |
|
|
|
$blockWidth = min($adjustedBlockSize, $width - $col * $adjustedBlockSize); |
|
|
|
$blockHeight = min($adjustedBlockSize, $height - $row * $adjustedBlockSize); |
|
|
|
|
|
|
|
// 计算块内像素的平均颜色 |
|
|
|
$avgColor = $this->calculateAverageColor($image, $blockX, $blockY, $blockWidth, $blockHeight); |
|
|
|
|
|
|
|
// 填充整个块为平均颜色 |
|
|
|
imagefilledrectangle( |
|
|
|
$image, |
|
|
|
$blockX, |
|
|
|
$blockY, |
|
|
|
$blockX + $blockWidth - 1, |
|
|
|
$blockY + $blockHeight - 1, |
|
|
|
$avgColor |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 根据需要应用额外模糊 |
|
|
|
if ($blurStrength > 1) { |
|
|
|
$blurRegion = imagecrop($image, ['x' => $x, 'y' => $y, 'width' => $width, 'height' => $height]); |
|
|
|
if ($blurRegion !== false) { |
|
|
|
// 应用模糊 |
|
|
|
for ($i = 0; $i < $blurStrength; $i++) { |
|
|
|
imagefilter($blurRegion, IMG_FILTER_GAUSSIAN_BLUR); |
|
|
|
} |
|
|
|
|
|
|
|
// 将模糊后的区域放回原图 |
|
|
|
imagecopymerge($image, $blurRegion, $x, $y, 0, 0, $width, $height, 100); |
|
|
|
imagedestroy($blurRegion); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 计算图像区域的平均颜色 |
|
|
|
* |
|
|
|
* @param resource $image 图像资源 |
|
|
|
* @param int $x 起始X坐标 |
|
|
|
* @param int $y 起始Y坐标 |
|
|
|
* @param int $width 区域宽度 |
|
|
|
* @param int $height 区域高度 |
|
|
|
* @return int 颜色标识符 |
|
|
|
*/ |
|
|
|
protected function calculateAverageColor($image, $x, $y, $width, $height) { |
|
|
|
$totalR = 0; |
|
|
|
$totalG = 0; |
|
|
|
$totalB = 0; |
|
|
|
$totalAlpha = 0; |
|
|
|
$pixelCount = 0; |
|
|
|
|
|
|
|
// 遍历区域内的所有像素 |
|
|
|
for ($i = 0; $i < $width; $i++) { |
|
|
|
for ($j = 0; $j < $height; $j++) { |
|
|
|
$px = $x + $i; |
|
|
|
$py = $y + $j; |
|
|
|
|
|
|
|
// 确保像素在图像范围内 |
|
|
|
if ($px >= imagesx($image)) continue; |
|
|
|
if ($py >= imagesy($image)) continue; |
|
|
|
|
|
|
|
// 获取像素颜色 |
|
|
|
$color = imagecolorat($image, $px, $py); |
|
|
|
$rgba = imagecolorsforindex($image, $color); |
|
|
|
|
|
|
|
// 累加颜色值 |
|
|
|
$totalR += $rgba['red']; |
|
|
|
$totalG += $rgba['green']; |
|
|
|
$totalB += $rgba['blue']; |
|
|
|
$totalAlpha += $rgba['alpha']; |
|
|
|
$pixelCount++; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 计算平均值 |
|
|
|
if ($pixelCount === 0) { |
|
|
|
return imagecolorallocatealpha($image, 0, 0, 0, 127); |
|
|
|
} |
|
|
|
|
|
|
|
$avgR = round($totalR / $pixelCount); |
|
|
|
$avgG = round($totalG / $pixelCount); |
|
|
|
$avgB = round($totalB / $pixelCount); |
|
|
|
$avgAlpha = round($totalAlpha / $pixelCount); |
|
|
|
|
|
|
|
// 返回平均颜色 |
|
|
|
return imagecolorallocatealpha($image, $avgR, $avgG, $avgB, $avgAlpha); |
|
|
|
} |
|
|
|
} |
|
|
|
|