Geoff's Nikon on Linux Page

In August, 2003 I put my thumb through the shutter in my Nikon FE2 (don't ask) and decided I needed a replacement for taking pictures of the kids.  Since I'm a tech guy digital was the way to go and so I bought a Nikon Coolpix 4300.  Not an equivalent camera, for sure, but very nice for a point-and-shoot you can take anywhere.  Eventually, though, I just got tired of missing shots, not having a depth of field control, and whatnot and bought a Nikon D70 in December 2004.  All this time I've used (almost) only Linux and, in the spirit of open-source, I thought I'd share some of the hints, scripts, links, and other assorted foo I've gathered thus far.

Anything to add?  I'm sure you can figure out how to email me based on this URL.  But I'm not a support resource :)

My Linux Environment
Getting Pictures from the Coolpix 4300
Getting Pictures from the Nikon D70
Getting Pictures with a Card Reader
Nikon Coolpix 4300 Setup
Nikon D70 Setup
Post-Processing Your Pictures
Extracting Exif Data
Playing with RAW Files
Sample Pictures
Printing Pictures
Useful Links

My Linux Environment

    hardware:
generic workstation running Fedora Core 2
IBM Thinkpad A31 running Fedora Core 1
VMware Workstation 4.5.2 running Windows 2000 (why?  look here)

    software that you will want (at least if you want to run my scripts):
rsync (included with Fedora)
jhead
jpegtran (included with Fedora)
exifautotran
jpegexiforient (just gcc -o jpegexiforient jpegexiforient.c)
Image::ExifTool
    exiftool (included with Image::ExifTool)
ImageMagick (included with Fedora)
neftags2jpg (requires this version of exiv)
cjpeg (included with Fedora)
dcraw


Getting Pictures from the Coolpix 4300

    Basically, both cameras support USB Mass Storage, so getting the pictures from the camera to your computer couldn't be easier.  If you're new to digital photography you might be tempted to use gtkam, gphoto, or some other tool, but USB Mass Storage is much easier, especially for the Nikons.

    Fedora Core 1 and Core 2 both recognized the cameras when plugged directly into the computer.  How do you know?  check dmesg.  This is what it spits out after I connect the Coolpix 4300:

$ dmesg

...
usb 1-6: new high speed USB device using address 2
Initializing USB Mass Storage driver...
scsi1 : SCSI emulation for USB Mass Storage devices
  Vendor: SanDisk   Model: SDCFH-512         Rev:  0 0
  Type:   Direct-Access                      ANSI SCSI revision: 02
SCSI device sda: 1000944 512-byte hdwr sectors (512 MB)
sda: assuming Write Enabled
sda: assuming drive cache: write through
 sda: sda1
Attached scsi removable disk sda at scsi1, channel 0, id 0, lun 0
USB Mass Storage device found at 2
usbcore: registered new driver usb-storage
USB Mass Storage support registered.
usb 1-6: USB disconnect, address 2

Along with that, it created a new mount point, /mnt/camera,  so

$ mount /mnt/camera

$ cd /mnt/camera/
$ ll
total 12
drwxr-xr-x  3 geoff geoff 4096 Dec 31  2003 dcim
drwxr-xr-x  2 geoff geoff 4096 Dec 31  2003 misc
-rwxr-xr-x  1 geoff geoff  512 Dec 31  2003 nikon001.dsc

and I'm golden - the pictures are in dcim/100nikon/ just waiting to be moved to your workstation.  how do you do that?  well, I wrote a script for it:

#!/bin/ksh

 
# first, mount the camera
mount /mnt/camera
 
# now copy the pictures from the camera to /pictures
rsync -rtuv --exclude info.txt /mnt/camera/dcim/100nikon/ /pictures/
 
# umount the camera now, just to be safe - we don't
# want to manipulate pictures on the CF card until
# we know they were transfered properly
umount /mnt/camera
 
# protect your pictures!  make sure you can't delete them by accident
cd /pictures/
chmod 0444 *.jpg
 
# now, shuffle the pictures around a bit
for i in *.jpg
do
 
  # extract the date/time from the exif data and
  # make it match the timestamp on the file itself
  time=`exiftool -d '%c' -DateTimeOriginal $new | sed 's/.* ://'`
  touch -d "$time" $i
 
  # create /pictures/YYYY-MM to store the pictures in, if required
  dir=`date -d "$time" +"%Y-%m"`
 
  if [ ! -d $dir ]; then
    mkdir $dir
  fi
 
  # move the pictures to /pictures/YYYY-MM
  if [ -e $dir/$i ]; then
    echo "removing $i - $dir/$i exists?"
    rm -f $i
  else
    mv --reply=no $i $dir
  fi
 
