Wednesday, March 3, 2010

J2ME: EXIF and lightmetering Part 1

I am a bit of a camera obsessive. I got into photography with a digital P&S, progressed to a DSLR, and then got into film. Since then, my camera collection has taken over several surfaces in the flat. I don't have that many, but then I don't have that many surfaces.

Most of the collection consists of old cameras; my theory is that if you want to take crisp "perfect" images, a DSLR is the way to go. This is a theory based mainly on laziness, but it works for me.

In general, the film cameras have been chosen for looks at least as much as quality. The Rolleiflex has both in spades, of course.

Most of the old cameras do not have a light meter, and many with the old selenium cell meters simply do not work any more.

I do own a couple of lightmeters, but I find they are a pain to use, and new ones are basically extremely expensive flash looking versions with exactly the same functionality.

What I have been doing it using the dSLR to take a preview shot, then transferring the settings over to whatever camera I am currently playing with. However, this becomes a bit tedious after a while, and also having, say, the Rolleiflex and the dSLR round my neck results in severe neck strain.

So, ideally, I want a very small camera than can take a preview shot with the ability to tell it the ISO and, usually, the aperture I want. I can then check the preview looks okay, and transfer the settings over with any modifications required. However, P&S cameras with these manual settings are not cheap and often have big limitations on the ISO and f/stop they allow you to set, so an alternative solution is to take the preview with whatever settings the camera wants, then allow me to easily convert them into ones I can use.

This is where my mobile comes in. It is extremely small, I always have it on me, and it has a camera with a full auto mode that takes JPEGs stuffed full with the EXIF data for the exposure. Perfect. Except that, on the phone, there is no way of actually viewing the EXIF.

However, the phone, a Sony Ericsson C903, has mobile Java, and I've seen some Java before, so I decided to give writing an app for it a shot.

It was an interesting exercise, and along the way I discovered several fun things. For example, mobile Java is one of the most frustratingly NON-device independent environments it's been my misfortune to use, the certification requirements are beyond absurd, and my phone has one of the most annoying bugs ever to have existed - when your app works perfectly and is extremely useful, having the phone randomly lose and/or corrupt the memory card it's sitting on is rather irritating.

The first bit of the code, which we have finally come to, is something that will read EXIF data out of JPEGs. I had a fish round for some libraries and found lots of great code that was either extremely big, extremely non J2ME compatible, or both.

Then I discovered this Javascript library, which I have to say, is brilliant. It's a use for client side Javascript and AJAX that simply would never have occurred to me in a million years. It is perfect for my uses because being entirely client side Javascript it uses very basic language features and is very small, ideal for conversion to Java by someone who hasn't used Java for about 8 years :o)

The code was written in the J2ME 3.0 SDK editor, which seems to have mangled the indentation for any other editor, but source code formatters are not exactly hard to find. The basic EXIF when compiled has not J2ME specific imports, so can be linked into any Java project; this is very handy for testing, obviously.

I made a couple of changes; I added X_FNumberAsString as a new data item for laziness, and created a Fraction class to help with maintaining the normal form of shutter speeds when manipulating them (a later post).

The ByteArrayWrapper class duplicates the required functionality from binaryajax.js.

EXIFReader contains the main functionality, and EXIFTags the tag names / descriptions and offsets, and also the list constants for various tags.

The classes live in the package rext.simpleexif.

It is pretty easy to use; you simply load in an image file into a byte[], then create the reader:

EXIFReader reader = new EXIFReader();
  
boolean ok = false;

try
{
 ok = reader.readEXIFFromByteArry(data);
}
catch(Exception e)
{
}

The reader object has three Hashtables for the various tags, EXIF, TIFF and GPS, and a Vector for debug messages called LOG.

Print out all EXIF tags to the console:

Enumeration exifk = reader.EXIF.keys();

while(exifk.hasMoreElements())
{
 String s = (String)exifk.nextElement();
 System.out.println(s + ": " + String.valueOf(reader.EXIF.get(s)));
}

You can get the code from the link below, including a small test console app that will print off the debug info then the EXIF data for a JPEG file.

1 comment:

  1. hi robw, i'm newbie in j2me, i got error on

    import rext.simpleexif.*;

    can you help me?

    thanks

    ReplyDelete