Building a TYPO3 extension in Extbase/Fluid

ViewHelper returning image width and height

Another one of those oddities in TYPO3: you cannot access the width and height of an image in a Fluid template. Which is fine as long as you want to write an <img> tag for which a Fluid ViewHelper exists. But what if you need width and height of an image in another context, e.g. in data-Attributes in a div?

Here’s the image data available in your Fluid templates by default:

filename:    {imageRefField.originalResource.name}
filepath:    {imageRefField.originalResource.publicUrl} // relative to root, with no leading slash, e.g. “fileadmin/images/my-image.jpg”
title:       {imageRefField.originalResource.title}
description: {imageRefField.originalResource.description}
alt:         {imageRefField.originalResource.alternative}
alt:         {imageRefField.originalResource.alternative}

Title, description, and alternative automatically show either the data stored with the original file or the overwritten value stored with the file reference.

imageRefField is the name of the property of your domain model that stores the reference to the image.


ViewHelper and Template Code

File paths are relative to the root of your extension /typo3conf/ext/your_extension/

/Classes/ViewHelpers/ImageDataViewHelper.php

<?php
namespace VendorName\YourExtension\ViewHelpers;

use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;

class ImageDataViewHelper extends AbstractViewHelper
{
    /**
     * output will not be escaped (for returnVal: 'htmlWidthHeight')
     */

    protected $escapeOutput = false;

    public function initializeArguments()
    {
        parent::initializeArguments();
        $this->registerArgument('imgPath', 'string', 'The path to the image, usually given as {imageRefField.originalResource.publicUrl}', false, null);
        $this->registerArgument('returnVal', 'string', 'One of the return values; if null, array will be returned', false, null);
    }

    /**
     * @return bool
     */

    public function render()
    {
        $imgPath = $this->arguments['imgPath'];
        if ($imgPath !== null) {
            $dim = getimagesize($imgPath);
            $returnArray = [
                'width' => $dim[0],
                'height' => $dim[1],
                'htmlWidthHeight' => $dim[3]
            ];

            $returnVal = $this->arguments['returnVal'];
            if ($returnVal === null) {
                return $returnArray;
            } else {
                return $returnArray[$returnVal];
            }
        }
    }
}
    }
}

The Fluid Template

/Resources/Private/Templates/…

Lines 3+4 show how to call the ViewHelper only once, store its returned array in a Fluid variable, and then use both width and height in attributes of a DIV.

The last line calls the returnVal htmlWidthHeight in order to write the respective attributes into an html <img> tag.

imageRefField is the name of the property of your domain model that stores the reference to the image.

{namespace someName = VendorName\YourExtension\ViewHelpers}

<f:variable name="imageData">{someName:imageData(imgPath: imageRefField.originalResource.publicUrl)}</f:variable>
<div style="background-image: url(/{imageRefField.originalResource.publicUrl})" data-img-width="{imageData.width}" data-img-height="{imageData.height}">

<img src="/{imageRefField.originalResource.publicUrl}" {namespace:imageData(imgPath: imageRefField.originalResource.publicUrl, returnVal: 'htmlWidthHeight')}>

(note the added leading slash before the filepath)

This will return something like:

<div style="background-image: url(/path/to-your/image.jpg)" data-img-width="800" data-img-height="350">

<img src="/path/to-your/image.jpg" width="800" height="350">