done
 
cd -

now, you might be asking why I bother to extract out the exif data and transfer the time the picture was taken to the file on disk.  well, because I have two cameras the picture names overlap and sort order gets all messed up.  by doing this I can sort via mtime and my pictures list in their proper chronological order, not the order in which I chose to transfer them to my computer.


Getting Pictures from the D70

    This is pretty much the same as with the 4300.  The only difference is the name of the directory the D70 puts the pictures in on the CF card, and the fact that the D70 knows the orientation of the pictures so we can rotate them on the fly.

    I should note that this script assumes you're shooting in JPG mode and not RAW mode.  I'm really nowhere near a professional, so a 3MB jpeg is just fine for me.  YMMV.
#!/bin/ksh
 
# first, mount the camera
mount /mnt/camera
 
# now copy the pictures from the camera to /pictures
rsync -rtuv /mnt/camera/dcim/100ncd70/ /pictures/
 
# umount the camera now, just to be safe - we don't
# want to manipulate pictures on the CF card until
# we know they were transfered properly
umount /mnt/camera
 
# the D70 messes with the picture names - depending
# on the RGB setting it could be called _dsc0001.jpg
# or dsc_0001.jpg.  I find this annoying, so I normalize
# the names
cd /pictures/
for i in *.jpg; do new=`echo $i | sed -e 's/_//'`; mv --reply=no $i $new; done
 
# rotate the pictures based on exif orientation data
exifautotran *.jpg
 
# protect your pictures!  make sure you can't delete them by accident
chmod 0444 *.jpg
 
# now, shuffle the pictures around a bit
for i in *.jpg
do
 
  # extract the date/time from the exif data and
  # make it match the timestamp on the file itself
  time=`exiftool -d '%c' -DateTimeOriginal $new | sed 's/.* ://'`
  touch -d "$time" $i
 
  # create /pictures/YYYY-MM to store the pictures in, if required
  dir=`date -d "$time" +"%Y-%m"`
 
  if [ ! -d $dir ]; then
    mkdir $dir
  fi
 
  # move the pictures to /pictures/YYYY-MM
  if [ -e $dir/$i ]; then
    echo "removing $i - $dir/$i exists?"
    rm -f $i
  else
    mv --reply=no $i $dir
  fi
 
done
 
cd -

