diff --git a/Classes/Domain/Model/PictureConfiguration.php b/Classes/Domain/Model/PictureConfiguration.php
index c6daf3d..87b3c8a 100644
--- a/Classes/Domain/Model/PictureConfiguration.php
+++ b/Classes/Domain/Model/PictureConfiguration.php
@@ -17,8 +17,8 @@
class PictureConfiguration
{
protected bool $useRetina = false;
- // 2x is default. Use multiple if retina is set in TypoScript settings.
- protected array $retinaSettings = [2 => '2x'];
+ protected array $retinaSettings = [2 => '2x']; // 2x is default. Use multiple if retina is set in TypoScript settings.
+ protected bool $addAvif = false;
protected bool $addWebp = false;
protected bool $lossless = false;
protected bool $addBreakpoints = false;
@@ -34,11 +34,14 @@ public function __construct(array $arguments, array $typoScriptSettings, FileInt
$this->arguments = $arguments;
$fileExtension = $arguments['fileExtension'] ?? $image->getExtension();
if ($image->getExtension() !== 'svg') {
- $this->addWebp = (bool)($fileExtension === 'webp' ? false : ($arguments['addWebp'] ?? $typoScriptSettings['addWebp'] ?? false));
$this->useRetina = (bool)($arguments['useRetina'] ?? $typoScriptSettings['useRetina'] ?? false);
if (isset($typoScriptSettings['retina.'])) {
$this->retinaSettings = $typoScriptSettings['retina.'];
}
+
+ $this->addAvif = (bool)($fileExtension === 'avif' ? false : ($arguments['addAvif'] ?? $typoScriptSettings['addAvif'] ?? false));
+ $this->addWebp = (bool)($fileExtension === 'webp' ? false : ($arguments['addWebp'] ?? $typoScriptSettings['addWebp'] ?? false));
+
$this->lossless = (bool)($arguments['lossless'] ?? $typoScriptSettings['lossless'] ?? false);
if (isset($typoScriptSettings['breakpoints.'])) {
$this->addBreakpoints = true;
@@ -105,7 +108,7 @@ public function getRetinaSettings(): array
public function pictureTagShouldBeAdded(): bool
{
- return $this->addWebp || $this->addSources;
+ return $this->addAvif || $this->addWebp || $this->addSources;
}
protected function breakPointsShouldBeAdded(): bool
@@ -130,12 +133,17 @@ public function sourcesShouldBeAdded(): bool
public function webpShouldBeAddedBeforeSrcset(): bool
{
- return $this->addWebp && !$this->addSources;
+ return $this->addWebp && !$this->addSources;// TODO : MOD ??
}
public function webpShouldBeAddedAfterSrcset(): bool
{
- return $this->addWebp && $this->addSources;
+ return $this->addWebp && $this->addSources;// TODO : MOD ??
+ }
+
+ public function avifShouldBeAdded(): bool
+ {
+ return $this->addAvif;
}
public function webpShouldBeAdded(): bool
diff --git a/Classes/ViewHelpers/ImageViewHelper.php b/Classes/ViewHelpers/ImageViewHelper.php
index 9132279..6f8b15d 100644
--- a/Classes/ViewHelpers/ImageViewHelper.php
+++ b/Classes/ViewHelpers/ImageViewHelper.php
@@ -72,6 +72,12 @@ public function initializeArguments(): void
'Specifies if image should be displayed for retina as well.'
);
+ $this->registerArgument(
+ 'addAvif',
+ 'bool',
+ 'Specifies if a picture element with an additional avif image should be rendered.'
+ );
+
$this->registerArgument(
'addWebp',
'bool',
@@ -141,6 +147,7 @@ public function render(): string
// Add a webp source tag and activate nesting within a picture element only if no sources are set.
if ($this->pictureConfiguration->webpShouldBeAddedBeforeSrcset()) {
$tag = $this->addWebpImage($this->arguments);
+ // TODO : ADD ??
$output[] = $tag->render();
}
@@ -150,9 +157,14 @@ public function render(): string
$sourceOutputs = [];
$tag = $this->buildSingleTag('source', $sourceConfiguration);
$sourceOutputs[] = $tag->render();
+ $type = $tag->getAttribute('type');
+ // Build additional source with type avif if attribute addAvif is set and previously build tag is not type of avif already.
+ if ($type !== 'image/avif' && $this->pictureConfiguration->avifShouldBeAdded()) {
+ $tag = $this->addAvifImage($sourceConfiguration);
+ array_unshift($sourceOutputs, $tag->render());
+ }
// Build additional source with type webp if attribute addWebp is set and previously build tag is not type of webp already.
- $type = $tag->getAttribute('type');
if ($type !== 'image/webp' && $this->pictureConfiguration->webpShouldBeAdded()) {
$tag = $this->addWebpImage($sourceConfiguration);
array_unshift($sourceOutputs, $tag->render());
@@ -165,6 +177,7 @@ public function render(): string
// add a webp fallback for the default/non-sources image if addWebp is set
if ($this->pictureConfiguration->webpShouldBeAddedAfterSrcset()) {
$tag = $this->addWebpImage($this->arguments);
+ // TODO : ADD ??
$output[] = $tag->render();
}
}
@@ -377,6 +390,17 @@ protected function addRetina(array $processingInstructions, TagBuilder $tag): vo
$tag->addAttribute('srcset', $tagValue);
}
+ /**
+ * Function to add a avif element nested by a picture element.
+ */
+ protected function addAvifImage(array $configuration): TagBuilder
+ {
+ $configuration['fileExtension'] = 'avif';
+ $tag = $this->buildSingleTag('source', $configuration);
+ $tag->addAttribute('type', 'image/avif');
+ return $tag;
+ }
+
/**
* Function to add a webp element nested by a picture element.
*/
@@ -474,6 +498,13 @@ protected function getFrontendController(): ?TypoScriptFrontendController
*/
protected function applyProcessingInstructions(array $processingInstructions): ProcessedFile
{
+ if (($processingInstructions['fileExtension'] ?? '') === 'avif'
+ && $this->image->getExtension() !== 'avif'
+ ) {
+ $jpegQuality = MathUtility::forceIntegerInRange($GLOBALS['TYPO3_CONF_VARS']['GFX']['jpg_quality'], 10, 100, 85);
+ $processingInstructions['additionalParameters'] = '-quality ' . $jpegQuality;
+ }
+
if (($processingInstructions['fileExtension'] ?? '') === 'webp'
&& $this->image->getExtension() !== 'webp'
) {
diff --git a/Configuration/TypoScript/setup.typoscript b/Configuration/TypoScript/setup.typoscript
index a41020e..329e6ac 100644
--- a/Configuration/TypoScript/setup.typoscript
+++ b/Configuration/TypoScript/setup.typoscript
@@ -1,13 +1,7 @@
plugin.tx_picture {
- # Default for adding of images as webp.
- addWebp = 0
-
# Default for adding retina images.
useRetina = 0
- # Default for using lossless compression for webp.
- lossless = 0
-
# Works only in combination with useRetina = 1.
# The key must be the multiplier of the image size and the value the multiplier string added in the srcset
# attribute's value. E.g. add "3 = 3x" to array:
@@ -17,6 +11,15 @@ plugin.tx_picture {
2 = 2x
}
+ # Default for adding of images as avif.
+ addAvif = 0
+
+ # Default for adding of images as webp.
+ addWebp = 0
+
+ # Default for using lossless compression for webp.
+ lossless = 0
+
# Breakpoints for media query specified in the sources attribute:
# breakpoints {
# sm = 640
diff --git a/README.md b/README.md
index afaf2f2..4d2c838 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ and renders a single src element or a picture element depending on the specified
Install the extension using composer: `composer req b13/picture`.
-Include the TypoScript within your main template:
+Include the TypoScript within your main template:
```
@import 'EXT:picture/Configuration/TypoScript/setup.typoscript'
@@ -34,8 +34,9 @@ See `EXT:picture/Configuration/TypoScript/setup.typoscript` for possible configu
| TypoScript Configuration option | Description |
|---------------------------------|-------------|
-| addWebp | Add webp alternative image files as sources. _default: 0_ |
| useRetina | Add retina (2x) version of all images as sizes variants. _default: 0_ |
+| addAvif | Add avif alternative image files as sources. _default: 0_ |
+| addWebp | Add webp alternative image files as sources. _default: 0_ |
| lossless | Enable lossless compression for webp images. _default: 0_ |
| retina | Use custom or multiple multipliers for calculating retina image variants. _default: retina.2 = 2x Only works in combination with `useRetina = 1` |
| breakpoints | Use named breakpoints for easier markup of different image sizes for one picture element. _default: empty_. |
@@ -55,6 +56,11 @@ Our image ViewHelper extends from the Fluid Image ViewHelper, so it has all the
If useRetina is set and not further specified in TypoScript setup, the corresponding `img` tag's or `source` tag’s
attribute `srcset` is extended by a 2x retina version of the image.
+### addAvif
+Adds rendering of additional images in avif format. If it is specified without a given sources attribute, it renders a
+picture tag instead of a single img tag in order to maintain a browser fallback. If it is specified together with
+`sources` it adds an additional `source` tag above any `source` tag rendered by a given `sources` element.
+
### addWebp
Adds rendering of additional images in webp format. If it is specified without a given sources attribute, it renders a
picture tag instead of a single img tag in order to maintain a browser fallback. If it is specified together with
@@ -62,7 +68,7 @@ picture tag instead of a single img tag in order to maintain a browser fallback.
### lossless
Enable lossless compression for webp images. If you find your webp images lacking in quality compared to jpg/png images, enable
-this option to overwrite default settings for ImageMagick/GraphicsMagick.
+this option to overwrite default settings for ImageMagick/GraphicsMagick.
### variants and sizes
Adds multiple variants of an image with different image sizes, optionally add a sizes-attribute to image tags:
@@ -96,7 +102,7 @@ Add a CSS class used for the `picture` element (if rendered using `