Wednesday, November 12, 2008

Opening files with LightZone from command-line

LightZone is a very useful commercial photo editor with some unique features like non-destructive and layer-based editing. To my mind, the developers has taken a very clever approach to save resulting edits inside of smaller-size JPEG files (thumbnails), so that any program can be used for previewing the resulting image, but opening of the file in LightZone will load the original image and show all the edits again with the possibility to make any changes and export a full-resolution image. The cool thing here is that edited files are very small especially when compared to 10Mb+ source RAW photos, contain all the editing history and can be previewed quickly with any software. And all this runs on Linux (thanks to Java - write once, run almost anywhere).

The only problem with LightZone (at least the Linux version) is that it doesn't accept filenames from the command-line! You have to start the program and select the file manually using the embedded file browser. Of course, this is not an option if you want to run LightZone from another application as an external editor, eg from F-Spot (more on this in a later post).

To make a long story short, I have written a small Java program that takes a filename on the command-line and then modifies LightZone preferences, so when you run it next time it will directly open the specified image.

Here it is:

import java.io.*;
import java.net.*;
import java.util.prefs.*;

/**
* LightZoneOpener - will modify LightZone preferences to open the
* specified file (image) on next startup.
* This is useful to force LightZone to open a particular file from
* the command-line, just run this code before starting LightZone.
*
* @author Anton Keks
*/
public class LightZoneOpener {

public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("Please specify filename to open in LightZone");
System.exit(1);
}
String filename = args[0];
if (filename.startsWith("file:"))
filename = new URI(filename).getPath();
File file = new File(filename).getCanonicalFile();
if (!file.exists()) {
System.err.println(file + " doesn't exist!");
System.exit(2);
}
File fileDir = file.getParentFile();

// set image folder as current one
Preferences folderPrefs = Preferences.userRoot().node("com/lightcrafts/ui/browser/folders");
int i = 0; File dir = file;
while ((dir = dir.getParentFile()) != null) {
folderPrefs.put("BrowserTreePath" + i++, dir.getName().isEmpty() ? "/" : dir.getName());
}
folderPrefs.remove("BrowserTreePath" + i);

// set selected image in the current folder
Preferences appPrefs = Preferences.userRoot().node("com/lightcrafts/app");
appPrefs.put("BrowserSelectionMemory" + fileDir.getPath().hashCode(), file.getPath());
// tell LightZone that last startup was OK just in case
appPrefs.put("StartupSuccessful", "true");

System.out.println("LightZone is now ready to open " + file + " on next start");
}
}

Here is what to do:
  1. save it to LightZoneOpener.java
  2. compile with javac LightZoneOpener.java
  3. run with java LightZoneOpener

Then you can create a small script that will automate the stuff for you (save it to ~/bin/LightZone):
#!/bin/bash
java -cp ~/bin LightZoneOpener "$@"
~/LightZone/LightZone

This assumes that you have extracted LightZone to ~/LightZone (in your home dir) and have the following two files in the ~/bin dir: the compiled LightZoneOpener.class and the script file LightZone (don't forget to set the execute permission with chmod a+x ~/bin/LightZone)

Here is all this pre-compiled. Just extract the file directly in your home and it will put all needed files into the bin directory. After next login your local bin will be in $PATH, so you will be able to use it.

Now you can run LightZone filename on the command-line in Linux (or using Alt+F2)! Have fun!


32 comments: