nextcloud-custom-apps-face-.../facerecognition/lib/Helper/TempImage.php
2024-09-03 09:12:12 +05:00

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);
}
}