actually, these are only close approximations of the scripts I use - since I have both cameras and fiddle with raw (compressed NEF) data files from time to time I combined them.  the real script I use is this (yeah, it's ugly, but my shell skills are weakening thanks to Perl ;)

#!/bin/ksh
 
cd /pictures/ 
mount /mnt/camera
if [ $? -ne 0 ]; then
  echo "no camera to mount?"
  exit 1
fi 
if [ -d /mnt/camera/dcim/100ncd70/ ]; then
  rsync -rtuv /mnt/camera/dcim/100ncd70/ /pictures/
  umount /mnt/camera
  exifautotran *.jpg
else
  rsync -rtuv --exclude info.txt /mnt/camera/dcim/100nikon/ /pictures/
  umount /mnt/camera
fi 
for i in *.jpg
do
  if [ ! -e $i ]; then
    echo "*** no jpg files to process"
    continue
  fi 
  new=`echo $i | sed -e 's/_//'`
  mv --reply=no $i $new
  chmod 0444 $new 
  time=`exiftool -d '%c' -DateTimeOriginal $new | sed 's/.* ://'` 
  touch -d "$time" $new 
  dir=`date -d "$time" +"%Y-%m"` 
  if [ ! -d $dir ]; then
    mkdir $dir
  fi 
  if [ -e $dir/$new ]; then
    echo "removing $new - $dir/$new exists?"
    rm -f $new
  else
    mv --reply=no $new $dir
  fi
done 
for i in *.nef
do
  if [ ! -e $i ]; then
    echo "*** no nef files to process"
    continue
  fi 
  new=`echo $i | sed -e 's/_//'`
  mv --reply=no $i $new
  chmod 0444 $new 
  time=`exiftool -d '%c' -DateTimeOriginal $new | sed 's/.* ://'` 
  touch -d "$time" $new 
  dir=`date -d "$time" +"%Y-%m"` 
  if [ ! -d raw/$dir ]; then
    mkdir raw/$dir
  fi 
  if [ -e raw/$dir/$new ]; then
    echo "removing $new - raw/$dir/$new exists?"
    rm -f $new
  else
    jpg=`echo $new | sed -e s/\.nef/-raw\.jpg/` 
    echo "writing nef $dir/$jpg"
    dcraw -c -w $new | cjpeg -Q 95 > $dir/$jpg
    neftags2jpg $new $dir/$jpg
    chmod 0444 $dir/$jpg
    touch -d "$time" $dir/$jpg 
    mv --reply=no $new raw/$dir
  fi
done
cd -



Getting Pictures from a Card Reader

    Plugging in the camera all the time is a drag, especially when you consider how quickly the 4300 drains its battery.  So, I  use a card reader now instead.  Unfortunately, Fedora didn't give me mount points for either of my cards automatically (a SanDisk 128MB for the 4300 and SanDisk 512MB Ultra II for the D70) so I had to create entries for them myself in /etc/updfstab.conf.default.  I chose to add the entry under the camera device so that my scripts would work no matter how I connect to the CF card.

device camera {

    partition 1
    match   hd DSC
    match   hd CAMERA
    match   hd USB-DRIVEUNIT
    match   hd PENTAX
    match   hd PSC
    match   hd SanDisk
}

with the "match hd SanDisk" entry added I was free to mount /mnt/camera and extract the pictures using the same script I use to move pictures directly from the cameras.  The SanDisk part matches the output from dmesg above, so if you're not using a SanDisk card, check your own dmesg ouput and adjust accordingly.


Coolpix 4300 Setup

    There really isn't much to do with the 4300.  The only tweaks I have made is to set the scene mode to portrait, center weighted, and the manual mode to multiple exposure mode.  that way I can quickly switch between getting a close-up of my kids or snapping of a few shots in a row, hoping to get a smile.


Nikon D70 Setup

    Ok, this is why I really am writing this page.  Setting up the D70 isn't all that difficult, but there are a bunch of things you can do to make life easier.  These are just a few I've found helpful.

    You can't really take good pictures right out of the box - they will be dark, unbalanced and an overall disappointment.  I think Nikon does this because it expects users of a higher-end camera like this will post-process all of their pictures using photoshop or something.  yeah, like I have the time for that.

    If you are like me and want relatively good looking pictures all the time, you will want to place a color curve directly on the camera and adjust a few other settings.  Rather than repeat what others have done, I'll just point you to the right places:

1. Do this
2. Then do this
3. Then bookmark this for later reading

note that for the second step (installation of the custom color curve) you will need Nikon Capture, which only runs on windows and which isn't included with the camera.  Nikon offers you a 30 day trial period, which is sufficient for uploading a curve to your camera.  Remember that you can always turn off the custom curve, so there really isn't any harm in loading it up just in case.

    Oh, and since you're a geek you'll probably see the firmware link and run off to upgrade your firmware but there probably isn't a need - if you just purchased the camera and are reading this then the camera you have probably has the latest firmware already, so check your versions before you waste your time.

    I should say that when I first got the camera I took about 100 shots of the same thing (an outdoor still) using various settings - with the curve, without the curve, with and without the tone and sharpness settings suggested in the first step, and everything inbetween.  I found that the pictures I took with the suggested settings really did look the best, but YMMV.

After you get the color settings for the camera situated, you might want to tweak the interface as well.  These are some settings that may help you get started - I like like almost all of his suggestions, but you can make up your own mind.  In addition to those, I've made some additional tweaks not mentioned there:
1. Turn the CSM Menu option to Detailed (page 161 in the D70 manual).  This lets you see all the menu options available to you, not just a subset.
2. Set the File Number Sequence setting to On (page 159).  If you don't do this then the picture numbering will start at 0001 every time you use a different card, reformat the current card, etc.  how annoying.
3. Set Rotate Tall to Off (page 126).  This allows you to actually see the picture in the review screen after you take a portrait-oriented picture.  It doesn't affect the image on the CF card in any way.
4. I prefer to shoot in Aperature Priority mode, but don't like that the aperature control is the dial on the front of the camera.  You can toggle which dial controls the aperature using the Command Dial menu option (page 147).


Post-Processing Your Pictures

    I'm still learning about post-processing, so I don't have much to share with you here.  But I will point you to GimpGuru, a great site with lots of very useful tutorials for using the Gimp (a free photoshop-equivalent program).

    to just make thumnails or something I use convert, one of the command line tools that comes with ImageMagick.

$ convert -size 71 foo.jpg -resize 71 /pictures/thumb/foo.jpg



Extracting Exif Data

    Image::ExifTool is a great Perl package for extracting out Exif data, including all of the Nikon-specific tags that other tools (like jhead) don't know about.  this is a quick script I use to look at the data from an image:

use Image::ExifTool;
 
my $info = Image::ExifTool->new->ImageInfo($ARGV[0]);
 
foreach my $key (sort keys %$info) {
  (my $value = $info->{$key}) =~ s/\s+/ /g;
  print "$key => $value\n";
}

but viewers like gThumb have most of this, so you may not need it.  however, one thing I like to do is extract exif data out to a file and diff it against other images to see which setting in a series worked best, and this script helps.  in fact, I wrote exifdiff, which will accept a list of files and then tabulate and show only (important) differences.  like this:

$ exifdiff dsc0448.jpg dsc0449.jpg dsc0450.jpg

tag                      dsc0448.jpg              dsc0449.jpg              dsc0450.jpg
--------------------------------------------------------------------------------------------------
ExposureCompensation     -1/3                     -2/3                     0
ShutterSpeed             1/200                    1/250                    1/250

the code behind exifdiff is so ugly that I just can't share it at the moment.  after I clean it up I'll post it, though.


Playing with RAW Files

    I have started playing around with raw files, which in the case of the D70 are compressed NEF format.  dcraw  and cjpeg are the keys here, allowing me to script conversions from raw to jpeg without needing to use Nikon Capture.  besides the conversion to jpeg you need to copy the exif data from the raw file as well, which is what neftags2jpg does.  as you can see from the above script, this is the way I have been converting .nef files to .jpg:

$ dcraw -c -w dsc0001.nef | cjpeg -Q 95 > dsc0001.jpg
$ neftags2jpg dsc0001.nef dsc0001.jpg

I found that the -w flag on dcraw produces a color that I like much better than the resuls from dcraw's default, the in-camera jpg, or Nikon Capture, but that dcraw tends to blow out the highlights a bit.  worst case, I figure I can always use Nikon Capture to recreate the jpg that the camera would have produced, so I'm no worse off for using dcraw.

here is a sample image in a few different formats.  for this tests I shot in RAW+BASIC mode so you wouldn't be distracted by subtle differences in picture composition.  the original NEF file is 5.0M.

camera generated jpg (BASIC, originally 709K)
camera generated jpg
too dull and grey

nikon capture generated jpg using my in-camera settings and no exposure compensation (originally 1.1MB)
nikon capture
a bit better, but not by much

dcraw without -w (originally 1.5M)
dcraw without -w
way too blue

dcraw with -w (originally 1.5M)
dcraw with -w
the best of the lot, I think.  I probably could have done better with nikon capture if I had played with things a bit.  but this is just as good as having RAW+FINE (which we don't), and gives me a better idea of what I could get with nikon capture or a gimp plugin like UFRaw.


Sample Pictures

    As I said, I am by no means a professional photographer, but I'm trying my best to create some good pictures of the family we'll all look back on a smile about.  That said, here are some pictures you can look at if you want to see the color saturations, etc of the different cameras.  They aren't meant to be works of artistic genius or anything - I simply thought they had nice contrast to them, and were representative of how each camera tends to look to me.

    Please keep in mind that these are ~100k in size (to save bandwidth), whereas the original picture is around 1.2MB (for the 4300) or 3MB (for the D70) - sharpness and other attributes are lost in the compression and the real pictures look much better.

D70 pictures (camera set up as above in FINE mode, but with no post-processing)
4300 pictures (in FINE mode, no post-processing)


Printing Pictures

    A friend of mine who has been at digital photography longer than I have said he tried absolutely every digital processing place there is (for US customers, at least) and couldn't find one with better pictures than Ofoto.  I've used only Ofoto exclusively and think the pictures look great.  The only problem with Ofoto is that they don't have an API so I can script uploads, which is a drag.  But maybe someone will reverse engineer one someday...


Useful Links

Another D70 on Linux page - lots of stuff on RAW manipulations
Thom Hogan's Nikon page
his D70 review actually has things you will want to know
Another D70 review that includes techincal details you will want to know about
UFRaw a RAW converter for Gimp that seems to do the job well