Merge pull request #3612 from splitbrain/resizecache

correctly (re)cache modified images
This commit is contained in:
Andreas Gohr 2022-02-04 22:44:07 +01:00 committed by GitHub
commit ab74e8ec48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 107 additions and 60 deletions

View File

@ -0,0 +1,56 @@
<?php
namespace dokuwiki\Cache;
/**
* Handle the caching of modified (resized/cropped) images
*/
class CacheImageMod extends Cache
{
/** @var string source file */
protected $file;
/**
* @param string $file Original source file
* @param int $w new width in pixel
* @param int $h new height in pixel
* @param string $ext Image extension - no leading dot
* @param bool $crop Is this a crop?
*/
public function __construct($file, $w, $h, $ext, $crop)
{
$fullext = '.media.' . $w . 'x' . $h;
$fullext .= $crop ? '.crop' : '';
$fullext .= ".$ext";
$this->file = $file;
$this->setEvent('IMAGEMOD_CACHE_USE');
parent::__construct($file, $fullext);
}
/** @inheritdoc */
public function makeDefaultCacheDecision()
{
if (!file_exists($this->file)) {
return false;
}
return parent::makeDefaultCacheDecision();
}
/**
* Caching depends on the source and the wiki config
* @inheritdoc
*/
protected function addDependencies()
{
parent::addDependencies();
$this->depends['files'] = array_merge(
[$this->file],
getConfigFiles('main')
);
}
}

View File

@ -7,11 +7,11 @@
*/
use dokuwiki\ChangeLog\MediaChangeLog;
use dokuwiki\Extension\Event;
use dokuwiki\Form\Form;
use dokuwiki\HTTP\DokuHTTPClient;
use dokuwiki\Logger;
use dokuwiki\Subscriptions\MediaSubscriptionSender;
use dokuwiki\Extension\Event;
use dokuwiki\Form\Form;
use dokuwiki\Ui\Media\DisplayRow;
use dokuwiki\Ui\Media\DisplayTile;
use dokuwiki\Ui\MediaDiff;
@ -1689,6 +1689,49 @@ function media_nstree_li($item){
'<img src="'.$img.'" alt="'.$alt.'" />';
}
/**
* Resizes or crop the given image to the given size
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string $file filename, path to file
* @param string $ext extension
* @param int $w desired width
* @param int $h desired height
* @param bool $crop should a center crop be used?
* @return string path to resized or original size if failed
*/
function media_mod_image($file, $ext, $w, $h=0, $crop=false)
{
global $conf;
if(!$h) $h = $w;
// we wont scale up to infinity
if($w > 2000 || $h > 2000) return $file;
$operation = $crop ? 'crop' : 'resize';
$options = [
'quality' => $conf['jpg_quality'],
'imconvert' => $conf['im_convert'],
];
$cache = new \dokuwiki\Cache\CacheImageMod($file, $w, $h, $ext, $crop);
if(!$cache->useCache()) {
try {
Slika::run($file, $options)
->autorotate()
->$operation($w, $h)
->save($cache->cache, $ext);
if($conf['fperm']) @chmod($cache->cache, $conf['fperm']);
} catch (\splitbrain\slika\Exception $e) {
Logger::debug($e->getMessage());
return $file;
}
}
return $cache->cache;
}
/**
* Resizes the given image to the given size
*
@ -1700,35 +1743,9 @@ function media_nstree_li($item){
* @param int $h desired height
* @return string path to resized or original size if failed
*/
function media_resize_image($file, $ext, $w, $h=0){
global $conf;
if(!$h) $h = $w;
// we wont scale up to infinity
if($w > 2000 || $h > 2000) return $file;
//cache
$local = getCacheName($file,'.media.'.$w.'x'.$h.'.'.$ext);
$mtime = (int) @filemtime($local); // 0 if not exists
$options = [
'quality' => $conf['jpg_quality'],
'imconvert' => $conf['im_convert'],
];
if( $mtime <= (int) @filemtime($file) ) {
try {
Slika::run($file, $options)
->autorotate()
->resize($w, $h)
->save($local, $ext);
if($conf['fperm']) @chmod($local, $conf['fperm']);
} catch (\splitbrain\slika\Exception $e) {
Logger::debug($e->getMessage());
return $file;
}
}
return $local;
function media_resize_image($file, $ext, $w, $h = 0)
{
return media_mod_image($file, $ext, $w, $h, false);
}
/**
@ -1742,35 +1759,9 @@ function media_resize_image($file, $ext, $w, $h=0){
* @param int $h desired height
* @return string path to resized or original size if failed
*/
function media_crop_image($file, $ext, $w, $h=0){
global $conf;
if(!$h) $h = $w;
// we wont scale up to infinity
if($w > 2000 || $h > 2000) return $file;
//cache
$local = getCacheName($file,'.media.'.$w.'x'.$h.'.crop.'.$ext);
$mtime = (int) @filemtime($local); // 0 if not exists
$options = [
'quality' => $conf['jpg_quality'],
'imconvert' => $conf['im_convert'],
];
if( $mtime <= (int) @filemtime($file) ) {
try {
Slika::run($file, $options)
->autorotate()
->crop($w, $h)
->save($local, $ext);
if($conf['fperm']) @chmod($local, $conf['fperm']);
} catch (\splitbrain\slika\Exception $e) {
Logger::debug($e->getMessage());
return $file;
}
}
return $local;
function media_crop_image($file, $ext, $w, $h = 0)
{
return media_mod_image($file, $ext, $w, $h, true);
}
/**