First Steps Toward ExIf35 on Mac

My first attempt to convert ExIf35 from .NET to Mono to run on Mac has not gone very well…

Unhandled Exception: System.Reflection.TargetInvocationException:
Exception has been thrown by the target of an invocation. —>
System.OverflowException: Number overflow.
 at (wrapper managed-to-native)
object:__icall_wrapper_mono_array_new_specific (intptr,int)
 at System.Drawing.Icon.InitFromStreamWithSize (System.IO.Stream
stream, Int32 width, Int32 height) [0x00000]
 at System.Drawing.Icon..ctor
(System.Runtime.Serialization.SerializationInfo info, StreamingContext
context) [0x00000]
 at (wrapper managed-to-native)
System.Reflection.MonoCMethod:InternalInvoke
(object,object[],System.Exception&)
 at System.Reflection.MonoCMethod.Invoke (System.Object obj,
BindingFlags invokeAttr, System.Reflection.Binder binder,
System.Object[] parameters, System.Globalization.CultureInfo culture)
[0x00000]
 — End of inner exception stack trace —
 at System.Reflection.MonoCMethod.Invoke (System.Object obj,
BindingFlags invokeAttr, System.Reflection.Binder binder,
System.Object[] parameters, System.Globalization.CultureInfo culture)
[0x00000]
 at System.Reflection.MethodBase.Invoke (System.Object obj,
System.Object[] parameters) [0x00000]
 at System.Runtime.Serialization.ObjectRecord.LoadData
(System.Runtime.Serialization.ObjectManager manager,
ISurrogateSelector selector, StreamingContext context) [0x00000]
 at System.Runtime.Serialization.ObjectManager.DoFixups () [0x00000]
 at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadNextObject
(System.IO.BinaryReader reader) [0x00000]
 at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectGraph
(System.IO.BinaryReader reader, Boolean readHeaders, System.Object&
result, System.Runtime.Remoting.Messaging.Header[]& headers) [0x00000]
 at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.NoCheckDeserialize
(System.IO.Stream serializationStream,
System.Runtime.Remoting.Messaging.HeaderHandler handler) [0x00000]
 at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize
(System.IO.Stream serializationStream) [0x00000]
 at System.Resources.ResourceReader.ReadNonPredefinedValue
(System.Type exp_type) [0x00000]
 at System.Resources.ResourceReader.ReadValueVer2 (Int32 type_index) [0x00000]
 at System.Resources.ResourceReader.LoadResourceValues
(.ResourceCacheItem[] store) [0x00000]
 at System.Resources.ResourceReader+ResourceEnumerator.FillCache () [0x00000]
 at System.Resources.ResourceReader+ResourceEnumerator..ctor
(System.Resources.ResourceReader readerToEnumerate) [0x00000]
 at System.Resources.ResourceReader.GetEnumerator () [0x00000]
 at System.Resources.ResourceSet.ReadResources () [0x00000]
 at System.Resources.ResourceSet.GetObjectInternal (System.String
name, Boolean ignoreCase) [0x00000]
 at System.Resources.ResourceSet.GetObject (System.String name,
Boolean ignoreCase) [0x00000]
 at System.Resources.RuntimeResourceSet.GetObject (System.String
name, Boolean ignoreCase) [0x00000]
 at System.Resources.ResourceManager.GetObject (System.String name,
System.Globalization.CultureInfo culture) [0x00000]
 at System.Resources.ResourceManager.GetObject (System.String name) [0x00000]
 at ExIF35.Form2.InitializeComponent () [0x00d04] in
/home/curtis/Development/ExIF35/ExIF35/Form2.Designer.cs:334
 at ExIF35.Form2..ctor () [0x0002a] in
/home/curtis/Development/ExIF35/ExIF35/Form2.cs:21
 at (wrapper remoting-invoke-with-check) ExIF35.Form2:.ctor ()
 at ExIF35.Program.Main () [0x0000b] in
/home/curtis/Development/ExIF35/ExIF35/Program.cs:18

ExIf 35

With all that has been going on with ExIf 35 and the amount I have blogged about it, it has occurred to me that I haven’t really introduced the app on my blog at all, outside of the problems I have been having with getting things working exactly the way that I want.

First, a screenshot:

