picocms/Pico

Exif data from photos with a plugin

Closed this issue · 2 comments

I have written a twig with a lightbox gallery for displaying my photos.
What I also want to display is the Exif data of the photos. I know that it can be achieved by the php function exif_read_data()
A plugin is therefore necessary. My php skills and the understanding of creating a plugin are not that good. So I am stuck.

I have tried to understand the example in the link: https://github.com/picocms/Pico/issues/489 . But I was not able to make it work.
So my question is, can somebody give me a hint to resolve my issue. A small example of a plugin so that I can make a twig file out if it.

A starting point for your plugin:

class ExifData extends AbstractPicoPlugin
{
    const API_VERSION = 3;
    protected $enabled = true;
    protected $dependsOn = array();
    
    public function onTwigRegistered(Twig_Environment &$twig)
    {
        $twig->addFunction(new \Twig\TwigFunction('getExif', function($imagePath) {
            return $this->getExifData($imagePath);
        }));
    }
    
    private function getExifData($imagePath)
    {
        // check: is an image?
        $supportedFormats = ['image/jpeg', 'image/tiff'];
        $fileType = mime_content_type($imagePath);
        if (!in_array($fileType, $supportedFormats)) {
            return null;
        }

        // Read EXIF data
        $exif = exif_read_data($imagePath, 0, true);      

        // We export some data
        return [
            'Camera' => $exif['IFD0']['Model'] ?? 'N/A',
            'Brand' => $exif['IFD0']['Make'] ?? 'N/A',
            'DateTime' => $exif['EXIF']['DateTimeOriginal'] ?? 'N/A',
            'Focal' => isset($exif['EXIF']['FocalLength]) ? $this->focalLength($exif['EXIF']['FocalLength']) : 'N/A',
            'Aperture' => isset($exif['EXIF']['FNumber']) ? $this->fnumber($exif['EXIF']['FNumber']) : 'N/A',
            'ISO' => $exif['EXIF']['ISOSpeedRatings'] ?? 'N/A',
        ];
    }
    
    private function focalLength($focalLength) 
    {
        if (is_string($focalLength) && strpos($focalLength, '/') !== false) {
            list($num, $denom) = explode('/', $focalLength);
            return $denom != 0 ? round($num / $denom, 2) . ' mm' : $focalLength;
        }
    }
    
    private function fNumber($aperture)
    {
        // Usually f/2.0 is noted as 2/1 or 200/100 by camera firmware
        if (is_string($aperture) && strpos($aperture, '/') !== false) {
            list($num, $denom) = explode('/', $aperture);
            // simple math
            $aperture = $denom != 0 ? round($num / $denom, 1) : 0;
        }
        return sprintf('f/%.1f', $aperture);
    }
}

The plugin returns an array, and you can handle the values like this:

{# put your image here #}
{% set exif = getExif('assets/sample.jpg') %}

<ul>
    {# grab all Exif data from getExif #}
    {% for key, value in exif %}
        <li>{{ key }}: {{ value }}</li>
    {% endfor %}
</ul>

Many thanks. It works.
For the record I added an additional quote in line:
'Focal' => isset($exif['EXIF']['FocalLength]')
Now I also understand how the plugin works.