Skip to content

Commit

Permalink
Merge pull request #14 from kdambekalns/feature/variant-preset-support
Browse files Browse the repository at this point in the history
!!! FEATURE: Variant preset support
  • Loading branch information
mficzel authored Oct 29, 2019
2 parents 204d7f9 + 30dfee3 commit cbf0e6d
Show file tree
Hide file tree
Showing 12 changed files with 325 additions and 80 deletions.
43 changes: 20 additions & 23 deletions Classes/Controller/DummyImageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@
use Imagine\Image\Palette\Color\ColorInterface;
use Imagine\Image\Point;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Log\Utility\LogEnvironment;
use Neos\Flow\Mvc\Controller\ActionController;
use Neos\Flow\Package\Exception\UnknownPackageException;
use Neos\Flow\Package\PackageManager;
use Neos\Flow\ResourceManagement\ResourceManager;
use Psr\Log\LoggerInterface;

class DummyImageController extends ActionController
{
Expand All @@ -34,6 +37,12 @@ class DummyImageController extends ActionController
*/
protected $packageManager;

/**
* @Flow\Inject
* @var LoggerInterface
*/
protected $logger;

/**
* Get a dummy-image
*
Expand All @@ -45,36 +54,25 @@ class DummyImageController extends ActionController
* @param string $f
* @return string
*/
public function imageAction (int $w = 600, int $h = 400, string $bg = '#000', string $fg = '#fff', string $t = null, string $f = 'png'): string
public function imageAction(int $w = 600, int $h = 400, string $bg = '#000', string $fg = '#fff', string $t = null, string $f = 'png'): string
{
// limit input arguments
if ($w > 9999) {
$w = 9999;
} elseif ($w < 10) {
$w = 10;
}

if ($h > 9999) {
$h = 9999;
}

// limit input arguments
if ($w < 10) {
$w = 10;
}

if ($h < 10) {
} elseif ($h < 10) {
$h = 10;
}

if ($t === null) {
$t = (string)$w . ' x ' . (string)$h;
}

$width = $w;
$height = $h;
$text = $t;

try {
// create imagine
$palette = new Palette\RGB();
$backgroundColor = $palette->color($bg);
$foregroundColor = $palette->color($fg);
Expand All @@ -84,14 +82,9 @@ public function imageAction (int $w = 600, int $h = 400, string $bg = '#000', st
$image = $this->imagineService->create($imageBox);
$image->usePalette($palette);

// render border
$renderBorder = ($width >= 70 && $height >= 70);

// render shape
$renderShape = ($width >= 200 && $height >= 100);

$renderText = ($width >= 50 && $height >= 30);

$renderPattern = ($width >= 20 && $height >= 20);

$this->renderBackground($image, $foregroundColor, $backgroundColor, $width, $height);
Expand All @@ -104,7 +97,8 @@ public function imageAction (int $w = 600, int $h = 400, string $bg = '#000', st
$this->renderBorder($image, $foregroundColor, $backgroundColor, $width, $height);
}

if ($t && $renderText) {
if ($renderText) {
$text = trim((string)$t) ?: sprintf('%s x %s', $width, $height);
$this->renderText($image, $foregroundColor, $width, $height, $text, $renderShape ? false : true);
}

Expand All @@ -115,14 +109,16 @@ public function imageAction (int $w = 600, int $h = 400, string $bg = '#000', st
// render image
$result = $image->get($f);
if (!$result) {
throw new \Exception('Something went wrong without throwing an exception');
throw new \RuntimeException('Something went wrong without throwing an exception');
}

// build result
$this->response->setHeader('Cache-Control', 'max-age=883000000');
$this->response->setHeader('Content-type', 'image/' . $f);
return $result;
} catch (\Exception $e) {
} catch (\Exception $exception) {
$this->logger->error($exception->getMessage(), LogEnvironment::fromMethodName(__METHOD__));

// something went wrong we return the error image png
$this->response->setStatusCode(500);
$this->response->setHeader('Content-type', 'image/png');
Expand Down Expand Up @@ -250,6 +246,7 @@ protected function renderBorder(ImageInterface $image, ColorInterface $foregroun
* @param int $height
* @param string $text
* @param bool $center
* @throws UnknownPackageException
*/
protected function renderText(ImageInterface $image, ColorInterface $textColor, int $width, int $height, string $text, bool $center = false): void
{
Expand Down
65 changes: 58 additions & 7 deletions Classes/EelHelpers/AbstractImageSourceHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
namespace Sitegeist\Kaleidoscope\EelHelpers;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Log\Utility\LogEnvironment;
use Neos\Utility\Arrays;
use Psr\Log\LoggerInterface;

/**
* Class AbstractImageSourceHelper
Expand All @@ -28,12 +30,29 @@ abstract class AbstractImageSourceHelper implements ImageSourceHelperInterface
*/
protected $targetFormat;

/**
* @var array
*/
protected $targetImageVariant = [];

/**
* @Flow\Inject
* @var LoggerInterface
*/
protected $logger;

/**
* @var array
* @Flow\InjectConfiguration(path="thumbnailPresets", package="Neos.Media")
*/
protected $thumbnailPresets;

/**
* @var array
* @Flow\InjectConfiguration(path="variantPresets", package="Neos.Media")
*/
protected $variantPresets;

/**
* @param int|null $targetWidth
* @param bool $preserveAspect
Expand Down Expand Up @@ -83,30 +102,62 @@ public function setDimensions(int $targetWidth = null, int $targetHeight = null)
}

/**
* Apply definitions from a preset to this image source
* DEPRECATED Apply definitions from a thumbnail preset to this image source
*
* @param string $name
* @deprecated use applyThumbnailPreset
* @return ImageSourceHelperInterface
*/
public function applyPreset(string $name): ImageSourceHelperInterface
{
return $this->applyThumbnailPreset($name);
}

/**
* Apply definitions from a thumbnail preset to this image source
*
* @param string $name
* @return ImageSourceHelperInterface
*/
public function applyThumbnailPreset(string $name): ImageSourceHelperInterface
{
$newSource = clone $this;
if ($this->thumbnailPresets && isset($this->thumbnailPresets[$name])) {
if (isset($this->thumbnailPresets[$name])) {
$preset = $this->thumbnailPresets[$name];
if ($width = $preset['width'] ?? null) {
$newSource->setWidth($width);
$newSource = $newSource->setWidth($width);
} elseif ($width = $preset['maximumWidth'] ?? null) {
$newSource->setWidth($width);
$newSource = $newSource->setWidth($width);
}
if ($height = $preset['height'] ?? null) {
$newSource->setHeight($height);
$newSource = $newSource->setHeight($height);
} elseif ($height = $preset['maximumHeight'] ?? null) {
$newSource->setHeight($height);
$newSource = $newSource->setHeight($height);
}
} else {
$this->logger->warning(sprintf('Thumbnail preset "%s" is not configured', $name), LogEnvironment::fromMethodName(__METHOD__));
}
return $newSource;
}

/**
* Use the variant generated from the given variant preset in this image source
*
* @param string $presetIdentifier
* @param string $presetVariantName
* @return ImageSourceHelperInterface
*/
public function useVariantPreset(string $presetIdentifier, string $presetVariantName): ImageSourceHelperInterface
{
if (!isset($this->variantPresets[$presetIdentifier]['variants'][$presetVariantName])) {
$this->logger->warning(sprintf('Variant "%s" of preset "%s" is not configured', $presetVariantName, $presetIdentifier), LogEnvironment::fromMethodName(__METHOD__));
}

$newSource = clone $this;
$newSource->targetImageVariant = ['presetIdentifier' => $presetIdentifier, 'presetVariantName' => $presetVariantName];
return $newSource;
}

/**
* Render sourceset Attribute for various media descriptors
*
Expand Down Expand Up @@ -150,7 +201,7 @@ public function srcset($mediaDescriptors): string
*/
public function allowsCallOfMethod($methodName)
{
if (in_array($methodName, ['setWidth', 'setHeight', 'setDimensions', 'setFormat', 'applyPreset', 'src', 'srcset'])) {
if (in_array($methodName, ['setWidth', 'setHeight', 'setDimensions', 'setFormat', 'applyPreset', 'applyThumbnailPreset', 'useVariantPreset', 'src', 'srcset'])) {
return true;
}

Expand Down
86 changes: 86 additions & 0 deletions Classes/EelHelpers/AbstractScalableImageSourceHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,24 @@

namespace Sitegeist\Kaleidoscope\EelHelpers;

use Imagine\Image\Box;
use Imagine\Image\ImagineInterface;
use Neos\Flow\Annotations as Flow;
use Neos\Media\Domain\ValueObject\Configuration\VariantPreset;
use Neos\Media\Domain\Model\Adjustment\ImageAdjustmentInterface;
use Neos\Media\Domain\Model\Adjustment\ResizeImageAdjustment;
use Neos\Media\Domain\Model\Adjustment\CropImageAdjustment;
use Neos\Media\Domain\ValueObject\Configuration\Adjustment;
use Neos\Utility\ObjectAccess;

abstract class AbstractScalableImageSourceHelper extends AbstractImageSourceHelper implements ScalableImageSourceHelperInterface
{
/**
* @var ImagineInterface
* @Flow\Inject
*/
protected $imagineService;

/**
* @var int
*/
Expand Down Expand Up @@ -100,4 +116,74 @@ public function getCurrentHeight(): int
return $this->baseHeight;
}

/**
* @param string $presetIdentifier
* @param string $presetVariantName
* @return Box
*/
protected function estimateDimensionsFromVariantPresetAdjustments(string $presetIdentifier, string $presetVariantName): Box
{
$imageBox = new Box(
$this->baseWidth,
$this->baseHeight
);

$assetVariantPreset = VariantPreset::fromConfiguration($this->variantPresets[$presetIdentifier]);
foreach ($assetVariantPreset->variants()[$presetVariantName]->adjustments() as $adjustmentConfiguration) {
$adjustment = $this->createAdjustment($adjustmentConfiguration);

switch (true) {
case ($adjustment instanceof ResizeImageAdjustment):
$image = $this->imagineService->create($imageBox);
if ($adjustment->canBeApplied($image)) {
$image = $adjustment->applyToImage($image);
return new Box(
(int)round($image->getSize()->getWidth()),
(int)round($image->getSize()->getHeight())
);
}
break;
case ($adjustment instanceof CropImageAdjustment):
$desiredAspectRatio = $adjustment->getAspectRatio();
if ($desiredAspectRatio !== null) {
[, , $newWidth, $newHeight] = CropImageAdjustment::calculateDimensionsByAspectRatio($this->baseWidth, $this->baseHeight, $desiredAspectRatio);
} else {
$newWidth = $adjustment->getWidth();
$newHeight = $adjustment->getHeight();
}
return new Box(
(int)round($newWidth),
(int)round($newHeight)
);
break;
}
}

return $imageBox;
}

/**
* @param Adjustment $adjustmentConfiguration
* @return ImageAdjustmentInterface
*/
protected function createAdjustment(Adjustment $adjustmentConfiguration): ImageAdjustmentInterface
{
$adjustmentClassName = $adjustmentConfiguration->type();
if (!class_exists($adjustmentClassName)) {
throw new \RuntimeException(sprintf('Unknown image variant adjustment type "%s".', $adjustmentClassName), 1568213194);
}
$adjustment = new $adjustmentClassName();
if (!$adjustment instanceof ImageAdjustmentInterface) {
throw new \RuntimeException(sprintf('Image variant adjustment "%s" does not implement "%s".', $adjustmentClassName, ImageAdjustmentInterface::class), 1568213198);
}
foreach ($adjustmentConfiguration->options() as $key => $value) {
ObjectAccess::setProperty($adjustment, $key, $value);
}

if (!$adjustment instanceof ImageAdjustmentInterface) {
throw new \RuntimeException(sprintf('Could not apply the %s adjustment to image because it does not implement the ImageAdjustmentInterface.', get_class($adjustment)), 1381400362);
}

return $adjustment;
}
}
Loading

0 comments on commit cbf0e6d

Please sign in to comment.