ExifTool Forum

ExifTool => Developers => Topic started by: RitchieB on December 04, 2014, 03:48:30 PM

Title: Decode Makernotes in C#
Post by: RitchieB on December 04, 2014, 03:48:30 PM
Hi

First, Phil, thanks so much for sharing all the info that you have on this  topic! Awesome!

I hope I'm not off sides by asking this but have been struggling for weeks on this...

I've written an app in C# to extract basic EXIF Tags. I'm using the code below to extract the makenotes tag, but cannot fathom how to decode it


PropertyItem propItem = image.GetPropertyItem(37500);
byte[] pv0 = propItem.Value;


This returns a byte array of about 7600 bytes.

I have looked at http://www.exiftool.org/TagNames/Canon.html but still cant seem to get it?

Is there a way to decode this byte array or am I totally on the wrong path?


Hope you can help  :)
Title: Re: Decode Makernotes in C#
Post by: Phil Harvey on December 04, 2014, 04:02:31 PM
Most maker notes are formatted as a TIFF IFD, usually after some sort of identifying byte string (although Canon does not do this).  You could take a look at MakerNotes.pm for some hints about this.

- Phil
Title: Re: Decode Makernotes in C#
Post by: RitchieB on December 04, 2014, 04:32:10 PM
Thanks Phil!!  :)

I am specifically targeting my camera (Canon 650D)

Sorry for my ignorance - where dO I find Makernotes.pm
Title: Re: Decode Makernotes in C#
Post by: Hayo Baan on December 05, 2014, 07:02:11 AM
Download the full version of exiftool from the website (http://www.exiftool.org/Image-ExifTool-9.77.tar.gz) and look in the source tree for the mentioned file.

HTH,
Hayo
Title: Re: Decode Makernotes in C#
Post by: Phil Harvey on December 05, 2014, 08:47:14 AM
I was trying to add a link to MakerNotes.pm on SourceForge (http://sourceforge.net/p/exiftool/code/ci/master/tree/lib/Image/ExifTool/MakerNotes.pm), but ran out of time when I made my last post.

- Phil
Title: Re: Decode Makernotes in C#
Post by: RitchieB on December 06, 2014, 06:35:05 PM
Thanks Phil & Hayo

I guess it boils down to


sub ProcessCanon($$$)
{
    my ($et, $dirInfo, $tagTablePtr) = @_;
    # identify Canon MakerNote footer in HtmlDump
    # (this code moved from FixBase so it also works for Adobe MakN in DNG images)
    if ($$et{HTML_DUMP} and $$dirInfo{DirLen} > 8) {
        my $dataPos = $$dirInfo{DataPos};
        my $dirStart = $$dirInfo{DirStart} || 0;
        my $footerPos = $dirStart + $$dirInfo{DirLen} - 8;
        my $footer = substr(${$$dirInfo{DataPt}}, $footerPos, 8);
        if ($footer =~ /^(II\x2a\0|MM\0\x2a)/ and substr($footer,0,2) eq GetByteOrder()) {
            my $oldOffset = Get32u(\$footer, 4);
            my $newOffset = $dirStart + $dataPos;
            my $str = sprintf('Original maker note offset: 0x%.4x', $oldOffset);
            if ($oldOffset != $newOffset) {
                $str .= sprintf("\nCurrent maker note offset: 0x%.4x", $newOffset);
            }
            my $filePos = ($$dirInfo{Base} || 0) + $dataPos + $footerPos;
            $et->HDump($filePos, 8, '[Canon MakerNotes footer]', $str);
        }
    }
    # process as normal
    return Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr);
}


As a novice C# hacker... not really making head or tail of this.

Would there be any merit in creating, with Phil's permission, a .NET PhilHarveyPhotoImageData Class? I'm a novice but would love to get involved in a project like this.

Or a little PhilHarvey PhotoSorter app.. After a shoot, dump your images in a folder, and flip though them, zoom, pan, deleting crap  photo's , moving good ones to a 'keep' folder, and on each image, display all the camera settings that were used for the shot (where I'm at at the moment EXCEPT for makernotes).. And perhaps add a crop feature without messing up the metadata..
Title: Re: Decode Makernotes in C#
Post by: Phil Harvey on December 07, 2014, 08:41:58 AM
Aside from checking the Canon-specific footer, that subroutine just calls ProcessExif() to process the maker notes as a standard EXIF.

