Skip to content

Commit

Permalink
Merge pull request #2 from sitegeist/feature/integrateCustomDummyImag…
Browse files Browse the repository at this point in the history
…eService

Feature: Integrate custom dummy image service
  • Loading branch information
mficzel committed Jul 16, 2018
2 parents 15786f0 + 5698ff3 commit a98b8dc
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 15 deletions.
170 changes: 170 additions & 0 deletions Classes/Controller/DummyImageController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<?php
namespace Sitegeist\Kaleidoscope\Controller;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Package\PackageManagerInterface;
use Neos\Flow\ResourceManagement\ResourceManager;
use Neos\Flow\Mvc\Controller\ActionController;

use Imagine\Image\ImagineInterface;
use Imagine\Image\ImageInterface;
use Imagine\Image\Palette\Color\ColorInterface;
use Imagine\Image\Palette;
use Imagine\Image\Box;
use Imagine\Image\Point;

class DummyImageController extends ActionController
{
/**
* @var ImagineInterface
* @Flow\Inject
*/
protected $imagineService;

/**
* @var ResourceManager
* @Flow\Inject
*/
protected $resourceManager;

/**
* @var PackageManagerInterface
* @Flow\Inject
*/
protected $packageManager;

/**
* Get a dummy-image
*
* @param int $width
* @param int $height
* @param string $backgroundColor
* @param string $foregroundColor
* @param string $text
*/
public function imageAction (int $width = 600, int $height = 400, string $backgroundColor = '#000', string $foregroundColor = '#fff', string $text = null)
{
// limit input arguments
if ($width > 9999 || $height > 9999 ) {
$width = 9999;
}

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

if (is_null($text)) {
$text = (string)$width . ' x ' . (string)$height;
}

// create imagine
$palette = new Palette\RGB();
$bgColor = $palette->color($backgroundColor);
$textColor = $palette->color($foregroundColor);

// create image
$imageBox = new Box($width, $height);
$image = $this->imagineService->create($imageBox, $bgColor);

// render shape
$this->renderShape($image, $textColor, $width, $height);

// render text
if ($text) {
$this->renderText($image, $textColor, $width, $height, $text);
}

// build result
$this->response->setHeader( 'Cache-Control', 'max-age=883000000');
$this->response->setHeader( 'Content-type', 'image/png');
return $image->get('png');
}

/**
* @param ImageInterface $image
* @param ColorInterface $color
* @param int $width
* @param int $height
*/
protected function renderShape(ImageInterface $image, ColorInterface $color, int $width, int $height): void
{
$imageAspectRatio = $width / $height;
$baseShapeWidth = 600;
$baseShapeHeight = 400;
$baseShapeAspectRatio = $baseShapeWidth / $baseShapeHeight;

$baseShape = [
new Point(15, 250), // left ground
new Point(15, 15), // left top
new Point(585, 15), // right top
new Point(585, 250), // right ground
new Point(580, 250),

new Point(440, 110), // small mountain
new Point(360, 190), // saddle
new Point(220, 50), // big mountain

new Point(20, 250),
];

// transform shape to center of the image
$factor = ($imageAspectRatio > $baseShapeAspectRatio) ? (float)$height / (float)$baseShapeHeight : (float)$width / (float)$baseShapeWidth;
$xoffset = ($imageAspectRatio > $baseShapeAspectRatio) ? ($width - ($baseShapeWidth * $factor)) / 2.0 : 0.0;
$yoffset = ($imageAspectRatio < $baseShapeAspectRatio) ? ($height - ($baseShapeHeight * $factor)) / 2.0 : 0.0;
$transformedShape = array_map(
function (Point $point) use ($factor, $xoffset, $yoffset) {
return new Point($point->getX() * $factor + $xoffset, $point->getY() * $factor + $yoffset);
},
$baseShape
);

// adjust some points based on aspect ratio
if ($imageAspectRatio < $baseShapeAspectRatio) {
$transformedShape[1] = new Point($transformedShape[1]->getX(), $baseShape[1]->getY() * $factor);
$transformedShape[2] = new Point($transformedShape[2]->getX(), $baseShape[2]->getY() * $factor);
} else {
$transformedShape[0] = new Point($baseShape[0]->getX() * $factor, $transformedShape[0]->getY());
$transformedShape[1] = new Point($baseShape[0]->getX() * $factor, $transformedShape[1]->getY());
$transformedShape[2] = new Point($width - $baseShape[0]->getX() * $factor, $transformedShape[2]->getY());
$transformedShape[3] = new Point($width - $baseShape[0]->getX() * $factor, $transformedShape[3]->getY());
}

// finally draw image
$image->draw()->polygon(
$transformedShape,
$color,
true,
1
);
}

/**
* @param ImageInterface $image
* @param ColorInterface $textColor
* @param int $width
* @param int $height
* @param string $text
*/
protected function renderText(ImageInterface $image, ColorInterface $textColor, int $width, int $height, string $text): void
{
$initialFontSize = 10;
$fontFile = $this->packageManager->getPackage('Neos.Neos')->getPackagePath() . "Resources/Public/Fonts/NotoSans/NotoSans-Regular.ttf";
$initialFont = $this->imagineService->font($fontFile, $initialFontSize, $textColor);

// scale text to fit the image
$initialFontBox = $initialFont->box($text);
$targetFontWidth = $width * .5;
$targetFontHeight = $height * .3;
$correctedFontSizeByWidth = $targetFontWidth * $initialFontSize / $initialFontBox->getWidth();
$correctedFontSizeByHeight = $targetFontHeight * $initialFontSize / $initialFontBox->getHeight();

// render actual text
$actualFont = $this->imagineService->font($fontFile, min([$correctedFontSizeByWidth, $correctedFontSizeByHeight]), $textColor);
$actualFontBox = $actualFont->box($text);
$imageCenterPosition = new Point($width / 2 , $height / 2);
$textCenterPosition = new Point\Center($actualFontBox);
$centeredTextPosition = new Point($imageCenterPosition->getX() - $textCenterPosition->getX(), ($height * .73 - $actualFontBox->getHeight() * .5));
$image->draw()->text($text, $actualFont, $centeredTextPosition);
}

}
31 changes: 20 additions & 11 deletions Classes/EelHelpers/DummyImageSourceHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ class DummyImageSourceHelper extends AbstractImageSourceHelper implements Scalab

