PHP图像处理虽然不比其他语言性能高,但应付日常来说业务来说是够用的。本类大部分是自己编写其他则参考来自PHP手册的代码。另外,要想正确使用记得要启用GD库。
简单的使用像这样:
$src= '/path/IMAGE_NAME.jpg';
$img = new UImage($src);
$path = $img->negate(); // 颜色翻转
$path = $img->compress(); // 图像压缩
// 第二个参数如果启用的话将会覆盖原图, 其他操作一样
$img = new UImage($src, true);
注意的是处理后的图像并不会覆盖源文件,重命名的部分可以自行调整代码
<?php
/**
* YCZ - UImage
* present by YCZ
* Author: Nomandia
* Date: 2019/7/31 10:40
*/
class UImage
{
/**
* @var int 图片宽
*/
public $width = 0;
/**
* @var int 图片高
*/
public $height = 0;
/**
* @var int 图片类型
*/
public $type;
/**
* @var string 图片扩展名
*/
public $extension;
/**
* @var string 图片MimeType
*/
public $mimeType;
/**
* @var array 图片属性
*/
public $attr;
/**
* @var string 原始图像地址
*/
public $src;
/**
* @var string 创建临时图像的方法
*/
public $createfunc;
/**
* @var string 输出图像的方法
*/
public $exportfunc;
/**
* @var bool 是否处理后覆盖原图
*/
public $cover = false;
/**
* @var string 输出路径
*/
public $exportPath;
/**
* UImage constructor.
* @param string $src
* @param bool $cover
* @return $this
*/
function __construct($src = null, $cover = false)
{
$this->setSrc($src);
$this->cover = $cover;
return $this;
}
/**
* @param string $src
* @return $this|bool
* Author: Great Nomandia
* Created At 2019/7/31 12:16
*/
function setSrc($src)
{
if (!$src || !is_file($src) || !getimagesize($src)) {
return false;
}
// getimagesize 获取图像的基础信息
list($this->width, $this->height, $this->type, $this->attr) = getimagesize($this->src = $src);
$this->extension = image_type_to_extension($this->type, false);
$this->mimeType = image_type_to_mime_type($this->type);
// 这里根据扩展名获取相应的处理方法
$this->createfunc = 'imagecreatefrom' . $this->extension;
if (!function_exists($this->createfunc)) {
Yii::error($this->exportfunc . ' not exists', 'api.uimage.createfunc');
return false;
}
$this->exportfunc = 'image' . $this->extension;
if (!function_exists($this->exportfunc)) {
Yii::error($this->exportfunc . ' not exists', 'api.uimage.exportfunc');
return false;
}
return $this;
}
/**
* 输出路径
* @param string $exportPath
* @param string $suffix
* @return string
* Author: Great Nomandia
* Created At 2019/7/31 18:07
*/
protected function getExportPath($exportPath = null, $suffix = null)
{
// 指定了输出路径直接返回
if ($exportPath) {
return $exportPath;
}
if ($this->cover) {
// 覆盖时返回源文件路径
return $this->src;
}
$pathinfo = pathinfo($this->src);
return $this->exportPath = $pathinfo['dirname'] . DIRECTORY_SEPARATOR . $pathinfo['filename'] . $suffix . '.' . $this->extension;
}
/**
* 翻转图
* @param string $exportPath
* @return bool|UImage
* Author: Great Nomandia
* Created At 2019/7/31 15:15
*/
function negate($exportPath = null)
{
return $this->process(IMG_FILTER_NEGATE, $exportPath);
}
/**
* 灰度图
* @param string $exportPath
* @return bool|UImage
* Author: Great Nomandia
* Created At 2019/7/31 15:24
*/
function grayscale($exportPath = null)
{
return $this->process(IMG_FILTER_GRAYSCALE, $exportPath);
}
/**
* 边界图
* @param string $exportPath
* @return bool|UImage
* Author: Great Nomandia
* Created At 2019/7/31 15:24
*/
function edgedetect($exportPath = null)
{
return $this->process(IMG_FILTER_EDGEDETECT, $exportPath);
}
/**
* 浮雕图
* @param string $exportPath
* @return bool|UImage
* Author: Great Nomandia
* Created At 2019/7/31 15:24
*/
function emboss($exportPath = null)
{
return $this->process(IMG_FILTER_EMBOSS, $exportPath);
}
/**
* 高斯模糊
* @param string $exportPath
* @return bool|UImage
* Author: Great Nomandia
* Created At 2019/7/31 15:43
*/
function gaussianblur($exportPath = null)
{
return $this->process(IMG_FILTER_GAUSSIAN_BLUR, $exportPath);
}
/**
* 严选
* @param string $exportPath
* @return bool|UImage
* Author: Great Nomandia
* Created At 2019/7/31 15:24
*/
function selective($exportPath = null)
{
return $this->process(IMG_FILTER_SELECTIVE_BLUR, $exportPath);
}
/**
* 轮廓图
* @param string $exportPath
* @return bool|UImage
* Author: Great Nomandia
* Created At 2019/7/31 15:23
*/
function meanremoval($exportPath = null)
{
return $this->process(IMG_FILTER_MEAN_REMOVAL, $exportPath);
}
/**
* 亮度
* @param string $exportPath
* @param int $level 0-100
* @return bool|UImage
* Author: Great Nomandia
* Created At 2019/7/31 15:23
*/
function brightness($exportPath = null, $level = 50)
{
return $this->process(IMG_FILTER_BRIGHTNESS, $exportPath, $level);
}
/**
* 对比度
* @param string $exportPath
* @param int $level 0-100 越高颜色越少
* @return bool|UImage
* Author: Great Nomandia
* Created At 2019/7/31 15:23
*/
function contrast($exportPath = null, $level = 30)
{
return $this->process(IMG_FILTER_CONTRAST, $exportPath, $level);
}
/**
* 柔化
* @param string $exportPath
* @param int $level
* @return bool|UImage
* Author: Great Nomandia
* Created At 2019/7/31 15:23
*/
function smooth($exportPath = null, $level = 3)
{
return $this->process(IMG_FILTER_SMOOTH, $exportPath, $level);
}
/**
* 彩色灰度图
* @param string $exportPath
* @param int $red
* @param int $blue
* @param int $green
* @return bool|UImage
* Author: Great Nomandia
* Created At 2019/7/31 15:21
*/
function colorize($exportPath = null, $red = 255, $blue = 0, $green = 0)
{
return $this->process(IMG_FILTER_COLORIZE, $exportPath, $red, $blue, $green);
}
/**
* @param string $mark_src
* @param int $x
* @param int $y
* @return $this
* Author: Great Nomandia
* Created At 2019/7/31 18:13
*/
function watermark($mark_src, $x, $y)
{
$image = call_user_func($this->createfunc, $this->src);
list($w, $h, $type, $attr) = getimagesize($mark_src);
$extension = image_type_to_extension($type, false);
// 加载水印图
$marker = call_user_func('imagecreatefrom' . $extension, $mark_src);
imagecopy($image, $marker, $x, $y, 0, 0, $this->width, $this->height);
// 注意这里会覆盖原图
call_user_func($this->exportfunc, $image, $this->getExportPath($this->src, 'WM'));
imagedestroy($image);
imagedestroy($marker);
return $this;
}
/**
* 图片旋转
* @param int $angle 旋转角度(正数为逆时针旋转 负数为顺时针)
* @param int $bgd_color 背景颜色
* @return $this|UImage
* Author: Great Nomandia
* Created At 2019/7/31 17:14
*/
function rotate($angle, $bgd_color = 0, $exportPath = null)
{
$image = call_user_func($this->createfunc, $this->src);
$image = imagerotate($image, $angle, $bgd_color);
call_user_func($this->exportfunc, $image, $this->getExportPath($exportPath, '.R'));
imagedestroy($image);
return $this;
}
/**
* X轴翻转 垂直翻转
* @param string $exportPath
* @return UImage
* Author: Great Nomandia
* Created At 2019/7/31 18:35
*/
function flipX($exportPath = null)
{
return $this->flip(IMG_FLIP_VERTICAL, $exportPath);
}
/**
* Y轴翻转 水平翻转
* @param string $exportPath
* @return mixed
* Author: Great Nomandia
* Created At 2019/7/31 18:34
*/
function flipY($exportPath = null)
{
return $this->flip(IMG_FLIP_HORIZONTAL, $exportPath);
}
/**
* 双向翻转
* @param string $exportPath
* @return UImage
* Author: Great Nomandia
* Created At 2019/7/31 18:34
*/
function flipBoth($exportPath = null)
{
return $this->flip(IMG_FLIP_BOTH, $exportPath);
}
/**
* @param int $mode
* @param string $exportPath
* @return $this|UImage
* Author: Great Nomandia
* Created At 2019/7/31 17:23
*/
function flip($mode = IMG_FLIP_HORIZONTAL, $exportPath = null)
{
$image = call_user_func($this->createfunc, $this->src);
imageflip($image, $mode);
call_user_func($this->exportfunc, $image, $this->getExportPath($exportPath, '.F'));
imagedestroy($image);
return $this;
}
/**
* 裁剪图像
* @param int $dst_x
* @param int $dst_y
* @param int $width
* @param int $height
* @param int $quality
* @param bool $no_blank 无留空,即当裁切区域不足以填充新图时也会留空白, true则不会但宽高会被裁剪
* @param null $exportPath
* @return string|null
* Author: Great Nomandia
* Created At 2019/7/31 16:51
*/
function cut($dst_x, $dst_y, $width, $height, $quality = 80, $no_blank = false, $exportPath = null)
{
if ($no_blank) {
$width = $this->width - $dst_x > $width ? $width : $this->width - $dst_x;
$height = $this->height - $dst_y > $height ? $height : $this->height - $dst_y;
}
return $this->copy($exportPath, 0, 0, $dst_x, $dst_y, $width, $height, $width, $height, $quality);
}
/**
* 等比缩放
* @param int $scale
* @param int $quality
* @param string $exportPath
* @return string|null
* Author: Great Nomandia
* Created At 2019/7/31 16:42
*/
function scale($scale = 1.0, $quality = 80, $exportPath = null)
{
return $this->copy($exportPath, 0, 0, 0, 0, $this->width * $scale, $this->height * $scale, null, null, $quality);
}
/**
* 重置大小
* @param int $width
* @param int $height
* @param int $quality
* @param string $exportPath
* @return string|null
* Author: Great Nomandia
* Created At 2019/7/31 16:33
*/
function resize($width, $height, $quality = 80, $exportPath = null)
{
return $this->copy($exportPath, 0, 0, 0, 0, $width, $height, null, null, $quality);
}
/**
* 复制图像
* @param string $exportPath
* @param int $dst_x
* @param int $dst_y
* @param int $src_x
* @param int $src_y
* @param int $dst_width
* @param int $dst_height
* @param int $quality
* @return string|null
* Author: Great Nomandia
* Created At 2019/7/31 16:32
*/
function copy($exportPath = null, $dst_x = 0, $dst_y = 0, $src_x = 0, $src_y = 0, $dst_width = null, $dst_height = null, $src_width = null, $src_height = null, $quality = 70)
{
$image = call_user_func($this->createfunc, $this->src);
$dst_width = $dst_width ?: $this->width;
$dst_height = $dst_height ?: $this->height;
$src_width = $src_width ?: $this->width;
$src_height = $src_height ?: $this->height;
$thump = function_exists('imagecreatetruecolor') ?
imagecreatetruecolor($dst_width, $dst_height) :
imagecreate($dst_width, $dst_height);
// 注意如果纵横比改变了那图像将被拉伸
imagecopyresampled($thump, $image, $dst_x, $dst_y, $src_x, $src_y, $dst_width, $dst_height, $src_width, $src_height);
call_user_func($this->exportfunc, $thump, $this->getExportPath($exportPath, $dst_width . 'x' . $dst_height), $quality);
imagedestroy($image);
imagedestroy($thump);
return $exportPath;
}
/**
* 处理图片
* @param int $filter
* @param string $exportPath
* @return $this|bool
* Author: Great Nomandia
* Created At 2019/7/31 14:59
*/
function process($filter, $exportPath = null)
{
if (null === $filter) {
return false;
}
$image = call_user_func($this->createfunc, $this->src);
switch ($filter) {
case IMG_FILTER_NEGATE: // 0. 颜色翻转
case IMG_FILTER_GRAYSCALE: // 1. 灰度图
case IMG_FILTER_EDGEDETECT: // 5. 边缘图
case IMG_FILTER_EMBOSS: // 6. 浮雕图
case IMG_FILTER_GAUSSIAN_BLUR: // 7. 高斯模糊
case IMG_FILTER_SELECTIVE_BLUR: // 8. 别样模糊
case IMG_FILTER_MEAN_REMOVAL : // 9. 轮廓图
imagefilter($image, $filter);
break;
case IMG_FILTER_BRIGHTNESS: // 2. 亮度调节
case IMG_FILTER_CONTRAST: // 3. 对比度
imagefilter($image, $filter, func_get_arg(2));
break;
case IMG_FILTER_SMOOTH: // 10. 柔化
imagefilter($image, $filter, func_get_arg(2));
break;
case IMG_FILTER_COLORIZE: // 4. 指定颜色的灰度图, 参数1=R 2=B 3=G, 值范围0-255
imagefilter($image, $filter, func_get_arg(2), func_get_arg(3), func_get_arg(4));
break;
default:
// 非有效图像不做处理
imagedestroy($image);
return $this;
}
call_user_func($this->exportfunc, $image, $this->getExportPath($exportPath, '.' . $filter));
imagedestroy($image);
return $this;
}
/**
* 模糊处理
* @param string $exportPath 输出路径(含文件名)
* @param int $factor
* @return $this|bool
* Author: Great Nomandia
* Created At 2019/7/31 14:37
*/
function blur($exportPath = null, $factor = 3)
{
if (!$this->createfunc) {
return false;
}
$image = call_user_func($this->createfunc, $this->src);
$factor = round($factor);
$originalWidth = imagesx($image);
$originalHeight = imagesy($image);
$smallestWidth = ceil($originalWidth * pow(0.5, $factor));
$smallestHeight = ceil($originalHeight * pow(0.5, $factor));
// for the first run, the previous image is the original input
$prevImage = $image;
$prevWidth = $originalWidth;
$prevHeight = $originalHeight;
// scale way down and gradually scale back up, blurring all the way
for ($i = 0; $i < $factor; $i++) {
// determine dimensions of next image
$nextWidth = $smallestWidth * pow(2, $i);
$nextHeight = $smallestHeight * pow(2, $i);
// resize previous image to next size
$nextImage = imagecreatetruecolor($nextWidth, $nextHeight);
imagecopyresized($nextImage, $prevImage, 0, 0, 0, 0, $nextWidth, $nextHeight, $prevWidth, $prevHeight);
// apply blur filter
imagefilter($nextImage, IMG_FILTER_GAUSSIAN_BLUR);
// now the new image becomes the previous image for the next step
$prevImage = $nextImage;
$prevWidth = $nextWidth;
$prevHeight = $nextHeight;
}
// scale back to original size and blur one more time
imagecopyresized($image, $nextImage, 0, 0, 0, 0, $originalWidth, $originalHeight, $nextWidth, $nextHeight);
imagefilter($image, IMG_FILTER_GAUSSIAN_BLUR);
// clean up
imagedestroy($prevImage);
call_user_func($this->exportfunc, $image, $this->getExportPath($exportPath, '.B' . $factor));
imagedestroy($image);
return $this;
}
/**
* 压缩图像
* @param float $ratio 保持原图比例(等比缩放)
* @param int $quality 图片质量 0-100,越大越好
* @param string $exportPath 保存路径 null 时将覆盖源文件
* @return string
* Author: Great Nomandia
* Created At 2019/7/31 10:38
*/
function compress($ratio = 1.0, $quality = 60, $exportPath = null)
{
// 从SRC中创建一个图像
if (!$this->createfunc) {
return false;
}
$image = call_user_func($this->createfunc, $this->src);
if (!$image) {
// 临时图创建失败
return false;
}
// 临时图的宽高
$new_height = $this->height * $ratio;
$new_width = $this->width * $ratio;
// 创建临时图
if (function_exists('imagecreatetruecolor')) {
// 需要GD2支持,老版用imagecreate
$thump = imagecreatetruecolor($new_width, $new_height);
} else { // 此方法试过会失真
$thump = imagecreate($new_width, $new_height);
}
// 复制源图像到临时文件
imagecopyresampled($thump, $image, 0, 0, 0, 0, $new_width, $new_height, $this->width, $this->height);
// 压缩后的图片的命名,以及回存路径
// IOS 图片旋转问题
// 1:0°,6:顺时针90°, 8:逆时针90°,3:180°
if ((IMAGETYPE_JPEG == $this->type || IMAGETYPE_TIFF_II == $this->type)
&& function_exists('exif_read_data')) {
// JPEG 或 TIFF 文件中读取 EXIF 头信息, 这里自动处理旋转的照片
$exif = exif_read_data($this->src);
if (isset($exif['Orientation'])) {
switch ($exif['Orientation']) {
case 3:
$thump = imagerotate($thump, 180, 0);
break;
case 6:
$thump = imagerotate($thump, -90, 0);
break;
case 8:
$thump = imagerotate($thump, 90, 0);
break;
}
}
}
// 生成图片, 注意quality并非所有方法都试用
// 另外 quality实测高于80时无效果,文件反而更大
call_user_func($this->exportfunc, $thump, $this->getExportPath($exportPath, '.C'), $quality);
// 销毁
imagedestroy($thump);
imagedestroy($image);
return $this;
}
}