C#

Personal Journaling

I have many times in my past thought of starting a personal journal. I started at first a long time ago with a paper journal, and considered keeping a word processing document, but nothing ever seemed to work for me. In August 2004 with the opening of this blog I got a little closer to being able to do what I wanted to do, at least on the external perspective. I still do not have anything personal. I tried to do it in GITI for a personal way, but I just could never remember to write stuff and it just didn’t quite seem as together and coherent as I would like. I am now considering writing a software that will reside on a desktop computer, but will be able to write information somewhere that GITI can access it. The reason I feel I need to write my own software for this is that I want to keep more information in a journal than just a daily narrative and other plain text information. I want to be able to store sample photos from the day, and maybe a tracklog and other information that seems relevant to the events of the day. In some ways it would be nice to form my daily journal entries from a variety of little pieces of information and just have them grouped by the date. Those pieces include:

  • Text of day’s activities
  • Report of what is on the calendar
  • Collection of status posts and their timestamps
  • Photo(s) selected from the day, if available
  • Tracklog from the day, if available
  • Recipes for foods I create that day

In some ways social media stuff handles a lot of this, except for the more private aspects, but I do not want something like a journal stuck in the cloud. I want control of the information and I do not want to be bound to some type of information system that can loose data, change control or in some other way be subverted by an outside force. This is probably crazy and excessive, but it will give me something to work on in my spare time.

New App: Match Maker Duplicate Finder

At some point over the last few hours I threw together this application, its a minor app. I needed a way to identify potentially duplicate files in a certain folder on my network, and I really didn’t want to do it manually, so here is a quick little program to take care of that task in a rather dirty fashion. I use the program to identify potentially duplicate videos that have been stored in dated folders after being downloaded.

The application is written in C# and requires .NET 3.5 to run (if you are on a modern Windows OS, you are ok). The program will take a folder you specify and treat it as the top of the tree, and from there recursively gather filenames. Once those names are gathered it compares all of the base file names as well as sizes. Not a fancy app, but thought it might be useful to someone.

For Download: http://media.icurtis.me/software/DuplicateFinder.exe  [14KB]

image

Writing Destructive Code Is Fun

I don’t know why, but writing code that is somewhat destructive is really fun. I was thinking earlier that there is no way in ExIf35 itself to fully remove the configuration file and remove personally-identifying information from the application. This seemed like it could be a bad things, so I set out to make a simple feature addition to ExIf35, a kill switch. It’s probably a little childish to make it this dramatic or to enjoy writing the code this much, but how often do you get to tell an application to go through and individually remove every file in a (system) folder? I didn’t do the really annoying application kill thing where there are 5 nested boxes asking variations of “Are you sure?”.

image

Red is always a fun color for a button, makes it look important and mysterious.

Cross Platform Compatibility Crushed

