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 0x9204) 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;
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);