You are free to create whatever .NET classes you want.  There is no need to attach my name to them.

- Phil
Title: Re: Decode Makernotes in C#
Post by: RitchieB on December 08, 2014, 10:35:59 PM
Hi Phil

Are you saying that the data returned bv


PropertyItem propItem = image.GetPropertyItem(37500);
byte[] pv0 = propItem.Value;


is structured as per JEITA CP-3451.In other words 12 byte IFD headers

Bytes 0-1  Tag
Bytes 2-3 Type
Bytes 4-7 Count
Bytes 8-11 Offset

Below are the first couple of bytes from the Makernotes tag for and image shot with a Canon 650D.
ByteIndex   Hex
0   27
1   0
2   1-> Tag = 1
3   0
4   3 -> Data Type = Short = 2 Byte Unsigned int
5   0
6   31 -> Length = Hex31 = 49 Shorts (98 Bytes)
7   0
8   0
9   0
10   68 - Offset to data (568 hex = 1384 bytes from the start of makernotes tag???)
11   5 - Offset to data
12   0
13   0
14   2 \tag no 2
15   0
16   3 -> Data Type = Short = 2 Byte Unsigned int
17   0
18   4
19   0
20   0
21   0
22   CA
23   5
24   0
25   0
26   3

If I ignore the first two bytes, then the values every 12 bytes (Red) seem like they may be tag numbers, and bytes 2-3 after the tag seem to fall within the range that specifies the data type.

Edit: It seems like the first two bytes of the Makernotes Tag indicate the number of sub tags

Am I on the right track?

