Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
jkphl committed Sep 12, 2020
2 parents 9e1e9ce + d8e06fd commit 309b429
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 9 deletions.
101 changes: 101 additions & 0 deletions Classes/Service/AvifConverterService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

/**
* tollwerk
*
* @category Jkphl
* @package Jkphl\Rdfalite
* @subpackage Tollwerk\TwBase\Service
* @author Joschi Kuphal <[email protected]> / @jkphl
* @copyright Copyright © 2019 Joschi Kuphal <[email protected]> / @jkphl
* @license http://opensource.org/licenses/MIT The MIT License (MIT)
*/

/***********************************************************************************
* The MIT License (MIT)
*
* Copyright © 2019 Joschi Kuphal <[email protected]> / @jkphl
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
***********************************************************************************/

namespace Tollwerk\TwBase\Service;

use Tollwerk\TwBase\Utility\ResponsiveImagesUtility;
use TYPO3\CMS\Core\Resource\File;
use TYPO3\CMS\Core\Resource\FileInterface;
use TYPO3\CMS\Core\Resource\Processing\TaskInterface;
use TYPO3\CMS\Core\Utility\CommandUtility;

/**
* AVIF converter service
*/
class AvifConverterService extends AbstractImageFileConverterService
{
/**
* Name of the TypoScript key to enable this service
*
* @var bool|string|null
*/
protected $typoscriptEnableKey = 'converters.avif';

/**
* Check whether this converer accepts a particular file for conversion
*
* @param FileInterface $image File
*
* @return bool File is accepted for conversion
*/
public function acceptsFile(FileInterface $image): bool
{
return in_array(strtolower($image->getExtension()), ResponsiveImagesUtility::SRCSET_FILE_EXTENSIONS);
}

/**
* Process a file
*
* @param TaskInterface $task Image processing task
* @param array $configuration Service configuration
*
* @return array|null Result
*/
public function processImageFile(TaskInterface $task, array $configuration = []): ?array
{
/** @var File $sourceFile */
$sourceFile = $task->getSourceFile();
$sourceFilePath = $sourceFile->getForLocalProcessing();
$this->registerTempFile($sourceFilePath);

$targetFilePath = dirname($sourceFilePath).DIRECTORY_SEPARATOR.pathinfo(
$sourceFilePath,
PATHINFO_FILENAME
).'.avif';
$this->registerTempFile($targetFilePath);

$avifencCommand = 'avifenc -j '.CommandUtility::escapeShellArgument(max(1, intval($configuration['jobs'])));
$avifencCommand .= ' --min '.CommandUtility::escapeShellArgument(max(0, min(63, intval($configuration['min']))));
$avifencCommand .= ' --max '.CommandUtility::escapeShellArgument(max(0, min(63, intval($configuration['max']))));
$avifencCommand .= ' '.CommandUtility::escapeShellArgument($sourceFilePath);
$avifencCommand .= ' '.CommandUtility::escapeShellArgument($targetFilePath);

$output = $returnValue = null;
CommandUtility::exec($avifencCommand, $output, $returnValue);

return $returnValue ? null : ['filePath' => $targetFilePath];
}
}
2 changes: 2 additions & 0 deletions Classes/Service/Resource/Processing/ImageConvertTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ protected function determineTargetFileExtension()
switch ($this->configuration['converter']['type']) {
case 'webp':
return 'webp';
case 'avif':
return 'avif';
}
}

Expand Down
5 changes: 3 additions & 2 deletions Classes/Service/WebpConverterService.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
use TYPO3\CMS\Core\Utility\CommandUtility;

