Jump to content
Nico Knoll

ImageEXIF

Recommended Posts

--- ALPHA WARNING ---

Hey,

today I'm going to release a module which especially is nice for photographers I guess: ImageEXIF (it's in the module repository).

What does it do?

This module the EXIF data of an image to it's object.

There are some aliases (e.g. "exposureTime" and "tv") and unformatted values (e.g. "focalLengthUnformatted") included.

Example for which EXIF data get's added:

{
"aperture":5.6,
"apertureUnformatted":"56\/10",
"av":5.6,
"exposure":"1\/320",
"exposureTime":"1\/320",
"tv":"1\/320",
"shutterTime":"1\/320",
"cameraMake":"Canon",
"cameraModel":"Canon EOS 1100D",
"name":"image",
"filename":"image.jpg",
"filesize":2346963,
"mimeType":"image\/jpeg",
"height":2056,
"width":3088,
"artist":null,
"photographer":null,
"comment":"",
"copyright":null,
"flash":"Flash did not fire, compulsory flash mode",
"flashUnformatted":16,
"focalLength":"250mm",
"focalLengthUnformatted":250,
"iso":640,
"ISO":640,
"orientation":1,
"orientationUnformatted":1,
"date":"2013-10-27",
"time":" 15:53:07",
"timestamp":1382885587,
"whiteBalance":"Daylight",
"whiteBalanceUnformatted":1
}

How to use (example):

<?php
$image = $page->images->first();
echo 'ISO: '.$image->EXIF->iso; // $image->exif->iso would work, too
?>

Did I forget some important data? Other wishes?

  • Like 5

Share this post


Link to post
Share on other sites

@Nico: Hey, a new metadata man! :)

I have had a quick look to it, not installed and tested yet. But I already spotted a few lines where I may suggest to

  • test if function_exists("exif_read_data") in/before install(), just to be on the save side!
     
  • there are a ton of possible data names outside in the wild, actually you have cut them down to a more or less small set of the most needed ones, but if for example a photographer uses / needs some that you have not in your list, the module is useless for him. I recommend to add the ability to access the raw data as object, unfiltered, not cutted, etc.

What I really like is that you just read the information from the original imagefile on demand and do not try to store/cache it elsewhere!

ALso really nice for me is the Line 88, your comment on this. :) For me, that I do not use / need EXIF-data at all, this is the one and only important information from all that EXIF-data. It tells us in which direction the camera was turned when taking the shot, for example. (have a look here and here, followed by 985 and 1000). We use it to autoRotate images where needed.

  • Like 2

Share this post


Link to post
Share on other sites

My ImagesManager also supports reading exif data and saves it to a field.

  • Like 1

Share this post


Link to post
Share on other sites

@horst: I updated it with most of your suggestions included. It's now possible to get the whole data by using image->exif->full/raw/all (one of them, but all will work). It's also possible to get EXIF data directly (take a look here: L37). The priority is "custom" (generated by the module) > "EXIF" > "IFD0" > "FILE". (It's easier to understand by just looking at the code :) )

@soma: Nice! I just did a quick research by entering "EXIF" in the modules manager and haven't found any modules back then, so I think I missed yours...

Share this post


Link to post
Share on other sites

@Nico: I have installed it, but it was hard to get it returning some data for me!

There are some really heavy faults with your module:

  • you need to check image type before passing a file to exif_read_data, please test with png and/or gif and set debug to true!
     
  • there is no error handling, null, nix, nada.  :angry:  With some jpeg images I get: Warning: exif_read_data(motiv_wood.jpg): Incorrect APP1 Exif Identifier Code in .../site/modules/ImageEXIF/ImageEXIF.module on line 29, and then there is no retrieved data available!
     
  • there are tons of PHP Notices regarding undefined indexes! depending on available data in the exif headers.
     
  • there are also no checks for any of the needed APP marker (EXIF, IFD0, FILE)
     

Some minor issues may be:

  • when my original data for FocalLength is "107/25", you return me: focalLengthUnformatted = 4.28 and additionally focalLength = "4.28mm". For what is this useful? I would expect that you give me: FocalLengthIn35mmFilm = 35, regardless if added "mm" or not. That one is commonly important but missing.
     
  • I get returned this: comment = "ASCII\x0\x0\x0© John Doe", The \x0 are binary NULL, what truncates any following string data! This way the users of your module never will get their UserComments returned. But exif_read_data already computes this to:
    UserCommentEncoding = "ASCII" and
    UserComment = "© John Doe". Why don't you use that when already returning filtering and manipulating data?
     
  • a micro-issue: is returning the mimetype useful? It only can be image/jpeg, or what else?
     
  • there is more, but I become more and more angry  >:D   >:(  ...

Nico, it is signed "BETA, close to stable" in the directory. This is a joke, no? Maybe the cool kids today do not need testing / debugging anymore?

I don't mind if anyone personally like to jump out of an airplane flying 10.000 feets high without using a parachute. But I'm really angry if someone throws out other people without them giving a parachute!

I'm curious about what docs / specs you have read about EXIF and about how many people already have tested this (besides you) before you uploaded this to the directory as "close to stable"?

I would have expected that you turn on debugging when developing a module for the public and also would have expected that you first post it here into the forum as alpha module. But most of all the usage of errorhandling!

Thanks for reading. I will review your next release if you like - but not when it is missing the above mentioned things. :P:lol:

------

PS: here is a good summary on the subject in German: http://www.dslr-forum.de/showthread.php?t=131920

Edited by horst
added link to a summary from german dslr forum
  • Like 1

Share this post


Link to post
Share on other sites

Sorry for disappointing you.. I changed it to alpha. 

I tested it with some jpgs I uploaded on my local PW installation and there everything worked fine. 

I'll take care of the points you mentioned and update this post here afterwards.

  • Like 3

Share this post


Link to post
Share on other sites

Sorry for disappointing you.. I changed it to alpha. 

I tested it with some jpgs I uploaded on my local PW installation and there everything worked fine. 

I'll take care of the points you mentioned and update this post here afterwards.

I'm a old bloke and doesn't get really disappointed by this. :)  But sometimes it seems to be helpful to raise the voice and threatening with the finger. You normally publish much, much better work!

If you are interested in this EXIF stuff, you should get you ExifTool, a (platform independant) Perl library.

Here a download from heise, - and there is also a GUI available for Win and there seems to be some kind of GUI for Mac too.

You can manipulate all Metadata with it, what enables you to create a good set of test images. :) Also don't forget to throw in some gif and png into your test set.