I discovered last night that Mono does not contain certain parts required to make ExIf35 work on other platform, mainly, the basic parts of the Windows Presentation Foundation, which allow the metadata writing components that I use to function. At the moment I have no idea how I am going to proceed. It has crossed my mind to neuter out Form3 (the thing that writes exif to the files) and ship the application as is for other platforms, but that is somehow less than optimal. I have also considered doing everything normal, but then creating a special form3 that will write a .xmp sidecar file for each image, for later reintegration by another application. At the moment I am attempting to locate any way possible to write those values to the file that doesn’t use any part of WPF, so that there will be a chance that Mono can use it. My fear is that I will end up having to learn how to write directly to the image file in byte form to implement all of these fields. It would be neat to learn how to do that, but at the same time, quite a huge annoyance. So for now, sorry Mac users, it isn’t going to happen any time soon :-(

Working Around a Flaw

I have been fighting with a problem in code for several weeks now relating to the writing of a negative exposure bias value to exif information using the .NET framework’s metadata class. The class has a set of properties and a table of what is allowed to be written to each of those properties. Unfortunately for my project, there was an oversight in that system. A variety of properties, such as System.Photo.ExposureBiasNumerator, do not accept negative values, even though they are supposed to hold signed integers. This has caused me to need to cast an absolute value on all of my exposure bias values, making them all positive. I have attempted to inquire through the MSDN forums and other sources for a reason for this, waiting for someone to point out that I’m wrong, but so far, no one has, so I must assume that there is a flaw. All other values are easy enough to write correctly with no special cases.

Tonight I have reinstated the ability to write negative values to exposure bias. Effective in ExIf 35 build 20100410 that functionality will be again functional.

I knew that there had to be a way to make it work, since those values are present in other applications and applications using the .NET Framework can read those values. I pulled some images into my diagnostic form and began reading /app1/ifd/exif/{ushort=37380} (thats ExIf 0×9204) from each of them. I found that there was an 11 digit number recorded in the space for all of them, both with positive and negative values. This got me curious, since a 32 bit integer is only 10 digits. I double checked with Visual Studio and it turns out that my two signed integers were being stored as one giant unsigned 64 bit integer. I began by trying to determine what those numbers could represent, trying to find any and all relationships between those 64 bit integers and the 2 part signed shorts I was working with (relationship between 30064771068 and –2/3 for example). Finally I gave up and decided to read the bytes.  30064771068 is 251, 255, 255, 255,6,0,0,0. I know they are supposed to be 32 bit numbers, so that takes us to 251, 255, 255, 255 and 6,0,0,0. 251 –255 = –4, and 6 = 6, making a rational of –4/6, reducing to my expected –2/3. Now it all makes sense, but I ask myself, why must I generate a 64-bit integer manually to make this work when Microsoft has created perfectly understandable way to write this crap to a file. I guess sometimes being able to do things the old way has its benefits.

So, now I present, my code:

//Assume exp.ExposureBias is a string such as -2/3
if (exp.ExposureBias.Contains("/")) //check for rational
{
double tmp = Convert.ToDouble(exp.ExposureBias.Split('/')[0]);
tmp = tmp / Convert.ToDouble(exp.ExposureBias.Split('/')[1]);
tmp = Math.Round(tmp, 1);
exp.ExposureBias = tmp.ToString();
}
//convert to a valid integer value
int exposureBias = Convert.ToInt16(Math.Floor(Convert.ToDouble(exp.ExposureBias) * 10));
//create the array to hold the 64 bits
Byte[] exposureBiasByte = new Byte[8];
if (exposureBias < 0)
{
exposureBias = 256 + exposureBias;
exposureBiasByte[1] = 255;
exposureBiasByte[2] = 255;
exposureBiasByte[3] = 255;
}
else
{
exposureBiasByte[1] = 0;
exposureBiasByte[2] = 0;
exposureBiasByte[3] = 0;
}
exposureBiasByte[0] = Convert.ToByte(exposureBias);
exposureBiasByte[4] = 10;
exposureBiasByte[5] = 0;
exposureBiasByte[6] = 0;
exposureBiasByte[7] = 0;
Int64 exposureBiasLong = BitConverter.ToInt64(exposureBiasByte, 0);

Changing of ExIf Tools

As of Monday, ExIf 35 had its first major release. With the release of “Milestone 1″, daily build number 20100405, I decided that the application was feature complete and stable. The entire build package contained the released executable for the Windows version of the application, as well as two different mobile platforms (PocketPC 2003, Windows Mobile 5). The application works quite well for what its designed for, which is nothing more than tagging scanned negatives or prints with proper information that was recorded when the image was taken. This comes with several major problems, the least of which is that every film photographer in the world except me runs a Mac. The worst of the problems is that the majority of film photographers are not in it for the art of it, or any nostalgic purpose, they are just lazy and un-adaptive, which means that they are avoiding the digital side of things for convenience and in general do not record exposure details. In my opinion, there is as much science as art in photography, especially in film (we can say for certain that there is chemistry), and as scientists of light and optics it is our responsibility to record details about each “experiment” we capture.

Now, off of my film soapbox, I am finding that the level of precision and care I take to tagging and keeping orderly my film information I wish to apply at least partially to my digital work. Of course the exif portion is already handled for me (thank the great maker for that), but I will be working on ExIfDSC to further manage this information. This will allow for manual adjustment of orientation, adding of tags, titles and descriptions. I plan to make the application function in two ways, first, just an image-by-image view that will let the user easily make adjustments without being distracted by 36 thumbnails on screen. Next there is to be a gallery view that will allow multiple image manipulation, mass rotations and such. ExIf35 works from its XML files, so will ExIfDSC, but it won’t be limited by them. ExIfDSC will support a majority of its processes by way of interacting directly with the image files. On the other hand, the gallery view will support forming gallery files, which will be images selected by the user that are important, have significance or are display-worthy. Sort of a more polished way of viewing images, eliminating much of the clutter that is associated with digital photography.

I am not abandoning ExIf35 and intend to actively support and promote it (as well as poke at it frequently for minor tweaks), but I need to change my focus to ExIfDSC so that all of the processes can be streamlined and my photographic world can be a happier place (but my happy place is a topic for another blog entry).

Problems with Images in C#

I am encountering a not-so-happy issue with programming in .NET for something that works with images. Because I write metadata and I don’t just read it, I am encountering issues regarding image quality and compression. If I let the happy little framework do things its way, I end up with files of reduced size. If I change the quality setting to be 100% (which I interpreted as “don’t fuck with it”), I get files that are much larger. I am intending to work only with metadata, not the images themselves, so I am at a loss as to what is going on here. I would really like to be able to directly copy the data from one file to the new file (since .NET requires a new file for each time a modification is done). I am so pissed off right now, since I have been releasing software for the past few weeks that will reduce image quality if allowed to overwrite the originals, and because I wasn’t using real files until now (just my sample images, which are simple geometric forms, under 10KB), I had no clue it was doing it. I knew a long time ago that my first pass (ExIf) was doing it, but I had no clue it was going on with the 2nd pass (XMP).

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 Bytes

I am victorious over ExIf! The documentation for ExIf overcomplicates things. While ExIf uses a lot of different types (0×1 through 0xA), it is possible to interact with most common values utilizing only 2 of these, 0×2 and 0×5. 0×2 is the null terminated string, and 0×5 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 0×2, 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 == 0×2)

{

tmpProp.Len = value.Length + 1;

value = value + nullChar;

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

}

else
if (Type == 0×5)

{

 


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.

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.