Fixed errors discovered by Nick Hall. Remove dependencies on ImageMagick and Jhead. Convert is being done by PIL.Image, and delete is being done by local computer delete command. Thank you Nick and Benny

svn: r17817
This commit is contained in:
Rob G. Healey 2011-06-20 06:31:22 +00:00
parent 107ee62f58
commit e2e399799c

View File

@ -28,6 +28,7 @@ import os
from datetime import datetime from datetime import datetime
import calendar import calendar
import time import time
from PIL import Image
# abilty to escape certain characters from output... # abilty to escape certain characters from output...
from xml.sax.saxutils import escape as _html_escape from xml.sax.saxutils import escape as _html_escape
@ -108,42 +109,19 @@ if (software_version and (software_version < Min_VERSION)):
WarningDialog(msg) WarningDialog(msg)
raise Exception(msg) raise Exception(msg)
# ******************************************************************* # check to make sure that exiv2 is installed and some kind of delete command...
# Determine if we have access to outside Programs installed on this computer,
# which will extend the functionality of this addon?
#
# The programs are ImageMagick, and jhead
# * ImageMagick -- Convert and Delete all Exif metadata...
# * jhead -- re-initialize a jpeg, and other features...
# * del/ rm -- delete old files from the convert command...
#********************************************************************
# Windows 32bit systems
system_platform = os.sys.platform system_platform = os.sys.platform
if system_platform == "win32": if system_platform == "Win32":
_MAGICK_FOUND = "convert.exe" if Utils.search_for("convert.exe") else False DEL_FOUND_ = "del.exe" if Utils.search_for("del.exe") else False
_JHEAD_FOUND = "jhead.exe" if Utils.search_for("jhead.exe") else False EXIV2_OUND_ = "exiv2.exe" if Utils.search_for("exiv2.exe") else False
_DEL_FOUND = "del.exe" if Utils.search_for("del.exe") else False
elif system_platform == "linux2": elif system_platform == "linux2":
_MAGICK_FOUND = "convert" if Utils.search_for("convert") else False DEL_FOUND_ = "rm" if Utils.search_for("rm") else False
_JHEAD_FOUND = "jhead" if Utils.search_for("jhead") else False EXIV2_FOUND_ = "exiv2" if Utils.search_for("exiv2") else False
_DEL_FOUND = "rm" if Utils.search_for("rm") else False
else: else:
_MAGICK_FOUND = "convert" if Utils.search_for("convert") else False DEL_FOUND_ = "del" if Utils.search_for("del") else False
_JHEAD_FOUND = "jhead" if Utils.search_for("jhead") else False EXIV2_FOUND_ = "exiv2" if Utils.search_for("exiv2") else False
_DEL_FOUND = "del" if Utils.search_for("del") else False
# if external programs are not found, let the user know about the missing functionality?
if not _MAGICK_FOUND:
print(_("ImageMagick's convert program was not found on this computer.\n"
"You may download it from here: %s...") % (
"http://www.imagemagick.org/script/index.php"))
if not _JHEAD_FOUND:
print(_("Jhead program was not found on this computer.\n"
"You may download it from: %s...") % (
"http://www.sentex.net/~mwandel/jhead/"))
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Constants # Constants
@ -217,20 +195,18 @@ _BUTTONTIPS = {
# Edit screen button... # Edit screen button...
"Edit" : _("This will open up a new window to allow you to edit/ modify this image's Exif metadata.\n" "Edit" : _("This will open up a new window to allow you to edit/ modify this image's Exif metadata.\n"
"It will also allow you to be able to Save the modified metadata.") } "It will also allow you to be able to Save the modified metadata."),
if (_MAGICK_FOUND or _JHEAD_FOUND): # Thumbnail Viewing Window button...
_BUTTONTIPS.update( { "Thumbnail" : _("Will produce a Popup window showing a Thumbnail Viewing Area"),
# Thumbnail Viewing Window button... # Convert to different image type...
"Thumbnail" : _("Will produce a Popup window showing a Thumbnail Viewing Area"), "Convert" : _("If your image is not of an image type that can have "
"Exif metadata read/ written to/from, convert it to a type that can?"),
# Convert to .Jpeg button... # Delete/ Erase/ Wipe Exif metadata button...
"Convert" : _("If your image is not a .jpg image, convert it to a .jpg image?"), "Delete" : _("WARNING: This will completely erase all Exif metadata "
"from this image! Are you sure that you want to do this?") }
# Delete/ Erase/ Wipe Exif metadata button...
"Delete" : _("WARNING: This will completely erase all Exif metadata "
"from this image! Are you sure that you want to do this?") } )
# ------------------------------------------------------------------------ # ------------------------------------------------------------------------
# #
@ -250,9 +226,9 @@ class EditExifMetadata(Gramplet):
self.exif_widgets = {} self.exif_widgets = {}
self.dates = {} self.dates = {}
self.orig_image = False self.image_path = False
self.image_path = False self.orig_image = False
self.plugin_image = False self.plugin_image = False
vbox = self.build_gui() vbox = self.build_gui()
self.connect_signal("Media", self.update) self.connect_signal("Media", self.update)
@ -308,12 +284,9 @@ class EditExifMetadata(Gramplet):
thc_box.add( self.__create_button( thc_box.add( self.__create_button(
"Thumbnail", _("Thumbnail"), [self.thumbnail_view]) ) "Thumbnail", _("Thumbnail"), [self.thumbnail_view]) )
# is ImageMagick installed? # Convert button...
if _MAGICK_FOUND: thc_box.add( self.__create_button(
"Convert", False, [self.__convert_dialog], gtk.STOCK_CONVERT) )
# Convert button...
thc_box.add( self.__create_button(
"Convert", False, [self.__convert_dialog], gtk.STOCK_CONVERT) )
# Help, Edit, and Delete horizontal box # Help, Edit, and Delete horizontal box
hed_box = gtk.HButtonBox() hed_box = gtk.HButtonBox()
@ -328,7 +301,7 @@ class EditExifMetadata(Gramplet):
hed_box.add( self.__create_button( hed_box.add( self.__create_button(
"Edit", False, [self.display_edit_window], gtk.STOCK_EDIT) ) "Edit", False, [self.display_edit_window], gtk.STOCK_EDIT) )
if _MAGICK_FOUND: if EXIV2_FOUND_:
# Delete All Metadata button... # Delete All Metadata button...
hed_box.add(self.__create_button( hed_box.add(self.__create_button(
"Delete", False, [self.__wipe_dialog], gtk.STOCK_DELETE) ) "Delete", False, [self.__wipe_dialog], gtk.STOCK_DELETE) )
@ -372,12 +345,10 @@ class EditExifMetadata(Gramplet):
self.set_has_data(False) self.set_has_data(False)
return return
# get image from database and try to find it on the computer?
self.orig_image = db.get_object_from_handle(active_handle) self.orig_image = db.get_object_from_handle(active_handle)
self.image_path = Utils.media_path_full(db, self.orig_image.get_path() ) self.image_path = Utils.media_path_full(db, self.orig_image.get_path() )
basename, self.extension = os.path.splitext(self.image_path) if (not self.orig_image or not os.path.isfile(self.image_path) ):
if (not self.orig_image or not os.path.isfile(self.image_path)):
self.exif_widgets["MessageArea"].set_text(_("Image is either missing or deleted,\n"
"Please choose a different image..."))
self.set_has_data(False) self.set_has_data(False)
return return
@ -388,41 +359,34 @@ class EditExifMetadata(Gramplet):
"Please choose a different image...")) "Please choose a different image..."))
return return
# make sure that the image type is workable with exiv2?
if not any(exiv2type == self.extension for exiv2type in _vtypes):
return
# Activate the Clear and Edit buttons...
self.activate_buttons(["Edit"])
# check image write privileges... # check image write privileges...
_writable = os.access(self.image_path, os.W_OK) _writable = os.access(self.image_path, os.W_OK)
if not _writable: if not _writable:
self.exif_widgets["MessageArea"].set_text(_("Image is NOT writable,\n" self.exif_widgets["MessageArea"].set_text(_("Image is NOT writable,\n"
"You will NOT be able to save Exif metadata....")) "You will NOT be able to save Exif metadata...."))
# Activate the Edit button...
self.activate_buttons(["Edit"])
# display file description/ title... # display file description/ title...
self.exif_widgets["MediaLabel"].set_text(_html_escape( self.exif_widgets["MediaLabel"].set_text(_html_escape(
self.orig_image.get_description() ) ) self.orig_image.get_description() ) )
# Mime type information... # Mime type information...
mime_type = self.orig_image.get_mime_type() mime_type = self.orig_image.get_mime_type()
self.exif_widgets["MimeType"].set_text(gen.mime.get_description(mime_type) ) self.exif_widgets["MimeType"].set_text(gen.mime.get_description(mime_type))
# display all button tooltips only... # display all button tooltips only...
# 1st argument is for Fields, 2nd argument is for Buttons... # 1st argument is for Fields, 2nd argument is for Buttons...
self._setup_widget_tips([False, True]) self._setup_widget_tips([False, True])
# get dirpath and basename, and extension...
basename, self.extension = os.path.splitext(self.image_path)
# determine if it is a mime image object? # determine if it is a mime image object?
if mime_type: if mime_type:
if mime_type.startswith("image"): if mime_type.startswith("image"):
# Checks to make sure that ImageMagick is installed on this computer and
# the image is NOT a (".jpeg", ".jfif", or ".jpg") image...
# This allows you to Convert the nonjpeg image to a jpeg file...
if (_MAGICK_FOUND and self.extension not in [".jpeg", ".jpg", ".jfif"] ):
self.activate_buttons(["Convert"])
# creates, and reads the plugin image instance... # creates, and reads the plugin image instance...
self.plugin_image = self.setup_image(self.image_path) self.plugin_image = self.setup_image(self.image_path)
@ -447,6 +411,11 @@ class EditExifMetadata(Gramplet):
if thumbnail: if thumbnail:
self.activate_buttons(["Thumbnail"]) self.activate_buttons(["Thumbnail"])
# if image file type is not an Exiv2 acceptable image type,
# offer to convert it....
if self.extension not in _vtypes:
self.activate_buttons(["Convert"])
# display all exif metadata... # display all exif metadata...
mediadatatags = _get_exif_keypairs(self.plugin_image) mediadatatags = _get_exif_keypairs(self.plugin_image)
if mediadatatags: if mediadatatags:
@ -574,8 +543,7 @@ class EditExifMetadata(Gramplet):
self.exif_widgets["ImageSize"].set_text(_("Image Size : %04d x %04d pixels") % (width, height)) self.exif_widgets["ImageSize"].set_text(_("Image Size : %04d x %04d pixels") % (width, height))
# Activate Delete button if ImageMagick or jhead is found?... # Activate Delete button if ImageMagick or jhead is found?...
if (_MAGICK_FOUND or _JHEAD_FOUND): self.activate_buttons(["Delete"])
self.activate_buttons(["Delete"])
for keytag_ in metadatatags_: for keytag_ in metadatatags_:
if LesserVersion: # prior to pyexiv2-0.2.0 if LesserVersion: # prior to pyexiv2-0.2.0
@ -747,81 +715,80 @@ class EditExifMetadata(Gramplet):
main_vbox.show_all() main_vbox.show_all()
return main_vbox return main_vbox
def __convert_dialog(self, obj): def __convert_dialog(self, object):
""" """
Handles the Convert question Dialog... Handles the Convert question Dialog...
""" """
# if ImageMagick and delete has been found on this computer? # Convert and delete original file...
if (_MAGICK_FOUND and _DEL_FOUND): if DEL_FOUND_:
OptionDialog(_("Edit Image Exif Metadata"), _("WARNING: You are about to convert this " OptionDialog(_("Edit Image Exif Metadata"), _("WARNING: You are about to convert this "
"image into a .jpeg image. Are you sure that you want to do this?"), "image into a .jpeg image. Are you sure that you want to do this?"),
_("Convert and Delete original"), self.convertdelete, _("Convert and Delete"), self.__convert_dalete, _("Convert"), self.__convert_file)
_("Convert"), self.convert2Jpeg)
# is ImageMagick is installed?
elif _MAGICK_FOUND:
else:
QuestionDialog(_("Edit Image Exif Metadata"), _("Convert this image to a .jpeg image?"), QuestionDialog(_("Edit Image Exif Metadata"), _("Convert this image to a .jpeg image?"),
_("Convert"), self.convert2Jpeg) _("Convert"), self.__convert_file)
def convertdelete(self, object): def __convert_file(self, full_path =None):
"""
will convert2Jpeg and delete original non-jpeg image.
"""
self.convert2Jpeg()
if system_platform == "linux2":
try:
delete = subprocess.check_call( ["rm", "-rf", self.image_path] )
delete_results = str(delete)
except subprocess.CalledProcessError:
delete_results = False
else:
try:
delete = subprocess.check_call( ["del", "-y", self.image_path])
delete_results = str(delete)
except subprocess.CalledProcessError:
delete_results = False
if delete_results:
self.exif_widgets["MessageArea"].set_text(_("Image has been converted to a .jpg image,\n"
"and original image has been deleted!"))
else:
self.exif_widgets["Message:Area"].set_text(_("There was an error in converting and deleting your image..."))
def convert2Jpeg(self):
""" """
Will attempt to convert an image to jpeg if it is not? Will attempt to convert an image to jpeg if it is not?
""" """
filepath, basename = os.path.split(self.image_path) if full_path is None:
basename, oldext = os.path.splitext(self.image_path) full_path = self.image_path
newextension = ".jpeg"
basename, oldext = os.path.splitext(full_path)
filepath, basename = os.path.split(basename)
basename += ".tiff"
dest_file = os.path.join(filepath, basename)
# Convert the file based upon file suffix
im = Image.open(full_path)
im.save(dest_file)
if LesserVersion: # prior to pyexiv2-0.2.0...
src_meta = pyexiv2.Image(full_path)
# Copy the image metadata...
dest_meta = pyexiv2.Image(dest_file)
dest_meta.readMetadata()
src_meta.readMetadata()
src_meta.copy(dest_meta, comment =False)
dest_meta.writeMetadata()
else: # pyexiv2-0.2.0 and above...
src_meta = pyexiv2.ImageMetadata(full_path)
# Copy the image metadata...
dest_meta = pyexiv2.ImageMetadata(dest_file)
src_meta.read()
dest_meta.read()
src_meta.copy(dest_meta, comment =False)
dest_meta.write()
def __convert_dalete(self, full_path =None):
"""
will convert an image file and delete original non-jpeg image.
"""
if full_path is None:
full_path = self.image_path
# Convert image and copy over it's Exif metadata (if any)
self.__convert_file(full_path)
# delete original file from this computer...
try: try:
convert = subprocess.check_call(["convert", self.image_path, if system_platform == "linux2":
os.path.join(filepath, basename + newextension) ] ) delete = subprocess.check_call( [DEL_FOUND_, " -rf", full_path] )
convert_results = str(convert)
else:
delete = subprocess.check_call( [DEL_FOUND_, " -y", full_path] )
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
convert_results = False pass
if convert_results:
# set Message Area to Convert...
self.exif_widgets["MessageArea"].set_text(_("Converting image,\n"
"You will need to delete the original image file..."))
self.deactivate_buttons(["Convert"])
else:
self.exif_widgets["Message:Area"].set_text(_("There has been an "
"issue in converting your image,\n coverting did not happen..."))
def __help_page(self, object): def __help_page(self, object):
""" """
@ -871,7 +838,7 @@ class EditExifMetadata(Gramplet):
# set Message Area to Entering Data... # set Message Area to Entering Data...
self.exif_widgets["MessageArea"].set_text(_("Entering data...")) self.exif_widgets["MessageArea"].set_text(_("Entering data..."))
if _MAGICK_FOUND: if EXIV2_FOUND_:
if not self.exif_widgets["Delete"].get_sensitive(): if not self.exif_widgets["Delete"].get_sensitive():
self.activate_buttons(["Delete"]) self.activate_buttons(["Delete"])
@ -1186,7 +1153,7 @@ class EditExifMetadata(Gramplet):
return keyvalue_ return keyvalue_
def clear_metadata(self, object): def clear_metadata(self):
""" """
clears all data fields to nothing clears all data fields to nothing
""" """
@ -1504,26 +1471,19 @@ class EditExifMetadata(Gramplet):
Will completely and irrevocably erase all Exif metadata from this image. Will completely and irrevocably erase all Exif metadata from this image.
""" """
# update the image Exif metadata... # make sure the image has Exif metadata...
mediadatatags_ = _get_exif_keypairs(self.plugin_image) mediadatatags_ = _get_exif_keypairs(self.plugin_image)
if not mediadatatags_: if not mediadatatags_:
return return
if _MAGICK_FOUND: if EXIV2_FOUND_:
try: try:
erase = subprocess.check_call( ["convert", self.image_path, "-strip", self.image_path] ) erase = subprocess.check_call( [EXIV2_FOUND_, "delete", self.image_path] )
erase_results = str(erase) erase_results = str(erase)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
erase_results = False erase_results = False
elif (_JHEAD_FOUND and self.extension in [".jpeg", ".jfif", ".jpg"]):
try:
erase = subprocess.check_call( ["jhead", "-purejpeg", self.image_path] )
except subprocess.CalledProcessError:
erase_results = False
else: else:
if mediadatatags_: if mediadatatags_:
for keytag_ in mediadatatags_: for keytag_ in mediadatatags_:
@ -1535,18 +1495,17 @@ class EditExifMetadata(Gramplet):
if erase_results: if erase_results:
# set Message Area for deleting... # Clear the Viewing and Edit Areas
self.exif_widgets["MessageArea"].set_text(_("Deleting all Exif metadata..."))
# Clear the Edit Areas
self.model.clear() self.model.clear()
self.clear_metadata(_TOOLTIPS)
self.exif_widgets["MessageArea"].set_text(_("All Exif metadata has been " self.exif_widgets["MessageArea"].set_text(_("All Exif metadata "
"deleted from this image...")) "has been deleted from this image..."))
self.update() self.update()
else: else:
self.exif_widgets["Message:Area"].set_text(_("There was an error in wiping the Exif metadata from your image...")) self.exif_widgets["MessageArea"].set_text(_("There was an error "
"in wiping the Exif metadata from your image..."))
def _get_exif_keypairs(plugin_image): def _get_exif_keypairs(plugin_image):
""" """