38 private $vector =
false;
45 private $icon =
false;
52 private $avif =
false;
59 private $imagick =
null;
87 public function load($file) {
92 require_once
'base/Ego_MimeType.php';
94 $mime_type = $mime->autoDetect($file);
96 $this->vector = in_array($mime_type, array(
'image/svg',
'image/svg+xml',
'image/x-icon',
'image/vnd.microsoft.icon'));
97 $this->icon = in_array($mime_type, array(
'image/x-icon',
'image/vnd.microsoft.icon'));
98 $this->avif = $mime_type ==
'image/avif';
100 $this->imagick = $this->vector || $this->icon ? null :
new Imagick($file);
102 if (!$this->vector) {
103 $this->image = $this->imagick->getImageFilename();
104 $this->imagick->setImageOrientation(Imagick::ORIENTATION_TOPLEFT);
108 $this->imagick->setImageFormat(
'avif');
111 $this->image = $file;
113 }
catch (Exception $e) {
124 return $this->vector;
135 public function save($file, $type =
'', $quality = 100) {
140 if (in_array($type, [
'jpg',
'jpeg',
'webp',
'avif'])) {
141 $this->imagick->setImageCompressionQuality($quality);
143 return $this->imagick->writeImages($file,
true);
152 if ($this->imagick) {
153 $this->imagick->clear();
165 private function modify($action, $params = array()) {
177 $resize =
function(Imagick &
$image) use ($params) {
178 $image->scaleImage($params[
'width'], $params[
'height'], $params[
'width'] && $params[
'height']);
187 $crop =
function(Imagick &
$image) use ($params) {
188 $image->cropImage($params[
'width'], $params[
'height'], $params[
'x'], $params[
'y']);
189 $image->setImagePage($params[
'width'], $params[
'height'], 0, 0);
198 $rotate =
function(Imagick &
$image) use ($params) {
199 $image->rotateImage(
new ImagickPixel(
'#00000000'), $params[
'deg']);
208 $mirror =
function(Imagick &
$image) use ($params) {
209 if ($params[
'horizontal']) {
212 if ($params[
'vertical']) {
223 $grayscale =
function(Imagick &
$image) {
224 $image->setImageType(Imagick::IMGTYPE_GRAYSCALEMATTE);
227 if (isset($$action)) {
228 if ($this->imagick->getNumberImages() > 1) {
230 $image = $this->imagick->coalesceImages();
231 foreach (
$image as $frame) {
234 $this->imagick =
$image->optimizeImageLayers();
236 $$action($this->imagick);
239 throw new Exception(
'Invalid modify action.');
253 public function crop($x1, $y1, $x2, $y2) {
254 $this->modify(
'crop', array(
255 'width' => $x2 - $x1,
256 'height' => $y2 - $y1,
270 $this->modify(
'rotate', array(
283 public function mirror($vertical, $horizontal) {
284 $this->modify(
'mirror', array(
285 'vertical' => $vertical,
286 'horizontal' => $horizontal
297 $this->modify(
'grayscale');
308 public function resize($width, $height) {
309 $this->modify(
'resize', array(
334 $this->
resize(0, $height);
349 $watermark =
new Imagick($file);
352 $image_w = $this->imagick->getImageWidth();
353 $image_h = $this->imagick->getImageHeight();
354 $watermark_w = $watermark->getImageWidth();
355 $watermark_h = $watermark->getImageHeight();
357 if ($image_w < $watermark_w || $image_h < $watermark_h) {
358 $watermark->scaleImage($image_w, 0);
359 $watermark_w = $watermark->getImageWidth();
360 $watermark_h = $watermark->getImageHeight();
361 if ($image_h < $watermark_h) {
362 $watermark->scaleImage(0, $image_h);
363 $watermark_w = $watermark->getImageWidth();
364 $watermark_h = $watermark->getImageHeight();
368 $x = floor(($image_w - $watermark_w) / 2);
369 $y = floor(($image_h - $watermark_h) / 2);
371 $this->imagick->compositeImage($watermark, Imagick::COMPOSITE_OVER, $x, $y);
382 public function thumbnail($width, $height, $params = []) {
387 $type = $params[
'type'] ??
'png';
389 $this->imagick->setImageFormat($type);
390 $this->imagick->scaleImage($width, $height ? $height : $width,
true);
391 $this->imagick->setImageAlphaChannel(Imagick::VIRTUALPIXELMETHOD_WHITE);
394 $file = tempnam($GLOBALS[
'egotec_conf'][
'bin_dir'] .
'tmp',
'thumbnail');
395 if ($this->
save($file, $type, $params[
'quality'] ?? $GLOBALS[
'egotec_conf'][
'image'][
'quality'] ?? 100)) {
408 public function convert($format, $params = []) {
409 if (!$this->vector) {
410 $this->imagick->setImageFormat($format);
412 if (!empty($params[
'output'])) {
414 $file = $params[
'output'];
421 $file = tempnam($GLOBALS[
'egotec_conf'][
'bin_dir'] .
'tmp',
'converted_' . $format);
423 if ($this->
save($file, $format, $params[
'quality'] ?? $GLOBALS[
'egotec_conf'][
'image'][
'quality'] ?? 100)) {
425 } elseif (empty($params[
'output'])) {
447 $result = $this->imagick->compareImages(
new Imagick($file), Imagick::METRIC_MEANSQUAREERROR);
448 return 'data:' . $result[0]->getImageMimeType() .
';base64,' . base64_encode($result[0]->getImageBlob());
449 }
catch (Exception $e) {
460 return $this->vector ? 0 : $this->imagick->getImageWidth();
469 return $this->vector ? 0 : $this->imagick->getImageHeight();
482 $data = @getimagesize($this->image);
483 if (is_array($data)){
515 return $this->vector ?
'image/svg+xml' : $this->imagick->getImageMimeType();
527 public function getExif(
int $entry = self::EXIF_ALL) {
530 && function_exists(
'exif_read_data')
531 && ($data = @exif_read_data($this->imagick->getImageFilename())) !==
false
540 foreach ($GLOBALS[
'site']->conf[
'exif'][
'import'][
'default'] as $field) {
541 if ($field[
'copyright']) {
542 $copyrightKey = $GLOBALS[
'site']->admin[
'exif_import'][
'exif_' . md5($field[
'title']) .
'_keys'];
547 if ($copyrightKey && $data[$copyrightKey]) {
548 $value = $data[$copyrightKey];
550 $value = trim($data[
'Copyright'] ?? $data[
'COMPUTED'][
'Copyright'] ?? $data[
'Artist']);
553 if (empty($value) && isset($data[
'COMMENT'])) {
554 if (is_array($data[
'COMMENT'])) {
555 $value = implode(
', ', $data[
'COMMENT']);
557 $value = $data[
'COMMENT'];
561 return trim(str_replace(
'©',
'', $value));
581 $fields = array_merge((array) $GLOBALS[
'site']->conf[
'exif'][
'import'][
'default'], (array) $GLOBALS[
'site']->conf[
'exif'][
'import'][
'custom']);
584 $exifData = @exif_read_data($this->imagick->getImageFilename()) ?: [];
587 getimagesize($this->imagick->getImageFilename(), $info);
588 $iptcData = @iptcparse($info ? (
string) $info[
'APP13'] :
'') ?: [];
590 $getData =
function($item) use ($exifData, $iptcData) {
591 if ($item[
'copyright']) {
592 return $this->
getExif(self::EXIF_COPYRIGHT);
595 $keyString = $GLOBALS[
'site']->admin[
'exif_import'][
'exif_' . md5($item[
'title']) .
'_keys'];
598 if ($keyString && ($keys = explode(
',', $keyString))) {
599 foreach ($keys as $key) {
600 $value = $exifData[$key] ?? $iptcData[$key] ?? [];
611 foreach ($fields as $field) {
612 if ($GLOBALS[
'site']->admin[
'exif_import'][
'exif_' . md5($field[
'title']) .
'_keys']) {
613 $imageData[] = array_merge($field, [
'value' => $getData($field)]);
633 $fallback =
function() use ($file) {
636 return [$image->getImageWidth(), $image->getImageHeight()];
637 }
catch (Exception $e) {
643 $size = getimagesize($file);
644 if (empty($size) || ($size[0] === 0 && $size[1] === 0)) {
648 }
catch (Exception $e) {
convert($format, $params=[])
mirror($vertical, $horizontal)
thumbnail($width, $height, $params=[])
getExif(int $entry=self::EXIF_ALL)
static getDimensions($file)
save($file, $type='', $quality=100)
static file_put_contents($filename, $data, $flags=0, $context=null)
static file_exists($file)
static mkdir($dir, $mode=0755, $recursive=true)
static copy($src, $dest, $except='', $useLinks=false, $noArchive=false, $preserveDate=false)