diff --git a/Classes/Domain/AbstractImageSource.php b/Classes/Domain/AbstractImageSource.php index 026178b..5dcf31f 100644 --- a/Classes/Domain/AbstractImageSource.php +++ b/Classes/Domain/AbstractImageSource.php @@ -25,6 +25,11 @@ abstract class AbstractImageSource implements ImageSourceInterface, ProtectedCon */ protected $targetHeight; + /** + * @var int|null + */ + protected $targetQuality; + /** * @var string|null */ @@ -104,6 +109,22 @@ public function withHeight(int $targetHeight, bool $preserveAspect = false): Ima return $newSource; } + /** + * @deprecated + */ + public function setQuality(int $quality): ImageSourceInterface + { + return $this->withQuality($quality); + } + + public function withQuality(int $quality): ImageSourceInterface + { + $newSource = clone $this; + $newSource->targetQuality = $quality; + + return $newSource; + } + /** * @deprecated */ @@ -277,6 +298,7 @@ public function allowsCallOfMethod($methodName) 'withTitle', 'withDimensions', 'withFormat', + 'withQuality', 'withWidth', 'withHeight', 'withThumbnailPreset', @@ -286,6 +308,7 @@ public function allowsCallOfMethod($methodName) 'setHeight', 'setDimensions', 'setFormat', + 'setQuality', 'applyPreset', 'applyThumbnailPreset', 'useVariantPreset', diff --git a/Classes/Domain/AssetImageSource.php b/Classes/Domain/AssetImageSource.php index 9a0ce68..411fec9 100644 --- a/Classes/Domain/AssetImageSource.php +++ b/Classes/Domain/AssetImageSource.php @@ -45,6 +45,13 @@ class AssetImageSource extends AbstractScalableImageSource */ protected $request; + /** + * Runtime cache for the src uri for the asset. + * + * @var string|null + */ + private $srcCache = null; + /** * @param ImageInterface $asset * @param string|null $title @@ -112,6 +119,10 @@ public function src(): string return ''; } + if ($this->srcCache !== null) { + return $this->srcCache; + } + $width = $this->getCurrentWidth(); $height = $this->getCurrentHeight(); @@ -126,7 +137,7 @@ public function src(): string $allowCropping, $allowUpScaling, $async, - null, + $this->targetQuality, $this->targetFormat ); @@ -136,11 +147,14 @@ public function src(): string $this->request ); - if ($thumbnailData === null) { - return ''; - } + $this->srcCache = ($thumbnailData === null) ? '' : $thumbnailData['src']; - return $thumbnailData['src']; + return $this->srcCache; + } + + public function __clone(): void + { + $this->srcCache = null; } public function dataSrc(): string @@ -163,7 +177,7 @@ public function dataSrc(): string $allowCropping, $allowUpScaling, $async, - null, + $this->targetQuality, $this->targetFormat ); diff --git a/Classes/Domain/ImageSourceInterface.php b/Classes/Domain/ImageSourceInterface.php index 9a8c45d..9a2c4f3 100644 --- a/Classes/Domain/ImageSourceInterface.php +++ b/Classes/Domain/ImageSourceInterface.php @@ -19,6 +19,8 @@ public function withWidth(int $targetWidth, bool $preserveAspect = false): Image public function withHeight(int $targetHeight, bool $preserveAspect = false): ImageSourceInterface; + public function withQuality(int $targetQuality): ImageSourceInterface; + public function withThumbnailPreset(string $format): ImageSourceInterface; public function withVariantPreset(string $presetIdentifier, string $presetVariantName): ImageSourceInterface; diff --git a/Classes/EelHelpers/ImageSourceHelperInterface.php b/Classes/EelHelpers/ImageSourceHelperInterface.php index 92162b9..acc23ed 100644 --- a/Classes/EelHelpers/ImageSourceHelperInterface.php +++ b/Classes/EelHelpers/ImageSourceHelperInterface.php @@ -28,6 +28,11 @@ public function setHeight(int $height, bool $preserveAspect = false): ImageSourc */ public function setDimensions(int $width, int $height): ImageSourceInterface; + /** + * @deprecated use withQuality + */ + public function setQuality(int $quality): ImageSourceInterface; + /** * @deprecated use withFormat */ diff --git a/Classes/FusionObjects/AbstractImageSourceImplementation.php b/Classes/FusionObjects/AbstractImageSourceImplementation.php index 567b9f1..d19c882 100644 --- a/Classes/FusionObjects/AbstractImageSourceImplementation.php +++ b/Classes/FusionObjects/AbstractImageSourceImplementation.php @@ -25,6 +25,14 @@ public function getHeight(): ?int return $this->fusionValue('height'); } + /** + * @return int|null + */ + public function getQuality(): ?int + { + return $this->fusionValue('quality'); + } + /** * @return string|null */ @@ -94,6 +102,10 @@ public function evaluate(): ?ImageSourceInterface $helper = $helper->withHeight($height); } + if ($quality = $this->getQuality()) { + $helper = $helper->withQuality($quality); + } + if ($format = $this->getFormat()) { $helper = $helper->withFormat($format); } diff --git a/README.md b/README.md index 4c1e3ff..812d584 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ Props: - `sizes`: sizes attribute of the default image (string ot array) - `loading`: (optional, default "lazy") loading attribute for the img tag - `format`: (optional) the image-format like `webp` or `png`, will be applied to the `imageSource` +- `quality`: (optional) the image quality from 0 to 100, will be applied to the `imageSource` - `width`: (optional) the base width, will be applied to the `imageSource` - `height`: (optional) the base height, will be applied to the `imageSource` - `alt`: alt-attribute for the img tag (default "") @@ -136,11 +137,13 @@ Props: - `media`: (optional) the media attribute for this source - `type`: (optional) the type attribute for this source - `format`: (optional) the image-format for the source like `webp` or `png`, is applied to `imageSource` and `type` + - `quality`: (optional) the image quality from 0 to 100, will be applied to the `imageSource` - `width`: (optional) the base width, will be applied to the `imageSource` - `height`: (optional) the base height, will be applied to the `imageSource` - `srcset`: media descriptors like '1.5x' or '600w' of the default image (string ot array) - `sizes`: sizes attribute of the default image (string ot array) - `formats`: (optional) image formats that will be rendered as sources of separate type (string or array) +- `quality`: (optional) the image quality from 0 to 100, will be applied to the `imageSource` - `width`: (optional) the base width, will be applied to the `imageSource` - `height`: (optional) the base height, will be applied to the `imageSource` - `loading`: (optional, default "lazy") loading attribute for the img tag @@ -212,6 +215,7 @@ Props: - `srcset`: media descriptors like '1.5x' or '600w' of the default image (string ot array, inherited from picture) - `sizes`: (optional) sizes attribute (string or array, inherited from picture) - `format`: (optional) the image-format like `webp` or `png`, will be applied to `imageSource` and `type` +- `quality`: (optional) the image quality from 0 to 100, will be applied to the `imageSource` - `width`: (optional) the base width, will be applied to the `imageSource` - `height`: (optional) the base height, will be applied to the `imageSource` - `type`: (optional) the type attribute for the source like `image/png` or `image/webp`, the actual format is enforced via `imageSource.withFormat()` @@ -307,6 +311,7 @@ Arguments: - `thumbnailPreset`: `width` and `height` are supported as explained above - `variantPreset`: as explained above - `format`: Set the image output format, like webp (default null) +- `quality`: Set the image quality from 0 to 100 (default null) - `alt`: The alt attribute if not specified otherwise (default null) - `title`: The title attribute if not specified otherwise (default null) @@ -355,6 +360,7 @@ Methods of ImageSource-Helpers that are accessible via Eel: - `withThumbnailPreset( string )`: Set width and/or height via named thumbnail preset from Settings `Neos.Media.thumbnailPresets` - `withVariantPreset( string, string )`: Select image variant via the named variant preset (parameters are "preset identifier" key and "preset variant name" key from Settings `Neos.Media.variantPresets`) - `withFormat( string )`: Set the image format to generate like `webp`, `png` or `jpeg` +- `withQuality( integer )`: Set the image quality from 0 to 100 - `withAlt( ?string )`: Set the alt atttribute for the image tag - `withTitle( ?string )`: Set the title atttribute for the image tag @@ -373,6 +379,7 @@ deprecated methods: - `setHeight( integer $height, bool $preserveAspect = false )`: Set the intended height - `setDimensions( integer, interger)`: Set the intended width and height - `setFormat( string )`: Set the image format to generate like `webp`, `png` or `jpeg` +- `setQuality( integer )`: Set the image quality from 0 to 100 Note: The Eel-helpers cannot be created directly. They have to be created by using the `Sitegeist.Kaleidoscope:AssetImageSource` or diff --git a/Resources/Private/Fusion/Prototypes/AssetImageSource.fusion b/Resources/Private/Fusion/Prototypes/AssetImageSource.fusion index a27ab3b..3bdfa47 100644 --- a/Resources/Private/Fusion/Prototypes/AssetImageSource.fusion +++ b/Resources/Private/Fusion/Prototypes/AssetImageSource.fusion @@ -8,4 +8,5 @@ prototype(Sitegeist.Kaleidoscope:AssetImageSource) { width = null height = null format = null + quality = null } diff --git a/Resources/Private/Fusion/Prototypes/Image.fusion b/Resources/Private/Fusion/Prototypes/Image.fusion index 3e9e7f1..c157b20 100644 --- a/Resources/Private/Fusion/Prototypes/Image.fusion +++ b/Resources/Private/Fusion/Prototypes/Image.fusion @@ -124,6 +124,7 @@ prototype(Sitegeist.Kaleidoscope:Image) < prototype(Neos.Fusion:Component) { width = null height = null format = null + quality = null attributes = Neos.Fusion:DataStructure renderDimensionAttributes = true allowSrcsetUpScaling = false @@ -139,6 +140,7 @@ prototype(Sitegeist.Kaleidoscope:Image) < prototype(Neos.Fusion:Component) { imageSource.@process.applyWidth = ${(props.width && !props.height) ? value.withWidth(props.width, props.preserveAspect) : value} imageSource.@process.applyHeight = ${(props.height && !props.width) ? value.withHeight(props.height, props.preserveAspect) : value} imageSource.@process.applyFormat = ${props.format ? value.withFormat(props.format) : value} + imageSource.@process.applyQuality = ${props.quality ? value.withQuality(props.quality) : value} srcset = ${props.srcset} sizes = ${props.sizes} diff --git a/Resources/Private/Fusion/Prototypes/Picture.fusion b/Resources/Private/Fusion/Prototypes/Picture.fusion index a678adc..8ef380d 100644 --- a/Resources/Private/Fusion/Prototypes/Picture.fusion +++ b/Resources/Private/Fusion/Prototypes/Picture.fusion @@ -54,6 +54,7 @@ prototype(Sitegeist.Kaleidoscope:Picture) < prototype(Neos.Fusion:Component) { loading = 'lazy' sources = null formats = null + quality = null width = null height = null alt = '' @@ -78,6 +79,7 @@ prototype(Sitegeist.Kaleidoscope:Picture) < prototype(Neos.Fusion:Component) { __width = ${this.width} __height = ${this.height} __format = ${this.format} + __quality = ${this.quality} } renderer = Neos.Fusion:Component { @@ -89,6 +91,7 @@ prototype(Sitegeist.Kaleidoscope:Picture) < prototype(Neos.Fusion:Component) { imageSource.@process.applyWidth = ${(props.width && !props.height) ? value.withWidth(props.width, props.preserveAspect) : value} imageSource.@process.applyHeight = ${(props.height && !props.width) ? value.withHeight(props.height, props.preserveAspect) : value} imageSource.@process.applyFormat = ${props.format ? value.withFormat(props.format) : value} + imageSource.@process.applyQuality = ${props.quality ? value.setQuality(props.quality) : value} srcset = ${props.srcset} sizes = ${props.sizes} @@ -116,6 +119,7 @@ prototype(Sitegeist.Kaleidoscope:Picture) < prototype(Neos.Fusion:Component) { format={source.format} width={source.width} height={source.height} + quality={source.quality} srcset={source.srcset ? source.srcset : props.srcset} sizes={source.sizes ? source.sizes : props.sizes} renderDimensionAttributes={props.renderDimensionAttributes} diff --git a/Resources/Private/Fusion/Prototypes/Source.fusion b/Resources/Private/Fusion/Prototypes/Source.fusion index 0fba9c5..7560058 100644 --- a/Resources/Private/Fusion/Prototypes/Source.fusion +++ b/Resources/Private/Fusion/Prototypes/Source.fusion @@ -10,6 +10,7 @@ prototype(Sitegeist.Kaleidoscope:Source) < prototype(Neos.Fusion:Component) { width = null height = null format = null + quality = null type = null media = null renderDimensionAttributes = true @@ -21,6 +22,7 @@ prototype(Sitegeist.Kaleidoscope:Source) < prototype(Neos.Fusion:Component) { @context { imageSource = ${props.imageSource || __imageSource} format = ${props.format || __format} + quality = ${props.quality || __quality} width = ${props.width || __width} height = ${props.height || __height} srcset = ${props.srcset || __srcset} @@ -35,6 +37,7 @@ prototype(Sitegeist.Kaleidoscope:Source) < prototype(Neos.Fusion:Component) { imageSource.@process.applyWidth = ${(props.width && !props.height) ? value.withWidth(props.width, props.preserveAspect) : value} imageSource.@process.applyHeight = ${(props.height && !props.width) ? value.withHeight(props.height, props.preserveAspect) : value} imageSource.@process.applyFormat = ${props.format ? value.withFormat(props.format) : value} + imageSource.@process.applyQuality = ${quality ? value.withQuality(quality) : value} type = ${format ? 'image/' + format : props.type} srcset = ${srcset}