[Tutor] adding a watermark to a sequence of images
Terry Carroll
carroll at tjc.com
Tue Jul 22 07:56:33 CEST 2008
On Mon, 21 Jul 2008, Christopher Spears wrote:
> By all means, share your script! Even if I don't use it, I can learn
> something from it!
Well, maybe. If nothing else, perhaps you'll learn some new bad habits.
The timestamp on this file shows that I dropped this project in June 2005,
and you can see it's unfinished. It still has a few raw edges (including
a prompt for a "preserve EXIF" feature that never got written; and lots of
debugging print statements), but it's not bad as a proof-of-concept.
The code imports and depends on Gene Cash's EXIF.py module; it now
apparently lives at http://sourceforge.net/projects/exif-py/ rather than
the URL in the code. But still, if the EXIF module doesn't exist, it just
uses the file's timestamp as the date -- not exactly the safest way of
figuring the date the photo was taken.
At the time I wrote this, I was unaware that PIL had some
then-undocumented EXIF support; I probably would have used that to avoid
importing a non-standard module.
Use this code however you wish, if you find it helpful. Ignore the
copyright statement; BaishuSoft was just a little joke between my wife and
me.
------snip-------
import Tkinter as Tk
import tkFileDialog
import os, sys, time
import Image, ImageDraw, ImageFont, ImageTk
class MyApp:
"""Begin a Tkinter-based application"""
def __init__(self, root):
"""initializer for Tkinter-based application"""
self.root=root
self.root.title("Picture TimeStamper")
NoticeFrame = Tk.Frame(self.root)
NoticeFrame.pack()
headertext = u"""
Baishusoft Picture TimeStamper
\U000000A9 2005 Baishusoft LLP
"""
Tk.Label(NoticeFrame,text=headertext).pack()
ButtonFrame = Tk.Frame(self.root)
ButtonFrame.pack()
SelButton = Tk.Button(ButtonFrame,
text="Select Directory", command=self.select)
SelButton.pack(side="left")
QuitButton = Tk.Button(ButtonFrame, text="Quit",
command=self.quit)
QuitButton.pack(side="left")
OptionsFrame = Tk.Frame(self.root)
OptionsFrame.pack()
self.EXIFvar = Tk.IntVar()
self.EXIFCheckbox = Tk.Checkbutton(
OptionsFrame,
text="Preserve EXIF (requires JHead)",
variable = self.EXIFvar)
self.EXIFCheckbox.pack(side="top")
self.Progressvar = Tk.IntVar()
self.ProgressCheckbox = Tk.Checkbutton(
OptionsFrame,
text="Show progress",
variable = self.Progressvar)
self.ProgressCheckbox.pack(side="left")
self.StatusFrame = Tk.Frame(self.root)
self.StatusFrame.pack()
self.ImageLabel = Tk.Label(self.StatusFrame)
self.ImageLabel.pack()
self.FilenameLabel = Tk.Label(self.StatusFrame)
self.FilenameLabel.pack()
def select(self):
dirname = tkFileDialog.askdirectory()
if dirname != '':
os.path.walk(dirname, self.process_files, None)
print "PROCESSING COMPLETED. SELECT MORE FILES OR QUIT."
else:
print "NO DIRECTORY SELECTED."
return
def quit(self):
print "EXITING."
sys.exit()
def process_files(self, junk, dirpath, namelist):
for filename in namelist:
stamped_filename = self.getstampedfilename(filename)
if stamped_filename is not None:
if os.path.isfile(os.path.join(dirpath,stamped_filename)):
print "FILE EXISTS, SKIPPING:", stamped_filename
else:
self.updatestatus(dirpath, filename)
datetext = self.timestamp(dirpath, filename,
stamped_filename)
print "FILE IMPRINTED:", stamped_filename, datetext
def updatestatus(self,dirpath,filename):
im=Image.open(os.path.join(dirpath, filename))
print time.asctime(), "thumbnailing...", filename, im.mode, im.size
im.thumbnail((100,75))
print time.asctime(), "showing...", filename, im.mode, im.size
#im.show()
self.Tkimage = ImageTk.PhotoImage(im)
print "created"
self.ImageLabel.config(image=self.Tkimage)
self.ImageLabel.pack()
self.FilenameLabel.config(text=filename)
self.FilenameLabel.pack()
self.StatusFrame.pack()
self.root.update()
def getstampedfilename(self, filename):
fn, ft = os.path.splitext(filename)
if ft.upper() in [".JPG", ".JPEG"] and \
not (fn.upper().endswith("-DATED")):
return fn + "-dated" + ft
else:
return None
def timestamp(self, dirpath, original_filename, new_filename):
full_original_filename = os.path.join(dirpath, original_filename)
full_new_filename = os.path.join(dirpath, new_filename)
font=ImageFont.truetype("Arial.ttf", 40)
datetext = GetFileDate(full_original_filename)
im = Image.open(full_original_filename)
im0 = Imprint(im, datetext, font=font, opacity=0.6,
color=(255,255,255))
im0.save(full_new_filename, "JPEG")
return datetext
def GetFileDate(file):
"""
Returns the date associated with a file.
For JPEG files, it will use the EXIF data, if available
"""
try:
import EXIF
# EXIF.py from http://home.cfl.rr.com/genecash/digital_camera.html
f = open(file, "rb")
tags = EXIF.process_file(f)
f.close()
return str(tags['Image DateTime'])
except (KeyError, ImportError):
# EXIF not installed or no EXIF date available
import os.path, time
return time.ctime(os.path.getmtime(file))
def ReduceOpacity(im, opacity):
"""
Returns an image with reduced opacity.
Taken from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/362879
"""
import ImageEnhance
assert opacity >= 0 and opacity <= 1
if im.mode != 'RGBA':
im = im.convert('RGBA')
else:
im = im.copy()
alpha = im.split()[3]
alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
im.putalpha(alpha)
return im
def Imprint(im, inputtext, font=None, color=None, opacity=.6, margin=(30,30)):
"""
imprints a PIL image with the indicated text in lower-right corner
"""
if im.mode != "RGBA":
im = im.convert("RGBA")
textlayer = Image.new("RGBA", im.size, (0,0,0,0))
textdraw = ImageDraw.Draw(textlayer)
textsize = textdraw.textsize(inputtext, font=font)
textpos = [im.size[i]-textsize[i]-margin[i] for i in [0,1]]
textdraw.text(textpos, inputtext, font=font, fill=color)
if opacity != 1:
textlayer = ReduceOpacity(textlayer,opacity)
return Image.composite(textlayer, im, textlayer)
root = Tk.Tk()
myapp = MyApp(root)
root.mainloop()
More information about the Tutor
mailing list