The application is designed for film photographers (me) to store information about each exposure on a roll. The original intent of the application was to simply store the information into an XML file, but after that portion of the application was finished being written I added the ability for the application to write the information in the image file for the scanned negative or print. At some point I also decided that I wanted to keep up with lens information, which of course required me to learn a new skill of putting information into the files using XMP, what a joyful experience that was. Now the application is on the path to fully utilizing XMP, including contact information (I still have to put that feature in). I am also working on utilizing some custom fields in XMP that will store the information that is specific to the film process, such as the film type, developing chemicals used and the date the roll was developed. I intend to in the future (when the application has a web presence) to post the specifications for the custom fields that I utilize. In the future I may also add functionality for managing the rolls and not just the images on the rolls.

This is the form used to add or edit images on a roll.

This form is used to manage the lenses available to the exposures.

Finally, this form will be used to write the information to the JPEG files. As you can see, it also allows the inclusion or not of other information.

 

SourceForge Project: https://sourceforge.net/projects/exif35/

Download From: https://sourceforge.net/projects/exif35/files/ (latest has Windows icon beside it)

Lens Information Stored

Finally, I have managed to store lens information in my JPEG files! It isn’t using ExIf though, because honestly, it’s way too hard and would require me learning way too much information about how the Makernote segment of ExIf works. As an alternative, I am using XMP. XMP is an Adobe developed standard based on XML that is embedded into JPG files (or as a standalone beside RAW). I am so far using two fields of XMP that come from Microsoft’s standards used for Windows Vista/7’s image management tools, those are /xmp/MicrosoftPhoto:LensManufacturer and /xmp/MicrosoftPhoto:LensModel as well as /xmp/xmp:lens and /xmp/aux:Lens. I’ve gone from having 0 places for lens information to having 3 places for lens information. At this point I am just happy it’s in there, but now that I am using XMP, I have more places to put information which means I can allow for the option of storing more information in the files. I now have intentions on letting ExIf 35 store contact information in the files when the option is selected. Additional things I would like to store is things like the chemicals used in developing and a better way to do the film information, other than just a user comment area that states “Shot on ____ film”. Because things are moving more digital, I am likely to have to write my own schema addition to XMP and store the information. It’s likely that the only thing that will read those fields is ExIf 35 itself, but I’m hopeful that if it has to be done, I might be able to convince Flickr to adopt my schema addition as well, since it is quite likely it would be the only one anywhere near supporting film information. All of this information is relevant to the image, and it would be great to get it all in.

ExIf Lens Information

I think I have managed to accomplish all that I wanted with ExIf except for one thing. I still want to store lens information in the ExIf info. Unfortunately, the only place to do that is MakerNotes, and I don’t know how to work with them. It is my understanding that I would have to pick a specific set of makernotes to use for this, but I’m not even sure how to go about that. Because of the nature of my project I am not tied down to one particular set of notes, but that also means that I don’t need all of the tags included in a full set. I can’t make heads or tails out of how makernotes function. Do I have to somehow specify what the notes are? Are there internal references between the notes that tell photo viewers what each tag is? I don’t have a clue and its starting to get to me. Is it possible to create my own maker notes? My guess on that is no, since everyone seems to be desperate to track down makernotes for every major camera ever created. I feel like I am Googling in circles at the moment trying to make things work.

What is deserving of film?

What images are deserving of being stored on film? As I have only taken 7 exposures of film so far I have found myself thinking about this a good bit. I don’t think I would want to us film for special occasions, as there are way too many things that could go wrong, and yet, I don’t want to use film for frivolous photography because film is expensive. I suppose this puts film in the category of “serious art photography”, but I don’t like that, as I don’t think “serious” and “art” go together, one pollutes the other. I do believe I want to use film only for art photography and not for the other purposes mentioned. I still question what I should shoot as I don’t think I have ever thought about photography in this way. With clay I have to put a lot of effort and focus into what I do because the clay is precious. When thinking about it, film is even more precious because while you can make a bowl, even though it may be a bad bowl, it still has all of the basic properties of a bowl, it can hold things. With film, a bad exposure is just that, a bad exposure. I suspect my problem here in the question of what deserves film is more or less about my compositional skill, which at the moment is pretty non-existent. With digital I shoot until things look right, with film I don’t have that option. Perhaps it’s time for me to wander around with a viewfinder to my head and answer my own question.

