25 12 2015
Decode EXIF from a raw photo
I’m writing a python script to sort my raw photos. Precisely group my HDR together. The idea is to read EXIF tags inside the raw file. And correlate them to group raw photo for each HDR.
I started to use rawkit (https://rawkit.readthedocs.org/en/latest/) but the values of Exif tags I was looking for was not really great.
Someone suggest me to use ExifRead library to read Exif tags in a raw file. In fact it’s a better choice, I’m writting a python script. With ExifRead no need of extra C library dependency.
Python ExifRead provide EXIF.py script to output Exif tags.
I was looking for 4 things
- Exposure time
Unfortunately the value for aperture seems wrong (3 instead of 2.8).
My photo was taken with a 2.8 aperture. I first thought : maybe a rounded value on this flag, it’s a dumb error. I decided to try to find myself the value in the raw file to know what’s going on.
Reading this excellent link Understanding What is stored in a Canon RAW .CR2 file, How and Why, I found the graal to decode a raw file cr2_poster.pdf
At this point, I thought the best value I could get was in my canon specific MakerNote section on the FNumber value. (All values description is here canon_tags)
I opened the file with an Hexa editor (hexedit) and … I was totally lost.
Key things you need to remember to decode the file :
- 1) An offset is a address in the file that will contain your value.
- 2) Read : C8 05 in the file sould be read 05C8. Example for an offset, the address is 0x5C8
With that, found the Canon MakeNote section is easy.
The quick way is to search directly the 0x927c MarkerNote (so in the file 7C 92) flag that contain the address of the MakerNote section. If you are not able to found that, go throught the IFD section to find the EXIF subsection. And then in that subsection you will find the MakerNote section
The content is an offset : 84 03 00 00 -> 00 00 03 84 (0x384 address)
Go to this address and search in the MakerNote section the FNumber 0x3
Go to the offset 0x5C8 to find our value (count 4 x type 3 ushort, 16 bits)
And … fail, in fact my canon does not filled this section.
Reading Metadata reference tables for http://www.exiv2.org/tags.html The FNumber can be found also in standard EXIF subsection.
Let’s try to do the same process to read FNumber in the EXIF subsection “0x829d Exif.Image.FNumbertype 5 Rational” Rational type is composed of 64 bits (numerator and denominator ulongs) Rational_data_type
And then read the 0x334 offset
As we can read in Hexa : 0x1C / 0XA In decimal, do the math : 28/10 = 14/5 = 2.8
Wow, that explain a log this Verify I have this :
I was looking for 2.8 float and this value is stored in fractional format. So the library don’t convert this value in float, just simplify the fraction.
This is why we have 14/5 and not 2.8 as expected.
Now it’s time to code :
And Voila !