Removed ImageMagick and Jhead dependencies as requested using PIL.Image, exiv2, and os.remove. Thank you, Nick Hall, John Ralls, Benny Malengier, and Brian Matherly.

svn: r17833
This commit is contained in:
Rob G. Healey 2011-06-27 04:46:27 +00:00
parent 23967fae03
commit 04d9b96dc8

View File

@ -28,7 +28,7 @@
import os
from datetime import datetime, date
import calendar, time
import subprocess
# abilty to escape certain characters from output...
from xml.sax.saxutils import escape as _html_escape
@ -39,7 +39,7 @@ from decimal import Decimal, getcontext
getcontext().prec = 4
from fractions import Fraction
import subprocess
from PIL import Image, ImageEnhance, ImageFilter
# ------------------------------------------------------------------------
# GTK modules
@ -62,7 +62,7 @@ import gen.mime
import Utils
from PlaceUtils import conv_lat_lon
from QuestionDialog import WarningDialog, QuestionDialog
from QuestionDialog import WarningDialog, QuestionDialog, OptionDialog
from gen.ggettext import gettext as _
@ -107,55 +107,19 @@ if (software_version and (software_version < Min_VERSION)):
WarningDialog(msg)
raise Exception(msg)
# *******************************************************************
# Determine if we have access to outside Programs
#
# The programs are ImageMagick, and jhead
# * ImageMagick -- Convert and Delete all Exif metadata...
# * jhead -- re-initialize a jpeg, and other features...
# * del/ rm -- used to delete the original file after converting
# if requested...
#********************************************************************
# Windows 32bit systems
system_platform = os.sys.platform
MAGICK_FOUND_ = False
JHEAD_FOUND_ = False
if system_platform == "win32":
MAGICK_FOUND_ = "convert.exe" if Utils.search_for("convert.exe") else False
_JHEAD_FOUND_ = "jhead.exe" if Utils.search_for("jhead.exe") else False
DEL_FOUND_ = "del.exe" if Utils.search_for("del.exe") else False
elif system_platform == "linux2":
MAGICK_FOUND_ = "convert" if Utils.search_for("convert") else False
JHEAD_FOUND_ = "jhead" if Utils.search_for("jhead") else False
DEL_FOUND_ = "rm" if Utils.search_for("rm") else False
else:
MAGICK_FOUND_ = "convert" if Utils.search_for("convert") else False
JHEAD_FOUND_ = "jhead" if Utils.search_for("jhead") 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
# ------------------------------------------------------------------------
# available image types for exiv2 and pyexiv2
# ["jpeg", "jpg", "exv", "tiff", "dng", "nef", "pef", "pgf", "png", "psd", "jp2"]
if os.sys.platform == "win32":
EXIV2_FOUND_ = "exiv2.exe" if Utils.search_for("exiv2.exe") else False
else:
EXIV2_FOUND_ = "exiv2" if Utils.search_for("exiv2") else False
# define tooltips for all entries
_TOOLTIPS = {
# Description...
"Description" : _("Provide a short descripion for this image."),
@ -210,19 +174,14 @@ _BUTTONTIPS = {
# Save Exif Metadata button...
"Save" : _("Saves/ writes the Exif metadata to this image.\n"
"WARNING: Exif metadata will be erased if you save a blank entry field...") }
# if ImageMagick is installed on this computer then, add button
# tooltips for these two buttons...
if MAGICK_FOUND_:
_BUTTONTIPS.update( {
# Convert to .Jpeg button...
"Convert" : _("If your image is not a jpeg image, convert it to jpeg?"),
"WARNING: Exif metadata will be erased if you save a blank entry field..."),
# 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?") } )
"from this image! Are you sure that you want to do this?"),
# Convert to .Jpeg button...
"Convert" : _("If your image is not an exiv2 compatible image, convert it?") }
_BUTTONTIPS = dict( [widget, tooltip] for widget, tooltip in _BUTTONTIPS.items() )
# ------------------------------------------------------------------------
@ -304,12 +263,9 @@ class EditExifMetadata(Gramplet):
ccc_box.add( self.__create_button(
"Clear", False, [self.clear_metadata], gtk.STOCK_CLEAR, False) )
# is ImageMagick installed?
if MAGICK_FOUND_:
# Convert button...
ccc_box.add( self.__create_button(
"Convert", False, [self.__convert_dialog],
gtk.STOCK_CONVERT, False) )
# Convert button...
ccc_box.add( self.__create_button(
"Convert", False, [self.__convert_dialog], gtk.STOCK_CONVERT, False) )
for items in [
@ -360,10 +316,9 @@ class EditExifMetadata(Gramplet):
"Save", False, [self.save_metadata, self.update, self.display_exif_tags, self.copyto],
gtk.STOCK_SAVE, False))
if MAGICK_FOUND_:
# Delete All Metadata button...
hsd_box.add(self.__create_button(
"Delete", False, [self.__delete_dialog], gtk.STOCK_DELETE, False))
# Delete All Metadata button...
hsd_box.add(self.__create_button(
"Delete", False, [self.__delete_dialog], gtk.STOCK_DELETE, False))
# adds Exif Metadata Viewing Area
vbox.pack_start(view, padding =10)
@ -441,11 +396,7 @@ class EditExifMetadata(Gramplet):
self.model.clear()
# De-activate the buttons except for Help...
self.deactivate_buttons(["CopyTo", "Clear", "Save"])
# de-activate the Convert and Delete buttons...
if MAGICK_FOUND_:
self.deactivate_buttons(["Convert", "Delete"])
self.deactivate_buttons(["CopyTo", "Clear", "Save", "Convert", "Delete"])
# Re-post initial image message...
self.exif_widgets["Message:Area"].set_text(_("Select an "
@ -499,12 +450,9 @@ class EditExifMetadata(Gramplet):
# will create the image and read it...
self.setup_image(self.image_path, True)
# Checks to make sure that ImageMagick is installed on
# this computer and the image is NOT a jpeg image...
if MAGICK_FOUND_:
basename, self.extension = os.path.splitext(self.image_path)
if self.extension not in [".jpeg", ".jpg", ".jfif"]:
self.activate_buttons(["Convert"])
self.basename, self.extension = os.path.splitext(self.image_path)
if self.extension not in [".jpeg", ".jpg", ".jfif"]:
self.activate_buttons(["Convert"])
# displays the imge Exif metadata
self.display_exif_tags()
@ -566,16 +514,6 @@ class EditExifMetadata(Gramplet):
return button
def __convert_dialog(self, object):
"""
Handles the Convert question Dialog...
"""
# is ImageMagick installled?
if MAGICK_FOUND_:
QuestionDialog(_("Edit Image Exif Metadata"), _("Convert this "
"image to a .jpeg image?"), _("Convert"), self.convert2Jpeg)
def __delete_dialog(self, object):
"""
Handles the Delete Dialog...
@ -585,6 +523,82 @@ class EditExifMetadata(Gramplet):
"about to completely delete the Exif metadata from this image?"),
_("Delete"), self.strip_metadata)
def __convert_dialog(self, object):
"""
Handles the Convert question Dialog...
"""
# Convert and delete original file...
if EXIV2_FOUND_:
OptionDialog(_("Edit Image Exif Metadata"), _("WARNING: You are "
"about to convert this image into an .tiff image. Tiff "
"images are the industry standard for lossless compression.\n\n"
"Are you sure that you want to do this?"), _("Convert and Delete"),
self.__convert_delete, _("Convert"), self.__convert_file)
def __convert_file(self, full_path =None):
"""
Will attempt to convert an image to jpeg if it is not?
"""
if full_path is None:
full_path = self.image_path
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_delete(self, full_path =None):
"""
will convert an image file and delete original non-jpeg image.
"""
self.db = self.dbstate.db
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:
os.remove(full_path)
delete_results = True
except (IOError, OSError):
delete_results = False
if delete_results:
filepath, __basename = os.path.split(self.basename)
self.exif_widgets["Message:Area"].set_text(_("Your image has been "
"converted and the original file has been deleted..."))
def setup_image(self, full_path, createimage =False):
"""
will return an image instance and read the Exif metadata.
@ -717,7 +731,7 @@ class EditExifMetadata(Gramplet):
self.set_has_data(True)
# Activate Clear and Save buttons...
self.activate_buttons(["Clear", "Save", "CopyTo"])
self.activate_buttons(["Clear", "Save", "CopyTo", "Delete"])
# set Message Area to Display...
self.exif_widgets["Message:Area"].set_text(_("Displaying image "
@ -822,9 +836,6 @@ class EditExifMetadata(Gramplet):
# enable Save button after metadata has been "Copied to Edit Area"...
self.activate_buttons(["Save"])
if MAGICK_FOUND_:
self.activate_buttons(["Delete"])
# Clear the Message Area...
self.exif_widgets["Message:Area"].set_text("")
@ -850,28 +861,6 @@ class EditExifMetadata(Gramplet):
else:
self.exif_widgets["DateTime"].set_text("")
def convert2Jpeg(self):
"""
Will attempt to convert an image to jpeg if it is not?
"""
# if ImageMagick's convert is installed...
if MAGICK_FOUND_:
filepath, basename = os.path.split(self.image_path)
basename, oldext = os.path.splitext(self.image_path)
newextension = ".jpeg"
convert = subprocess.check_call(["convert", self.image_path,
os.path.join(filepath, basename + newextension) ] )
if str(convert):
# set Message Area to Convert...
self.exif_widgets["Message:Area"].set_text(_("Converting image,\n"
"You will need to delete the original image file..."))
self.deactivate_buttons(["Convert"])
def _set_exif_keytag(self, keytag, KeyValue):
"""
sets the value for the metadata keytags
@ -1080,9 +1069,7 @@ class EditExifMetadata(Gramplet):
# writes all Exif Metadata to image even if the fields are all empty.
self.write_metadata(self.plugin_image)
# Activate Delete button...
if MAGICK_FOUND_:
self.activate_buttons(["Delete"])
self.activate_buttons(["Delete"])
def __process_lat_long(self, latitude, longitude):
"""
@ -1163,43 +1150,48 @@ class EditExifMetadata(Gramplet):
self._set_exif_keytag(_DATAMAP["Longitude"], longitude)
self._set_exif_keytag(_DATAMAP["LongitudeRef"], longituderef)
def strip_metadata(self, erase_results =None):
def strip_metadata(self, mediadatatags =None):
"""
Will completely and irrevocably erase all Exif metadata from this image.
"""
if MAGICK_FOUND_:
erase = subprocess.check_call( ["convert", self.image_path,
"-strip", self.image_path] )
erase_results = str(erase)
# make sure the image has Exif metadata...
mediadatatags_ = _get_exif_keypairs(self.plugin_image)
if not mediadatatags_:
return
if EXIV2_FOUND_:
try:
erase = subprocess.check_call( [EXIV2_FOUND_, "delete", self.image_path] )
erase_results = str(erase)
except subprocess.CalledProcessError:
erase_results = False
else:
mediadatatags_ = _get_exif_keypairs(self.plugin_image)
if mediadatatags_:
for keytag in mediadatatags_:
del self.plugin_image[keytag]
for keytag_ in mediadatatags_:
del self.plugin_image[keytag_]
erase_results = True
# write wiped metadata to image...
self.write_metadata(self.plugin_image)
if erase_results:
# Clear the Display and Edit Areas
self.clear_metadata(self.plugin_image)
for widget in ["Media:Label", "Mime:Type", "Message:Area"]:
self.exif_widgets[widget].set_text("")
# Clear the Viewing Area...
self.model.clear()
# Notify the User...
self.exif_widgets["Message:Area"].set_text(_("All Exif metadata has been "
"deleted from this image..."))
self.exif_widgets["Message:Area"].set_text(_("All Exif metadata "
"has been deleted from this image..."))
self.update()
# re- initialize the image...
if (JHEAD_FOUND_ and self.extension in [".jpg", ".jpeg", ".jfif"]):
QuestionDialog(_("Edit Image Exif Metadata"),
_("Using -purejpg -- Delete all JPEG sections that aren't "
"necessary for rendering the image. Strips any metadata "
"that various applications may have left in the image..."),
_("Re- initialize"), self.__reinitialize_jpeg)
else:
self.exif_widgets["Message:Area"].set_text(_("There was an error "
"in stripping the Exif metadata from this image..."))
def __reinitialize_jpeg(self):
"""