The Many Ways to Flash (or Not to Flash)

Just thought of adding some of the more fun flash codes to my ExIf tool, but have decided against it for now unless someone directly requests it. I am perfectly happy with the binary choice of 0 (Flash did not fire) or 1 (Flash fired). All of the other options are roughly as easy from a logical standpoint, but they are much harder to pass into my existing code for encoding into the ExIf of image files.

0000.H = Flash did not fire.

0001.H = Flash fired.

0005.H = Strobe return light not detected.

0007.H = Strobe return light detected.

0009.H = Flash fired, compulsory flash mode

000D.H = Flash fired, compulsory flash mode, return light not detected

000F.H = Flash fired, compulsory flash mode, return light detected

0010.H = Flash did not fire, compulsory flash mode

0018.H = Flash did not fire, auto mode

0019.H = Flash fired, auto mode

001D.H = Flash fired, auto mode, return light not detected

001F.H = Flash fired, auto mode, return light detected

0020.H = No flash function

0041.H = Flash fired, red-eye reduction mode

0045.H = Flash fired, red-eye reduction mode, return light not detected

0047.H = Flash fired, red-eye reduction mode, return light detected

0049.H = Flash fired, compulsory flash mode, red-eye reduction mode

004D.H = Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected

004F.H = Flash fired, compulsory flash mode, red-eye reduction mode, return light detected

0059.H = Flash fired, auto mode, red-eye reduction mode

005D.H = Flash fired, auto mode, return light not detected, red-eye reduction mode

005F.H = Flash fired, auto mode, return light detected, red-eye reduction mode

On the other hand, I have decided to add all 21 types of light, since that seems more useful (and is less likely to give me a headache)

1 = Daylight

2 = Fluorescent

3 = Tungsten (incandescent light)

4 = Flash

9 = Fine weather

10 = Cloudy weather

11 = Shade

12 = Daylight fluorescent (D 5700 – 7100K)

13 = Day white fluorescent (N 4600 – 5400K)

14 = Cool white fluorescent (W 3900 – 4500K)

15 = White fluorescent (WW 3200 – 3700K)

17 = Standard light A

18 = Standard light B

19 = Standard light C

20 = D55

21 = D65

22 = D75

23 = D50

24 = ISO studio tungsten

255 = other light source

ExIf Bliss

After a little more fighting, I finally got things about as far as I think I can. I do not have any lens information in yet, but as far as I can tell there is no officially supported tag for it, only things like Nikon’s maker note fields for it. It sucks, but unfortunately I am limited by the complexities of ExIf itself. I am starting to feel a bit like I am doing a lot of work for nothing, because in general I feel like I have no real results. I have not developed any of my own film and scanned it, so I won’t be able to do this with real images until I do.

Camera: Nikon N80QD
Exposure: 0.001 sec (1/1000)
Aperture: f/2.8
Focal Length: 50 mm
ISO Speed: 400
Flash: No Flash
File Size: 5.7 kB
File Type: JPEG
MIME Type: image/jpeg
Image Width: 554
Image Height: 267
Encoding Process: Baseline DCT, Huffman coding
Bits Per Sample: 8
Color Components: 3
X-Resolution: 96 dpi
Y-Resolution: 96 dpi
Image Description: Test image for the Nikon N80QD
Orientation: Horizontal (normal)
Software: ExIf 35
Date and Time (Modified): 2010:03:05 14:00:00
Artist: Curtis M. Kularski
Exposure Program: Aperture-priority AE
Date and Time (Original): 2010:03:05 14:00:00
Date and Time (Digitized): 2010:03:08 21:53:53
Metering Mode: Average
User Comment: Shot on Fujifilm Neopan 400
Focal Length In35mm Format: 50 mm

ExIf Bytes

I am victorious over ExIf! The documentation for ExIf overcomplicates things. While ExIf uses a lot of different types (0x1 through 0xA), it is possible to interact with most common values utilizing only 2 of these, 0x2 and 0x5. 0x2 is the null terminated string, and 0x5 is the 2 pair of Long Ints, acting as a rational. It would also seem that even though the documentation suggests that length only matters for 0x2, it cares for all of them, so it is a must to give the length of the byte array used to carry the long ints. A small error on my part was trying to convert directly from String (because I used System.Window.Forms.TextBox to get the information) to byte[] without passing through the intermediate int, or trying to convert to byte[] from double, which was very nasty. I learned these little tricks about things by reading in ExIf information in the application itself without the aid of any little helper apps that try to clean things up, it make the structure a lot more clear.

