网站首页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();


评论