Skip to content

Commit

Permalink
Merge pull request #365 from pulsejet/patch-heic
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelklehr committed Oct 12, 2022
2 parents 9392988 + 471d5d2 commit 1b0db65
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 15 deletions.
9 changes: 7 additions & 2 deletions .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:
php-versions: ['7.4', '8.0', '8.1']
databases: ['sqlite', 'mysql', 'pgsql']
server-versions: ['stable25', 'master']
imagick: ['']
s3: ['']
container: ['']
include:
Expand All @@ -35,6 +36,10 @@ jobs:
php-versions: 8.0
databases: sqlite
container: nextcloud:fpm-alpine
- server-versions: stable25
php-versions: 8.0
databases: sqlite
imagick: 'imagick'
- server-versions: stable25
php-versions: 8.0
databases: mysql
Expand All @@ -44,7 +49,7 @@ jobs:
databases: mysql
s3: s3

name: php${{ matrix.php-versions }} ${{ matrix.databases }} ${{ matrix.server-versions }} ${{ matrix.container }} ${{ matrix.s3 }}
name: php${{ matrix.php-versions }} ${{ matrix.databases }} ${{ matrix.server-versions }} ${{ matrix.container }} ${{ matrix.s3 }} ${{ matrix.imagick }}

container: ${{ matrix.container }}

Expand Down Expand Up @@ -124,7 +129,7 @@ jobs:
with:
php-version: ${{ matrix.php-versions }}
tools: phpunit
extensions: mbstring, iconv, fileinfo, intl, mysql, pdo_mysql, gd, zip
extensions: mbstring, iconv, fileinfo, intl, mysql, pdo_mysql, gd, zip, ${{ matrix.imagick }}
coverage: none

- name: Install app
Expand Down
5 changes: 3 additions & 2 deletions lib/Classifiers/Audio/MusicnnClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use OCA\Recognize\Service\TagManager;
use OCP\Files\IRootFolder;
use OCP\IConfig;
use OCP\ITempManager;

class MusicnnClassifier extends Classifier {
public const AUDIO_TIMEOUT = 40; // seconds
Expand All @@ -22,8 +23,8 @@ class MusicnnClassifier extends Classifier {
private TagManager $tagManager;
private IConfig $config;

public function __construct(Logger $logger, IConfig $config, TagManager $tagManager, QueueService $queue, IRootFolder $rootFolder) {
parent::__construct($logger, $config, $rootFolder, $queue);
public function __construct(Logger $logger, IConfig $config, TagManager $tagManager, QueueService $queue, IRootFolder $rootFolder, ITempManager $tempManager) {
parent::__construct($logger, $config, $rootFolder, $queue, $tempManager);
$this->config = $config;
$this->tagManager = $tagManager;
}
Expand Down
52 changes: 50 additions & 2 deletions lib/Classifiers/Classifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@

namespace OCA\Recognize\Classifiers;

use OC\Files\Node\Node;
use OCA\Recognize\Constants;
use OCA\Recognize\Service\Logger;
use OCA\Recognize\Service\QueueService;
use OCP\DB\Exception;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IConfig;
use OCP\ITempManager;
use Psr\Log\LoggerInterface;
use Symfony\Component\Process\Exception\ProcessTimedOutException;
use Symfony\Component\Process\Exception\RuntimeException;
Expand All @@ -23,12 +26,14 @@ class Classifier {
private IConfig $config;
private IRootFolder $rootFolder;
private QueueService $queue;
private ITempManager $tempManager;

public function __construct(Logger $logger, IConfig $config, IRootFolder $rootFolder, QueueService $queue) {
public function __construct(Logger $logger, IConfig $config, IRootFolder $rootFolder, QueueService $queue, ITempManager $tempManager) {
$this->logger = $logger;
$this->config = $config;
$this->rootFolder = $rootFolder;
$this->queue = $queue;
$this->tempManager = $tempManager;
}

/**
Expand All @@ -46,7 +51,7 @@ public function classifyFiles(string $model, array $queueFiles, int $timeout): \
continue;
}
try {
$paths[] = $files[0]->getStorage()->getLocalFile($files[0]->getInternalPath());
$paths[] = $this->getConvertedFilePath($files[0]);
$processedFiles[] = $queueFile;
} catch (NotFoundException $e) {
$this->logger->warning('Could not find file', ['exception' => $e]);
Expand Down Expand Up @@ -141,4 +146,47 @@ public function classifyFiles(string $model, array $queueFiles, int $timeout): \
throw new \RuntimeException('Classifier process could not be started');
}
}

/**
* Get path of file to process.
* If the file is an image and not JPEG, it will be converted using ImageMagick.
* Images will also be downscaled to a max dimension of 4096px.
*
* @param Node $file
* @return string Path to file to process
*/
private function getConvertedFilePath(Node $file): string {
$path = $file->getStorage()->getLocalFile($file->getInternalPath());

// check if this is an image to convert / downscale
$mime = $file->getMimeType();
if (!in_array($mime, Constants::IMAGE_FORMATS)) {
return $path;
}

// Check if ImageMagick is installed
if (!extension_loaded('imagick')) {
return $path;
}

// Create a temporary file *with the correct extension*
$tmpname = $this->tempManager->getTemporaryFile('.jpg');

try {
// Convert to a temporary JPEG file optionally downscaling
$imagick = new \Imagick($path);
$dimensions = $imagick->getImageGeometry();
if ($dimensions['width'] > 4096 || $dimensions['height'] > 4096) {
// downscale
$imagick->scaleImage(4096, 4096, true);
}
$imagick->setImageFormat('jpeg');
$imagick->writeImage($tmpname);
} catch (\ImagickException $e) {
// If conversion fails, just use the original file
return $path;
}

return $tmpname;
}
}
5 changes: 3 additions & 2 deletions lib/Classifiers/Images/ClusteringFaceClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use OCP\Files\Config\IUserMountCache;
use OCP\Files\IRootFolder;
use OCP\IConfig;
use OCP\ITempManager;

class ClusteringFaceClassifier extends Classifier {
public const IMAGE_TIMEOUT = 120; // seconds
Expand All @@ -33,8 +34,8 @@ class ClusteringFaceClassifier extends Classifier {
private IUserMountCache $userMountCache;
private IJobList $jobList;

public function __construct(Logger $logger, IConfig $config, FaceDetectionMapper $faceDetections, QueueService $queue, IRootFolder $rootFolder, IUserMountCache $userMountCache, IJobList $jobList) {
parent::__construct($logger, $config, $rootFolder, $queue);
public function __construct(Logger $logger, IConfig $config, FaceDetectionMapper $faceDetections, QueueService $queue, IRootFolder $rootFolder, IUserMountCache $userMountCache, IJobList $jobList, ITempManager $tempManager) {
parent::__construct($logger, $config, $rootFolder, $queue, $tempManager);
$this->logger = $logger;
$this->config = $config;
$this->faceDetections = $faceDetections;
Expand Down
5 changes: 3 additions & 2 deletions lib/Classifiers/Images/ImagenetClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use OCP\DB\Exception;
use OCP\Files\IRootFolder;
use OCP\IConfig;
use OCP\ITempManager;

class ImagenetClassifier extends Classifier {
public const IMAGE_TIMEOUT = 480; // seconds
Expand All @@ -25,8 +26,8 @@ class ImagenetClassifier extends Classifier {
private QueueService $queue;
private Logger $logger;

public function __construct(Logger $logger, IConfig $config, TagManager $tagManager, QueueService $queue, IRootFolder $rootFolder) {
parent::__construct($logger, $config, $rootFolder, $queue);
public function __construct(Logger $logger, IConfig $config, TagManager $tagManager, QueueService $queue, IRootFolder $rootFolder, ITempManager $tempManager) {
parent::__construct($logger, $config, $rootFolder, $queue, $tempManager);
$this->config = $config;
$this->tagManager = $tagManager;
$this->queue = $queue;
Expand Down
5 changes: 3 additions & 2 deletions lib/Classifiers/Images/LandmarksClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use OCA\Recognize\Service\TagManager;
use OCP\Files\IRootFolder;
use OCP\IConfig;
use OCP\ITempManager;

class LandmarksClassifier extends Classifier {
public const IMAGE_TIMEOUT = 480; // seconds
Expand All @@ -24,8 +25,8 @@ class LandmarksClassifier extends Classifier {
private TagManager $tagManager;
private IConfig $config;

public function __construct(Logger $logger, IConfig $config, TagManager $tagManager, QueueService $queue, IRootFolder $rootFolder) {
parent::__construct($logger, $config, $rootFolder, $queue);
public function __construct(Logger $logger, IConfig $config, TagManager $tagManager, QueueService $queue, IRootFolder $rootFolder, ITempManager $tempManager) {
parent::__construct($logger, $config, $rootFolder, $queue, $tempManager);
$this->logger = $logger;
$this->config = $config;
$this->tagManager = $tagManager;
Expand Down
5 changes: 3 additions & 2 deletions lib/Classifiers/Video/MovinetClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use OCA\Recognize\Service\TagManager;
use OCP\Files\IRootFolder;
use OCP\IConfig;
use OCP\ITempManager;

class MovinetClassifier extends Classifier {
public const VIDEO_TIMEOUT = 480; // seconds
Expand All @@ -22,8 +23,8 @@ class MovinetClassifier extends Classifier {
private TagManager $tagManager;
private IConfig $config;

public function __construct(Logger $logger, IConfig $config, TagManager $tagManager, QueueService $queue, IRootFolder $rootFolder) {
parent::__construct($logger, $config, $rootFolder, $queue);
public function __construct(Logger $logger, IConfig $config, TagManager $tagManager, QueueService $queue, IRootFolder $rootFolder, ITempManager $tempManager) {
parent::__construct($logger, $config, $rootFolder, $queue, $tempManager);
$this->config = $config;
$this->tagManager = $tagManager;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace OCA\Recognize;

class Constants {
public const IMAGE_FORMATS = ['image/jpeg', 'image/png', 'image/bmp'];
public const IMAGE_FORMATS = ['image/jpeg', 'image/png', 'image/bmp', 'image/heic', 'image/heif', 'image/tiff'];
public const AUDIO_FORMATS = ['audio/mpeg', 'audio/mp4', 'audio/ogg', 'audio/vnd.wav', 'audio/flac'];
public const VIDEO_FORMATS = ['image/gif', 'video/mp4', 'video/MP2T', 'video/x-msvideo', 'video/x-ms-wmv', 'video/quicktime', 'video/ogg', 'video/mpeg', 'video/webm', 'video/x-matroska'];
public const MAX_FILE_SIZE = 10000000;
Expand Down

0 comments on commit 1b0db65

Please sign in to comment.