Passed
Push — master ( 2da96f...f3a9cc )
by Matias
13:54
created

TempImage   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 168
Duplicated Lines 0 %

Test Coverage

Coverage 70.49%

Importance

Changes 6
Bugs 0 Features 0
Metric Value
eloc 64
c 6
b 0
f 0
dl 0
loc 168
ccs 43
cts 61
cp 0.7049
rs 10
wmc 18

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getTempPath() 0 2 1
A getRatio() 0 2 1
A getSkipped() 0 2 1
A __construct() 0 16 1
A getResizeRatio() 0 3 1
A resizeOCImage() 0 20 4
A clean() 0 2 1
B prepareImage() 0 46 8
1
<?php
2
declare(strict_types=1);
3
/**
4
 * @copyright Copyright (c) 2018-2019 Branko Kokanovic <[email protected]>
5
 * @copyright Copyright (c) 2018-2020 Matias De lellis <[email protected]>
6
 *
7
 * @author Branko Kokanovic <[email protected]>
8
 *
9
 * @license GNU AGPL version 3 or any later version
10
 *
11
 * This program is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License as
13
 * published by the Free Software Foundation, either version 3 of the
14
 * License, or (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 *
24
 */
25
namespace OCA\FaceRecognition\Helper;
26
27
use OCP\Image;
28
use OCP\ITempManager;
29
use OCA\FaceRecognition\Helper\Imaginary;
30
31
class TempImage extends Image {
32
33
	/** @var Imaginary */
34
	private $imaginary;
35
36
	/** @var string */
37
	private $imagePath;
38
39
	/** @var string */
40
	private $tempPath;
41
42
	/** @var string */
43
	private $preferredMimeType;
44
45
	/** @var int */
46
	private $maxImageArea;
47
48
	/** @var ITempManager */
49
	private $tempManager;
50
51
	/** @var int */
52
	private $minImageSide;
53
54
	/** @var float */
55
	private $ratio = -1.0;
56
57
	/** @var bool */
58
	private $skipped = false;
59
60 5
	public function __construct(string $imagePath,
61
	                            string $preferredMimeType,
62
	                            int    $maxImageArea,
63
	                            int    $minImageSide)
64
	{
65 5
		parent::__construct();
66
67 5
		$this->imagePath         = $imagePath;
68 5
		$this->preferredMimeType = $preferredMimeType;
69 5
		$this->maxImageArea      = $maxImageArea;
70 5
		$this->minImageSide      = $minImageSide;
71
72 5
		$this->tempManager       = \OC::$server->getTempManager();
73 5
		$this->imaginary         = new Imaginary();
74
75 5
		$this->prepareImage();
76
	}
77
78
	/**
79
	 * Get the path of temporary image
80
	 *
81
	 * @return string
82
	 */
83 3
	public function getTempPath(): string {
84 3
		return $this->tempPath;
85
	}
86
87
	/**
88
	 * Obtain the ratio of the temporary image against the original
89
	 *
90
	 * @return float
91
	 */
92 2
	public function getRatio(): float {
93 2
		return $this->ratio;
94
	}
95
96
	/** Return if image was skipped
97
	 *
98
	 * @return bool
99
	 */
100 4
	public function getSkipped(): bool {
101 4
		return $this->skipped;
102
	}
103
104
	/**
105
	 * Clean temporary files
106
	 */
107 4
	public function clean() {
108 4
		$this->tempManager->clean();
109
	}
110
111
	/**
112
	 * Obtain a temporary image according to the imposed restrictions.
113
	 *
114
	 */
115 5
	private function prepareImage() {
116
117 5
		if ($this->imaginary->isEnabled()) {
118
			$fileInfo = $this->imaginary->getInfo($this->imagePath);
119
120
			$widthOrig = $fileInfo['width'];
121
			$heightOrig = $fileInfo['height'];
122
			if (($widthOrig < $this->minImageSide) ||
123
			    ($heightOrig < $this->minImageSide)) {
124
				$this->skipped = true;
125
				return;
126
			}
127
128
			$scaleFactor = $this->getResizeRatio($widthOrig, $heightOrig);
129
130
			$newWidth = intval(round($widthOrig * $scaleFactor));
131
			$newHeight = intval(round($heightOrig * $scaleFactor));
132
133
			$resizedResource = $this->imaginary->getResized($this->imagePath, $newWidth, $newHeight, $fileInfo['autorotate'], $this->preferredMimeType);
134
			$this->loadFromData($resizedResource);
135
136
			if (!$this->valid()) {
137
				throw new \RuntimeException("Imaginary image response is not valid.");
138
			}
139
140
			$this->ratio = 1 / $scaleFactor;
141
		}
142
		else {
143 5
			$this->loadFromFile($this->imagePath);
144 5
			$this->fixOrientation();
145
146 5
			if (!$this->valid()) {
147 1
				throw new \RuntimeException("Local image is not valid, probably cannot be loaded");
148
			}
149
150 4
			if ((imagesx($this->resource()) < $this->minImageSide) ||
151 4
			    (imagesy($this->resource()) < $this->minImageSide)) {
152 2
				$this->skipped = true;
153 2
				return;
154
			}
155
156 3
			$this->ratio = $this->resizeOCImage();
157
		}
158
159 3
		$this->tempPath = $this->tempManager->getTemporaryFile();
160 3
		$this->save($this->tempPath, $this->preferredMimeType);
161
162
	}
163
164
	/**
165
	 * Resizes the image to reach max image area, but preserving ratio.
166
	 *
167
	 * @return float Ratio of resize. 1 if there was no resize
168
	 */
169 3
	private function resizeOCImage(): float {
170 3
		$widthOrig = imagesx($this->resource());
171 3
		$heightOrig = imagesy($this->resource());
172
173 3
		if (($widthOrig <= 0) || ($heightOrig <= 0)) {
174
			$message = "Image is having non-positive width or height, cannot continue";
175
			throw new \RuntimeException($message);
176
		}
177
178 3
		$scaleFactor = $this->getResizeRatio($widthOrig, $heightOrig);
179
180 3
		$newWidth = intval(round($widthOrig * $scaleFactor));
181 3
		$newHeight = intval(round($heightOrig * $scaleFactor));
182
183 3
		$success = $this->preciseResize($newWidth, $newHeight);
184 3
		if ($success === false) {
185
			throw new \RuntimeException("Error during image resize");
186
		}
187
188 3
		return 1 / $scaleFactor;
189
	}
190
191
	/**
192
	 * Resizes the image to reach max image area, but preserving ratio.
193
	 *
194
	 * @return float Ratio of resize. 1 if there was no resize
195
	 */
196 3
	private function getResizeRatio($widthOrig, $heightOrig): float {
197 3
		$areaRatio = $this->maxImageArea / ($widthOrig * $heightOrig);
198 3
		return sqrt($areaRatio);
199
	}
200
201
}