[patch] Read ISO data from Nikon Makernote, Fallback ApertureValue to FNumber
- From: Jared Roberts <jaredr gmail com>
- To: f-spot-list gnome org
- Subject: [patch] Read ISO data from Nikon Makernote, Fallback ApertureValue to FNumber
- Date: Tue, 4 Oct 2005 22:39:44 -0700
Attached is a patch which adds a couple of things to ExifUtils:
* Fallback to EXIF FNumber when ApertureValue is not present
* Read the ISO-speed exposure information from the Makernote field
of certain models
of Nikon cameras (tested with my GF's D70) as a fallback for when
the data is not
available in the normal EXIF spot.
This is my Hello World in C#. I hadn't touched C#, image file
formats, EXIF or any of that before a couple of days ago, so take this
code with a pinch of salt, all I can say is it seems to work for me.
I tried to make the code look as much as possible like the code around
it, but I'm sure there are C# idioms that I haven't picked up,
guidance would be much appreciated. In particular, I assume there's a
better solution than copying the makernote array, but everything I
thought of involved an unsafe block, so I assume I just haven't seen
the light yet.
One thing that's kind of baffling is that the info I had said the
maker note was an array of ushorts, and an exif dump confirmed this,
but I had to use GetDataUInt to get the data. I suspect there's a bug
with shorts and endian translation, but maybe I was just being
boneheaded somewhere. Can someone please confirm this for me?
--- f-spot-0.1.3/src/ExifUtils.cs 2005-09-29 00:56:25.000000000 -0700
+++ f-spot-0.1.3.hacked/src/ExifUtils.cs 2005-10-04 22:27:24.000000000 -0700
@@ -19,32 +19,35 @@
{
Exif.ExifData exif_data = new Exif.ExifData (path);
-#if UNSED_CODE
MakerType maker = MakerType.Unknown;
- string maker_tag_value = exif_data.LookupString (ExifTag.Make);
+ string maker_tag_value = exif_data.LookupFirstValue (Exif.Tag.Make);
if (maker_tag_value != null) {
- if (maker_tag_value.ToLower () == "nikon")
+ if (maker_tag_value.ToLower () == "nikon" ||
+ maker_tag_value.ToLower () == "nikon corporation") {
maker = MakerType.Nikon;
+ }
else if (maker_tag_value.ToLower () == "canon")
maker = MakerType.Canon;
}
-#endif
ExposureInfo info = new ExposureInfo ();
info.ApertureValue = exif_data.LookupFirstValue (Exif.Tag.ApertureValue);
+ if(info.ApertureValue == null) info.ApertureValue = exif_data.LookupFirstValue (Exif.Tag.FNumber);
info.ExposureTime = exif_data.LookupFirstValue (Exif.Tag.ExposureTime);
info.DateTime = exif_data.LookupFirstValue (Exif.Tag.DateTimeOriginal);
info.IsoSpeed = exif_data.LookupFirstValue (Exif.Tag.ISOSpeedRatings);
-// FIXME not sure why, this doesn't work.
-#if BROKEN_CODE
// Use the maker note to figure out the ISO speed rating if it's not in the standard spot.
- if (info.IsoSpeed == null && exif_data.LookupData (ExifTag.MakerNote) != null) {
+ Exif.ExifEntry maker_note = exif_data.LookupFirst (Exif.Tag.MakerNote);
+ if (info.IsoSpeed == null && maker_note != null) {
+ byte [] maker_note_data = maker_note.Data;
switch (maker) {
+// FIXME not sure why, this doesn't work.
+// may need JFIF "Exif\0" bumper -- see Nikon type 3 below
+#if BROKEN_CODE
case MakerType.Canon:
- byte [] maker_note = exif_data.LookupData (ExifTag.MakerNote);
- ExifData maker_ifd = new ExifData (maker_note_copy, (uint) maker_note_copy.Length);
- byte [] data = maker_ifd.LookupData ((ExifTag) 0x1);
+ ExifData maker_ifd = new Exif.ExifData (maker_note_data, (uint) maker_note_data.Length);
+ byte [] data = maker_ifd.LookupData ((Exif.Tag) 0x1);
if (data.Length > 0x10) {
switch (data [0x10]) {
@@ -59,12 +62,42 @@
}
}
break;
+#endif
+ case MakerType.Nikon:
+ // see: http://www.ozhiker.com/electronics/pjmt/jpeg_info/nikon_mn.html
+ if(maker_note_data.Length >= 6
+ && System.Text.Encoding.ASCII.GetString (maker_note_data, 0, 6) == "Nikon\0") {
+ if (maker_note_data[6] == 0x1 && maker_note_data[7] == 0x0) {
+ // Nikon Type 1 -- Not Implemented
+ }
+ if (maker_note_data[6] == 0x2
+ && (maker_note_data[7] == 0x0 || maker_note_data[7] == 0x10)) {
+ // Nikon Type 3
+ const int offset = 10; // nikon header is 10 bytes
+
+ byte [] maker_note_copy = new byte [maker_note_data.Length-offset+6];
+ // Apparently libexif doesn't recognize TIFF exif data
+ // because it lacks the JFIF "Exif\0" bumper
+ Array.Copy (System.Text.Encoding.ASCII.GetBytes ("Exif\0\0"), 0, maker_note_copy, 0, 6);
+ Array.Copy (maker_note_data, offset, maker_note_copy, 6, maker_note_data.Length-offset);
+ Exif.ExifData maker_ifd = new Exif.ExifData (maker_note_copy, (uint) maker_note_copy.Length);
+
+ Exif.ExifEntry iso_entry = maker_ifd.LookupFirst ((Exif.Tag) 0x2);
+ if (iso_entry != null) {
+ /* type should be ushort, but doesn't seem to work (?) */
+ uint [] iso_entry_data = iso_entry.GetDataUInt ();
+ if (iso_entry_data != null && iso_entry_data.Length > 0x1)
+ info.IsoSpeed = iso_entry_data[0x1].ToString();
+ }
+ }
+ }
+ // Nikon Type 2 makernotes jump straight to TIFF data -- Not Implemented
+ break;
// FIXME: Add support for other MakerNotes, see:
// http://www.fifi.org/doc/jhead/exif-e.html#APP1
}
}
-#endif
return info;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]