For anyone else trying a similar exercise in futility, here is a bit of my code:


if (Type == 0x2)

{

tmpProp.Len = value.Length + 1;

value = value + nullChar;

tmpProp.Value = ASCIIEncoding.ASCII.GetBytes(value);

}

else
if (Type == 0x5)

{

 


Byte[] tmp1 = BitConverter.GetBytes(Convert.ToInt32(value.Split(‘/’)[0]));


Byte[] tmp2 = BitConverter.GetBytes(Convert.ToInt32(value.Split(‘/’)[1]));


Byte[] tmp3 = new
Byte[tmp1.Length + tmp2.Length];

tmp1.CopyTo(tmp3,0);

tmp2.CopyTo(tmp3, tmp1.Length);

 

tmpProp.Value = tmp3;

tmpProp.Len = tmp3.Length;

}

I love C#, so simple, but yet such a pain in the ass, all at once.

The Downfall of Distance Education

When I first started distance education (online) courses back in 2004 things were different than they are now. From that statement you might gather that things have improved, you know, something technical, so it has to have gotten better. The situation is quite the opposite. When I started online courses, I liked them better than lecture courses because they were better on many different aspects. Online instructors used to be specialized in what they did, they had a special affection for the online course delivery method. Often instructors would use such tools as web based chat, interactive websites and sometimes even video to keep students engaged in courses. The point being that the courses were actually web based courses, using the Internet as a key part of the instructional process and not just as the delivery method for the course. Now courses seem to be more structured like independent study courses that merely utilize the Internet as a method for sending in papers or taking quizzes. There is no instruction and often instructors are primarily lecturers looking to pick up a few extra hours on their schedule. To students, these instructors barely exist. I have a hard time remembering the names of my instructors because of their lack of interaction. I remember a time when I took online courses and I had a message in my inbox from an instructor at least once a week, sometimes more. Instructors would do things like send out links that may be of interest, or some little personal observation about course performance. Now the courses are pretty much forced to run themselves. It is quite a sad change. I feel as though the changes in the way online courses have been treated will eventually cause the online method to either be terminated, or force them into a completely different accreditation status.

I believe the change in the way distance education courses have been taught in recent years has a lot to do with adult learners wanting to complete degrees. Those adult students do not want a lot of a materials to handle, or any type of interaction, they just want to do the reading for the course, take the test, and then get a meaningless piece of paper to stick on the wall. I do not believe those students truly want an education, they want a degree. With that downturn of academic ambition there isn’t a lot of reason for instructors to be involved or to do much more than a copy/paste online course in Blackboard. The courses are technically capable of running themselves, they can grade a lot of their own material and they can handle operating on a schedule, no intervention required, but do we really want to change the way academic institutions are structured to have students interacting with a course and not an instructor? If this pattern continues, that’s what will happen, no more instructors, just courses and “course designers” (the people that presently prepare courses for instructors).

I hope that when I begin my masters program I won’t find the same thing in graduate courses as I am finding in undergrad courses.

Still an ExIf No Go

I am still trying to wrap my head around everything in ExIf. The Strings are no big deal, they just convert cleanly to byte arrays and go into the file, but I don’t even know where to begin making things the right format for everything else. If anyone can make any sense of this, please see the documents below, and if you think you can help, request to be added to the project on SourceForge so you can have SVN access to active code.

http://msdn.microsoft.com/en-us/library/system.drawing.imaging.propertyitem.type.aspx Defines the types I am forced into using

http://www.exif.org/samples/nikon-e950.html Gives some examples of the fields and their values (still not helpful, since it doesn’t give me the raw input form)

http://msdn.microsoft.com/en-us/library/ms534418%28VS.85%29.aspx The tags, in order, that VS supports.

http://exif35.svn.sourceforge.net/viewvc/exif35/ExIF35/ My source code. Feel free to poke around.

 

The problem:

Everything has to be converted to an array of bytes (byte[]). I do not know how to get things like 1/100, 2.8/1 and 50/1 into the proper forms (see first link above) to put them into the byte array. I am just so incredibly frustrated at this point.