Skip to content

Commit

Permalink
Merge pull request #122 from sitegeist/task/imageWithDimensions
Browse files Browse the repository at this point in the history
[FEATURE] Provide image dimensions in data structures
  • Loading branch information
ulrichmathes authored Oct 11, 2024
2 parents 76f978b + 2eed90a commit b02ff69
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 12 deletions.
41 changes: 36 additions & 5 deletions Classes/Domain/Model/FalImage.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@
namespace SMS\FluidComponents\Domain\Model;

use SMS\FluidComponents\Domain\Model\Traits\FalFileTrait;
use SMS\FluidComponents\Interfaces\ImageWithCropVariants;
use SMS\FluidComponents\Interfaces\ImageWithDimensions;
use SMS\FluidComponents\Interfaces\ProcessableImage;
use TYPO3\CMS\Core\Imaging\ImageManipulation\Area;
use TYPO3\CMS\Core\Imaging\ImageManipulation\CropVariantCollection;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Service\ImageService;

/**
* Data structure as a wrapper around a FAL object to be passed to a component.
*/
class FalImage extends Image
class FalImage extends Image implements ImageWithDimensions, ImageWithCropVariants, ProcessableImage
{
use FalFileTrait;

Expand All @@ -27,13 +34,37 @@ public function getCopyright(): ?string
return parent::getCopyright() ?? $this->file->getProperty('copyright');
}

public function getHeight()
public function getHeight(): int
{
return $this->file->getProperty('height');
return (int) $this->file->getProperty('height');
}

public function getWidth()
public function getWidth(): int
{
return $this->file->getProperty('width');
return (int) $this->file->getProperty('width');
}

public function getDefaultCrop(): Area
{
$cropVariantCollection = CropVariantCollection::create((string)$this->file->getProperty('crop'));
return $cropVariantCollection->getCropArea();
}

public function getCropVariant(string $name): Area
{
$cropVariantCollection = CropVariantCollection::create((string)$this->file->getProperty('crop'));
return $cropVariantCollection->getCropArea($name);
}

public function process(int $width, int $height, ?string $format, Area $cropArea): FalImage
{
$imageService = GeneralUtility::makeInstance(ImageService::class);
$processedImage = $imageService->applyProcessingInstructions($this->getFile(), [
'width' => $width,
'height' => $height,
'fileExtension' => $format,
'crop' => ($cropArea->isEmpty()) ? null : $cropArea->makeAbsoluteBasedOnFile($this->getFile())
]);
return new FalImage($processedImage);
}
}
57 changes: 54 additions & 3 deletions Classes/Domain/Model/LocalImage.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@

namespace SMS\FluidComponents\Domain\Model;

use SMS\FluidComponents\Exception\InvalidFilePathException;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use SMS\FluidComponents\Interfaces\ImageWithDimensions;
use SMS\FluidComponents\Exception\InvalidFilePathException;
use SMS\FluidComponents\Interfaces\ProcessableImage;
use TYPO3\CMS\Core\Imaging\GraphicalFunctions;
use TYPO3\CMS\Core\Imaging\ImageManipulation\Area;

