201 lines
5.1 KiB
PHP
201 lines
5.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
/**
|
|
* @copyright Copyright (c) 2018-2019 Branko Kokanovic <branko@kokanovic.org>
|
|
* @copyright Copyright (c) 2018-2020 Matias De lellis <mti86dl@gmail.com>
|
|
*
|
|
* @author Branko Kokanovic <branko@kokanovic.org>
|
|
*
|
|
* @license GNU AGPL version 3 or any later version
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
namespace OCA\FaceRecognition\Helper;
|
|
|
|
use OCP\Image;
|
|
use OCP\ITempManager;
|
|
use OCA\FaceRecognition\Helper\Imaginary;
|
|
|
|
class TempImage extends Image {
|
|
|
|
/** @var Imaginary */
|
|
private $imaginary;
|
|
|
|
/** @var string */
|
|
private $imagePath;
|
|
|
|
/** @var string */
|
|
private $tempPath;
|
|
|
|
/** @var string */
|
|
private $preferredMimeType;
|
|
|
|
/** @var int */
|
|
private $maxImageArea;
|
|
|
|
/** @var ITempManager */
|
|
private $tempManager;
|
|
|
|
/** @var int */
|
|
private $minImageSide;
|
|
|
|
/** @var float */
|
|
private $ratio = -1.0;
|
|
|
|
/** @var bool */
|
|
private $skipped = false;
|
|
|
|
public function __construct(string $imagePath,
|
|
string $preferredMimeType,
|
|
int $maxImageArea,
|
|
int $minImageSide)
|
|
{
|
|
parent::__construct();
|
|
|
|
$this->imagePath = $imagePath;
|
|
$this->preferredMimeType = $preferredMimeType;
|
|
$this->maxImageArea = $maxImageArea;
|
|
$this->minImageSide = $minImageSide;
|
|
|
|
$this->tempManager = \OC::$server->getTempManager();
|
|
$this->imaginary = new Imaginary();
|
|
|
|
$this->prepareImage();
|
|
}
|
|
|
|
/**
|
|
* Get the path of temporary image
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getTempPath(): string {
|
|
return $this->tempPath;
|
|
}
|
|
|
|
/**
|
|
* Obtain the ratio of the temporary image against the original
|
|
*
|
|
* @return float
|
|
*/
|
|
public function getRatio(): float {
|
|
return $this->ratio;
|
|
}
|
|
|
|
/** Return if image was skipped
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function getSkipped(): bool {
|
|
return $this->skipped;
|
|
}
|
|
|
|
/**
|
|
* Clean temporary files
|
|
*/
|
|
public function clean() {
|
|
$this->tempManager->clean();
|
|
}
|
|
|
|
/**
|
|
* Obtain a temporary image according to the imposed restrictions.
|
|
*
|
|
*/
|
|
private function prepareImage() {
|
|
|
|
if ($this->imaginary->isEnabled()) {
|
|
$fileInfo = $this->imaginary->getInfo($this->imagePath);
|
|
|
|
$widthOrig = $fileInfo['width'];
|
|
$heightOrig = $fileInfo['height'];
|
|
if (($widthOrig < $this->minImageSide) ||
|
|
($heightOrig < $this->minImageSide)) {
|
|
$this->skipped = true;
|
|
return;
|
|
}
|
|
|
|
$scaleFactor = $this->getResizeRatio($widthOrig, $heightOrig);
|
|
|
|
$newWidth = intval(round($widthOrig * $scaleFactor));
|
|
$newHeight = intval(round($heightOrig * $scaleFactor));
|
|
|
|
$resizedResource = $this->imaginary->getResized($this->imagePath, $newWidth, $newHeight, $fileInfo['autorotate'], $this->preferredMimeType);
|
|
$this->loadFromData($resizedResource);
|
|
|
|
if (!$this->valid()) {
|
|
throw new \RuntimeException("Imaginary image response is not valid.");
|
|
}
|
|
|
|
$this->ratio = 1 / $scaleFactor;
|
|
}
|
|
else {
|
|
$this->loadFromFile($this->imagePath);
|
|
$this->fixOrientation();
|
|
|
|
if (!$this->valid()) {
|
|
throw new \RuntimeException("Local image is not valid, probably cannot be loaded");
|
|
}
|
|
|
|
if ((imagesx($this->resource()) < $this->minImageSide) ||
|
|
(imagesy($this->resource()) < $this->minImageSide)) {
|
|
$this->skipped = true;
|
|
return;
|
|
}
|
|
|
|
$this->ratio = $this->resizeOCImage();
|
|
}
|
|
|
|
$this->tempPath = $this->tempManager->getTemporaryFile();
|
|
$this->save($this->tempPath, $this->preferredMimeType);
|
|
|
|
}
|
|
|
|
/**
|
|
* Resizes the image to reach max image area, but preserving ratio.
|
|
*
|
|
* @return float Ratio of resize. 1 if there was no resize
|
|
*/
|
|
private function resizeOCImage(): float {
|
|
$widthOrig = imagesx($this->resource());
|
|
$heightOrig = imagesy($this->resource());
|
|
|
|
if (($widthOrig <= 0) || ($heightOrig <= 0)) {
|
|
$message = "Image is having non-positive width or height, cannot continue";
|
|
throw new \RuntimeException($message);
|
|
}
|
|
|
|
$scaleFactor = $this->getResizeRatio($widthOrig, $heightOrig);
|
|
|
|
$newWidth = intval(round($widthOrig * $scaleFactor));
|
|
$newHeight = intval(round($heightOrig * $scaleFactor));
|
|
|
|
$success = $this->preciseResize($newWidth, $newHeight);
|
|
if ($success === false) {
|
|
throw new \RuntimeException("Error during image resize");
|
|
}
|
|
|
|
return 1 / $scaleFactor;
|
|
}
|
|
|
|
/**
|
|
* Resizes the image to reach max image area, but preserving ratio.
|
|
*
|
|
* @return float Ratio of resize. 1 if there was no resize
|
|
*/
|
|
private function getResizeRatio($widthOrig, $heightOrig): float {
|
|
$areaRatio = $this->maxImageArea / ($widthOrig * $heightOrig);
|
|
return sqrt($areaRatio);
|
|
}
|
|
|
|
} |