xref: /plugin/mediathumbnails/thumb_engines.php (revision 33e1a0054f2dab2cf0a761eedbc1a23c7b1ef21b)
147d2d32aSternite<?php
247d2d32aSternite/**
347d2d32aSternite * DokuWiki Plugin mediathumbnails (thumb_engine class and subclasses)
447d2d32aSternite *
547d2d32aSternite * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
647d2d32aSternite * @author  Thomas Schäfer <thomas.schaefer@itschert.net>
747d2d32aSternite */
847d2d32aSternite
947d2d32aSterniteabstract class thumb_engine {
1047d2d32aSternite
1147d2d32aSternite	private ?thumbnail $thumbnail = null;
1247d2d32aSternite
1347d2d32aSternite	public function __construct(thumbnail $thumbnail) {
1447d2d32aSternite		$this->thumbnail = $thumbnail;
1547d2d32aSternite	}
1647d2d32aSternite
1747d2d32aSternite	protected function getSourceFilepath() {
1847d2d32aSternite		return $this->thumbnail->getSourceFilepath();
1947d2d32aSternite	}
2047d2d32aSternite
2147d2d32aSternite	protected function getTargetFilepath() {
2247d2d32aSternite		return $this->thumbnail->getFilepath();
2347d2d32aSternite	}
2447d2d32aSternite
2547d2d32aSternite	protected function getTargetMaxDimension() {
2647d2d32aSternite		return $this->thumbnail->getMaxDimension();
2747d2d32aSternite	}
2847d2d32aSternite
2947d2d32aSternite	public function act() {
3047d2d32aSternite		if ($this->act_internal()) {
3147d2d32aSternite			// Set timestamp to the source file's timestamp (this is used to check in later passes if the file already exists in the correct version).
3247d2d32aSternite			if (filemtime($this->getSourceFilepath()) !== filemtime($this->getTargetFilepath())) {
3347d2d32aSternite				touch($this->getTargetFilepath(), filemtime($this->getSourceFilepath()));
3447d2d32aSternite			}
3547d2d32aSternite			return true;
3647d2d32aSternite		}
3747d2d32aSternite		return false;
3847d2d32aSternite	}
3947d2d32aSternite
4047d2d32aSternite	// Checks if a thumbnail file for the current file version has already been created
4147d2d32aSternite	protected function thumb_needs_update() {
4247d2d32aSternite		return !file_exists($this->getTargetFilepath()) || filemtime($this->getTargetFilepath()) !== filemtime($this->getSourceFilepath());
4347d2d32aSternite	}
4447d2d32aSternite
4547d2d32aSternite	public abstract function act_internal();
4647d2d32aSternite
4747d2d32aSternite	public abstract function getFileSuffix();
4847d2d32aSternite}
4947d2d32aSternite
5047d2d32aSterniteclass thumb_pdf_engine extends thumb_engine {
5147d2d32aSternite
5247d2d32aSternite	public function getFileSuffix() {
5347d2d32aSternite		return "jpg";
5447d2d32aSternite	}
5547d2d32aSternite
5647d2d32aSternite	public function act_internal() {
5747d2d32aSternite		if ($this->thumb_needs_update()) {
5847d2d32aSternite			$im = new imagick($this->getSourceFilepath()."[0]");
59*33e1a005Sternite            // the following line was in the original code. Issue #6 (https://github.com/ternite/dokuwiki-plugin-mediathumbnails/issues/6)
60*33e1a005Sternite            // indicated there might be problems with colors, so I uncommented the line (TS, 2025-10-11)
61*33e1a005Sternite			//$im->setImageColorspace(255);
6247d2d32aSternite			$im->setResolution(300, 300);
6347d2d32aSternite			$im->setCompressionQuality(95);
6447d2d32aSternite			$im->setImageFormat('jpeg');
6547d2d32aSternite			//$im->resizeImage($this->getTargetMaxDimension(),0,imagick::FILTER_LANCZOS,0.9);
6647d2d32aSternite			//$im->thumbnailImage($this->getTargetMaxDimension(),$this->getTargetMaxDimension(),true,false);
6747d2d32aSternite			$im->writeImage($this->getTargetFilepath());
6847d2d32aSternite			$im->clear();
6947d2d32aSternite			$im->destroy();
7047d2d32aSternite
7147d2d32aSternite			// unfortunately, resizeImage or thumbnailImage leads to a black thumbnail in my setup, so I reopen the file and resize it now.
7247d2d32aSternite			$im = new imagick($this->getTargetFilepath());
7347d2d32aSternite			$im->thumbnailImage($this->getTargetMaxDimension(),$this->getTargetMaxDimension(),true,false);
7447d2d32aSternite			$im->writeImage($this->getTargetFilepath());
7547d2d32aSternite			$im->clear();
7647d2d32aSternite			$im->destroy();
7747d2d32aSternite
7847d2d32aSternite			return true;
7947d2d32aSternite		} else {
8047d2d32aSternite			return true;
8147d2d32aSternite		}
8247d2d32aSternite	}
8347d2d32aSternite}
8447d2d32aSternite
8547d2d32aSterniteclass thumb_img_engine extends thumb_engine {
8647d2d32aSternite
8747d2d32aSternite	public function getFileSuffix() {
8847d2d32aSternite		return getFileSuffix($this->getSourceFilepath());
8947d2d32aSternite	}
9047d2d32aSternite
9147d2d32aSternite	public function act_internal() {
9247d2d32aSternite		if ($this->thumb_needs_update()) {
9347d2d32aSternite			$im = new imagick( $this->getSourceFilepath() );
9447d2d32aSternite			$im->thumbnailImage($this->getTargetMaxDimension(),$this->getTargetMaxDimension(),true,false);
9547d2d32aSternite			$im->writeImage($this->getTargetFilepath());
9647d2d32aSternite			$im->clear();
9747d2d32aSternite			$im->destroy();
9847d2d32aSternite
9947d2d32aSternite			return true;
10047d2d32aSternite		} else {
10147d2d32aSternite			return true;
10247d2d32aSternite		}
10347d2d32aSternite	}
10447d2d32aSternite}
10547d2d32aSternite
10647d2d32aSterniteclass thumb_zip_engine extends thumb_engine {
10747d2d32aSternite
10847d2d32aSternite	private array $thumb_paths;
10947d2d32aSternite	private $file_suffix = "";
11047d2d32aSternite
11147d2d32aSternite	public function __construct(thumbnail $thumbnail, array $thumb_paths) {
11247d2d32aSternite		parent::__construct($thumbnail);
11347d2d32aSternite		$this->thumb_paths = $thumb_paths;
11447d2d32aSternite	}
11547d2d32aSternite
11647d2d32aSternite	public function getFileSuffix() {
11747d2d32aSternite		return $this->file_suffix;
11847d2d32aSternite	}
11947d2d32aSternite
12047d2d32aSternite	public function act_internal() {
12147d2d32aSternite
12247d2d32aSternite		$zip = new ZipArchive;
12347d2d32aSternite		if ($zip->open($this->getSourceFilepath()) !== true) {
12447d2d32aSternite			// file is no zip or cannot be opened
12547d2d32aSternite			return false;
12647d2d32aSternite		}
12747d2d32aSternite
12847d2d32aSternite		// The media file exists and acts as a zip file!
12947d2d32aSternite
13047d2d32aSternite		// Check all possible paths (configured in configuration key 'thumb_paths') if there is a file available
13147d2d32aSternite		foreach($this->thumb_paths as $thumbnail_path) {
13247d2d32aSternite			$this->file_suffix = substr(strrchr($thumbnail_path,'.'),1);
13347d2d32aSternite
13447d2d32aSternite			if ($zip->locateName($thumbnail_path) !== false) {
13547d2d32aSternite
13647d2d32aSternite				if (!$this->thumb_needs_update()) {
13747d2d32aSternite					return true;
13847d2d32aSternite				}
13947d2d32aSternite
14047d2d32aSternite				// Get the thumbnail file!
14147d2d32aSternite				$fp = $zip->getStream($thumbnail_path);
14247d2d32aSternite				if(!$fp) {
14347d2d32aSternite					return false;
14447d2d32aSternite				}
14547d2d32aSternite
14647d2d32aSternite				$thumbnaildata = '';
14747d2d32aSternite				while (!feof($fp)) {
14847d2d32aSternite					$thumbnaildata .= fread($fp, 8192);
14947d2d32aSternite				}
15047d2d32aSternite
15147d2d32aSternite				fclose($fp);
15247d2d32aSternite
15347d2d32aSternite				// Write thumbnail file to media folder
15447d2d32aSternite				file_put_contents($this->getTargetFilepath(), $thumbnaildata);
15547d2d32aSternite
15647d2d32aSternite				return true;
15747d2d32aSternite			}
15847d2d32aSternite		}
15947d2d32aSternite
16047d2d32aSternite		return true;
16147d2d32aSternite	}
16247d2d32aSternite}