Jump to content

Metadata EXIF


horst
 Share

Recommended Posts

Metadata Exif

Version 0.9.0  (currently a WIP) for PW 2.8.+ / 3.0+

This is a new attempt to add easy EXIF reading support to ProcessWire. It should be an easy and less error prone API task. Thats why the module internally uses lowercase key names for all EXIF keys and all of your requested key names. But you are not forced to use lowercase key names, you can use any mixed chars for it as you like. You will get back an array or object with keynames / properties named the same (casesensitive) way as you have passed them in with your request.

API

The module adds one hook to the Pageimage: getExif($options = null)

Without any $options passed to the method, it returns all EXIF data in a RAW multidim array.

Passing a simple list with requested key names as array to it returns an array with only the values of those requested keynames.

If you want change the output from array to object, you can use the a boolean "toObject" set to true. Additionally to this and / or any other option, you need to put your requested keynames list to the option "keys".

$rawArray = $image->getExif();

$options = array('Whitebalance', 'Flash', 'ISOSpeedRatings', 'FNumber', 'UserComment');
$array = $image->getExif($options);

$options = array('toObject' => true, 'keys' => array('whitebalance', 'flash', 'isospeedratings', 'fnumber', 'usercomment'));
$object = $image->getExif($options);

 

Possible options are

Quote

              keys = array,
                       a list with case insensitive keynames

              thumbnail = bool,
                       you can set thumbnail explicitly as own option,
                       or you can add thumbnail as keyname to keys

              toObject = bool,
                       if is false or missing, an array is returned

              unformatted = bool,
                       if explicitly set to true, you will get back unformatted (raw) values

              returnRaw = bool,
                       when no $options are set, or no $options['keys'] are set,
                       or explicitly this param is set to true,
                       the complete RAW EXIF data is returned

 

A working example

    $options = array(
        'keys' => array('ISOSpeedRatings', 'FNumber', 'Flash')
    );
    echo "<table><tr>";
    foreach($options['keys'] as $key) echo "<th>{$key}</th>";
    echo "</tr>";
    foreach($page->images as $image) {
        $exif = $image->getExif($options);
        echo "<tr>";
        foreach($exif as $value) echo "<td>$value</td>";
        echo "</tr>";
    }
    echo "</table>";

 

This will output something like:

Quote
ISOSpeedRatings    FNumber    Flash
320    f/2.2    Flash did not fire, compulsory flash mode
100    f/4.0    Flash did not fire, compulsory flash mode

 

With the boolean option "unformatted" passed as true, the output would look like:

Quote
ISOSpeedRatings    FNumber    Flash
320    11/5    16
100    40/10    16

 

For some keys, that only store something like integer values, what are not very meaningful to most of us, the module contain xyzFormatted methods. This way, it is easy to enhance and maintain the module in the future. :)

 

Help wanted

It would be nice if some of you test the module and report back if the intended API suites your needs. And you are very welcome to post suggestions for which keys you want to have a ...Formatted method.

 

Thank you!

https://github.com/horst-n/MetadataExif

 

  • Like 12
Link to comment
Share on other sites

  • 7 months later...
var_dump(count($page->galleryimages));
$image = $page->galleryimages->first();
var_dump($image->url);
var_dump($image->getExif());

please verify that:

  • your field has at least one image
  • that the image is of type jpeg
  • that it (the original version) contains EXIF-data
  • that it contain an entry FNumber

 

Link to comment
Share on other sites

1 minute ago, horst said:

please verify that:

  • your field has at least one image
  • that the image is of type jpeg
  • that it (the original version) contains EXIF-data
  • that it contain an entry FNumber

 

Yes I can confirm all of this. The multi-image field has two images. Using your example array from the first post of this thread I can see Exif information being returned for both. Both files are jpg type files.

See array information returned from your working example code below.

 

Screenshot at Nov 27 17-12-27.png

Link to comment
Share on other sites

17 minutes ago, horst said:

var_dump(count($page->galleryimages));

returns - int(2)

Quote

$image = $page->galleryimages->first();

Returns - nothing.
 

Quote

var_dump($page->galleryimages->url);

returns - string(36) "/photography/site/assets/files/1031/" 

Quote

var_dump($page->galleryimages->getExif());

returns - array(2) { ["apc_0046.jpg"]=> NULL ["img_0335.jpg"]=> NULL }

Link to comment
Share on other sites

Quote

var_dump($page->galleryimages->first()->getExif());

