网站首页php
PHP图像处理类
发布时间:2025-07-10 18:42:48编辑:阅读(43)
支持处理图片效果:
blackWhite - 黑白图片效果
gray - 灰色调效果
flipImage - 翻转图片
oldPhoto - 旧图片效果
fogFilter - 雾化效果
frostedGlassEffect - 毛玻璃效果
embossEffect - 浮雕效果
<?php
class ImageMagic {
private $info;
private $source;
private $bwImage;
public function __construct($imagePath) {
$this->info = getimagesize($imagePath);
switch ($this->info['mime']) {
case 'image/jpeg':
$this->source = imagecreatefromjpeg($imagePath);
break;
case 'image/png':
$this->source = imagecreatefrompng($imagePath);
break;
case 'image/gif':
$this->source = imagecreatefromgif($imagePath);
break;
default:
throw new \exception('不支持的图片格式');
}
$this->bwImage = imagecreatetruecolor($this->info[0], $this->info[1]);
// 处理透明背景
if ($this->info['mime'] == 'image/png' || $this->info['mime'] == 'image/gif') {
imagealphablending($this->bwImage, false);
imagesavealpha($this->bwImage, true);
$transparent = imagecolorallocatealpha($this->bwImage, 0, 0, 0, 127);
imagefill($this->bwImage, 0, 0, $transparent);
}
}
public function __destruct() {
imagedestroy($this->source);
imagedestroy($this->bwImage);
}
/**
* name:转换黑白图片
* @param $this->sourceImage源图
* @param $threshold比率
* @param $target=file保存文件/screen输出到屏幕
* @return string|void
**/
public function blackWhite($threshold = 180, $target = 'file')
{
$white = imagecolorallocate($this->bwImage, 255, 255, 255);
$black = imagecolorallocate($this->bwImage, 0, 0, 0);
imagefill($this->bwImage, 0, 0, $white);
// 转换为黑白
for ($x = 0; $x < $this->info[0]; $x++) {
for ($y = 0; $y < $this->info[1]; $y++) {
$color = imagecolorat($this->source, $x, $y);
$rgba = imagecolorsforindex($this->source, $color);
$gray = (int)(0.299 * $rgba['red'] + 0.587 * $rgba['green'] + 0.114 * $rgba['blue']);
$bwColor = ($gray >= $threshold) ? $white : $black;
imagesetpixel($this->bwImage, $x, $y, $bwColor);
}
}
return $this;
}
/**
* name:转换灰色调图片
* @param $this->sourceImage源图
* @param $threshold比率
* @param $target=file保存文件/screen输出到屏幕
* @return string|void
**/
public function gray()
{
// 转为灰色调
for ($x = 0; $x < $this->info[0]; $x++) {
for ($y = 0; $y < $this->info[1]; $y++) {
$color = imagecolorat($this->source, $x, $y);
$rgba = imagecolorsforindex($this->source, $color);
// 使用标准灰度转换公式
$gray = (int)(0.299 * $rgba['red'] + 0.587 * $rgba['green'] + 0.114 * $rgba['blue']);
// 保留透明度
if ($rgba['alpha'] > 0) {
$grayColor = imagecolorallocatealpha($this->bwImage, $gray, $gray, $gray, $rgba['alpha']);
} else {
$grayColor = imagecolorallocate($this->bwImage, $gray, $gray, $gray);
}
imagesetpixel($this->bwImage, $x, $y, $grayColor);
}
}
return $this;
}
/**
* name:翻转图片
* @param $image源图句柄
* @param $flipType翻转方式(horizontal':水平反转|vertical':垂直反转|both':水平和垂直同时反转)
* @return $this
**/
public function flipImage($flipType) {
// 执行反转操作
switch ($flipType) {
case 'horizontal': // 水平反转
for ($x = 0; $x < $this->info[0]; $x++) {
imagecopy($this->bwImage, $this->source, $x, 0, $this->info[0] - $x - 1, 0, 1, $this->info[1]);
}
break;
case 'vertical': // 垂直反转
for ($y = 0; $y < $this->info[1]; $y++) {
imagecopy($this->bwImage, $this->source, 0, $y, 0, $this->info[1] - $y - 1, $this->info[0], 1);
}
break;
case 'both': // 水平和垂直同时反转
for ($x = 0; $x < $this->info[0]; $x++) {
for ($y = 0; $y < $this->info[1]; $y++) {
$srcX = $this->info[0] - $x - 1;
$srcY = $this->info[1] - $y - 1;
$color = imagecolorat($this->source, $srcX, $srcY);
imagesetpixel($this->bwImage, $x, $y, $color);
}
}
break;
}
return $this;
}
/**
* name: 旧照片
* @param $image源图句柄
* @param $intensity折旧率
* @return $this
**/
public function oldPhoto($intensity = 50) {
$intensity = max(0, min(100, $intensity)) / 100;
// 执行折旧操作
for ($x = 0; $x < $this->info[0]; $x++) {
for ($y = 0; $y < $this->info[1]; $y++) {
$color = imagecolorat($this->source, $x, $y);
$rgba = imagecolorsforindex($this->source, $color);
// 降低饱和度
$gray = (0.299 * $rgba['red'] + 0.587 * $rgba['green'] + 0.114 * $rgba['blue']);
$r = $rgba['red'] * (1 - $intensity * 0.7) + $gray * $intensity * 0.7;
$g = $rgba['green'] * (1 - $intensity * 0.7) + $gray * $intensity * 0.7;
$b = $rgba['blue'] * (1 - $intensity * 0.7) + $gray * $intensity * 0.7;
// 添加黄色调
$r = min(255, $r + ($intensity * 30));
$g = min(255, $g + ($intensity * 15));
$b = min(255, $b - ($intensity * 5));
// 降低亮度
$r *= (1 - $intensity * 0.2);
$g *= (1 - $intensity * 0.2);
$b *= (1 - $intensity * 0.2);
// 保留透明度
if (isset($rgba['alpha']) && $rgba['alpha'] > 0) {
$newColor = imagecolorallocatealpha($this->bwImage, $r, $g, $b, $rgba['alpha']);
} else {
$newColor = imagecolorallocate($this->bwImage, $r, $g, $b);
}
imagesetpixel($this->bwImage, $x, $y, $newColor);
}
}
// 添加噪点
$this->addNoise($this->bwImage);
// 添加暗角效果
$this->addVignette($this->bwImage, $this->info[0], $this->info[1]);
return $this;
}
// 添加噪点
private function addNoise($image, $level = 20) {
$this->info[0] = imagesx($image);
$this->info[1] = imagesy($image);
$level = max(1, min(100, $level));
for ($x = 0; $x < $this->info[0]; $x++) {
for ($y = 0; $y < $this->info[1]; $y++) {
$color = imagecolorat($image, $x, $y);
$rgba = imagecolorsforindex($image, $color);
// 添加随机噪点
$noise = rand(-$level, $level);
$r = max(0, min(255, $rgba['red'] + $noise));
$g = max(0, min(255, $rgba['green'] + $noise));
$b = max(0, min(255, $rgba['blue'] + $noise));
if (isset($rgba['alpha']) && $rgba['alpha'] > 0) {
$newColor = imagecolorallocatealpha($image, $r, $g, $b, $rgba['alpha']);
} else {
$newColor = imagecolorallocate($image, $r, $g, $b);
}
imagesetpixel($image, $x, $y, $newColor);
}
}
}
// 添加暗角效果
private function addVignette($image) {
$centerX = $this->info[0] / 2;
$centerY = $this->info[1] / 2;
$maxDist = sqrt($centerX * $centerX + $centerY * $centerY);
for ($x = 0; $x < $this->info[0]; $x++) {
for ($y = 0; $y < $this->info[1]; $y++) {
$color = imagecolorat($image, $x, $y);
$rgba = imagecolorsforindex($image, $color);
// 计算距离中心的距离
$distX = $x - $centerX;
$distY = $y - $centerY;
$dist = sqrt($distX * $distX + $distY * $distY);
// 计算暗角强度 (0到0.5之间)
$vignette = 0.5 * ($dist / $maxDist);
// 应用暗角效果
$r = $rgba['red'] * (1 - $vignette);
$g = $rgba['green'] * (1 - $vignette);
$b = $rgba['blue'] * (1 - $vignette);
if (isset($rgba['alpha']) && $rgba['alpha'] > 0) {
$newColor = imagecolorallocatealpha($image, $r, $g, $b, $rgba['alpha']);
} else {
$newColor = imagecolorallocate($image, $r, $g, $b);
}
imagesetpixel($image, $x, $y, $newColor);
}
}
}
/**
* name: 雾化效果
* @param $blurRadius模糊半径
* @param $fogDensity雾密度
* @param $fogColor雾颜色
* @param $preserveEdges保留边缘
* @return $this
**/
public function fogFilter($blurRadius = 5, $fogDensity = 0.3, $fogColor = 'ffffff', $preserveEdges = false) {
// 解析雾颜色
$fogR = hexdec(substr($fogColor, 0, 2));
$fogG = hexdec(substr($fogColor, 2, 2));
$fogB = hexdec(substr($fogColor, 4, 2));
// 创建雾层
$fogLayer = imagecreatetruecolor($this->info[0], $this->info[1]);
$fogColor = imagecolorallocate($fogLayer, $fogR, $fogG, $fogB);
imagefill($fogLayer, 0, 0, $fogColor);
// 如果需要保留边缘,先检测边缘
$edgeMask = null;
if ($preserveEdges) {
$edgeMask = $this->detectEdges($this->source, $this->info[0], $this->info[1]);
}
// 应用模糊效果
for ($i = 0; $i < $blurRadius; $i++) {
imagefilter($this->source, IMG_FILTER_GAUSSIAN_BLUR);
}
// 合并雾层和原图
for ($x = 0; $x < $this->info[0]; $x++) {
for ($y = 0; $y < $this->info[1]; $y++) {
$color = imagecolorat($this->source, $x, $y);
$rgba = imagecolorsforindex($this->source, $color);
// 如果有边缘遮罩,根据边缘强度调整雾密度
$currentDensity = $fogDensity;
if ($edgeMask) {
$edgeStrength = imagecolorat($edgeMask, $x, $y) & 0xFF;
$edgeFactor = $edgeStrength / 255;
$currentDensity = $fogDensity * (1 - $edgeFactor * 0.7); // 减少边缘处的雾效果
}
// 混合颜色
$r = $rgba['red'] * (1 - $currentDensity) + $fogR * $currentDensity;
$g = $rgba['green'] * (1 - $currentDensity) + $fogG * $currentDensity;
$b = $rgba['blue'] * (1 - $currentDensity) + $fogB * $currentDensity;
// 保留透明度
if (isset($rgba['alpha']) && $rgba['alpha'] > 0) {
$newColor = imagecolorallocatealpha($this->bwImage, $r, $g, $b, $rgba['alpha']);
} else {
$newColor = imagecolorallocate($this->bwImage, $r, $g, $b);
}
imagesetpixel($this->bwImage, $x, $y, $newColor);
}
}
return $this;
}
// 检测边缘
private function detectEdges($image) {
$edgeImage = imagecreatetruecolor($this->info[0], $this->info[1]);
imagefill($edgeImage, 0, 0, imagecolorallocate($edgeImage, 0, 0, 0));
// Sobel算子
$sobelX = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]];
$sobelY = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]];
for ($x = 1; $x < $this->info[0] - 1; $x++) {
for ($y = 1; $y < $this->info[1] - 1; $y++) {
$pixelX = 0;
$pixelY = 0;
// 应用Sobel算子
for ($i = -1; $i <= 1; $i++) {
for ($j = -1; $j <= 1; $j++) {
$color = imagecolorat($image, $x + $i, $y + $j);
$gray = (($color >> 16) & 0xFF) * 0.299 +
(($color >> 8) & 0xFF) * 0.587 +
($color & 0xFF) * 0.114;
$pixelX += $gray * $sobelX[$i + 1][$j + 1];
$pixelY += $gray * $sobelY[$i + 1][$j + 1];
}
}
// 计算梯度幅度
$magnitude = min(255, sqrt($pixelX * $pixelX + $pixelY * $pixelY));
$edgeColor = imagecolorallocate($edgeImage, $magnitude, $magnitude, $magnitude);
imagesetpixel($edgeImage, $x, $y, $edgeColor);
}
}
// 应用高斯模糊使边缘更平滑
imagefilter($edgeImage, IMG_FILTER_GAUSSIAN_BLUR);
return $edgeImage;
}
/**
* name: 磨砂玻璃效果
* @param $blurRadius模糊半径
* @param $brightness亮度
* @param $opacity不透明度
* @param $region区域
* @return $this
**/
public function frostedGlassEffect(
$blurRadius = 10,
$brightness = 0,
$opacity = 0.7,
$region = 'full',
$regionX = 0,
$regionY = 0,
$regionWidth = 100,
$regionHeight = 100
) {
// 复制原始图像
imagecopy($this->bwImage, $this->source, 0, 0, 0, 0, $this->info[0], $this->info[1]);
// 应用高斯模糊
for ($i = 0; $i < $blurRadius; $i++) {
imagefilter($this->bwImage, IMG_FILTER_GAUSSIAN_BLUR);
}
// 调整亮度
if ($brightness != 0) {
imagefilter($this->bwImage, IMG_FILTER_BRIGHTNESS, $brightness);
}
// 如果是局部区域处理
if ($region === 'partial') {
// 创建临时图像只处理选定区域
$regionImage = imagecreatetruecolor($regionWidth, $regionHeight);
imagecopy($regionImage, $this->bwImage, 0, 0, $regionX, $regionY, $regionWidth, $regionHeight);
// 将处理后的区域复制回原图
imagecopymerge(
$this->source,
$regionImage,
$regionX,
$regionY,
0,
0,
$regionWidth,
$regionHeight,
$opacity * 100
);
imagedestroy($regionImage);
} else {
// 全图处理
imagecopymerge(
$this->source,
$this->bwImage,
0,
0,
0,
0,
$this->info[0],
$this->info[1],
$opacity * 100
);
}
return $this;
}
/**
* name: 浮雕效果
* @param $depth深度
* @param $direction方向
* @param $background背景色
* @return $this
**/
public function embossEffect($depth = 3, $direction = 'top-left', $background = 'gray') {
// 设置背景色
switch ($background) {
case 'white':
$bgColor = imagecolorallocate($this->bwImage, 255, 255, 255);
break;
case 'black':
$bgColor = imagecolorallocate($this->bwImage, 0, 0, 0);
break;
default: // gray
$bgColor = imagecolorallocate($this->bwImage, 128, 128, 128);
}
imagefill($this->bwImage, 0, 0, $bgColor);
// 根据方向设置偏移量
$offsetX = 0;
$offsetY = 0;
switch ($direction) {
case 'top-left':
$offsetX = -1; $offsetY = -1;
break;
case 'top':
$offsetX = 0; $offsetY = -1;
break;
case 'top-right':
$offsetX = 1; $offsetY = -1;
break;
case 'left':
$offsetX = -1; $offsetY = 0;
break;
case 'right':
$offsetX = 1; $offsetY = 0;
break;
case 'bottom-left':
$offsetX = -1; $offsetY = 1;
break;
case 'bottom':
$offsetX = 0; $offsetY = 1;
break;
case 'bottom-right':
$offsetX = 1; $offsetY = 1;
break;
}
// 应用浮雕效果
for ($x = 1; $x < $this->info[0] - 1; $x++) {
for ($y = 1; $y < $this->info[1] - 1; $y++) {
// 获取当前像素和偏移像素的颜色
$color1 = imagecolorat($this->source, $x, $y);
$color2 = imagecolorat($this->source, $x + $offsetX, $y + $offsetY);
$r1 = ($color1 >> 16) & 0xFF;
$g1 = ($color1 >> 8) & 0xFF;
$b1 = $color1 & 0xFF;
$r2 = ($color2 >> 16) & 0xFF;
$g2 = ($color2 >> 8) & 0xFF;
$b2 = $color2 & 0xFF;
// 计算浮雕值
$r = min(255, max(0, ($r1 - $r2) * $depth + 128));
$g = min(255, max(0, ($g1 - $g2) * $depth + 128));
$b = min(255, max(0, ($b1 - $b2) * $depth + 128));
// 设置新颜色
$newColor = imagecolorallocate($this->bwImage, $r, $g, $b);
imagesetpixel($this->bwImage, $x, $y, $newColor);
}
}
return $this;
}
/**
* name:输出图片
* @param $target=file保存文件/screen输出到屏幕
* @return string|void
**/
public function output($target = 'screen') {
switch ($target) {
case 'file':
$newImageName= randStr(10) . '.png';
$outputImage = APP_PATH . '/public/cache/' . $newImageName;
// 保存为PNG
imagepng($this->bwImage, $this->outputImage);
// 释放内存
imagedestroy($this->source);
imagedestroy($this->bwImage);
return $this->config->application->hostUrl . '/cache/' . $newImageName;
case 'screen':
header('Content-Type: image/png');
imagepng($this->bwImage);
// 释放内存
imagedestroy($this->source);
imagedestroy($this->bwImage);
break;
}
}
}使用方式:
$imgSource = "http://yh.rzh178.top/uploads/20250710/Images-t1752138435702.jpg";
$img = new ImageMagic($imgSource);
// $img->gray()->output();
$img->flipImage('horizontal')->output();
评论