Tuesday, January 29, 2013

GIMP Script: Save as PNG

At my office, we have a few really cool fundus cameras. Well, I think they're cool anyway. Before I got there, they used to use CF cards to transfer photos from the Nidek NM200D (our fundus cameras) to a computer. This was not without problems: sometimes files wouldn't save right, the cameras produced really huge uncompressed tiffs, so not much could be stored, and a few other problems. The NM200D is supposed to be capable of transferring files via USB. Unfortunately, the software designed for it was really bad and unfriendly -- I could never actually get it to work. The drivers seemed fine, though. They are standard TWAIN drivers (but it still called itself a camera...), so I went to find a good solution that would meet my budgetary requirements ($0). There were a few contenders, but I settled on GIMP because it was open source (which I do so love) and would allow the doctors to import photos in quick succession while naming each individually.

We started out with GIMP 2.6. As you may know, GIMP 2.8 changed the way it handles saving by only allowing you to save in the native xcf format. For all other formats you have to export. That's not something that would fly well with the doctors. It's made worse by the fact that exporting to an image file without saving leads to a "scary" warning about unsaved content. There was no real reason to upgrade anyway, so I stayed on 2.6 and worked on other things.

Fast forward to today. I'm in the planning stages of upgrading the computers the fundus machines are connected to, as it's finally time to finish the Windows 7 migration at the office. The cameras actually seem to work great with Windows 7; I was afraid they may not play so kindly with it (though it does have to be 32-bit Windows 7). They actually work better judging from testing so far, as with XP they would only work with USB 1.1 (or fake USB 1.1 by disabling the 2.0 drivers causing Windows to fallback on legacy 1.1 support), but with 7 they seem to work fine with native 2.0. Naturally with an upgrade I'll want to use the latest software like GIMP 2.8, so I looked for solutions to the export problem. I found this "Save as JPG" script. For fundus photos, though, I'd rather have it saved in lossless PNG. I'd also like basic overwrite protection to keep the doctors from accidentally overwriting other fundus photos. A little bit of reading on some GIMP and pygtk documentation (never written a plugin for GIMP or used pygtk), and I had what I wanted: provide basic options for saving as PNG and offer overwrite protection when saving newly created files. Below is the code:

PasteBin

#!/usr/bin/env python

# save_as_png.py
# Provides a simple menu option to save as PNG with
# basic save options and overwrite warning for newly created files.
# Tested in GIMP 2.8.2 on Windows 7 (64 and 32-bit)
# Contact: Kevin Thomer (Defron) | http://blog.defron.org/
# Provided free and as-is under GPL v2.
#
# Based off of:

# save_as_jpg.py
# version 1.0 [gimphelp.org]
# last modified/tested by Paul Sherman
# 12/20/2012 on GIMP-2.8
#
# ==== Original Information ====================================================
# Save or export the current image -- do the right thing whether it's
# XCF (save) or any other format (export). This will mark the image clean,
# so GIMP won't warn you when you exit.
# Warning: this does not show a lot of extra dialogs, etc. or warn you
# if you're about to overwrite something! Use with caution.

# Copyright 2012 by Akkana Peck, http://www.shallowsky.com/software/
# You may use and distribute this plug-in under the terms of the GPL v2
# or, at your option, any later GPL version.
# ========================================================

from gimpfu import *
import gtk
import os, sys
import collections

def python_export_clean(img, drawable, interlace, background, compression) :
    filename = img.filename
    #These typecasts isn't really necessary in Python, just a habit of mine
    bg = int(background)
    interlacing = int(interlace)
# fullpath = pdb.gimp_image_get_uri(img)
# pdb.gimp_message(filename)

    if not filename :
        chooser = gtk.FileChooserDialog(
            title=None,action=gtk.FILE_CHOOSER_ACTION_SAVE,
            buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK)
            )
        # save folder will be desktop
        save_dir = os.path.join(os.path.expanduser('~'), 'Desktop')
            
        chooser.set_current_folder(save_dir)
        chooser.set_current_name("UNTITLED.png")
        chooser.set_do_overwrite_confirmation(True)
        
        filter = gtk.FileFilter()
        filter.set_name("Save as png")
        filter.add_pattern("*.png")
        chooser.add_filter(filter) 
        
        response = chooser.run()
        if response != gtk.RESPONSE_OK:
            return
        filename = chooser.get_filename()
        img.filename = filename
        chooser.destroy()
    
        pdb.file_png_save(img, drawable, filename, filename, interlacing, compression, bg, 0, 0, 1, 1)
        pdb.gimp_image_clean_all(img)  
            
        
    else:
        base = os.path.splitext(filename)[0]
        newname = base + ".png"

        pdb.gimp_edit_copy(img.active_drawable)
        image2 = pdb.gimp_edit_paste_as_new()
        pdb.file_png_save(image2, drawable, newname, newname, interlacing, compression, bg, 0, 0, 1, 1)
        pdb.gimp_image_delete(image2)  
        pdb.gimp_image_clean_all(img)


register(
        "python_fu_save_as_png",
        "Save the image as a PNG file, set interlacing & saving bg color\n\nFor more options and a proper file overwrite protected dialog, \nuse the FILE > EXPORT menu item when saving as a PNG.\n\n",
        "",
        "Kevin Thomer (Defron)",
        "GPL",
        "2013",
        "Save as PNG",
        "*",
        [
            (PF_IMAGE, "image", "Input image", None),
            (PF_DRAWABLE, "drawable", "Input drawable", None),
            (PF_TOGGLE, "interlace", "Interlacing (Adam7)", 0),
            (PF_TOGGLE, "background", "Save background color", 1),
            (PF_SLIDER, "Compression", "Set the PNG Compression Level", 9, (0, 9, 1) )
        ],
        [],
        python_export_clean,
        menu = "<Image>/File/Save/"
)

main()

It only has basic options, but that actually works out better for the doctors (simpler). It also has one more added benefit: before, the doctors would occasionally accidentally save fundus images as GIMP xcf files; with the new method it'll always be PNG. A real win-win.

One thing to note: this will only export the current layer, it doesn't flatten the image or anything. It's not really a problem in my case since the images are imported one at a time and saved separately, so I didn't bother looking into merging or flattening.

0 comments:

Post a Comment