Original: Saturday 29 March 2008    Update: Friday 19 September 2008

Since starting to use Adobe Lightroom, I have found a number of occasions where I am unable to manipulate a Nikon raw file (NEF) to my satisfaction using Lightroom's raw converter. In these cases, Nikon's CaptureNX does a much better job and so I needed a way to simply launch CaptureNX from Lightroom when required. The problem with Lightroom is that it assumes that any external editor can't do the raw conversion and so converts the raw file to a standard format such as TIFF and launches the editor with that file. This means that I don't get the benefits of the raw conversion in CaptureNX. I devised a workaround which works quite well.

I started using Nikon CaptureNX for raw conversion of my Nikon D70 NEF files as soon as I decided I was going to buy a Nikon D300 and this wasn't very long after the D300 was announced. Previously, I had been using Jasc's PaintShopPro 9 which while it did a pretty good job, PSP9 would not be able to read the NEF files from the D300. I found CaptureNX to be very good for converting my D70 NEF files and even better for the D300. I could get my images the way I want them in the camera and spend less time on post processing.

CaptureNX is not without its drawbacks. CaptureNX doesn't let me add text (watermarks) to my images, This meant I had to continue using PSP9 after raw conversion in CaptureNX. The browsing capabilities of Capture are not great as there is no way to see a large version of an image other than by opening it in the editor. This meant I had to use ViewNX for browsing. While this worked well, the three applications together used a lot of memory, especially ViewNX and CaptureNX, and would make my PC quite slow at times. I also didn't have a good way to catalogue my files.

I switched to Lightroom after seeing a demonstration of its cataloguing capabilities and the idea of using a single product from start to finish. While my trials and tribulations with Lightroom will be the subject of another blog entry, one of the big issues I have with Lightroom is the way it handles raw files. Users familiar with Adobe Camera Raw (ACR) would not at all be surprised with the conversion that Lightroom does because it is actually using ACR behind the scenes, however, uses that have not come from some other raw convertors (such as CaptureNX) may be bitterly disappointed with the results from Lightroom. I know I was.

With CaptureNX my images would look exactly they way I wanted them out of the camera, and if I shot raw+JPEG, the raw looks the same as the JPEG. This is not the case with Lightroom. It doesn't use any of the camera defaults (apparently because Nikon don't publish the internal format of the NEF files) and you are stuck with either a very flat file (using General - Zeroed preset), an image with too much contrast using Lightroom's default settings, or you have to tweak the settings yourself. One nice feature is you can save your tweaked settings in a preset but I have not been able to create a one-size-fits-all preset that gives me consistent results. Note that many people make their presets available so there's a lot to choose from.

I have found that for many of my images, it only takes a bit of tweaking to get an image with which I am happy and that looks close to the JPEG (if I captured that as well). I have had quite a few images that no matter how much I tweaked I could not get to look the way they should. The problem was mostly to do with colour where most of the colours were the way they should be, but one or two colours would be significantly different. See the examples below. Assuming I can get those colours correct, the others would be wrong. For these sorts of images, the best way to process them was with CaptureNX.


This is a JPEG image shot on my D300 using NEF (RAW)+JPEG Fine and processed within Lightroom


This is the result from using the NEF image from above and processing with Lightroom. The colours are just not the same.

Lightroom allows you to set up an external editor with which you can edit your images. Lightroom will still keep the image in its catalogue which is nice and you are able to use the capabilities of the other editor. For some reason, however, Lightroom doesn't give you the capability of directly editing the raw file in the other editor, that capability is only available if you choose to externally edit TIFF or JPG files in the catalogue. If you direct Lightroom to externally edit a raw file, it creates a TIFF or PSD file and then directs the editor to open that file rather than the original raw file. This is of little value to solving my problem.

I then had an idea. I wrote a batch file that would take the full path to the TIFF file that Lightroom created and open CaptureNX with the NEF file by replacing the extension of the passed filename with 'NEF'.


start "C:\Program Files\Nikon\Capture NX\capture nx.exe" %~dpn1.NEF

The batch file, which I called cnx.bat, to open the NEF file in CaptureNX.