------

Above I have tested your 0.4.0 version. The enhancements with 0.6.0 is nice and useful. The best experience for the users would be if they can pass a single keyname or an array with keynames to the get method, I think. Then it return a single value or an associative array / or object.

This module, once it is stable, or close to stable ;-) , it can be used directly in templates but also in other modules to read data and maybe write it into fields, for example on images upload. If you make it robust, it can (and should!) become the dependency for all following modules that want to handle EXIF data.

  • Like 1

Share this post


Link to post
Share on other sites

Was having a few problems with this module for photos which I had stripped meta data. Kept on getting an "Undefined Index" warning. Here's the fix...

    public function __get($string) {
        if(!$this->data) return '';
		
	// MY EDIT: make sure that what we're searching for is actually set, otherwise we get an error notice
	if(!isset($this->data[$string]) && !isset($this->exif['EXIF'][$string]) &&  !isset($this->exif['IFD0'][$string])  && !isset($this->exif['FILE'][$string])) return '';
        
        if(in_array($string, array_keys($this->data))) return $this->data[$string];
        
        if(in_array($string, array_keys($this->exif['EXIF']))) return $this->exif['EXIF'][$string];
        if(in_array($string, array_keys($this->exif['IFD0']))) return $this->exif['IFD0'][$string];
        if(in_array($string, array_keys($this->exif['FILE']))) return $this->exif['FILE'][$string];
        
        return '';
    }

Share this post


Link to post
Share on other sites

"timestamp" shows modified time.

i want to show datetimeoriginal of picture.

How can we add ?

Share this post


Link to post
Share on other sites
9 hours ago, Cengiz Deniz said:

"timestamp" shows modified time.

i want to show datetimeoriginal of picture.

How can we add ?

There is another module here:

It has more configurable methods to get out what you want.

Share this post


Link to post
Share on other sites

Thank you for your reply. Actualy I found my own solution without modul

I added following code to template and its works very well. This give main EXIF properties:

$image="http://cdeniz.com/".$img->url;
$exif = exif_read_data($image, NULL, true, true);
$date= $exif["EXIF"]["DateTimeOriginal"];
$camera= $exif["IFD0"]["Make"]." ".$exif["IFD0"]["Model"];
$sizes= $exif["COMPUTED"]["Width"]. " x ".$exif["COMPUTED"]["Height"];
$apertur= $exif["COMPUTED"]["ApertureFNumber"];
$exposure= $exif["EXIF"]["ExposureTime"];
$iso= $exif["EXIF"]["ISOSpeedRatings"];

 

Share this post


Link to post
Share on other sites

@Cengiz Deniz Yep, it works very well, but only until you request a key that is not available in an image, than it will throw notices or warnings.

The new module I linked to, lets you do the exact same as you does, but without the redundant hassle of validation.

 

So, you can use your code, but I suggest to add a check for available keys:

$image="http://cdeniz.com/".$img->url;
$exif = exif_read_data($image, NULL, true, true);
$tarih = isset($exif["EXIF"]["DateTimeOriginal"]) ? $exif["EXIF"]["DateTimeOriginal"] : 'N/A'; // or anything you want, like '', null, ...
$kamera= (isset($exif["IFD0"]["Make"]) ? $exif["IFD0"]["Make"] : '') . " " . (isset($exif["IFD0"]["Model"]) ? $exif["IFD0"]["Model"] : '');
... ... ...

 

Personally I find this to unreadable and redundant, therefore I prefer the new modules way:

$options = array('keys' => array('DateTimeOriginal', 'Make', 'Model'), 'toObject' => true);
$exif = $image->getExif($options);
// now I can access like this:
$tarih = $exif->DateTimeOriginal;
$kamera = $exif->Make . ' ' . $exif->Model;

 

Edited by horst
typo correction
  • Like 2

Share this post


Link to post
Share on other sites

thank you for your support.

I dont understand that why i get an error when property is emphty.

for example i copied following picture from internet and show with my exif code. it has no exif data. also no error.

 

 

Capture.JPG

Share this post


Link to post
Share on other sites

It is not when the property has empty values, it is when there isn't a key available.

Your request return multidimensional array. If there is, for what ever reason, not set a key 'Make' or 'Model' for example, PHP will throw a notice when you simply try to use $myArray['availableKey']['notAvailableKey'].

So, if you are 100% sure that all images that you ever will use with that code will have all requested EXIF-fields, let out the validation. :)

 

  • Like 2

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...