2016-09-01 23:13:23 +02:00
|
|
|
<?php
|
|
|
|
/*****************************************************************************
|
|
|
|
* Image.php
|
|
|
|
* Contains key class Image.
|
|
|
|
*
|
|
|
|
* Kabuki CMS (C) 2013-2015, Aaron van Geffen
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
class Image extends Asset
|
|
|
|
{
|
|
|
|
const TYPE_PANORAMA = 1;
|
|
|
|
const TYPE_LANDSCAPE = 2;
|
|
|
|
const TYPE_PORTRAIT = 4;
|
|
|
|
|
|
|
|
protected function __construct(array $data)
|
|
|
|
{
|
|
|
|
foreach ($data as $attribute => $value)
|
|
|
|
$this->$attribute = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function fromId($id_asset, $return_format = 'object')
|
|
|
|
{
|
|
|
|
$asset = parent::fromId($id_asset, 'array');
|
|
|
|
if ($asset)
|
2022-12-25 13:44:54 +01:00
|
|
|
return $return_format === 'object' ? new Image($asset) : $asset;
|
2016-09-01 23:13:23 +02:00
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function fromIds(array $id_assets, $return_format = 'object')
|
|
|
|
{
|
|
|
|
if (empty($id_assets))
|
|
|
|
return [];
|
|
|
|
|
|
|
|
$assets = parent::fromIds($id_assets, 'array');
|
|
|
|
|
2022-12-25 13:44:54 +01:00
|
|
|
if ($return_format === 'array')
|
2016-09-01 23:13:23 +02:00
|
|
|
return $assets;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$objects = [];
|
|
|
|
foreach ($assets as $id => $asset)
|
|
|
|
$objects[$id] = new Image($asset);
|
|
|
|
return $objects;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function save()
|
|
|
|
{
|
|
|
|
$data = [];
|
|
|
|
foreach ($this->meta as $key => $value)
|
|
|
|
$data[] = [
|
|
|
|
'id_asset' => $this->id_asset,
|
|
|
|
'variable' => $key,
|
|
|
|
'value' => $value,
|
|
|
|
];
|
|
|
|
|
|
|
|
return Registry::get('db')->insert('replace', 'assets_meta', [
|
|
|
|
'id_asset' => 'int',
|
|
|
|
'variable' => 'string',
|
|
|
|
'value' => 'string',
|
|
|
|
], $data);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getExif()
|
|
|
|
{
|
|
|
|
return EXIF::fromFile($this->getPath());
|
|
|
|
}
|
|
|
|
|
2022-07-05 12:01:02 +02:00
|
|
|
public function getImageUrls($width = null, $height = null)
|
2016-09-01 23:13:23 +02:00
|
|
|
{
|
2022-07-05 11:41:40 +02:00
|
|
|
$image_urls = [];
|
|
|
|
if (isset($width) || isset($height))
|
|
|
|
{
|
|
|
|
$thumbnail = new Thumbnail($this);
|
|
|
|
$image_urls[1] = $this->getThumbnailUrl($width, $height, false);
|
2022-07-07 14:05:33 +02:00
|
|
|
|
|
|
|
// Can we afford to generate double-density thumbnails as well?
|
|
|
|
if ((!isset($width) || $this->image_width >= $width * 2) &&
|
|
|
|
(!isset($height) || $this->image_height >= $height * 2))
|
|
|
|
$image_urls[2] = $this->getThumbnailUrl($width * 2, $height * 2, false);
|
2022-07-07 14:54:00 +02:00
|
|
|
else
|
|
|
|
$image_urls[2] = $this->getThumbnailUrl($this->image_width, $this->image_height, true);
|
2022-07-05 11:41:40 +02:00
|
|
|
}
|
2022-06-30 15:22:08 +02:00
|
|
|
else
|
2022-07-05 11:41:40 +02:00
|
|
|
$image_urls[1] = $this->getUrl();
|
2016-09-01 23:13:23 +02:00
|
|
|
|
2022-07-05 12:01:02 +02:00
|
|
|
return $image_urls;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getInlineImage($width = null, $height = null, $className = 'inline-image')
|
|
|
|
{
|
|
|
|
$image_urls = $this->getImageUrls($width, $height);
|
|
|
|
|
2022-07-05 11:41:40 +02:00
|
|
|
return '<img class="' . $className . '" src="' . $image_urls[1] . '" alt=""' .
|
|
|
|
(isset($image_urls[2]) ? ' srcset="' . $image_urls[2] . ' 2x"' : '') . '>';
|
2016-09-01 23:13:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param width: width of the thumbnail.
|
|
|
|
* @param height: height of the thumbnail.
|
|
|
|
* @param crop: whether and how to crop original image to fit. [false|true|'top'|'center'|'bottom']
|
|
|
|
* @param fit: whether to fit the image to given boundaries [true], or use them merely as an estimation [false].
|
2017-12-20 14:51:23 +01:00
|
|
|
* @param generate: whether or not to generate a thumbnail if no existing file was found.
|
2016-09-01 23:13:23 +02:00
|
|
|
*/
|
2017-12-20 14:51:23 +01:00
|
|
|
public function getThumbnailUrl($width, $height, $crop = true, $fit = true, $generate = false)
|
2016-09-01 23:13:23 +02:00
|
|
|
{
|
2017-12-20 14:51:23 +01:00
|
|
|
$thumbnail = new Thumbnail($this);
|
|
|
|
return $thumbnail->getUrl($width, $height, $crop, $fit, $generate);
|
2016-09-01 23:13:23 +02:00
|
|
|
}
|
|
|
|
|
2017-12-20 14:51:23 +01:00
|
|
|
public function getId()
|
|
|
|
{
|
|
|
|
return $this->id_asset;
|
|
|
|
}
|
|
|
|
|
2016-09-01 23:13:23 +02:00
|
|
|
public function width()
|
|
|
|
{
|
|
|
|
return $this->image_width;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function height()
|
|
|
|
{
|
|
|
|
return $this->image_height;
|
|
|
|
}
|
|
|
|
|
2017-12-20 14:51:23 +01:00
|
|
|
public function ratio()
|
|
|
|
{
|
|
|
|
return $this->image_width / $this->image_height;
|
|
|
|
}
|
|
|
|
|
2016-09-01 23:13:23 +02:00
|
|
|
public function isPanorama()
|
|
|
|
{
|
2017-12-20 14:51:23 +01:00
|
|
|
return $this->ratio() >= 2;
|
2016-09-01 23:13:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function isPortrait()
|
|
|
|
{
|
2017-12-20 14:51:23 +01:00
|
|
|
return $this->ratio() < 1;
|
2016-09-01 23:13:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public function isLandscape()
|
|
|
|
{
|
2017-12-20 14:51:23 +01:00
|
|
|
$ratio = $this->ratio();
|
2016-09-01 23:13:23 +02:00
|
|
|
return $ratio >= 1 && $ratio <= 2;
|
|
|
|
}
|
|
|
|
|
2023-12-19 21:57:29 +01:00
|
|
|
public function getType()
|
|
|
|
{
|
|
|
|
if ($this->isPortrait())
|
|
|
|
return self::TYPE_PORTRAIT;
|
|
|
|
elseif ($this->isPanorama())
|
|
|
|
return self::TYPE_PANORAMA;
|
|
|
|
else
|
|
|
|
return self::TYPE_LANDSCAPE;
|
|
|
|
}
|
|
|
|
|
2017-12-20 14:51:23 +01:00
|
|
|
public function getThumbnails()
|
|
|
|
{
|
|
|
|
return $this->thumbnails;
|
|
|
|
}
|
|
|
|
|
2016-09-01 23:13:23 +02:00
|
|
|
public function removeAllThumbnails()
|
|
|
|
{
|
2020-11-29 17:12:27 +01:00
|
|
|
foreach ($this->thumbnails as $key => $filename)
|
2016-09-01 23:13:23 +02:00
|
|
|
{
|
2020-11-29 17:12:27 +01:00
|
|
|
$thumb_path = THUMBSDIR . '/' . $this->subdir . '/' . $filename;
|
2016-09-01 23:13:23 +02:00
|
|
|
if (is_file($thumb_path))
|
|
|
|
unlink($thumb_path);
|
|
|
|
}
|
|
|
|
|
2017-12-20 14:51:23 +01:00
|
|
|
return Registry::get('db')->query('
|
2023-11-11 15:33:31 +01:00
|
|
|
DELETE FROM assets_thumbs
|
2017-12-20 14:51:23 +01:00
|
|
|
WHERE id_asset = {int:id_asset}',
|
|
|
|
['id_asset' => $this->id_asset]);
|
2016-09-01 23:13:23 +02:00
|
|
|
}
|
|
|
|
|
2020-11-29 17:12:27 +01:00
|
|
|
public function removeThumbnailsOfSize($width, $height)
|
|
|
|
{
|
|
|
|
foreach ($this->thumbnails as $key => $filename)
|
|
|
|
{
|
|
|
|
if (strpos($key, $width . 'x' . $height) !== 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
$thumb_path = THUMBSDIR . '/' . $this->subdir . '/' . $filename;
|
|
|
|
if (is_file($thumb_path))
|
|
|
|
unlink($thumb_path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Registry::get('db')->query('
|
|
|
|
DELETE FROM assets_thumbs
|
|
|
|
WHERE id_asset = {int:id_asset} AND
|
|
|
|
width = {int:width} AND
|
|
|
|
height = {int:height}',
|
|
|
|
[
|
|
|
|
'height' => $height,
|
|
|
|
'id_asset' => $this->id_asset,
|
|
|
|
'width' => $width,
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
2016-09-01 23:13:23 +02:00
|
|
|
public function replaceThumbnail($descriptor, $tmp_file)
|
|
|
|
{
|
|
|
|
if (!is_file($tmp_file))
|
|
|
|
return -1;
|
|
|
|
|
2017-12-20 14:51:23 +01:00
|
|
|
if (!isset($this->thumbnails[$descriptor]))
|
2016-09-01 23:13:23 +02:00
|
|
|
return -2;
|
|
|
|
|
|
|
|
$image = new Imagick($tmp_file);
|
|
|
|
$d = $image->getImageGeometry();
|
|
|
|
unset($image);
|
|
|
|
|
|
|
|
// Check whether dimensions match.
|
2017-12-20 14:51:23 +01:00
|
|
|
$test_descriptor = $d['width'] . 'x' . $d['height'];
|
2016-09-01 23:13:23 +02:00
|
|
|
if ($descriptor !== $test_descriptor && strpos($descriptor, $test_descriptor . '_') === false)
|
|
|
|
return -3;
|
|
|
|
|
|
|
|
// Save the custom thumbnail in the assets directory.
|
2017-12-20 14:51:23 +01:00
|
|
|
$destination = ASSETSDIR . '/' . $this->subdir . '/' . $this->thumbnails[$descriptor];
|
2016-09-01 23:13:23 +02:00
|
|
|
if (file_exists($destination) && !is_writable($destination))
|
|
|
|
return -4;
|
|
|
|
|
|
|
|
if (!copy($tmp_file, $destination))
|
|
|
|
return -5;
|
|
|
|
|
|
|
|
// Copy it to the thumbnail directory, overwriting the automatically generated one, too.
|
2017-12-20 14:51:23 +01:00
|
|
|
$destination = THUMBSDIR . '/' . $this->subdir . '/' . $this->thumbnails[$descriptor];
|
2016-09-01 23:13:23 +02:00
|
|
|
if (file_exists($destination) && !is_writable($destination))
|
|
|
|
return -6;
|
|
|
|
|
|
|
|
if (!copy($tmp_file, $destination))
|
|
|
|
return -7;
|
|
|
|
|
|
|
|
// A little bookkeeping
|
2017-12-20 14:51:23 +01:00
|
|
|
$this->meta['custom_' . $d['width'] . 'x' . $d['height']] = $this->thumbnails[$descriptor];
|
2016-09-01 23:13:23 +02:00
|
|
|
$this->saveMetaData();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|