The batch file did exactly what I wanted, but I encountered a problem with Lightroom that prevented its use as is. While Lightroom lets me select my desired external editor, it will only accept an executable file (.exe). It won't let me specify a batch file. After a bit more thinking I came up with the idea of writing a small program in C which would simply call a batch file of the same name and pass all the parameters to the batch file.


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main( argc, argv )
int argc;
char *argv[];
{
    int i;
    char s[256] = "";
    int len;
    char *result;

    // first we need to determine if the extension of the executable was used when the program was called
    result = strstr( argv[0], ".exe" );

    strcat( s, "\"" );
    if ( result == NULL || strlen( result ) != 4 ) // no .exe on argv[0]
    {
        strcat( s, argv[0] );
    }
    else                                           // .exe was appended to the end of argv[0]
    {
        len = strlen( argv[0] );
        strncat( s, argv[0], len-4 );
    }
    strcat( s, ".bat\" " );                        // append .bat to the name of the file


    // add all the arguments to the command line
    for (i=1; i<argc; i++)
    {
        strcat( s, argv[i] );
        strcat( s, " " );
    }

    // call the command
    system( s );

    return 0;
}


Source code for the C program used to call the batch file.

I probably could have had the C program do everything and call CaptureNX, but I thought it would be better to write a generic program that could in theory be used with anything where you want to call a batch file. Additionally, it is easier to modify the batch file to do whatever I wanted it to do.

The C program was compiled with lcc-win32 C Compiler which is available for free.

Both the executable, cnx.exe, and the batch file, cnx.bat, were placed into the same directory as the CaptureNX executable. On my machine this is: C:\Program Files\Nikon\Capture NX\. Lightroom was then configured to call cnx.exe as the external editor.

From the External Editing tab on the Preferences dialogue, I clicked the "Choose" button in the Additional External Editor section

With the external editor set up, I am now able to edit the raw image directly from Lightroom using CaptureNX as follows.

Select the image to be edited, then right click on the image to open the popup menu:

Select "Edit in cnx.exe..."

Choose TIFF as the file format, bit depth as 16 bit and make sure "Stack with original is selected". Click OK, and Lightroom creates the requested TIFF file and then launches cnx.exe which runs cnx.bat which launches CaptureNX with the NEF file of the same name.

The file can then be adjusted in CaptureNX and once editing is completed, the file is saved as a TIFF file overwriting the image created by Lightroom. The file should be saved as 16 bit. Lightroom automatically picks up the changes.


Here is the same image as above, but with raw conversion in CaptureNX and then exporting the resulting TIFF file.

There are some minor drawbacks with this approach. As the TIFF file gets created by CaptureNX from the untouched NEF file, metadata created in Lightroom is lost. I have yet to determine a way to apply the metadata automatically to the created TIFF file but I'm sure there is some way to do it.

The first time you externally edit the file, Lightroom creates a TIFF file of the same name as the NEF file which works well. If you edit again, a second TIFF file is created with -2 appended to the filename. As there is no corresponding -2 NEF file, the edit fails. I have found the simplest way around this is to just delete the previous TIFF file (from Lightroom so that it also deletes it from the disk). An alternative to this is the rename the first TIFF file to -2 (or some other name), that way you can keep both files.

I have set up the batch file using the start command so that it will terminate after it tells CaptureNX to open the NEF file. For some reason doing this makes Windows open the NEF file using the default viewer rather than the one specified in the command. I have Nikon Capture 4 Editor installed on my machine and this keeps being reset as the default program for NEF files. It is easy enough to set CaptureNX as the default (but at some point, perhaps on reboot, Capture 4 gets set back to the default).

