Closed derselbst closed 5 years ago
Thanks for reporting this and providing a test file. I'll have to investigate this. There's something in the code for Canon.AFInfo:
744 rmills@rmillsmbp:~/gnu/github/exiv2/0.27-maintenance $ build/bin/taglist Canon | grep -i afinfo
AFInfo, 38, 0x0026, Canon, Exif.Canon.AFInfo, Short, AF info
745 rmills@rmillsmbp:~/gnu/github/exiv2/0.27-maintenance $
However we are reporting a long stream of 273 shorts:
745 rmills@rmillsmbp:~/gnu/github/exiv2/0.27-maintenance $ exiv2 -pa --grep afinfo/i ~/Downloads/62878860-3c552580-bd2a-11e9-94c0-cd4617d1af80.JPG
Exif.Canon.AFInfo Short 273 546 2 63 61 6720 4480 6720 4480 218 218 ...
746 rmills@rmillsmbp:~/gnu/github/exiv2/0.27-maintenance $
I'll investigate. I believe I can add a binary decoder to report values from fields in that binary stream.
Something similar to this was reported in December concerning AFinfo on Nikon Cameras and the fix was released in Exiv2 v0.27.2 on 2019-07-29. So, I'm optimistic that I'll be able to fix this for you and get into a future "dot" later this year. https://github.com/Exiv2/exiv2/issues/646
I should have explained that the 273 shorts are what's stored in the Exif tag 0x0026 in the file:
747 rmills@rmillsmbp:~/gnu/github/exiv2/0.27-maintenance $ exiv2 -pR ~/Downloads/62878860-3c552580-bd2a-11e9-94c0-cd4617d1af80.JPG | grep 0x0026
1080 | 0x0026 | SHORT | 273 | 3258 | 546 2 63 61 6720 ...
748 rmills@rmillsmbp:~/gnu/github/exiv2/0.27-maintenance $
However, in reality it's a binary record in the MakerNote. I'll have to add a decoder to report the fields in that data.
Thx, looking forward to it. In case it helps understanding this issue, I'm also providing a test image from a EOS 500D: IMG_7600
Thanks. That's very helpful.
Now there are 48 SHORTS version '96'. There were 273 SHORTS version 536. So I'll probably need two decoders with a selector.
752 rmills@rmillsmbp:~/Downloads $ exiv2 -pR IMG_7600.jpg | grep 0x0026
984 | 0x0026 | SHORT | 48 | 3066 | 96 2 9 9 4752 ...
753 rmills@rmillsmbp:~/Downloads $ exiv2 -pa --grep afinfo/i IMG_7600.jpg
Exif.Canon.AFInfo Short 48 96 2 9 9 4752 3168 ...
754 rmills@rmillsmbp:~/Downloads $
For sure the cameras have different firmware versions:
756 rmills@rmillsmbp:~/Downloads $ exiv2 -pa --grep firm/i IMG_7600.jpg
Exif.Canon.FirmwareVersion Ascii 24 Firmware Version 1.1.1
757 rmills@rmillsmbp:~/Downloads $ exiv2 -pa --grep firm/i 62878860-3c552580-bd2a-11e9-94c0-cd4617d1af80.JPG
Exif.Canon.FirmwareVersion Ascii 24 Firmware Version 1.1.2
758 rmills@rmillsmbp:~/Downloads $
Perhaps the 50D/Rebel 18-200mm lens has a lot less sensors/focal points. I don't speak camera/photography, I'm a software guy!
758 rmills@rmillsmbp:~/Downloads $ exiv2 -pa --grep model/i 62878860-3c552580-bd2a-11e9-94c0-cd4617d1af80.JPG
Exif.Image.Model Ascii 21 Canon EOS 5D Mark IV
Exif.Canon.ModelID Long 1 EOS 5D Mark IV
Exif.Canon.LensModel Ascii 74 35mm F1.4 DG HSM | Art 012
Exif.Photo.LensModel Ascii 27 35mm F1.4 DG HSM | Art 012
759 rmills@rmillsmbp:~/Downloads $ exiv2 -pa --grep model/i IMG_7600.jpg
Exif.Image.Model Ascii 15 Canon EOS 500D
Exif.Canon.ModelID Long 1 EOS Rebel T1i / 500D / Kiss X3
Exif.Canon.LensModel Ascii 70 18-200mm
760 rmills@rmillsmbp:~/Downloads $
You have raised this issue at a good time. I'm writing a book "Image Metadata and Exiv2 Architecture". I could use this as a case study concerning MakerNote processing. https://github.com/Exiv2/exiv2/issues/911
While I hope to deal with this issue soon, this is quite complicated and will take some time. There's a dot release due at the end of September. If I can't complete the code by code freeze at the end of August, it'll be in the release at the end of December.
Now there are 48 SHORTS version '96'. There were 273 SHORTS version 536. So I'll probably need two decoders with a selector.
Assuming you meant 546 rather than 536, these are not versions. This is the AFInfoSize
field of the AFInfo2 chunk, which seems to simply specify the size of the chunk in bytes, given that
273 shorts * 2 bytes == 546
and 48 * 2 == 96
. So one decoder for the AFInfo2 chunk and perhaps another one in case you want to support the old AFInfo chunk as well.
Here are some notes about this. I'll probably edit this several times while I figure what's going on!
762 rmills@rmillsmbp:~/Downloads $ exiv2 -pa --grep af/i IMG_7600.jpg
Exif.CanonCs.AFPoint Short 1 (0)
Exif.CanonSi.AFPointUsed Short 1 0 focus points; none used
Exif.Canon.AFInfo Short 48 96 2 9 9 4752 3168 4272 2848 115 115 115 162 200 162 115 115 115 153 153 153 105 199 105 153 153 153 64409 64862 64862 0 0 0 674 674 1127 0 321 65215 603 0 64933 321 65215 0 16 256 0 65535
763 rmills@rmillsmbp:~/Downloads $ exiftool IMG_7600.jpg | grep -i af
Focus Mode : One-shot AF
AF Area Mode : Single-point AF
Num AF Points : 9
Valid AF Points : 9
AF Image Width : 4272
AF Image Height : 2848
AF Area Widths : 115 115 115 162 200 162 115 115 115
AF Area Heights : 153 153 153 105 199 105 153 153 153
AF Area X Positions : -1127 -674 -674 0 0 0 674 674 1127
AF Area Y Positions : 0 321 -321 603 0 -603 321 -321 0
AF Points In Focus : 4
AF Points Selected : 8
AF Assist Beam : Does not emit
Shutter-AE Lock : AF/AE lock
764 rmills@rmillsmbp:~/Downloads $
Phil's excellent documentation is: https://sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html#AFInfo2
Raw Data:
96 2 9 9 4752 3168 4272 2848
115 115 115 162 200 162 115 115 115
153 153 153 105 199 105 153 153 153
64409 64862 64862 0 0 0 674 674 1127
0 321 65215 603 0 64933 321 65215 0
16 256 0 65535
Index | Name | Value | Comment |
---|---|---|---|
0 | AFInfoSize | 96 | Length in bytes |
1 | AFMode | 2 | 0 = Off (Manual Focus) 2 = Single-point AF 4 = Multi-point AF 5 = Face Detect AF |
2 | AFNumPoints | 9 | |
3 | AFValidPoints | 9 | AF points in arrays |
4 | AFImageWidth | 4752 | Image Width |
5 | AFImageWidth | 3168 | Image Height |
6 | AFWidth | 4272 | AF coordinates |
7 | AFHeight | 2848 | |
8..16 | AFAreaWidths[] | 115 115 115 162 200 162 115 115 115 | SSHORT |
17..25 | AFAreaHeights[] | 153 153 153 105 199 105 153 153 153 | SSHORT |
26..34 | AFAreaXPositions[] | -1127 -674 -674 0 0 0 674 674 1127 | SSHORT |
35..43 | AFAreaYPositions[] | 0 321 -321 603 0 -603 321 -321 0 | SSHORT |
44 | AFPointsInFocus | 16 | |
45 | AFPointsSelected | 256 | |
46 | AFPrimaryPoint | 0 | |
47 | Don't Know | -1 |
This doesn't look painful. I'll investigate the code required this evening.
@derselbst Thanks for your comment about the size of the chunk. You can see that I realised that this morning. So while you were writing, I was figuring this out! This is looking straight forward. I'm taking my grand-kids to the park today as they are off school and their parents are working. I'll continue this evening.
Making progress: https://github.com/Exiv2/exiv2/pull/982
I've made progress with this today. The code now handles AfInfo and AfInfo2. However it's not populating the arrays in AfInfo2. I didn't write Exiv2, so I have to read/explore the code to know what already exists. It appears that the decoder expects a "static/fixed" structure of fields. AfInfo2 populates arrays whose dimension is in the metadata. I haven't found another structure with this layout. I've tried to dynamically create the structure at run-time and haven't yet got that to work. I'm going to take a break from this.
I've fixed to work with any number of points. Very pleased. Great end to the week.
It reports Exiv2.Canon.AFInfo as always (with unsigned shorts), however instead of creating a new group Exif.CanonAF.xxx, it extends Exif.Canon.AF* with entries such as Exif.Canon.AFMode and Exif.Canon.Exif.Canon.AFAreaWidths which is an array of SSHORT.
I've submitted a new PR #985 and closed #982
I expect this to be released in v0.27.3 scheduled for 2019-09-30. Your feedback and comments are welcome.
Here's an image which uses multiple AF focus points. It's too big for github. exiftool reports them to be:
AF Points In Focus : 20,21,25,45,46,47
AF Points Selected : 19,20,21,24,25,26,45,46,47
https://drive.google.com/open?id=1kgiEWPQJSSXsEI3OqsbOXEETaDp4-EgP
Thanks for the test file.
$ exiv2 -pa --grep af/i AAAA5440.CR2 | tail -3
Exif.Canon.AFPointsInFocus SShort 1 0
Exif.Canon.AFPointsSelected SShort 1 560
Exif.Canon.AFPrimaryPoint SShort 1 -8192
$
I'll only use that image if/when we modify the print function for AFPointsInFocus and AFPointsSelected.
I wonder if we have the data in the wrong order here. 560 and -8192 look like bit-masks. 0 doesn't.
Thanks for finding Phil's code. Maybe @boardhead could explain this magic. Couple of puzzles. What is {2}
? Does the mask use multiple unsignedShort? How can a mask mean 19,20,21,24,25,26,45,46,47 in an unsignedShort of 16 bits. What does adding 15 do? Shifts it left or something?
12 => {
Name => 'AFPointsInFocus',
Format => 'int16s[int(($val{2}+15)/16)]',
PrintConv => 'Image::ExifTool::DecodeBits($val, undef, 16)',
},
13 => [
{
Name => 'AFPointsSelected',
Condition => '$$self{Model} =~ /EOS/',
Format => 'int16s[int(($val{2}+15)/16)]',
PrintConv => 'Image::ExifTool::DecodeBits($val, undef, 16)',
},
{
Name => 'Canon_AFInfo2_0x000d',
Format => 'int16s[int(($val{2}+15)/16)+1]',
Unknown => 1,
},
],
14 => {
# usually, but not always, the lowest number AF point in focus
Name => 'PrimaryAFPoint',
Condition => '$$self{Model} !~ /EOS/ and not $$self{AFInfo3}', # (not valid for G1XmkII)
},
Parsing of those AFPoints is currently incomplete. $val
is the number of AF Points, I think {2} just converts it to some other type. (63+15)/16 == 4
, so these are actually 4 ushorts or an uint64. I'm working on a fix, confident to finish it today.
This team-work stuff really works. I don't know why nobody uses it in the office!
$val{2} is the value of tag with id 2. ie) NumAFPoints
In Perl, an expression like $var{key} is the value in a hash lookup for the specified key. All of the tables in ExifTool are hashes, and the keys are the tag ID's.
To answer a few more questions, the format is an array of 16-bit signed integers. You get the higher bit numbers since the array may contain more than one element.
The calculation for the size of the array is just to calculate the number of 16-bit integers required to store NumAFPoints bits. The "+15" is because you need 1 word to store 1 bit, and (1+15)/16 is 1.
Thanks, Phil. I think we have this nailed and working well. @derselbst figured out what you've just explained.
Fix submitted in #988
While testing #988 I also tried to figure out the meaning of AFPrimaryPoint
. Unfortunately without success, I just don't know how to trigger or reproduce it. If I ever find out, I'll let you know.
In any case, thanks again guys!
I've made (mostly made up/conjecture) a comment about "PrimaryPoint" here: https://github.com/Exiv2/exiv2/pull/988#issuecomment-524291454
I would guess that PrimaryAFPoint is the point that the camera used to actually focus the image.
That sounds right, Phil. I got a Digital Rebel about 2004 and I think you could change the a red dot in the view-finder. On the metadata here, AFPrimaryPoint is singular, yet it is a bitmask of points. We're left guessing!
I figured it out!
The number of actually usable AF points does not only depend on the minimum aperture of the lens, it also depends on the lens itself (at least, in the Canon world). This has to do with the beam path within the lens. Some Canon lenses may not use certain AF points by design. This is indeed documented in the manuals of the camera. Those unusable AF points are reported as AFPrimaryPoints
.
Perhaps it would be worth to rename that field to something like AFPointsUnusable
or AFPointsDisabled
.
Well done. Now it gets more challenging. What are ValidPoints and how can it be different from NumPoints? And PointsSelected. Is there a way to "select" points?
$ exiv2 -pa --grep AF test/data/test_issue_981a.exv
Exif.CanonCs.AFPoint Short 1 (0)
Exif.CanonSi.AFPointUsed Short 1 0 focus points; none used
Exif.Canon.AFInfo Short 48 96 2 9 9 4752 3168 ...
Exif.Canon.AFInfoSize SShort 1 96
Exif.Canon.AFAreaMode SShort 1 Single-point AF
Exif.Canon.AFNumPoints SShort 1 9
Exif.Canon.AFValidPoints SShort 1 9
Exif.Canon.AFCanonImageWidth SShort 1 4752
Exif.Canon.AFCanonImageHeight SShort 1 3168
Exif.Canon.AFImageWidth SShort 1 4272
Exif.Canon.AFImageHeight SShort 1 2848
Exif.Canon.AFAreaWidths SShort 9 115 115 115 162 200 162 115 115 115
Exif.Canon.AFAreaHeights SShort 9 153 153 153 105 199 105 153 153 153
Exif.Canon.AFXPositions SShort 9 -1127 -674 -674 0 0 0 674 674 1127
Exif.Canon.AFYPositions SShort 9 0 321 -321 603 0 -603 321 -321 0
Exif.Canon.AFPointsInFocus Short 1 4
Exif.Canon.AFPointsSelected Short 1 8
Exif.Canon.AFPrimaryPoint Short 1 (none)
$
Ok, a bit of documentation to hopefully clarify this mess. Feel free to share or embed it somewhere where it fits.
AFNumPoints
just describes the length of those arrays AFAreaWidth/Height
and AFX/YPositions
. Or in other words: the maximum number of AF points that may be stored in those fields.
AFValidPoints
describes the number of AF points of the above arrays that (technically) could be used by the camera given its current setting(s) (think of phase-AF vs. live-view AF). In other words for programmers: it tells you how many of the values in the previously mentioned arrays are initialized and usable for interpretation.
Depending on AFAreaMode
you can choose to select a single AF point or multiple points, which the camera should consider for focusing. Which points you've actually selected is indicated by AFPointsSelected
.
See the following examples that are based on the EOS 5D Mark IV:
The standard use-case: You take a picture by looking through the viewfinder. There you can use up to 61 phase-AF points:
Exif.Canon.AFAreaMode SShort 1 Single-point AF
Exif.Canon.AFNumPoints SShort 1 63
Exif.Canon.AFValidPoints SShort 1 61
Exif.Canon.AFAreaWidths SShort 63 218 218 218 218 [...] 0 0
Exif.Canon.AFAreaHeights SShort 63 218 218 218 218 [...] 0 0
Exif.Canon.AFXPositions SShort 63 -336 -746 -1101 -1437 [...] 0 0
Exif.Canon.AFYPositions SShort 63 547 625 625 625 [...] 0 0
Exif.Canon.AFPointsInFocus Short 4 29
Exif.Canon.AFPointsSelected Short 4 29
Exif.Canon.AFPrimaryPoint Short 4 (none)
You see, I've selected a single AF point, i.e. the 29'th point. The lens I used was a good one, so no AF-points were disabled (AFPrimaryPoint
).
Again you look through the viewfinder. But this time you've selected multiple points which the camera may use for focusing.
Exif.Canon.AFAreaMode SShort 1 Large Zone AF
Exif.Canon.AFNumPoints SShort 1 63
Exif.Canon.AFValidPoints SShort 1 61
Exif.Canon.AFAreaWidths SShort 63 218 218 218 218 [...] 0 0
Exif.Canon.AFAreaHeights SShort 63 218 218 218 218 [...] 0 0
Exif.Canon.AFXPositions SShort 63 -336 -746 -1101 -1437 [...] 0 0
Exif.Canon.AFYPositions SShort 63 547 625 625 625 [...] 0 0
Exif.Canon.AFPointsInFocus Short 4 0,21,25,26,46
Exif.Canon.AFPointsSelected Short 4 19,20,21,24,25,26,45,46,47,[...],58
Exif.Canon.AFPrimaryPoint Short 4 3,4,9,10,11,30,[...],40,41,55,59,60
As you see, only a subset of selected AF points are actually used by the camera to focus the picture (AFPointsInFocus
). However the lens you used was a cheap one. Therefore, some phase-AF points have been disabled and you cannot even select them when looking through the viewfinder.
You take a picture by using the live-view of the camera. In the live-view screen, you have a single small rectangle that you can move around and use for focusing the picture:
Exif.Canon.AFAreaMode SShort 1 Flexizone Single
Exif.Canon.AFNumPoints SShort 1 63
Exif.Canon.AFValidPoints SShort 1 1
Exif.Canon.AFAreaWidths SShort 63 600 0 0 0 0 [...]
Exif.Canon.AFAreaHeights SShort 63 512 0 0 0 0 [...]
Exif.Canon.AFXPositions SShort 63 -128 0 0 0 0 [...]
Exif.Canon.AFYPositions SShort 63 384 0 0 0 0 [...]
Exif.Canon.AFPointsInFocus Short 4 0
Exif.Canon.AFPointsSelected Short 4 0
Exif.Canon.AFPrimaryPoint Short 4 (none)
The camera still stores 63 AF points, but given the live-view setting, there is only one AF point available. Ofc, this is point number zero, which is both, selected and used to focus the picture. All the other AF points in that array are (thankfully) zeroed out to avoid to contain some uninitialized garbage.
Now it's getting interesting. Again live-view, but this time using multiple AF points and you let the camera decide which one(s) to use.
Exif.Canon.AFInfoSize SShort 1 546
Exif.Canon.AFAreaMode SShort 1 Flexizone Multi (49 point)
Exif.Canon.AFNumPoints SShort 1 63
Exif.Canon.AFValidPoints SShort 1 63
Exif.Canon.AFAreaWidths SShort 63 567 567 567 567 [...]
Exif.Canon.AFAreaHeights SShort 63 485 485 485 485 [...]
Exif.Canon.AFXPositions SShort 63 -2384 -1788 -1192 -596 [...]
Exif.Canon.AFYPositions SShort 63 1536 1536 1536 1536 [...]
Exif.Canon.AFPointsInFocus Short 4 22,23,24,31,32,33,40,41,42
Exif.Canon.AFPointsSelected Short 4 0,1,2,3,4,5,6,7,8,9,10,[ALL],62
Exif.Canon.AFPrimaryPoint Short 4 (none)
Surprisingly the 5D Mark IV now uses 63 AF points rather than only 61 as before. All of them are selected (that means "considered") when focusing the picture, but only a few of them are finally used to focus the picture.
Thanks, Tom. I'll add this to exiv2.org which is machine-generated. There are external references to bloggs discussing MakerNotes and other useful resources. I'll modify the makernote page to reference this discussion. https://exiv2.org/makernote.html
This will get done in September when I'm working on Exiv2 v0.27.3 (scheduled for 2019-09-30).
Describe the bug
Exif.Canon.AFInfo
is misinterpreted asunsigned short
. It should besigned short
though. From my understanding this applies to both AFInfo and AFInfo2, because the AF coordinates originate from the image center (0,0), thus some of them will be negative.To Reproduce Steps to reproduce the behaviour:
Provide image with which you observed the issue:
Executing
exiv2 -PEkycv 62878860-3c552580-bd2a-11e9-94c0-cd4617d1af80.JPG
yieldswith insanely high numbers > 60000 . They should be negative.
Expected behavior Exiftool reports it correctly:
exiftool -a -u -g1 62878860-3c552580-bd2a-11e9-94c0-cd4617d1af80.JPG
Desktop:
Linux 4.12.14-lp151.28.10-default x86_64
Additional context BTW: Exiftool also reports which focus point(s) was/were used:
I cannot find this information in exiv2. Am I missing smth.?