mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-11 18:42:54 +00:00
perf: 优化图片压缩
This commit is contained in:
parent
fd33eb3d1c
commit
29bbbd804a
@ -799,7 +799,7 @@ class SystemController extends AbstractController
|
||||
'thumb' => Base::fillUrl('images/other/dir.png'),
|
||||
'inode' => filemtime($v),
|
||||
];
|
||||
} elseif (!str_ends_with($filename, "_thumb.jpg")) {
|
||||
} elseif (!Base::isThumb($filename)) {
|
||||
$array = [
|
||||
'type' => 'file',
|
||||
'title' => $filename,
|
||||
@ -811,10 +811,11 @@ class SystemController extends AbstractController
|
||||
//
|
||||
$extension = pathinfo($dirPath . $filename, PATHINFO_EXTENSION);
|
||||
if (in_array($extension, array('gif', 'jpg', 'jpeg', 'webp', 'png', 'bmp'))) {
|
||||
if (file_exists($dirPath . $filename . '_thumb.jpg')) {
|
||||
$array['thumb'] .= '_thumb.jpg';
|
||||
if ($extension = Base::getThumbExt($dirPath . $filename)) {
|
||||
$array['thumb'] .= "_thumb.{$extension}";
|
||||
} else {
|
||||
$array['thumb'] = Base::fillUrl($array['thumb']);
|
||||
}
|
||||
$array['thumb'] = Base::fillUrl($array['thumb']);
|
||||
$files[] = $array;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ namespace App\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use App\Module\Base;
|
||||
use App\Module\Image;
|
||||
use App\Tasks\PushTask;
|
||||
use App\Exceptions\ApiException;
|
||||
use App\Tasks\WebSocketDialogMsgTask;
|
||||
@ -587,8 +588,8 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
$imagePath .= md5s($base64) . "." . $matchs[1][$key];
|
||||
if (Base::saveContentImage(public_path($imagePath), base64_decode($base64))) {
|
||||
$imageSize = getimagesize(public_path($imagePath));
|
||||
if (Base::imgThumb(public_path($imagePath), public_path($imagePath) . "_thumb.jpg", 320, 0)) {
|
||||
$imagePath .= "_thumb.jpg";
|
||||
if ($extension = Image::thumbImage(public_path($imagePath), public_path($imagePath) . "_thumb.{*}", 320, 0)) {
|
||||
$imagePath .= "_thumb.{$extension}";
|
||||
}
|
||||
$text = str_replace($matchs[0][$key], "[:IMAGE:browse:{$imageSize[0]}:{$imageSize[1]}:{$imagePath}::]", $text);
|
||||
}
|
||||
@ -653,7 +654,7 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
}
|
||||
if (str_starts_with($str, "{{RemoteURL}}")) {
|
||||
$imagePath = Base::leftDelete($str, "{{RemoteURL}}");
|
||||
$imagePath = Base::rightDelete($imagePath, "_thumb.jpg");
|
||||
$imagePath = Base::thumbRestore($imagePath);
|
||||
} else {
|
||||
$imagePath = "uploads/chat/" . date("Ym") . "/" . $dialog_id . "/";
|
||||
Base::makeDir(public_path($imagePath));
|
||||
@ -661,8 +662,8 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
}
|
||||
if (file_exists(public_path($imagePath))) {
|
||||
$imageSize = getimagesize(public_path($imagePath));
|
||||
if (Base::imgThumb(public_path($imagePath), public_path($imagePath) . "_thumb.jpg", 320, 0)) {
|
||||
$imagePath .= "_thumb.jpg";
|
||||
if ($extension = Image::thumbImage(public_path($imagePath), public_path($imagePath) . "_thumb.{*}", 320, 0)) {
|
||||
$imagePath .= "_thumb.{$extension}";
|
||||
}
|
||||
$text = str_replace($matchs[0][$key], "[:IMAGE:browse:{$imageSize[0]}:{$imageSize[1]}:{$imagePath}::]", $text);
|
||||
} else {
|
||||
@ -671,8 +672,8 @@ class WebSocketDialogMsg extends AbstractModel
|
||||
$text = str_replace($matchs[0][$key], "[:IMAGE:browse:90:90:images/other/imgerr.jpg::]", $text);
|
||||
} else if (Base::saveContentImage(public_path($imagePath), $image)) {
|
||||
$imageSize = getimagesize(public_path($imagePath));
|
||||
if (Base::imgThumb(public_path($imagePath), public_path($imagePath) . "_thumb.jpg", 320, 0)) {
|
||||
$imagePath .= "_thumb.jpg";
|
||||
if ($extension = Image::thumbImage(public_path($imagePath), public_path($imagePath) . "_thumb.{*}", 320, 0)) {
|
||||
$imagePath .= "_thumb.{$extension}";
|
||||
}
|
||||
$text = str_replace($matchs[0][$key], "[:IMAGE:browse:{$imageSize[0]}:{$imageSize[1]}:{$imagePath}::]", $text);
|
||||
}
|
||||
|
||||
@ -2128,11 +2128,11 @@ class Base
|
||||
if ($param['scale'] && is_array($param['scale'])) {
|
||||
list($width, $height) = $param['scale'];
|
||||
if (($width > 0 && $array['width'] > $width) || ($height > 0 && $array['height'] > $height)) {
|
||||
$cut = ($width > 0 && $height > 0) ? 1 : -1;
|
||||
$cut = ($width > 0 && $height > 0) ? 'cover' : 'percentage';
|
||||
$cut = $param['scale'][2] ?? $cut;
|
||||
//图片压缩
|
||||
$tmpFile = $array['file'] . '_tmp.jpg';
|
||||
if (Base::imgThumb($array['file'], $tmpFile, $width, $height, $cut)) {
|
||||
if (Image::thumbImage($array['file'], $tmpFile, $width, $height, $cut)) {
|
||||
$tmpSize = filesize($tmpFile);
|
||||
if ($tmpSize > $fileSize) {
|
||||
@unlink($tmpFile);
|
||||
@ -2158,7 +2158,7 @@ class Base
|
||||
}
|
||||
// 压缩图片
|
||||
if ($param['compress'] !== false) {
|
||||
ImgCompress::compress($array['file']);
|
||||
Image::compressImage($array['file']);
|
||||
$array['size'] = Base::twoFloat(filesize($array['file']) / 1024, true);
|
||||
}
|
||||
//生成缩略图
|
||||
@ -2167,8 +2167,8 @@ class Base
|
||||
$param['autoThumb'] = false;
|
||||
}
|
||||
if ($param['autoThumb'] !== false) {
|
||||
if (Base::imgThumb($array['file'], $array['file'] . "_thumb.jpg", 320, 0)) {
|
||||
$array['thumb'] .= "_thumb.jpg";
|
||||
if ($extension = Image::thumbImage($array['file'], $array['file'] . "_thumb.{*}", 320, 0)) {
|
||||
$array['thumb'] .= "_thumb.{$extension}";
|
||||
}
|
||||
}
|
||||
$array['thumb'] = Base::fillUrl($array['thumb']);
|
||||
@ -2312,11 +2312,11 @@ class Base
|
||||
if ($param['scale'] && is_array($param['scale'])) {
|
||||
list($width, $height) = $param['scale'];
|
||||
if (($width > 0 && $array['width'] > $width) || ($height > 0 && $array['height'] > $height)) {
|
||||
$cut = ($width > 0 && $height > 0) ? 1 : -1;
|
||||
$cut = ($width > 0 && $height > 0) ? 'cover' : 'percentage';
|
||||
$cut = $param['scale'][2] ?? $cut;
|
||||
//图片压缩
|
||||
$tmpFile = $array['file'] . '_tmp.jpg';
|
||||
if (Base::imgThumb($array['file'], $tmpFile, $width, $height, $cut)) {
|
||||
if (Image::thumbImage($array['file'], $tmpFile, $width, $height, $cut)) {
|
||||
$tmpSize = filesize($tmpFile);
|
||||
if ($tmpSize > $fileSize) {
|
||||
@unlink($tmpFile);
|
||||
@ -2346,15 +2346,15 @@ class Base
|
||||
$param['autoThumb'] = false;
|
||||
}
|
||||
if ($param['autoThumb'] !== false) {
|
||||
if (Base::imgThumb($array['file'], $array['file'] . "_thumb.jpg", 320, 0)) {
|
||||
$array['thumb'] .= "_thumb.jpg";
|
||||
if ($extension = Image::thumbImage($array['file'], $array['file'] . "_thumb.{*}", 320, 0)) {
|
||||
$array['thumb'] .= "_thumb.{$extension}";
|
||||
}
|
||||
}
|
||||
$array['thumb'] = Base::fillUrl($array['thumb']);
|
||||
}
|
||||
// 压缩图片
|
||||
if ($param['compress'] !== false) {
|
||||
ImgCompress::compress($array['file']);
|
||||
Image::compressImage($array['file']);
|
||||
$array['size'] = Base::twoFloat(filesize($array['file']) / 1024, true);
|
||||
}
|
||||
//
|
||||
@ -2396,141 +2396,46 @@ class Base
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成缩略图
|
||||
* @param string $src_img 源图绝对完整地址{带文件名及后缀名}
|
||||
* @param string $dst_img 目标图绝对完整地址{带文件名及后缀名}
|
||||
* @param int $width 缩略图宽{0:此时目标高度不能为0,目标宽度为源图宽*(目标高度/源图高)}
|
||||
* @param int $height 缩略图高{0:此时目标宽度不能为0,目标高度为源图高*(目标宽度/源图宽)}
|
||||
* @param int $cut 是否裁切{宽,高必须非0}:1是、0否、-1或'auto'保持等比
|
||||
* @param int $proportion 缩放{0:不缩放, 0<this<1:缩放到相应比例(此时宽高限制和裁切均失效)}
|
||||
* 是否缩略图
|
||||
* @param $file
|
||||
* @return bool
|
||||
*/
|
||||
public static function imgThumb($src_img, $dst_img, $width = 75, $height = 75, $cut = 0, $proportion = 0)
|
||||
public static function isThumb($file): bool
|
||||
{
|
||||
if (!is_file($src_img)) {
|
||||
return false;
|
||||
}
|
||||
if (empty($dst_img)) {
|
||||
$dst_img = $src_img;
|
||||
}
|
||||
$st = pathinfo($src_img, PATHINFO_EXTENSION);
|
||||
if (!in_array(strtolower($st), array('jpg', 'jpeg', 'webp', 'png', 'gif', 'bmp'))) {
|
||||
return false;
|
||||
}
|
||||
$ot = pathinfo($dst_img, PATHINFO_EXTENSION);
|
||||
$otfunc = 'image' . ($ot == 'jpg' ? 'jpeg' : $ot);
|
||||
$srcinfo = getimagesize($src_img);
|
||||
$src_w = $srcinfo[0];
|
||||
$src_h = $srcinfo[1];
|
||||
$type = strtolower(substr(image_type_to_extension($srcinfo[2]), 1));
|
||||
if (empty($type)) {
|
||||
return false;
|
||||
}
|
||||
$createfun = 'imagecreatefrom' . ($type == 'jpg' ? 'jpeg' : $type);
|
||||
return str_ends_with($file, '_thumb.jpg')
|
||||
|| str_ends_with($file, '_thumb.png');
|
||||
}
|
||||
|
||||
$dst_h = $height;
|
||||
$dst_w = $width;
|
||||
$x = $y = 0;
|
||||
|
||||
/**
|
||||
* 缩略图不超过源图尺寸(前提是宽或高只有一个)
|
||||
*/
|
||||
if (($width > $src_w && $height > $src_h) || ($height > $src_h && $width == 0) || ($width > $src_w && $height == 0)) {
|
||||
$proportion = 1;
|
||||
}
|
||||
if ($width > $src_w) {
|
||||
$dst_w = $width = $src_w;
|
||||
}
|
||||
if ($height > $src_h) {
|
||||
$dst_h = $height = $src_h;
|
||||
}
|
||||
|
||||
if (!$width && !$height && !$proportion) {
|
||||
return false;
|
||||
}
|
||||
if (!$proportion) {
|
||||
if ($cut == 'auto' || $cut == -1) {
|
||||
if ($dst_w && $dst_h) {
|
||||
$wB = $dst_w / $src_w;
|
||||
$hB = $dst_h / $src_h;
|
||||
if ($wB > $hB) {
|
||||
$dst_w = 0;
|
||||
} else {
|
||||
$dst_h = 0;
|
||||
}
|
||||
}
|
||||
$cut = 0;
|
||||
}
|
||||
if ($cut == 0) {
|
||||
|
||||
if ($dst_w && $dst_h) {
|
||||
if ($dst_w / $src_w > $dst_h / $src_h) {
|
||||
$dst_w = $src_w * ($dst_h / $src_h);
|
||||
$x = 0 - ($dst_w - $width) / 2;
|
||||
} else {
|
||||
$dst_h = $src_h * ($dst_w / $src_w);
|
||||
$y = 0 - ($dst_h - $height) / 2;
|
||||
}
|
||||
} else if ($dst_w xor $dst_h) {
|
||||
if ($dst_w && !$dst_h) //有宽无高
|
||||
{
|
||||
$propor = $dst_w / $src_w;
|
||||
$height = $dst_h = $src_h * $propor;
|
||||
} else if (!$dst_w && $dst_h) //有高无宽
|
||||
{
|
||||
$propor = $dst_h / $src_h;
|
||||
$width = $dst_w = $src_w * $propor;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!$dst_h) //裁剪时无高
|
||||
{
|
||||
$height = $dst_h = $dst_w;
|
||||
}
|
||||
if (!$dst_w) //裁剪时无宽
|
||||
{
|
||||
$width = $dst_w = $dst_h;
|
||||
}
|
||||
$propor = min(max($dst_w / $src_w, $dst_h / $src_h), 1);
|
||||
$dst_w = (int)round($src_w * $propor);
|
||||
$dst_h = (int)round($src_h * $propor);
|
||||
$x = ($width - $dst_w) / 2;
|
||||
$y = ($height - $dst_h) / 2;
|
||||
}
|
||||
/**
|
||||
* 获取缩略图后缀
|
||||
* @param $file
|
||||
* @return string
|
||||
*/
|
||||
public static function getThumbExt($file): string
|
||||
{
|
||||
if (file_exists($file . '_thumb.jpg')) {
|
||||
return 'jpg';
|
||||
} elseif (file_exists($file . '_thumb.png')) {
|
||||
return 'png';
|
||||
} else {
|
||||
$proportion = min($proportion, 1);
|
||||
$height = $dst_h = $src_h * $proportion;
|
||||
$width = $dst_w = $src_w * $proportion;
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists($createfun)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$src = $createfun($src_img);
|
||||
$dst = imagecreatetruecolor($width ?: $dst_w, $height ?: $dst_h);
|
||||
if (function_exists('imagecopyresampled')) {
|
||||
imagecopyresampled($dst, $src, $x, $y, 0, 0, $dst_w, $dst_h, $src_w, $src_h);
|
||||
/**
|
||||
* 缩略图还原
|
||||
* @param $file
|
||||
* @return mixed|string
|
||||
*/
|
||||
public static function thumbRestore($file): mixed
|
||||
{
|
||||
if (str_ends_with($file, '_thumb.jpg')) {
|
||||
return Base::rightDelete($file, '_thumb.jpg');
|
||||
} elseif (str_ends_with($file, '_thumb.png')) {
|
||||
return Base::rightDelete($file, '_thumb.png');
|
||||
} else {
|
||||
imagecopyresized($dst, $src, $x, $y, 0, 0, $dst_w, $dst_h, $src_w, $src_h);
|
||||
return $file;
|
||||
}
|
||||
try {
|
||||
if ($type == 'png') {
|
||||
imagesavealpha($dst, true);
|
||||
$transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127);
|
||||
imagefill($dst, 0, 0, $transparent);
|
||||
} else {
|
||||
$white = imagecolorallocate($dst, 255, 255, 255);
|
||||
imagefill($dst, 0, 0, $white);
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
|
||||
}
|
||||
|
||||
$otfunc($dst, $dst_img);
|
||||
imagedestroy($dst);
|
||||
imagedestroy($src);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2986,7 +2891,7 @@ class Base
|
||||
public static function saveContentImage($path, $content, $compress = true) {
|
||||
if (file_put_contents($path, $content)) {
|
||||
if ($compress) {
|
||||
ImgCompress::compress($path);
|
||||
Image::compressImage($path);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
235
app/Module/Image.php
Normal file
235
app/Module/Image.php
Normal file
@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
namespace App\Module;
|
||||
|
||||
use Imagick;
|
||||
|
||||
/**
|
||||
* 图片类:缩略图、调整大小、压缩
|
||||
*/
|
||||
class Image
|
||||
{
|
||||
private Imagick $image;
|
||||
|
||||
private string $path;
|
||||
|
||||
private int $height;
|
||||
|
||||
private int $width;
|
||||
|
||||
/**
|
||||
* @param $imagePath
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public function __construct($imagePath) {
|
||||
$this->path = $imagePath;
|
||||
$this->image = new Imagick($this->path);
|
||||
$geo = $this->image->getImageGeometry();
|
||||
$this->height = $geo['height'];
|
||||
$this->width = $geo['width'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片宽度
|
||||
* @return int
|
||||
*/
|
||||
public function getWidth(): int
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片高度
|
||||
* @return int
|
||||
*/
|
||||
public function getHeight(): int
|
||||
{
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建缩略图
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param string $mode = 'percentage|cover|contain' ($width 和 $height 都设置的情况下有效)
|
||||
* @return Image
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public function thumb(int $width, int $height, string $mode = 'percentage'): static
|
||||
{
|
||||
if ($height === 0 && $width === 0) {
|
||||
return $this;
|
||||
}
|
||||
if ($width && $height) {
|
||||
if ($mode === 'cover') {
|
||||
// 铺满背景(超出被裁掉)
|
||||
$this->image->cropThumbnailImage($width, $height);
|
||||
} else {
|
||||
// 等比缩放
|
||||
if ($this->width >= $this->height) {
|
||||
$this->image->thumbnailImage($width, 0);
|
||||
} else {
|
||||
$this->image->thumbnailImage(0, $height);
|
||||
}
|
||||
if ($mode === 'contain') {
|
||||
// 显示完整的图
|
||||
$background = new Imagick();
|
||||
$background->newImage($width, $height, 'none', strtolower(pathinfo($this->path, PATHINFO_EXTENSION)));
|
||||
$bg_width = $background->getImageWidth();
|
||||
$bg_height = $background->getImageHeight();
|
||||
$img_width = $this->image->getImageWidth();
|
||||
$img_height = $this->image->getImageHeight();
|
||||
if ($img_width / $bg_width > $img_height / $bg_height) {
|
||||
$width = $bg_width;
|
||||
$height = intval($img_height / ($img_width / $width));
|
||||
} else {
|
||||
$height = $bg_height;
|
||||
$width = intval($img_width / ($img_height / $height));
|
||||
}
|
||||
$this->image->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1);
|
||||
$x = intval(($bg_width - $width) / 2);
|
||||
$y = intval(($bg_height - $height) / 2);
|
||||
$background->compositeImage($this->image, Imagick::COMPOSITE_DEFAULT, $x, $y);
|
||||
$this->image->destroy();
|
||||
$this->image = $background;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->image->thumbnailImage($width, $height);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整图像大小
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @return Image
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public function resize(int $width, int $height): static
|
||||
{
|
||||
if ($height === 0 && $width === 0) {
|
||||
return $this;
|
||||
}
|
||||
$this->image->adaptiveResizeImage($width, $height);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩图片
|
||||
* @param int $quality
|
||||
* @return $this
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public function compress(int $quality = 100): static
|
||||
{
|
||||
$format = strtolower($this->image->getImageFormat());
|
||||
switch ($format) {
|
||||
case 'jpeg':
|
||||
case 'jpg':
|
||||
$this->image->setImageCompression(Imagick::COMPRESSION_JPEG);
|
||||
break;
|
||||
case 'png':
|
||||
$this->image->setImageCompression(Imagick::COMPRESSION_ZIP);
|
||||
break;
|
||||
case 'gif':
|
||||
$this->image->setImageCompression(Imagick::COMPRESSION_LZW);
|
||||
break;
|
||||
default:
|
||||
return $this;
|
||||
}
|
||||
if ($quality > 1) {
|
||||
$this->image->setImageCompressionQuality($quality);
|
||||
} elseif ($quality > 0) {
|
||||
$this->image->setImageCompressionQuality($quality * 100);
|
||||
} else {
|
||||
$this->image->setImageCompressionQuality(100);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存结果到文件
|
||||
* @param string $savePath Save path
|
||||
* @return void
|
||||
* @throws \ImagickException
|
||||
*/
|
||||
public function saveTo(string $savePath): void
|
||||
{
|
||||
$this->image->writeImage($savePath);
|
||||
$this->image->destroy();
|
||||
}
|
||||
|
||||
/** ******************************************************************************/
|
||||
/** ******************************************************************************/
|
||||
/** ******************************************************************************/
|
||||
|
||||
/**
|
||||
* 生成缩略图
|
||||
* @param string $imagePath 图片路径
|
||||
* @param string $savePath 保存路径
|
||||
* @param int $width 宽度
|
||||
* @param int $height 高度
|
||||
* @param string $mode 模式(percentage|cover|contain)
|
||||
* @return string|null 成功返回图片后缀,失败返回 false
|
||||
*/
|
||||
public static function thumbImage(string $imagePath, string $savePath, int $width, int $height, string $mode = 'percentage'): ?string
|
||||
{
|
||||
if (!file_exists($imagePath)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
$extension = strtolower(pathinfo($imagePath, PATHINFO_EXTENSION));
|
||||
if (str_contains($savePath, '.{*}')) {
|
||||
$savePath = str_replace('.{*}', '.' . $extension, $savePath);
|
||||
}
|
||||
$image = new Image($imagePath);
|
||||
$image->thumb($width, $height, $mode);
|
||||
$image->saveTo($savePath);
|
||||
return $extension;
|
||||
} catch (\ImagickException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩图片
|
||||
* @param string $imagePath 图片路径
|
||||
* @param string|null $savePath 保存路径(默认覆盖原图)
|
||||
* @param int $quality 压缩质量(0-100)
|
||||
* @param float $minSize 最小尺寸(单位:KB)
|
||||
* @return bool
|
||||
*/
|
||||
public static function compressImage(string $imagePath, string $savePath = null, int $quality = 100, float $minSize = 10): bool
|
||||
{
|
||||
if (Base::settingFind("system", "image_compress") === 'close') {
|
||||
return false;
|
||||
}
|
||||
if (!file_exists($imagePath)) {
|
||||
return false;
|
||||
}
|
||||
$imageSize = filesize($imagePath);
|
||||
if ($minSize > 0 && $imageSize < $minSize * 1024) {
|
||||
return false;
|
||||
}
|
||||
if (empty($savePath)) {
|
||||
$savePath = $imagePath;
|
||||
}
|
||||
$tmpPath = $imagePath . '.compress.tmp';
|
||||
try {
|
||||
$image = new Image($imagePath);
|
||||
$image->compress($quality);
|
||||
$image->saveTo($tmpPath);
|
||||
if (filesize($tmpPath) >= $imageSize) {
|
||||
copy($imagePath, $savePath);
|
||||
unlink($tmpPath);
|
||||
} else {
|
||||
rename($tmpPath, $savePath);
|
||||
}
|
||||
return true;
|
||||
} catch (\ImagickException) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,170 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Module;
|
||||
|
||||
@error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
|
||||
|
||||
/**
|
||||
* 图片压缩类:通过缩放来压缩。
|
||||
* 如果要保持源图比例,把参数$percent保持为1即可。
|
||||
* 即使原比例压缩,也可大幅度缩小。数码相机4M图片。也可以缩为700KB左右。如果缩小比例,则体积会更小。
|
||||
*
|
||||
* 结果:可保存、可直接显示。
|
||||
*/
|
||||
class ImgCompress
|
||||
{
|
||||
private $src;
|
||||
private $image;
|
||||
private $imageinfo;
|
||||
private $percent;
|
||||
|
||||
/**
|
||||
* 图片压缩
|
||||
* @param string $src 源图
|
||||
* @param float $percent 压缩比例
|
||||
*/
|
||||
public function __construct($src, $percent = 1)
|
||||
{
|
||||
$this->src = $src;
|
||||
$this->percent = $percent;
|
||||
}
|
||||
|
||||
/** 高清压缩图片
|
||||
* @param string $saveName 提供图片名(可不带扩展名,用源图扩展名)用于保存。或不提供文件名直接显示
|
||||
*/
|
||||
public function compressImg($saveName = '')
|
||||
{
|
||||
if (!$this->_openImage()) { //打开图片
|
||||
return;
|
||||
}
|
||||
if (!empty($saveName)) $this->_saveImage($saveName); //保存
|
||||
else $this->_showImage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部:打开图片
|
||||
*/
|
||||
private function _openImage()
|
||||
{
|
||||
list($width, $height, $type, $attr) = getimagesize($this->src);
|
||||
$this->imageinfo = array(
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'type' => image_type_to_extension($type, false),
|
||||
'attr' => $attr
|
||||
);
|
||||
$fun = "imagecreatefrom" . $this->imageinfo['type'];
|
||||
if (!function_exists($fun)) {
|
||||
return false;
|
||||
}
|
||||
$this->image = $fun($this->src);
|
||||
$this->_thumpImage();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部:操作图片
|
||||
*/
|
||||
private function _thumpImage()
|
||||
{
|
||||
$new_width = $this->imageinfo['width'] * $this->percent;
|
||||
$new_height = $this->imageinfo['height'] * $this->percent;
|
||||
$image_thump = imagecreatetruecolor($new_width, $new_height);
|
||||
//将原图复制带图片载体上面,并且按照一定比例压缩,极大的保持了清晰度
|
||||
imagecopyresampled($image_thump, $this->image, 0, 0, 0, 0, $new_width, $new_height, $this->imageinfo['width'], $this->imageinfo['height']);
|
||||
imagedestroy($this->image);
|
||||
$this->image = $image_thump;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出图片:保存图片则用saveImage()
|
||||
*/
|
||||
private function _showImage()
|
||||
{
|
||||
header('Content-Type: image/' . $this->imageinfo['type']);
|
||||
$funcs = "image" . $this->imageinfo['type'];
|
||||
$funcs($this->image);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存图片到硬盘:
|
||||
* @param string $dstImgName 1、可指定字符串不带后缀的名称,使用源图扩展名 。2、直接指定目标图片名带扩展名。
|
||||
*/
|
||||
private function _saveImage($dstImgName)
|
||||
{
|
||||
if (empty($dstImgName)) return false;
|
||||
if (str_contains($dstImgName, '.')) {
|
||||
$dstName = $dstImgName;
|
||||
} else {
|
||||
$allowImgs = ['.jpg', '.jpeg', '.webp', '.png', '.bmp', '.wbmp', '.gif']; //如果目标图片名有后缀就用目标图片扩展名 后缀,如果没有,则用源图的扩展名
|
||||
$dstExt = strrchr($dstImgName, ".");
|
||||
$sourseExt = strrchr($this->src, ".");
|
||||
if (!empty($dstExt)) $dstExt = strtolower($dstExt);
|
||||
if (!empty($sourseExt)) $sourseExt = strtolower($sourseExt);
|
||||
//有指定目标名扩展名
|
||||
if (!empty($dstExt) && in_array($dstExt, $allowImgs)) {
|
||||
$dstName = $dstImgName;
|
||||
} elseif (!empty($sourseExt) && in_array($sourseExt, $allowImgs)) {
|
||||
$dstName = $dstImgName . $sourseExt;
|
||||
} else {
|
||||
$dstName = $dstImgName . $this->imageinfo['type'];
|
||||
}
|
||||
}
|
||||
$funcs = "image" . $this->imageinfo['type'];
|
||||
if (!function_exists($funcs)) {
|
||||
return false;
|
||||
}
|
||||
$funcs($this->image, $dstName);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁图片
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->image) {
|
||||
imagedestroy($this->image);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 压缩图片静态方法
|
||||
* @param string $src 原图地址
|
||||
* @param float $percent 压缩比例
|
||||
* @param float $minSize 最小压缩大小,小于这个不压缩,单位KB
|
||||
* @return void
|
||||
*/
|
||||
public static function compress(string $src, float $percent = 1, float $minSize = 10): void
|
||||
{
|
||||
if (Base::settingFind("system", "image_compress") === 'close') {
|
||||
return;
|
||||
}
|
||||
if (!file_exists($src)) {
|
||||
return;
|
||||
}
|
||||
$allowImgs = ['.jpg', '.jpeg', '.webp', '.png', '.bmp', '.wbmp'];
|
||||
if (!in_array(strrchr($src, "."), $allowImgs)) {
|
||||
return;
|
||||
}
|
||||
$size = filesize($src);
|
||||
if ($minSize > 0 && $size < $minSize * 1024) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$img = new ImgCompress($src, $percent);
|
||||
$tmp = $src . '.compress.tmp';
|
||||
$img->compressImg($tmp);
|
||||
if (file_exists($tmp)) {
|
||||
if (filesize($tmp) > $size) {
|
||||
unlink($tmp);
|
||||
return;
|
||||
}
|
||||
unlink($src);
|
||||
rename($tmp, $src);
|
||||
}
|
||||
} catch (\Exception) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,7 @@
|
||||
"ext-libxml": "*",
|
||||
"ext-openssl": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-imagick": "*",
|
||||
"directorytree/ldaprecord-laravel": "^2.7",
|
||||
"fideloper/proxy": "^4.4.1",
|
||||
"fruitcake/laravel-cors": "^2.0.4",
|
||||
|
||||
@ -3,7 +3,7 @@ version: '3'
|
||||
services:
|
||||
php:
|
||||
container_name: "dootask-php-${APP_ID}"
|
||||
image: "kuaifan/php:swoole-8.0.rc9"
|
||||
image: "kuaifan/php:swoole-8.0.rc10"
|
||||
shm_size: "2gb"
|
||||
ulimits:
|
||||
core:
|
||||
|
||||
@ -60,7 +60,7 @@ export default {
|
||||
const dataSource = array.map(item => {
|
||||
if ($A.isJson(item)) {
|
||||
if (item.src) {
|
||||
item.src = $A.rightDelete(item.src, "_thumb.jpg");
|
||||
item.src = $A.thumbRestore(item.src);
|
||||
}
|
||||
if (parseInt(item.width) > 0 && parseInt(item.height) > 0) {
|
||||
return item
|
||||
@ -69,7 +69,7 @@ export default {
|
||||
}
|
||||
htmlZoom = true;
|
||||
return {
|
||||
html: `<div class="preview-image-swipe"><img src="${$A.rightDelete(item, "_thumb.jpg")}"/></div>`,
|
||||
html: `<div class="preview-image-swipe"><img src="${$A.thumbRestore(item)}"/></div>`,
|
||||
}
|
||||
})
|
||||
this.lightbox = new PhotoSwipeLightbox({
|
||||
|
||||
@ -216,7 +216,7 @@ export default {
|
||||
if ($A.isJson(item)) {
|
||||
item = item.src;
|
||||
}
|
||||
return $A.rightDelete(item, "_thumb.jpg");
|
||||
return $A.thumbRestore(item);
|
||||
},
|
||||
imgStyle() {
|
||||
const {scale, deg, offsetX, offsetY, enableTransition} = this.transform;
|
||||
|
||||
@ -35,9 +35,9 @@ export default {
|
||||
const position = Math.min(Math.max(this.$store.state.previewImageIndex, 0), this.$store.state.previewImageList.length - 1)
|
||||
const paths = l.map(item => {
|
||||
if ($A.isJson(item)) {
|
||||
return $A.rightDelete(item.src, "_thumb.jpg");
|
||||
return $A.thumbRestore(item.src);
|
||||
}
|
||||
return $A.rightDelete(item, "_thumb.jpg")
|
||||
return $A.thumbRestore(item)
|
||||
})
|
||||
$A.eeuiAppSendMessage({
|
||||
action: 'picturePreview',
|
||||
|
||||
11
resources/assets/js/functions/web.js
vendored
11
resources/assets/js/functions/web.js
vendored
@ -857,6 +857,17 @@
|
||||
|| /^(10)\./.test(u)
|
||||
|| /^(172)\.(1[6-9]|2[0-9]|3[0-1])\./.test(u)
|
||||
|| /^(192)\.(168)\./.test(u);
|
||||
},
|
||||
|
||||
/**
|
||||
* 缩略图还原
|
||||
* @param url
|
||||
* @returns {*|string}
|
||||
*/
|
||||
thumbRestore(url) {
|
||||
url = $A.rightDelete(url, '_thumb.jpg')
|
||||
url = $A.rightDelete(url, '_thumb.png')
|
||||
return url
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -2177,7 +2177,7 @@ export default {
|
||||
type: 'image',
|
||||
icon: '',
|
||||
label: '复制图片',
|
||||
value: $A.rightDelete(event.target.currentSrc, '_thumb.jpg'),
|
||||
value: $A.thumbRestore(event.target.currentSrc),
|
||||
})
|
||||
} else if (event.target.nodeName === 'A') {
|
||||
if (event.target.classList.contains("mention") && event.target.classList.contains("file")) {
|
||||
@ -2196,7 +2196,7 @@ export default {
|
||||
type: 'imagedown',
|
||||
icon: '',
|
||||
label: '下载图片',
|
||||
value: $A.rightDelete(event.target.currentSrc, '_thumb.jpg'),
|
||||
value: $A.thumbRestore(event.target.currentSrc),
|
||||
})
|
||||
}
|
||||
if (msgData.msg.text.replace(/<[^>]+>/g,"").length > 0) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user