Notice: Undefined offset: 0 in /Applications/XAMPP/xamppfiles/htdocs/photography/site/modules/MetadataExif/MetadataExif.module on line 44
array(5) { ["FILE"]=> array(6) { ["FileName"]=> string(12) "apc_0046.jpg" ["FileDateTime"]=> int(1511813872) ["FileSize"]=> int(1160717) ["FileType"]=> int(2) ["MimeType"]=> string(10) "image/jpeg" ["SectionsFound"]=> string(30) "ANY_TAG, IFD0, THUMBNAIL, EXIF" } ["COMPUTED"]=> array(9) { ["html"]=> string(26) "width="2797" height="3496"" ["Height"]=> int(3496) ["Width"]=> int(2797) ["IsColor"]=> int(1) ["ByteOrderMotorola"]=> int(0) ["ApertureFNumber"]=> string(5) "f/2.2" ["Copyright"]=> string(20) "photography" ["Thumbnail.FileType"]=> int(2) ["Thumbnail.MimeType"]=> string(10) "image/jpeg" } ["IFD0"]=> array(10) { ["ImageDescription"]=> string(36) "time flies" ["Make"]=> string(5) "Apple" ["Model"]=> string(14) "iPhone 6s Plus" ["XResolution"]=> string(5) "240/1" ["YResolution"]=> string(5) "240/1" ["ResolutionUnit"]=> int(2) ["Software"]=> string(49) "Adobe Photoshop Lightroom Classic 7.0 (Macintosh)" ["DateTime"]=> string(19) "2017:11:27 16:17:21" ["Copyright"]=> string(20) "j.sobers.photography" ["Exif_IFD_Pointer"]=> int(302) } ["THUMBNAIL"]=> array(6) { ["Compression"]=> int(6) ["XResolution"]=> string(4) "72/1" ["YResolution"]=> string(4) "72/1" ["ResolutionUnit"]=> int(2) ["JPEGInterchangeFormat"]=> int(896) ["JPEGInterchangeFormatLength"]=> int(17303) } ["EXIF"]=> array(26) { ["ExposureTime"]=> string(6) "1/2400" ["FNumber"]=> string(5) "22/10" ["ExposureProgram"]=> int(2) ["ISOSpeedRatings"]=> int(25) ["ExifVersion"]=> string(4) "0230" ["DateTimeOriginal"]=> string(19) "2017:07:10 11:47:22" ["DateTimeDigitized"]=> string(19) "2017:07:10 11:47:22" ["ShutterSpeedValue"]=> string(16) "11228819/1000000" ["ApertureValue"]=> string(15) "2275007/1000000" ["BrightnessValue"]=> string(8) "8488/781" ["ExposureBiasValue"]=> string(3) "0/1" ["MeteringMode"]=> int(5) ["Flash"]=> int(16) ["FocalLength"]=> string(5) "83/20" ["SubjectLocation"]=> array(4) { [0]=> int(2015) [1]=> int(1511) [2]=> int(2217) [3]=> int(1330) } ["SubSecTimeOriginal"]=> string(3) "208" ["SubSecTimeDigitized"]=> string(3) "208" ["ColorSpace"]=> int(1) ["SensingMethod"]=> int(2) ["SceneType"]=> string(1) "" ["ExposureMode"]=> int(0) ["WhiteBalance"]=> int(0) ["FocalLengthIn35mmFilm"]=> int(29) ["UndefinedTag:0xA432"]=> array(4) { [0]=> string(5) "83/20" [1]=> string(5) "83/20" [2]=> string(4) "11/5" [3]=> string(4) "11/5" } ["UndefinedTag:0xA433"]=> string(5) "Apple" ["UndefinedTag:0xA434"]=> string(39) "iPhone 6s Plus back camera 4.15mm f/2.2" } }

 

Quote

 

var_dump($page->galleryimages->first()->url);

 

 

string(48) "/photography/site/assets/files/1031/apc_0046.jpg"

 

Sorry about that, i corrected my mistake. see above.

Link to comment
Share on other sites

Sorry, now I see that you are using a single value string as $options. This is not possible.

Please refer to the examples above: you need to pass an array to the function, also if you want to retrieve a single value:

$image->getExif( array('FNumber') );

 

Link to comment
Share on other sites

you need to echo out your desired array key, or object property, depending on what you choosed.

You choosed an array for the return, therefore you need to output the key "FNumber" of the array:

$result = $page->galleryimages->first()->getExif( array('FNumber') );

// output the value for one key of the returned array
echo $result['FNumber'];

// if you have choosen the result as object, you would use
echo $result->FNumber;

This all you can read in the initial post of this thread.

  • Thanks 1
Link to comment
Share on other sites

Hi Horst,

With your instructions and help, I got it to work.

Thanks again for working with me in understanding proper methods for rendering the values I needed.

 

For Future reference for anyone else(including myself if I forget )... There are two methods for rendering data from Metadata EXIF module.

Array Method:

// output the value for one key of the returned array
$firstGalleryImage = $page->galleryimages->first()->getExif( array('FNumber') );
echo $firstGalleryImage['FNumber'];

Object Method:

// if you have choosen the result as object, you would use
$options = array('toObject' => true, 'keys' => array('FNumber'));
$object = $page->galleryimages->first()->getExif($options);
echo $object->FNumber; 

 

  • Like 1
Link to comment
Share on other sites

  • 2 years later...

Hi @horst,

Thanks for this module!

It would be great if the module alerted the user somehow if the required PHP exif extension is not installed. I spent some time trying to work out why I couldn't get any data back from images and it wasn't until I saw this in the module code...

if(!function_exists('exif_read_data')) return null;

...that I realised my local WAMP stack didn't have the exif extension enabled.

Link to comment
Share on other sites

10 hours ago, Robin S said:

It would be great if the module alerted the user somehow if the required PHP exif extension is not installed.

What do you think would be the best way? Returning false or throwing an exception?

 

Link to comment
Share on other sites

7 hours ago, horst said:

Returning false or throwing an exception?

I think the getExif() method should throw an exception if the module requirements aren't met.

But the module could also check for this when it's installed. Unfortunately I don't think it's possible to include PHP extensions in the "requires" item of getModuleInfo() but the Module documentation says (after correcting typo):

Quote

If the install() method determines that the module cannot be installed for some reason, it should throw a WireException.

So the install method could be this:

public function ___install() {
	if(!function_exists('exif_read_data')) {
		throw new WireException('MetadataExif requires the PHP exif extension.');
	};
}

 

Link to comment
Share on other sites

Many thanks for the suggestions, @Robin S

I think the main check / exception must be in the getExif method. 

A check during install will be useless when deploying a site folder from local to stage or live. But it is no harm to have it too. ?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...