Tag
Each tag is assigned a unique 2-byte number to identify the field. The tag numbers in the Exif 0th IFD and 1st IFD
are all the same as the TIFF tag numbers.
Type
The following types are used in Exif:
1 = BYTE An 8-bit unsigned integer.,
2 = ASCII An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL.,
3 = SHORT A 16-bit (2-byte) unsigned integer,
4 = LONG A 32-bit (4-byte) unsigned integer,
5 = RATIONAL Two LONGs. The first LONG is the numerator and the second LONG expresses the
denominator.,
7 = UNDEFINED An 8-bit byte that can take any value depending on the field definition,
9 = SLONG A 32-bit (4-byte) signed integer (2's complement notation),
10 = SRATIONAL Two SLONGs. The first SLONG is the numerator and the second SLONG is the
denominator.
Count
The number of values. It should be noted carefully that the count is not the sum of the bytes. In the case of one
value of SHORT (16 bits), for example, the count is '1' even though it is 2 bytes.
Value Offset
This tag records the offset from the start of the TIFF header to the position where the value itself is recorded. In
cases where the value fits in 4 bytes, the value itself is recorded. If the value is smaller than 4 bytes, the value is
stored in the 4-byte area starting from the left,
i.e., from the lower end of the byte offset area. For example, in big
endian format, if the type is SHORT and the value is 1, it is recorded as 00010000.H.
Title: Re: Decode Makernotes in C#
Post by: Phil Harvey on December 09, 2014, 02:12:45 PM
Yes.  The first 2 bytes are the number of entries in the IFD.  See the TIFF specification for details.

- Phil
Title: Re: Decode Makernotes in C#
Post by: RitchieB on December 16, 2014, 12:38:14 AM
Thanks Phil, I still don't have it quite right though.

Where does the offset start?

Below is the start of a MakerNote Tag from a Canon 650D.

First two bytes indicate 39 Tags - looks correct

Tag No 1 = CanonCameraSettings.
The values should be a count of 49 x 2Bytes, starting at ByteIndex 1384 (Offset from start of makernote) ?

ByteIndex   Hex   Item   Value
0   27   NoOfEntries   39
1   0   NoOfEntries   
2   1   TagNo   0x0001 - CanonCameraSettings
3   0   TagNo   
4   3   Type   Short (2-Byte)
5   0   Type   
6   31   Count   49
7   0   Count   
8   0   Count   
9   0   Count   
10   68   Offset   1384
11   5   Offset   
12   0   Offset   
13   0   Offset   

If I try to decode the 98 bytes from offset 1384, the values don't seem to match the settings used for the image.

There also seem to be some tags where the the data type x count is larger than 4 bytes (so the data should be found at the offset, and not stored in the 4 bytes allocated to the offset) but the offset indicated is larger that the 7632 bytes of the makernote?

ByteIndex   HexVal   Index2   Tag Name
1384   64   1   MacroMode
1385   0   1   MacroMode
1386   0   2   SelfTimer
1387   0   2   SelfTimer
1388   8   3   Quality
1389   0   3   Quality
1390   0   4   CanonFlashMode
1391   0   4   CanonFlashMode
1392   8   5   ContinuousDrive
1393   0   5   ContinuousDrive
1394   0   6   
1395   0   6   
1396   8   7   FocusMode
1397   0   7   FocusMode
1398   0   8   
1399   0   8   
1400   8   9   RecordMode
1401   0   9   RecordMode
1402   0   10   CanonImageSize
1403   0   10   CanonImageSize
1404   1   11   EasyMode
1405   0   11   EasyMode
1406   0   12   DigitalZoom
1407   0   12   DigitalZoom
1408   0   13   Contrast
1409   0   13   Contrast
1410   0   14   Saturation
1411   0   14   Saturation
1412   0   15   Sharpness
1413   0   15   Sharpness
1414   0   16   CameraISO
1415   0   16   CameraISO
1416   0   17   MeteringMode
1417   0   17   MeteringMode
1418   0   18   FocusRange
1419   0   18   FocusRange
1420   0   19   AFPoint
1421   0   19   AFPoint
1422   0   20   CanonExposureMode
1423   0   20   CanonExposureMode
1424   0   21   
1425   0   21   
1426   0   22   LensType
1427   0   22   LensType
1428   0   23   MaxFocalLength
1429   0   23   MaxFocalLength
1430   0   24   MinFocalLength
1431   0   24   MinFocalLength
1432   0   25   FocalUnits
1433   0   25   FocalUnits
1434   0   26   MaxAperture
1435   0   26   MaxAperture
1436   0   27   MinAperture
1437   0   27   MinAperture
1438   0   28   FlashActivity
1439   0   28   FlashActivity
1440   E3   29   FlashBits
1441   1   29   FlashBits
1442   0   32   FocusContinuous
1443   4   32   FocusContinuous
1444   0   33   AESetting
1445   4   33   AESetting
1446   94   34   ImageStabilization
1447   2   34   ImageStabilization
1448   0   35   DisplayAperture
1449   0   35   DisplayAperture
1450   0   36   ZoomSourceWidth
1451   0   36   ZoomSourceWidth
1452   0   37   ZoomTargetWidth
1453   0   37   ZoomTargetWidth
1454   0   39   SpotMeteringMode
1455   0   39   SpotMeteringMode
1456   0   40   PhotoEffect
1457   0   40   PhotoEffect
1458   0   41   ManualFlashOutput
1459   0   41   ManualFlashOutput
1460   0   42   ColorTone
1461   0   42   ColorTone
1462   0   43   
1463   0   43   
1464   0   44   
1465   0   44   
1466   0   45   
1467   0   45   
1468   0   46   SRAWQuality
1469   0   46   SRAWQuality
1470   0   47   
1471   0   47   
1472   0   48   
1473   0   48   
1474   0   49   
1475   0   49   

Title: Re: Decode Makernotes in C#
Post by: Phil Harvey on December 16, 2014, 06:49:27 AM
Hi Richie,

Have you tried the -htmlDump feature?  I should have mentioned this earlier.  This will give you and html page that may answer many of your questions.

- Phil