protected $text = null;

protected $baseUri = '';

/**
* @param ControllerContext $controllerContext
*/
public function __construct(string $baseUri)
{
$this->baseUri = $baseUri;
}

/**
* @param int $baseWidth
*/
Expand Down Expand Up @@ -73,17 +83,16 @@ public function scale(float $factor): ImageSourceHelperInterface

public function src(): string
{
$url = 'https://dummyimage.com';

$url .= '/' . $this->getWidth() . 'x' . $this->getHeight();
$url .= '/' . ($this->backgroundColor ?: '000');
$url .= '/' . ($this->foregroundColor ?: 'fff');

if ($this->text) {
$url .= '&text=' . urlencode($this->text);
}

return $url;
$uri = $this->baseUri . '?' . http_build_query (
[
'width' => $this->getWidth(),
'height' => $this->getHeight(),
'backgroundColor' => ($this->backgroundColor ?: '000'),
'foregroundColor' => ($this->foregroundColor ?: 'fff'),
'text' => ($this->text ?: $this->getWidth() . ' x ' . $this->getHeight())
]
);
return $uri;
}

public function getWidth() : int
Expand Down
5 changes: 4 additions & 1 deletion Classes/FusionObjects/DummyImageSourceImplementation.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ public function getText()
*/
public function createHelper() : ImageSourceHelperInterface
{
$helper = new DummyImageSourceHelper();
$uriBuilder = $this->runtime->getControllerContext()->getUriBuilder()->reset()->setCreateAbsoluteUri(true);
$baseUri = $uriBuilder->uriFor('image', [], 'DummyImage', 'Sitegeist.Kaleidoscope');

$helper = new DummyImageSourceHelper($baseUri);

if ($baseWidth = $this->getBaseWidth()) {
$helper->setBaseWidth($baseWidth);
Expand Down
5 changes: 5 additions & 0 deletions Configuration/Objects.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Sitegeist\Kaleidoscope\Controller\DummyImageController:
properties:
imagineService:
object:
factoryObjectName: Neos\Imagine\ImagineFactory
11 changes: 11 additions & 0 deletions Configuration/Policy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
privilegeTargets:
'Neos\Flow\Security\Authorization\Privilege\Method\MethodPrivilege':
'Sitegeist.Kaleidoscope:DummyImage':
matcher: 'method(Sitegeist\Kaleidoscope\Controller\DummyImageController->(image)Action())'

roles:
'Neos.Flow:Everybody':
privileges:
-
privilegeTarget: 'Sitegeist.Kaleidoscope:DummyImage'
permission: GRANT
12 changes: 12 additions & 0 deletions Configuration/Routes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
##
# Kaleidoscope-DummyImage

-
name: 'Kaleidoscope-DummyImage'
uriPattern: 'kaleidoscope/dummyimage'
defaults:
'@package': 'Sitegeist.Kaleidoscope'
'@controller': 'DummyImage'
'@action': 'image'
httpMethods: ['GET']
appendExceedingArguments: TRUE
6 changes: 6 additions & 0 deletions Configuration/Settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ Neos:
fusion:
autoInclude:
Sitegeist.Kaleidoscope: true

Flow:
mvc:
routes:
'Sitegeist.Kaleidoscope':
position: 'before Neos.Neos'
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ We want to help implementing responsive-images in the context of atomic-fusion
and enable previewing fusion-components and their full responsive behavior in the
Sitegeist.Monocle living styleguide.

Sitegeist.Kaleidoscope comes with Fusion-ImageSources for Assets, DummyImages, Resources
and static Uris.
Sitegeist.Kaleidoscope comes with four Fusion-ImageSources:

- Assets: Images uploaded by Editors
- DummyImages: Dummyimages created by a local service
- Resources: Static resources from Packages
- static Uris: any Url

### Authors & Sponsors

Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"require": {
"neos/flow": "*",
"neos/fusion-afx": "*",
"neos/media": "*"
"neos/media": "*",
"neos/imagine": "*"
},
"autoload": {
"psr-4": {
Expand Down

0 comments on commit a98b8dc

Please sign in to comment.