The approach above could in theory used with any external editor you wanted and could probably even be adapted for Apple Mac computers (although I don't know enough about the OS to know what is possible). Other than the drawbacks mentioned, I find this approach very helpful for difficult images.


Updated 19 September 2008

A few people have written to me about a few problems they have had with the code I have here.

One problem relates to the fact that in some cases (and touched on briefly above), Windows will open the NEF file with the associated program rather than CaptureNX even when it is explicit in the batch file. I found this only happened if I used "start" in the batch file rather than just running capturenx.exe. I prefer to use "start" as the batch file ends as soon as CaptureNX is launched. If you don't have NEF files associated with CaptureNX you can just remove "start" from the batch file.

Another problem you can encounter is if the directories you use include spaces. Calling cmd.exe from the C program results in the spaces in the directories or filenames being treated as parameter separators. One reader (Laurence Wood) sent me some code that he has used to get around this problem. I haven't used it, but other may find it useful.

Thanks to Laurence and the other readers for their comments.


#ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows Vista. 
#define _WIN32_WINNT 0x0600     // Change this to the appropriate value to target other versions of Windows. 
#endif 
  
#include  
#include  
#include  
#include  
  
  
BOOL AnsiToUnicode( LPSTR pszAnsiString, LPWSTR pszwUniBuff, DWORD dwUniBuffSize ) 

      int iRet = 0; 
    iRet = MultiByteToWideChar( 
            CP_ACP, 
            0, 
            pszAnsiString, 
            -1, 
            pszwUniBuff, 
            dwUniBuffSize 
            ); 
  
      return ( 0 != iRet ); 

  
int main(int argc, char* argv[]) 

      int isOk = 0; 
      int result = 0; 
      TCHAR msString1[_MAX_PATH]; 
      TCHAR msString2[_MAX_PATH]; 
      char fdrive[_MAX_PATH]; 
      char fdir[_MAX_PATH]; 
      char fname[_MAX_PATH]; 
      char fext[_MAX_PATH]; 
      char pathStringDelete[_MAX_PATH]; 
      char cmdString[_MAX_PATH]; 
      char commandLineString[_MAX_PATH]; 
      char directoryLineString[_MAX_PATH]; 
  
      memset( fdrive, 0, _MAX_PATH ); 
      memset( fdir, 0, _MAX_PATH ); 
      memset( fname, 0, _MAX_PATH ); 
      memset( fext, 0, _MAX_PATH ); 
      memset( pathStringDelete, 0, _MAX_PATH ); 
      memset( cmdString, 0, _MAX_PATH ); 
      memset( commandLineString, 0, _MAX_PATH ); 
      memset( directoryLineString, 0, _MAX_PATH ); 
  
      STARTUPINFO startupInfo; 
      PROCESS_INFORMATION processInformation; 
  
      GetStartupInfo( &startupInfo ); 
  
      if ( argc >= 2 ) 
      { 
            char* pArgOne = (char*) argv[1]; 
            _splitpath( (const char*) pArgOne, fdrive, fdir, fname, fext ); 
  
            strcpy( cmdString, "C:\\Windows\\System32\\cmd.exe /C" ); 
  
            strcpy( directoryLineString, "C:\\Program Files\\Nikon\\Capture NX\\" ); 
            strcpy( commandLineString, cmdString ); 
            strcat( commandLineString, " " ); 
            strcat( commandLineString, "\"C:\\Program Files\\Nikon\\Capture NX\\Capture NX.exe\"" ); 
            strcat( commandLineString, " " ); 
            strcat( commandLineString, fdrive ); 
            strcpy( pathStringDelete, fdrive ); 
            strcat( commandLineString, fdir ); 
            strcat( pathStringDelete, fdir ); 
            strcat( commandLineString, fname ); 
            strcat( pathStringDelete, fname ); 
            strcat( pathStringDelete, fext ); 
            strcat( commandLineString, ".nef" ); 
  
            // add all the arguments to the command line 
            for (int i=2; i             { 
                  strcat( commandLineString, argv[i] ); 
                  strcat( commandLineString, " " ); 
            } 
  
            AnsiToUnicode( commandLineString, msString1, _MAX_PATH ); 
            AnsiToUnicode( directoryLineString, msString2, _MAX_PATH ); 
  
            //if ( !strcmp( fext, ".tif" ) ) 
            //    ::DeleteFile( (LPCTSTR) pathStringDelete ); 
            //else if ( !strcmp( fext, ".psd" ) ) 
            //    ::DeleteFile( (LPCTSTR) pathStringDelete ); 
  
            result = ::CreateProcess( 
            NULL, 
            msString1, 
            NULL, 
            NULL, 
            FALSE, 
            DETACHED_PROCESS | NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, 
            NULL, 
            msString2, 
            &startupInfo, 
            &processInformation ); 
      } 
      else 
      { 
            isOk = 1; 
      } 
  
      return isOk; 


Source code for the C program suggested by Laurence Wood.



Please leave Feedback if you have any comments or questions about this blog entry.