/**
* Webp converter service
* WebP converter service
*/
class WebpConverterService extends AbstractImageFileConverterService
{
Expand Down Expand Up @@ -82,7 +82,8 @@ public function processImageFile(TaskInterface $task, array $configuration = [])
$this->registerTempFile($sourceFilePath);

$targetFilePath = dirname($sourceFilePath).DIRECTORY_SEPARATOR.pathinfo(
$sourceFilePath, PATHINFO_FILENAME
$sourceFilePath,
PATHINFO_FILENAME
).'.webp';
$this->registerTempFile($targetFilePath);

Expand Down
10 changes: 8 additions & 2 deletions Classes/Utility/ResponsiveImagesUtility.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ class ResponsiveImagesUtility implements SingletonInterface
*
* @var string[]
*/
const SRCSET_FILE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'webp', 'gif'];
const SRCSET_FILE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif'];
/**
* Image file extensions eligible for picture processing
*
* @var string[]
*/
const PICTURE_FILE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'webp', 'gif'];
const PICTURE_FILE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif'];
/**
* Object Manager
*
Expand Down Expand Up @@ -788,6 +788,12 @@ public function getAvailableConverters(FileInterface $image, array $skip = []):
if ($this->availableImageConverters === null) {
$this->availableImageConverters = [];

// Test if the AVIF converter is available
$avifConverterService = GeneralUtility::makeInstanceService('fileconvert', 'avif');
if ($avifConverterService instanceof AbstractImageFileConverterService) {
$this->availableImageConverters['avif'] = $avifConverterService;
}

// Test if the WebP converter is available
$webPConverterService = GeneralUtility::makeInstanceService('fileconvert', 'webp');
if ($webPConverterService instanceof AbstractImageFileConverterService) {
Expand Down
6 changes: 5 additions & 1 deletion Configuration/TCA/Overrides/tt_content.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,11 @@
[
'LLL:EXT:tw_base/Resources/Private/Language/locallang_db.xlf:tt_content.tx_twbase_skipconverter.I.webp',
'webp'
]
],
[
'LLL:EXT:tw_base/Resources/Private/Language/locallang_db.xlf:tt_content.tx_twbase_skipconverter.I.avif',
'avif'
],
],
],
],
Expand Down
16 changes: 14 additions & 2 deletions Configuration/TypoScript/Static/constants.typoscript
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,22 @@ plugin.tx_twbase {
}

converters {
# cat=plugin.tx_twbase/converters/a; type=options[Off=0,On=1]; label=LLL:EXT:tw_base/Resources/Private/Language/locallang_db.xlf:converters.webp
# cat=plugin.tx_twbase/converters/a; type=options[Off=0,On=1]; label=LLL:EXT:tw_base/Resources/Private/Language/locallang_db.xlf:converters.avif
avif = 1

# cat=plugin.tx_twbase/converters/b; type=int+; label=LLL:EXT:tw_base/Resources/Private/Language/locallang_db.xlf:converters.avif.jobs
avif.jobs = 1

# cat=plugin.tx_twbase/converters/c; type=int+; label=LLL:EXT:tw_base/Resources/Private/Language/locallang_db.xlf:converters.avif.min
avif.min = 35

# cat=plugin.tx_twbase/converters/d; type=int+; label=LLL:EXT:tw_base/Resources/Private/Language/locallang_db.xlf:converters.avif.max
avif.max = 50

# cat=plugin.tx_twbase/converters/e; type=options[Off=0,On=1]; label=LLL:EXT:tw_base/Resources/Private/Language/locallang_db.xlf:converters.webp
webp = 1

# cat=plugin.tx_twbase/converters/b; type=int+; label=LLL:EXT:tw_base/Resources/Private/Language/locallang_db.xlf:converters.webp.quality
# cat=plugin.tx_twbase/converters/f; type=int+; label=LLL:EXT:tw_base/Resources/Private/Language/locallang_db.xlf:converters.webp.quality
webp.quality = 80
}

Expand Down
4 changes: 4 additions & 0 deletions Configuration/TypoScript/Static/setup.typoscript
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ plugin.tx_twbase {
}

converters {
avif = {$plugin.tx_twbase.settings.converters.avif}
avif.jobs = {$plugin.tx_twbase.settings.converters.avif.jobs}
avif.min = {$plugin.tx_twbase.settings.converters.avif.min}
avif.max = {$plugin.tx_twbase.settings.converters.avif.max}
webp = {$plugin.tx_twbase.settings.converters.webp}
webp.quality = {$plugin.tx_twbase.settings.converters.webp.quality}
}
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
These services don't work out of the box and require particular software to be available on the server:

* For optimizing JPEG images using the **mozjpeg encoder**, install the [Mozilla JPEG Encoder Project](https://github.com/mozilla/mozjpeg) and create a `mozjpeg` alias to `jpegtran`.
* For creating WebP image variants, install the [WebP](https://developers.google.com/speed/webp/download) on the server and make sure the [cwebp](https://developers.google.com/speed/webp/docs/cwebp) encoder tool is available as `cwebp` on the command line.
* For creating WebP image variants, install the [WebP](https://developers.google.com/speed/webp/download) converter on the server and make sure the [cwebp](https://developers.google.com/speed/webp/docs/cwebp) encoder tool is available as `cwebp` on the command line.
* For creating AVIV image variants, install the [AVIF](hhttps://github.com/AOMediaCodec/libavif) converter on the server and make sure the encoder tool is available as `avifenc` on the command line.
* For compressing SVG images on the fly, install the [Node.js](https://nodejs.org/en/) based [SVGO](https://github.com/svg/svgo) tool and make sure it's available as `svgo` on the command line.
* For creating SVG previews for images with Primitive, install the [Go language](https://golang.org/) and [Primitive](https://github.com/fogleman/primitive) on your server and make sure `primitive` is available on the command line.
* For creating gzipped versions of merged CSS and JavaScript files you need to have the [GNU Gzip](https://www.gnu.org/software/gzip/) command line utility installed (standard on any Linux system), globally available as `gzip` binary.
Expand Down
15 changes: 15 additions & 0 deletions Resources/Private/Language/de.locallang_db.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@
<trans-unit id="converters.webp.quality" xml:space="preserve" approved="yes">
<source>WebP quality (0-100)</source>
<target state="translated">WebP-Qualität (0-100)</target></trans-unit>
<trans-unit id="converters.avif" xml:space="preserve" approved="yes">
<source>AVIF converter: Enable automatic encoding of AVIF image variants</source>
<target state="translated">AVIF-Konverter: Automatische Kodierung von AVIF-Bildvarianten aktivieren</target></trans-unit>
<trans-unit id="converters.avif.jobs" xml:space="preserve" approved="yes">
<source>Number of AVIF worker jobs (depends on your hardware)</source>
<target state="translated">Anzahl von AVIF-Worker-Prozessen (systemabhängig)</target></trans-unit>
<trans-unit id="converters.avif.min" xml:space="preserve" approved="yes">
<source>AVIF minimum quantizer (0-63, 0 = lossless)</source>
<target state="translated">AVIF Minimum Quantizer (0-63, 0 = verlustfrei)</target></trans-unit>
<trans-unit id="converters.avif.max" xml:space="preserve" approved="yes">
<source>AVIF minimum quantizer (0-63, 0 = lossless)</source>
<target state="translated">AVIF Maximum Quantizer (0-63, 0 = verlustfrei)</target></trans-unit>
<trans-unit id="images.srcset" xml:space="preserve" approved="yes">
<source>Additional Image Sizes for Responsive Images: Additional image sizes that should be generated for each content image (comma-separated list of either image widths specified in pixels or pixel density descriptors, e. g. "2x")</source>
<target state="translated">Zusätzliche Bildgrößen für Responsive Bilder: Zusätzliche Bildgrößen, die für jedes Inhaltsbild erzeugt werden sollen (kommaseparierte Liste von Bildbreiten in Pixeln oder Auflösungsfaktoren, z.B. "2x")</target></trans-unit>
Expand Down Expand Up @@ -147,6 +159,9 @@
<trans-unit id="tt_content.tx_twbase_skipconverter.I.webp" xml:space="preserve" approved="yes">
<source>WebP</source>
<target state="translated">WebP</target></trans-unit>
<trans-unit id="tt_content.tx_twbase_skipconverter.I.avif" xml:space="preserve" approved="yes">
<source>AVIF</source>
<target state="translated">AVIF</target></trans-unit>
<trans-unit id="tt_content.tx_twbase_video_tracks" xml:space="preserve" approved="yes">
<source>Tracks</source>
<target state="translated">Tracks</target></trans-unit>
Expand Down
15 changes: 15 additions & 0 deletions Resources/Private/Language/locallang_db.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@
<trans-unit id="converters.webp.quality" xml:space="preserve">
<source>WebP quality (0-100)</source>
</trans-unit>
<trans-unit id="converters.avif" xml:space="preserve">
<source>AVIF converter: Enable automatic encoding of AVIF image variants</source>
</trans-unit>
<trans-unit id="converters.avif.jobs" xml:space="preserve">
<source>Number of AVIF worker jobs (depends on your hardware)</source>
</trans-unit>
<trans-unit id="converters.avif.min" xml:space="preserve">
<source>AVIF minimum quantizer (0-63, 0 = lossless)</source>
</trans-unit>
<trans-unit id="converters.avif.max" xml:space="preserve">
<source>AVIF minimum quantizer (0-63, 0 = lossless)</source>
</trans-unit>
<trans-unit id="images.srcset" xml:space="preserve">
<source>Additional Image Sizes for Responsive Images: Additional image sizes that should be generated for each content image (comma-separated list of either image widths specified in pixels or pixel density descriptors, e. g. "2x")</source>
</trans-unit>
Expand Down Expand Up @@ -148,6 +160,9 @@
<trans-unit id="tt_content.tx_twbase_skipconverter.I.webp" xml:space="preserve">
<source>WebP</source>
</trans-unit>
<trans-unit id="tt_content.tx_twbase_skipconverter.I.avif" xml:space="preserve">
<source>AVIF</source>
</trans-unit>
<trans-unit id="tt_content.tx_twbase_video_tracks" xml:space="preserve">
<source>Tracks</source>
</trans-unit>
Expand Down
22 changes: 21 additions & 1 deletion ext_localconf.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,24 @@ function() {
)
);

// Register the AVIF image converter service
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addService(
'tw_base',
'fileconvert', // Service type
'tx_twbase_avif', // Service key
array(
'title' => 'avif',
'description' => 'Convert images using the AVIF converter (https://github.com/AOMediaCodec/libavif)',
'subtype' => 'avif',
'available' => true,
'priority' => 60,
'quality' => 80,
'os' => '',
'exec' => 'avifenc',
'className' => \Tollwerk\TwBase\Service\AvifConverterService::class
)
);

// Add plugin for generic ajax calls. Add array to SC_OPTIONS for registering callable ajax functions
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/tw_base']['ajax'] = [];
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
Expand All @@ -167,7 +185,6 @@ function() {
[\Tollwerk\TwBase\Controller\AjaxController::class => 'dispatch']
);


// Register additional image processing tasks
$GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['processingTaskTypes']['Image.CropScaleMaskCompress'] = \Tollwerk\TwBase\Service\Resource\Processing\ImageCropScaleMaskCompressTask::class;
$GLOBALS['TYPO3_CONF_VARS']['SYS']['fal']['processingTaskTypes']['Image.Convert'] = \Tollwerk\TwBase\Service\Resource\Processing\ImageConvertTask::class;
Expand All @@ -177,6 +194,9 @@ function() {
'className' => \Tollwerk\TwBase\Service\Resource\Processing\LocalImageProcessor::class,
];

// Register the AVIF MIME type
$GLOBALS['TYPO3_CONF_VARS']['SYS']['FileInfo']['fileExtensionToMimeType']['avif'] = 'image/avif';

// Override language files
$GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride']['EXT:form/Resources/Private/Language/Database.xlf'][] = 'EXT:tw_base/Resources/Private/Language/form_editor.xlf';

Expand Down

0 comments on commit 309b429

Please sign in to comment.