forkbb/app/Core/Image.php
2020-10-04 13:46:14 +07:00

159 lines
4.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace ForkBB\Core;
use ForkBB\Core\Files;
use ForkBB\Core\File;
use ForkBB\Core\Exceptions\FileException;
use InvalidArgumentException;
class Image extends File
{
/**
* Изображение
* @var false|resource
*/
protected $image;
/**
* Качество изображения
* @var int
*/
protected $quality = 100;
/**
* Паттерн для pathinfo
* @var string
*/
protected $pattern = '%^(?!.*?\.\.)([\w.\x5C/:-]*[\x5C/])?(\*|[\w.-]+)\.(\*|[a-z\d]+|\([a-z\d]+(?:\|[a-z\d]+)*\))$%i';
public function __construct(string $path, array $options)
{
parent::__construct($path, $options);
if (
! \extension_loaded('gd')
|| ! \function_exists('\\imagecreatetruecolor')
) {
throw new FileException('GD library not connected');
}
if (\is_string($this->data)) {
$this->image = @\imagecreatefromstring($this->data);
} else {
$this->image = @\imagecreatefromstring(\file_get_contents($this->path));
}
if (false === $this->image) {
throw new FileException('Invalid image data');
}
}
/**
* Изменяет размер изображения при необходимости
*/
public function resize(int $maxW, int $maxH): Image
{
$oldW = \imagesx($this->image);
$oldH = \imagesy($this->image);
$wr = ($maxW < 1) ? 1 : $maxW / $oldW;
$hr = ($maxH < 1) ? 1 : $maxH / $oldH;
$r = \min($wr, $hr, 1);
$width = \round($oldW * $r);
$height = \round($oldH * $r);
if (false === ($image = \imagecreatetruecolor($width, $height))) {
throw new FileException('Failed to create new truecolor image');
}
if (false === ($color = \imagecolorallocatealpha($image, 255, 255, 255, 127))) {
throw new FileException('Failed to create color for image');
}
if (false === \imagefill($image, 0, 0, $color)) {
throw new FileException('Failed to fill image with color');
}
\imagecolortransparent($image, $color);
$palette = \imagecolorstotal($this->image);
if (
$palette > 0
&& ! \imagetruecolortopalette($image, true, $palette)
) {
throw new FileException('Failed to convert image to palette');
}
if (
false === \imagealphablending($image, false)
|| false === \imagesavealpha($image, true)
) {
throw new FileException('Failed to adjust image');
}
if (false === \imagecopyresampled($image, $this->image, 0, 0, 0, 0, $width, $height, $oldW, $oldH)) {
throw new FileException('Failed to resize image');
}
$this->image = $image;
return $this;
}
/**
* Возвращает информацию о пути к сохраняемой картинке с учетом подстановок
*/
protected function pathinfo(string $path): ?array
{
$info = parent::pathinfo($path);
if (null === $info) {
return null;
}
if (\is_array($info['extension'])) {
if (\in_array($this->ext, $info['extension'])) {
$info['extension'] = $this->ext;
} else {
$info['extension'] = \reset($info['extension']); // ???? выбор расширения?
}
}
return $info;
}
/**
* Создает/устанавливает права на картинку
*/
protected function fileProc(string $path): bool
{
switch (\pathinfo($path, \PATHINFO_EXTENSION)) {
case 'jpg':
$result = @\imagejpeg($this->image, $path, $this->quality);
break;
case 'png':
$quality = \floor((100 - $this->quality) / 11);
$result = @\imagepng($this->image, $path, $quality);
break;
case 'gif':
$result = @\imagegif($this->image, $path);
break;
case 'webp':
$result = @\imagewebp($this->image, $path, $this->quality);
break;
default:
$this->error = 'File type not supported';
return false;
}
if (! $result) {
$this->error = 'Error writing file';
return false;
}
@\chmod($path, 0644);
return true;
}
public function __destruct() {
if (\is_resource($this->image)) {
\imagedestroy($this->image);
}
}
}