xref: /plugin/mediathumbnails/thumb_engines.php (revision 47d2d32a51e008f2a2fbe2231b85ab1545824cca)
1*47d2d32aSternite<?php
2*47d2d32aSternite/**
3*47d2d32aSternite * DokuWiki Plugin mediathumbnails (thumb_engine class and subclasses)
4*47d2d32aSternite *
5*47d2d32aSternite * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6*47d2d32aSternite * @author  Thomas Schäfer <thomas.schaefer@itschert.net>
7*47d2d32aSternite */
8*47d2d32aSternite
9*47d2d32aSterniteabstract class thumb_engine {
10*47d2d32aSternite
11*47d2d32aSternite	private ?thumbnail $thumbnail = null;
12*47d2d32aSternite
13*47d2d32aSternite	public function __construct(thumbnail $thumbnail) {
14*47d2d32aSternite		$this->thumbnail = $thumbnail;
15*47d2d32aSternite	}
16*47d2d32aSternite
17*47d2d32aSternite	protected function getSourceFilepath() {
18*47d2d32aSternite		return $this->thumbnail->getSourceFilepath();
19*47d2d32aSternite	}
20*47d2d32aSternite
21*47d2d32aSternite	protected function getTargetFilepath() {
22*47d2d32aSternite		return $this->thumbnail->getFilepath();
23*47d2d32aSternite	}
24*47d2d32aSternite
25*47d2d32aSternite	protected function getTargetMaxDimension() {
26*47d2d32aSternite		return $this->thumbnail->getMaxDimension();
27*47d2d32aSternite	}
28*47d2d32aSternite
29*47d2d32aSternite	public function act() {
30*47d2d32aSternite		if ($this->act_internal()) {
31*47d2d32aSternite			// 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).
32*47d2d32aSternite			if (filemtime($this->getSourceFilepath()) !== filemtime($this->getTargetFilepath())) {
33*47d2d32aSternite				touch($this->getTargetFilepath(), filemtime($this->getSourceFilepath()));
34*47d2d32aSternite			}
35*47d2d32aSternite			return true;
36*47d2d32aSternite		}
37*47d2d32aSternite		return false;
38*47d2d32aSternite	}
39*47d2d32aSternite
40*47d2d32aSternite	// Checks if a thumbnail file for the current file version has already been created
41*47d2d32aSternite	protected function thumb_needs_update() {
42*47d2d32aSternite		return !file_exists($this->getTargetFilepath()) || filemtime($this->getTargetFilepath()) !== filemtime($this->getSourceFilepath());
43*47d2d32aSternite	}
44*47d2d32aSternite
45*47d2d32aSternite	public abstract function act_internal();
46*47d2d32aSternite
47*47d2d32aSternite	public abstract function getFileSuffix();
48*47d2d32aSternite}
49*47d2d32aSternite
50*47d2d32aSterniteclass thumb_pdf_engine extends thumb_engine {
51*47d2d32aSternite
52*47d2d32aSternite	public function getFileSuffix() {
53*47d2d32aSternite		return "jpg";
54*47d2d32aSternite	}
55*47d2d32aSternite
56*47d2d32aSternite	public function act_internal() {
57*47d2d32aSternite		if ($this->thumb_needs_update()) {
58*47d2d32aSternite			$im = new imagick($this->getSourceFilepath()."[0]");
59*47d2d32aSternite			$im->setImageColorspace(255);
60*47d2d32aSternite			$im->setResolution(300, 300);
61*47d2d32aSternite			$im->setCompressionQuality(95);
62*47d2d32aSternite			$im->setImageFormat('jpeg');
63*47d2d32aSternite			//$im->resizeImage($this->getTargetMaxDimension(),0,imagick::FILTER_LANCZOS,0.9);
64*47d2d32aSternite			//$im->thumbnailImage($this->getTargetMaxDimension(),$this->getTargetMaxDimension(),true,false);
65*47d2d32aSternite			$im->writeImage($this->getTargetFilepath());
66*47d2d32aSternite			$im->clear();
67*47d2d32aSternite			$im->destroy();
68*47d2d32aSternite
69*47d2d32aSternite			// unfortunately, resizeImage or thumbnailImage leads to a black thumbnail in my setup, so I reopen the file and resize it now.
70*47d2d32aSternite			$im = new imagick($this->getTargetFilepath());
71*47d2d32aSternite			$im->thumbnailImage($this->getTargetMaxDimension(),$this->getTargetMaxDimension(),true,false);
72*47d2d32aSternite			$im->writeImage($this->getTargetFilepath());
73*47d2d32aSternite			$im->clear();
74*47d2d32aSternite			$im->destroy();
75*47d2d32aSternite
76*47d2d32aSternite			return true;
77*47d2d32aSternite		} else {
78*47d2d32aSternite			return true;
79*47d2d32aSternite		}
80*47d2d32aSternite	}
81*47d2d32aSternite}
82*47d2d32aSternite
83*47d2d32aSterniteclass thumb_img_engine extends thumb_engine {
84*47d2d32aSternite
85*47d2d32aSternite	public function getFileSuffix() {
86*47d2d32aSternite		return getFileSuffix($this->getSourceFilepath());
87*47d2d32aSternite	}
88*47d2d32aSternite
89*47d2d32aSternite	public function act_internal() {
90*47d2d32aSternite		if ($this->thumb_needs_update()) {
91*47d2d32aSternite			$im = new imagick( $this->getSourceFilepath() );
92*47d2d32aSternite			$im->thumbnailImage($this->getTargetMaxDimension(),$this->getTargetMaxDimension(),true,false);
93*47d2d32aSternite			$im->writeImage($this->getTargetFilepath());
94*47d2d32aSternite			$im->clear();
95*47d2d32aSternite			$im->destroy();
96*47d2d32aSternite
97*47d2d32aSternite			return true;
98*47d2d32aSternite		} else {
99*47d2d32aSternite			return true;
100*47d2d32aSternite		}
101*47d2d32aSternite	}
102*47d2d32aSternite}
103*47d2d32aSternite
104*47d2d32aSterniteclass thumb_zip_engine extends thumb_engine {
105*47d2d32aSternite
106*47d2d32aSternite	private array $thumb_paths;
107*47d2d32aSternite	private $file_suffix = "";
108*47d2d32aSternite
109*47d2d32aSternite	public function __construct(thumbnail $thumbnail, array $thumb_paths) {
110*47d2d32aSternite		parent::__construct($thumbnail);
111*47d2d32aSternite		$this->thumb_paths = $thumb_paths;
112*47d2d32aSternite	}
113*47d2d32aSternite
114*47d2d32aSternite	public function getFileSuffix() {
115*47d2d32aSternite		return $this->file_suffix;
116*47d2d32aSternite	}
117*47d2d32aSternite
118*47d2d32aSternite	public function act_internal() {
119*47d2d32aSternite
120*47d2d32aSternite		$zip = new ZipArchive;
121*47d2d32aSternite		if ($zip->open($this->getSourceFilepath()) !== true) {
122*47d2d32aSternite			// file is no zip or cannot be opened
123*47d2d32aSternite			return false;
124*47d2d32aSternite		}
125*47d2d32aSternite
126*47d2d32aSternite		// The media file exists and acts as a zip file!
127*47d2d32aSternite
128*47d2d32aSternite		// Check all possible paths (configured in configuration key 'thumb_paths') if there is a file available
129*47d2d32aSternite		foreach($this->thumb_paths as $thumbnail_path) {
130*47d2d32aSternite			$this->file_suffix = substr(strrchr($thumbnail_path,'.'),1);
131*47d2d32aSternite
132*47d2d32aSternite			if ($zip->locateName($thumbnail_path) !== false) {
133*47d2d32aSternite
134*47d2d32aSternite				if (!$this->thumb_needs_update()) {
135*47d2d32aSternite					return true;
136*47d2d32aSternite				}
137*47d2d32aSternite
138*47d2d32aSternite				// Get the thumbnail file!
139*47d2d32aSternite				$fp = $zip->getStream($thumbnail_path);
140*47d2d32aSternite				if(!$fp) {
141*47d2d32aSternite					return false;
142*47d2d32aSternite				}
143*47d2d32aSternite
144*47d2d32aSternite				$thumbnaildata = '';
145*47d2d32aSternite				while (!feof($fp)) {
146*47d2d32aSternite					$thumbnaildata .= fread($fp, 8192);
147*47d2d32aSternite				}
148*47d2d32aSternite
149*47d2d32aSternite				fclose($fp);
150*47d2d32aSternite
151*47d2d32aSternite				// Write thumbnail file to media folder
152*47d2d32aSternite				file_put_contents($this->getTargetFilepath(), $thumbnaildata);
153*47d2d32aSternite
154*47d2d32aSternite				return true;
155*47d2d32aSternite			}
156*47d2d32aSternite		}
157*47d2d32aSternite
158*47d2d32aSternite		return true;
159*47d2d32aSternite	}
160*47d2d32aSternite}