/**
* Data structure for a local image resource to be passed to a component.
*
* @deprecated, use FalImage instead
*/
class LocalImage extends Image
class LocalImage extends Image implements ImageWithDimensions, ProcessableImage
{
/**
* Type of image to differentiate implementations in Fluid templates.
Expand All @@ -23,6 +27,16 @@ class LocalImage extends Image
*/
protected string $filePath = '';

/**
* Image width, will be determined at first access
*/
protected int $width = 0;

/**
* Image height, will be determined at first access
*/
protected int $height = 0;

/**
* Creates an image object for a local image resource.
*
Expand Down Expand Up @@ -59,4 +73,41 @@ public function getPublicUrl(): string
{
return PathUtility::getAbsoluteWebPath($this->filePath);
}

public function getHeight(): int
{
if (!isset($this->height)) {
$this->getImageDimensions();
}
return $this->height;
}

public function getWidth(): int
{
if (!isset($this->height)) {
$this->getImageDimensions();
}
return $this->width;
}

protected function getImageDimensions(): void
{
$graphicalFunctions = GeneralUtility::makeInstance(GraphicalFunctions::class);
$imageDimensions = $graphicalFunctions->getImageDimensions($this->getFilePath());
$this->width = (int) $imageDimensions[0];
$this->height = (int) $imageDimensions[1];
}

public function process(int $width, int $height, ?string $format, Area $cropArea): ProcessableImage
{
$imageService = GeneralUtility::makeInstance(ImageService::class);
$file = $imageService->getImage($this->getFilePath(), null, false);
$processedImage = $imageService->applyProcessingInstructions($file, [
'width' => $width,
'height' => $height,
'fileExtension' => $format,
'crop' => ($cropArea->isEmpty()) ? null : $cropArea->makeAbsoluteBasedOnFile($file)
]);
return new FalImage($processedImage);
}
}
30 changes: 27 additions & 3 deletions Classes/Domain/Model/PlaceholderImage.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

namespace SMS\FluidComponents\Domain\Model;

use SMS\FluidComponents\Interfaces\ImageWithDimensions;
use SMS\FluidComponents\Interfaces\ProcessableImage;
use TYPO3\CMS\Core\Imaging\ImageManipulation\Area;

/**
* Data structure for a placeholder image to be passed to a component.
*/
class PlaceholderImage extends Image
class PlaceholderImage extends Image implements ImageWithDimensions, ProcessableImage
{
/**
* Type of image to differentiate implementations in Fluid templates.
Expand All @@ -22,13 +26,19 @@ class PlaceholderImage extends Image
*/
protected int $height = 0;

/**
* Image format of the image
*/
protected string $format = 'gif';

/**
* Creates an image object for a placeholder image.
*/
public function __construct(int $width, int $height)
public function __construct(int $width, int $height, string $format = 'gif')
{
$this->width = $width;
$this->height = $height;
$this->format = $format;
}

public function getWidth(): int
Expand All @@ -41,8 +51,22 @@ public function getHeight(): int
return $this->height;
}

public function getFormat(): string
{
return $this->format;
}

public function getPublicUrl(): string
{
return 'https://via.placeholder.com/' . $this->width . 'x' . $this->height;
return 'https://via.placeholder.com/' . $this->width . 'x' . $this->height . '.' . $this->format;
}

public function process(int $width, int $height, ?string $format, Area $cropArea): ProcessableImage
{
return new PlaceholderImage(
(int) round($cropArea->getWidth() * $width),
(int) round($cropArea->getHeight() * $height),
$format ?: $this->format
);
}
}
11 changes: 11 additions & 0 deletions Classes/Interfaces/ImageWithCropVariants.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace SMS\FluidComponents\Interfaces;

use TYPO3\CMS\Core\Imaging\ImageManipulation\Area;

interface ImageWithCropVariants
{
public function getDefaultCrop(): Area;
public function getCropVariant(string $name): Area;
}
9 changes: 9 additions & 0 deletions Classes/Interfaces/ImageWithDimensions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace SMS\FluidComponents\Interfaces;

interface ImageWithDimensions
{
public function getHeight(): int;
public function getWidth(): int;
}
10 changes: 10 additions & 0 deletions Classes/Interfaces/ProcessableImage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace SMS\FluidComponents\Interfaces;

use TYPO3\CMS\Core\Imaging\ImageManipulation\Area;

interface ProcessableImage
{
public function process(int $width, int $height, ?string $format, Area $cropArea): ProcessableImage;
}
2 changes: 1 addition & 1 deletion Classes/Utility/ComponentArgumentConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public function canTypeBeConvertedToType(string $givenType, string $toType): arr
// Check if the target type implements the constructor interface
// required for conversion
$conversionInfo = [];
if (isset($this->conversionInterfaces[$givenType][0]) &&
if (isset($this->conversionInterfaces[$givenType]) &&
is_subclass_of($toType, $this->conversionInterfaces[$givenType][0])
) {
$conversionInfo = $this->conversionInterfaces[$givenType];
Expand Down

0 comments on commit b02ff69

Please sign in to comment.