Класс Thumb
Объект $Thumb:
Объект для работы с изображениями
Исходный код
class Thumb extends \Cms\Site\Base { … }
Свойства
$quality
$Thumb->quality = 100;
JPEG quality.
Исходный код
var $quality = 100;
$Request
$Thumb->Request
Исходный код
var $Request;
Методы
route()
$Thumb->route($Request);
Обработка запроса
Параметры:
Имя | Описание |
---|---|
$Request |
Возвращает: true
– запрос обработан;
null
– запрос не обработан
Исходный код
function route($Request) {
if (strpos($Request->getSelf(), '/thumb.') !== false) {
$this->Request = $Request;
$Request->setStatus(200);
if (!$this->display()) $this->fallbackOutput();
return true;
}
}
display()
$Thumb->display($uri=null, $cache=true);
Исходный код
function display($uri = null, $cache = true) {
$App = $this->App();
$root = $this->root();
$App->largeMemoryLimit();
if ($uri === null) $uri = rawurldecode(array_shift(explode('?', $_SERVER['REQUEST_URI'], 2)));
if ($this->imageCheck($uri)) return $this->fileOutput($uri);
if (($x = strrpos($uri, '/')) !== false) {
$dir = substr($uri, 0, $x);
$image = substr($uri, $x + 1);
} else {
$dir = '';
$image = $uri;
}
$parts = explode('.', $image);
if (!in_array($ext = array_pop($parts), array( 'svg', 'jpg', 'webp' ))) return false;
if (array_shift($parts) != 'thumb') return false;
$count = count($parts);
if ($count == 0) return false;
if ($count == 1) return $this->fileOutput($dir . '/' . $parts[0]);
$transform = explode('_', array_pop($parts));
$last = $parts[$count - 2];
if (($x = strrpos($last, '_')) !== false) $parts[$count - 2] = substr($last, 0, $x) . '.' . substr($last, $x + 1);
$file = $dir . '/' . implode('.', $parts);
if (!is_file($root . $file)) return false;
$src = $this->imageRead($root . $file);
if (!$src) {
if ($parts[count($parts) - 1] === 'svg') return $this->fileOutput($file, 'image/svg+xml');
return false;
}
foreach ($transform as $tr) {
if (!strlen($tr)) {
continue;
} elseif (preg_match('~^r(-?\\d+)x(-?\\d+)(x([a-zA-Z0-9]{6}))?$~', $tr, $m)) {
list($w, $h) = $this->imageGeometry($src, $m[1], $m[2]);
$c = $this->imageColor($m[4]);
$this->imageResize($src, $w, $h, $c);
} elseif (preg_match('~^rc(-?\\d+)x(-?\\d+)(x([a-zA-Z0-9]{6}))?$~', $tr, $m)) {
list($w, $h) = $this->imageGeometry($src, $m[1], $m[2]);
$c = $this->imageColor($m[4]);
$this->imageResizeCrop($src, $w, $h, $c);
} elseif(preg_match('~^rf(-?\\d+)x(-?\\d+)(x([a-zA-Z0-9]{6}))?$~', $tr, $m)) {
list($w, $h) = $this->imageGeometry($src, $m[1], $m[2]);
$c = $this->imageColor($m[4]);
$this->imageResizeField($src, $w, $h, $c);
} elseif(preg_match('~^rh(-?\\d+)x(-?\\d+)(x([a-zA-Z0-9]{6}))?$~', $tr, $m)) {
list($w, $h) = $this->imageGeometry($src, $m[1], $m[2]);
$c = $this->imageColor($m[4]);
$this->imageResizeHorizontal($src, $w, $h, $c);
} elseif(preg_match('~^rv(-?\\d+)x(-?\\d+)(x([a-zA-Z0-9]{6}))?$~', $tr, $m)) {
list($w, $h) = $this->imageGeometry($src, $m[1], $m[2]);
$c = $this->imageColor($m[4]);
$this->imageResizeVertical($src, $w, $h, $c);
} elseif (preg_match('~^c(-?\\d+)x(-?\\d+)(x(-?\\d+)x(-?\\d+))?$~', $tr, $m)) {
list($w, $h) = $this->imageGeometry($src, $m[1], $m[2]);
$x = intval($m[4]);
$y = intval($m[5]);
$c = $this->imageColor(null);
$this->imageCrop($src, $w, $h, $x, $y, $c);
} elseif (preg_match('~^q(\\d+)$~', $tr, $m)) {
$this->quality = intval($m[1]);
}
}
if ($cache && $this->imageWrite($src, $root . $uri)) {
$contentType = 'image/jpeg';
if ($ext === 'svg') $contentType = 'image/svg+xml';
if ($ext === 'webp') $contentType = 'image/webp';
$this->fileOutput($uri, $contentType);
} else {
$this->imageOutput($src);
}
return true;
}
imageColor()
$Thumb->imageColor($c);
Исходный код
function imageColor($c) {
if (!strlen($c)) return array(0xff, 0xff, 0xff);
return array(
hexdec(substr($c, 0, 2)),
hexdec(substr($c, 2, 2)),
hexdec(substr($c, 4, 2)),
);
}
imageRead()
$Thumb->imageRead($path, $info=null);
Исходный код
function imageRead($path, $info = null) {
if ($info === null) $info = @getimagesize($path);
if (!$info) return;
$type = $info[2];
if ($type === IMAGETYPE_JPEG) {
return @imagecreatefromjpeg($path);
}
if ($type === IMAGETYPE_PNG) {
return @imagecreatefrompng($path);
}
if ($type === IMAGETYPE_GIF) {
return @imagecreatefromgif($path);
}
if (defined('IMAGETYPE_AVIF') && $type === constant('IMAGETYPE_AVIF') && function_exists('imagecreatefromavif')) {
return @imagecreatefromavif($path);
}
if (defined('IMAGETYPE_WEBP') && $type === constant('IMAGETYPE_WEBP') && function_exists('imagecreatefromwebp')) {
return @imagecreatefromwebp($path);
}
if (defined('IMAGETYPE_BMP') && $type === constant('IMAGETYPE_BMP') && function_exists('imagecreatefrombmp')) {
return @imagecreatefrombmp($path);
}
if (defined('IMAGETYPE_XBM') && $type === constant('IMAGETYPE_XBM') && function_exists('imagecreatefromxbm')) {
return @imagecreatefromxbm($path);
}
if (defined('IMAGETYPE_WBMP') && $type === constant('IMAGETYPE_WBMP') && function_exists('imagecreatefromwbmp')) {
return @imagecreatefromwbmp($path);
}
return $this->imageReadMagick($path);
}
imageWrite()
$Thumb->imageWrite(&$src, $path);
Исходный код
function imageWrite(&$src, $path) {
if (substr($path, -5) === '.webp')
if (@imagewebp($src, $path, $this->quality)) {
@chmod($path, 0666);
imagedestroy($src);
return true;
}
if (@imagejpeg($src, $path, $this->quality)) {
@chmod($path, 0666);
imagedestroy($src);
return true;
}
}
imageOutput()
$Thumb->imageOutput(&$src);
Исходный код
function imageOutput(&$src) {
$this->Request->addHeader('Content-Type: image/jpeg');
@imagejpeg($src, null, $this->quality);
imagedestroy($src);
return true;
}
imageReadMagick()
$Thumb->imageReadMagick($path);
Исходный код
function imageReadMagick($path) {
if (class_exists('Imagick')) {
try {
$src = new \Imagick;
@$src->readImage($path);
@$src->setImageFormat('png');
$dst = @imagecreatefromstring($src->getImageBlob());
@$src->clear();
return $dst;
} catch (\Exception $e) { }
}
}
imageGeometry()
$Thumb->imageGeometry(&$src, $w, $h);
Исходный код
function imageGeometry(&$src, $w, $h) {
$w = intval($w);
$h = intval($h);
if (!$w && !$h) {
$w = imagesx($src);
$h = imagesy($src);
} elseif (!$w) {
$w = intval(round($h * imagesx($src) / imagesy($src)));
} elseif (!$h) {
$h = intval(round($w * imagesy($src) / imagesx($src)));
}
return array($w, $h);
}
imageResize()
$Thumb->imageResize(&$src, $w, $h, $c);
Исходный код
function imageResize(&$src, $w, $h, $c) {
if ($dst = imagecreatetruecolor($w, $h)) {
imagefill($dst, 0, 0, imagecolorallocate($dst, $c[0], $c[1], $c[2]));
if ($w == imagesx($src) && $h == imagesy($src)) {
imagecopy($dst, $src, 0, 0, 0, 0, $w, $h);
} else {
imagecopyresampled($dst, $src, 0, 0, 0, 0, $w, $h, imagesx($src), imagesy($src));
$this->imageSharpen($dst);
}
imagedestroy($src);
$src = $dst;
return true;
}
}
imageResizeCrop()
$Thumb->imageResizeCrop(&$src, $w, $h, $c);
Исходный код
function imageResizeCrop(&$src, $w, $h, $c) {
if ($dst = imagecreatetruecolor($w, $h)) {
$width = imagesx($src);
$height = imagesy($src);
imagefill($dst, 0, 0, imagecolorallocate($dst, $c[0], $c[1], $c[2]));
if ($w / $h < $width / $height) {
imagecopyresampled($dst, $src, ($w - $h * $width / $height) / 2, 0, 0, 0, $h * $width / $height, $h, $width, $height);
} elseif ($w / $h > $width / $height) {
imagecopyresampled($dst, $src, 0, ($h - $w * $height / $width) / 2, 0, 0, $w, $w * $height / $width, $width, $height);
} else {
imagecopyresampled($dst, $src, 0, 0, 0, 0, $w, $h, $width, $height);
}
imagedestroy($src);
$src = $dst;
$this->imageSharpen($src);
return true;
}
}
imageResizeField()
$Thumb->imageResizeField(&$src, $w, $h, $c);
Исходный код
function imageResizeField(&$src, $w, $h, $c) {
if ($dst = imagecreatetruecolor($w, $h)) {
$width = imagesx($src);
$height = imagesy($src);
imagefill($dst, 0, 0, imagecolorallocate($dst, $c[0], $c[1], $c[2]));
if ($w / $h > $width / $height) {
imagecopyresampled($dst, $src, ($w - $h * $width / $height) / 2, 0, 0, 0, $h * $width / $height, $h, $width, $height);
} elseif ($w / $h < $width / $height) {
imagecopyresampled($dst, $src, 0, ($h - $w * $height / $width) / 2, 0, 0, $w, $w * $height / $width, $width, $height);
} else {
imagecopyresampled($dst, $src, 0, 0, 0, 0, $w, $h, $width, $height);
}
imagedestroy($src);
$src = $dst;
$this->imageSharpen($src);
return true;
}
}
imageCrop()
$Thumb->imageCrop(&$src, $w, $h, $x, $y, $c);
Исходный код
function imageCrop(&$src, $w, $h, $x, $y, $c) {
if ($dst = imagecreatetruecolor($w, $h)) {
imagefill($dst, 0, 0, imagecolorallocate($dst, $c[0], $c[1], $c[2]));
imagecopy($dst, $src, 0, 0, $x, $y, $w, $h);
imagedestroy($src);
$src = $dst;
return true;
}
}
imageResizeHorizontal()
$Thumb->imageResizeHorizontal(&$src, $w, $h, $c);
Исходный код
function imageResizeHorizontal(&$src, $w, $h, $c) {
if ($dst = imagecreatetruecolor($w, $h)) {
$width = imagesx($src);
$height = imagesy($src);
imagefill($dst, 0, 0, imagecolorallocate($dst, $c[0], $c[1], $c[2]));
if ($w / $h > $width / $height) {
imagecopyresampled($dst, $src, round(($w - $h * $width / $height) / 2), 0, 0, 0, round($h * $width / $height), $h, $width, $height);
} elseif ($w / $h < $width / $height) {
imagecopyresampled($dst, $src, round(($w - $h * $width / $height) / 2), 0, 0, 0, round($h * $width / $height), $h, $width, $height);
} else {
imagecopyresampled($dst, $src, 0, 0, 0, 0, $w, $h, $width, $height);
}
imagedestroy($src);
$src = $dst;
$this->imageSharpen($src);
return true;
}
}
imageResizeVertical()
$Thumb->imageResizeVertical(&$src, $w, $h, $c);
Исходный код
function imageResizeVertical(&$src, $w, $h, $c) {
if ($dst = imagecreatetruecolor($w, $h)) {
$width = imagesx($src);
$height = imagesy($src);
imagefill($dst, 0, 0, imagecolorallocate($dst, $c[0], $c[1], $c[2]));
if ($w / $h > $width / $height) {
imagecopyresampled($dst, $src, 0, round(($h - $w * $height / $width) / 2), 0, 0, $w, round($w * $height / $width), $width, $height);
} elseif ($w / $h < $width / $height) {
imagecopyresampled($dst, $src, 0, round(($h - $w * $height / $width) / 2), 0, 0, $w, round($w * $height / $width), $width, $height);
} else {
imagecopyresampled($dst, $src, 0, 0, 0, 0, $w, $h, $width, $height);
}
imagedestroy($src);
$src = $dst;
$this->imageSharpen($src);
return true;
}
}
imageSharpen()
$Thumb->imageSharpen(&$src);
Исходный код
function imageSharpen(&$src) {
if (!function_exists('imageconvolution')) return;
$matrix = array(
array(-1.2, -1, -1.2),
array(-1, 20, -1),
array(-1.2, -1, -1.2)
);
$divisor = array_sum(array_map('array_sum', $matrix));
$offset = 0;
imageconvolution($src, $matrix, $divisor, $offset);
}
imageCheck()
$Thumb->imageCheck($uri);
Исходный код
function imageCheck($uri) {
$root = $this->root();
if (strpos($uri, '/../') !== false) return false;
if (strpos($uri, '.php') !== false) return false;
if (!is_file($root . $uri)) return false;
return true;
}
fileOutput()
$Thumb->fileOutput($file=null, $mime=null);
Исходный код
function fileOutput($file = null, $mime = null) {
if (!$file) return $this->fallbackOutput();
$root = $this->root();
$real = $root . $file;
if (!is_file($real)) return false;
if (!is_readable($real)) return false;
if (!$mime) {
$info = @getimagesize($real);
if (!$info) return false;
$mime = $info['mime'];
}
$this->Request->addHeader('Content-Type: ' . $mime);
$this->Request->addHeader('Content-Length: ' . filesize($real));
readfile($real);
return true;
}
fallbackOutput()
$Thumb->fallbackOutput();
Исходный код
function fallbackOutput() {
$data = base64_decode('R0lGODlhAQABAJEAAAAAAP///////wAAACH5BAEAAAIALAAAAAABAAEAAAICVAEAOw==');
$this->Request->addHeader('Content-Type: image/gif');
$this->Request->addHeader('Content-Length: ' . strlen($data));
print $data;
return true;
}
truncate()
$Thumb->truncate($path, $maxWidth=0, $maxHeight=0, $quality=0);
Исходный код
function truncate($path, $maxWidth = 0, $maxHeight = 0, $quality = 0) {
$App = $this->App();
$Conf = $this->Conf();
if ($maxWidth <= 0 || $maxHeight <= 0) {
$imageSize = intval($Conf->get('image-size'));
if ($imageSize <= 0) return;
if ($maxWidth <= 0) $maxWidth = $imageSize;
if ($maxHeight <= 0) $maxHeight = $imageSize;
}
if ($quality <= 0) {
$quality = intval($Conf->get('image-quality'));
if ($quality <= 0) $quality = 100;
}
if (@filesize($path) > 1024 * 1024 * 100) {
return;
}
if (!$info = @getimagesize($path)) {
return;
}
if ($info[0] > 9999 || $info[1] > 9999) {
return;
}
if ($info[0] <= $maxWidth && $info[1] <= $maxHeight) {
return;
}
$App->largeMemoryLimit();
if (!$src = $this->imageRead($path, $info)) {
return;
}
if ($info[0] > $info[1]) {
$w = $maxWidth;
$h = round($maxWidth * $info[1] / $info[0]);
} else {
$h = $maxHeight;
$w = round($maxHeight * $info[0] / $info[1]);
}
if ($info[2] == IMAGETYPE_JPEG) {
if (function_exists('exif_read_data')) {
$rotate = 0;
$exif = @exif_read_data($path);
if ($exif && $exif['Orientation']) switch ($exif['Orientation']) {
case 3: $rotate = 180; break;
case 6: $rotate = 270; break;
case 8: $rotate = 90; break;
}
if ($rotate) {
if ($dst = @imagerotate($src, $rotate, imagecolorat($src, 0, 0))) {
$src = $dst;
if ($rotate == 90 || $rotate == 270) {
$_ = $w;
$w = $h;
$h = $_;
}
}
}
}
}
$dst = @imagecreatetruecolor($w, $h);
@imagefill($dst, 0, 0, imagecolorallocate($dst, 0xff, 0xff, 0xff));
@imagecopyresampled($dst, $src, 0, 0, 0, 0, $w, $h, imagesx($src), imagesy($src));
@imagejpeg($dst, $path, $quality);
@imagedestroy($src);
@imagedestroy($dst);
}
removeFileThumb()
$Thumb->removeFileThumb($filename);
Исходный код
function removeFileThumb($filename) {
$root = $this->root();
if (substr($filename, 0, strlen($root)) !== $root) {
$filename = $root . $filename;
}
$dirname = dirname($filename);
$basename = basename($filename);
$thumbPrefix = 'thumb.' . $basename . '.';
$thumbPrefixLength = strlen($thumbPrefix);
if ($D = @opendir($dirname)) {
while (strval($filename = @readdir($D)) !== '') {
if (substr($filename, 0, $thumbPrefixLength) === $thumbPrefix) {
@unlink($dirname . '/' . $filename);
}
}
@closedir($D);
}
}
thumbQualityJpeg()
$Thumb->thumbQualityJpeg();
Исходный код
function thumbQualityJpeg() {
static $quality;
if (!isset($quality)) {
if (!$quality = intval($this->Conf()->get('thumb-quality-jpeg'))) $quality = $this->quality;
}
return $quality;
}
thumbQualityWebp()
$Thumb->thumbQualityWebp();
Исходный код
function thumbQualityWebp() {
static $quality;
if (!isset($quality)) {
if (!$quality = intval($this->Conf()->get('thumb-quality-webp'))) $quality = $this->quality;
}
return $quality;
}