![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() (b) |
![]() (c) |
![]() (d) |
![]() (e) |
図1.backgrounder.py で生成する Window。
a) メイン window。
b) オリジナルサイズの画像に (GIF の場合)背景色をつけたもの。
c) 背景色調節用 window
d) ディレクトリ選択 window
e) 説明 window
[code 1] (backgrounder.py)
01: #! /usr/bin/env python 02: # -*- coding: shift_jis -*- 03: 04: """ 05: backgrounder.py 06: 07: view images in a directory 08: 09: July 04, 2005 10: """ 11: 12: import re 13: import os 14: import os.path as P 15: import Tkinter as Tk 16: import ScrolledText as S 17: import Image as I 18: import ImageTk as Itk 19: import ImageColor as Ic 20: import tkFileDialog as D 21: import tkMessageBox as M 22: 23: 24: SIZE = 100 25: IMAGR_TYPES = ['gif', 'png', 'bmp', 'jpg', 'tif', 'ppm'] 26: MAM_COLN = 6 27: GEO_MAIN = '680x600+20+20' 28: GEO_SATE = '+730+50' 29: GEO_SCAL = '+730+400' 30: 31: 32: ## functions ------------------------------------------------ 33: def get_size(tup): 34: """ It returns the size of images on the summary""" 35: x, y = tup 36: if (x<=100 and y<=100): 37: return (x, y) 38: elif x > y: 39: r = float(SIZE) / float(x) 40: return (100, int(y*r)) 41: else: 42: r = float(SIZE) / float(y) 43: return (int(x*r), 100) 44: 45: 46: def make_regexp(types): 47: """ It returns the regular expression of the image file type""" 48: str = "\.(" 49: for k, v in types.iteritems(): 50: if v.get(): 51: str += k + '|' 52: 53: str = str[0:-1] + ')$' 54: return re.compile(str, re.I) 55: 56: 57: ## classes ----------------------------------------------------------------------------------- 58: class ImageLabel: 59: """ A Label class to show an image """ 60: 61: id_original_size = None # ID of the Label showing an original size image 62: bg_var = None # variable for background color 63: image_file_now = None 64: 65: def __init__(self, stxt, image_file, img): 66: self.image= img 67: self.image_file = image_file 68: frame = Tk.Frame(stxt, height=115, width=100) 69: frame.pack_propagate(0) 70: txt_label=Tk.Label(frame, text=P.basename(self.image_file), font=('Helvetica', '8')) 71: txt_label.pack(side=Tk.BOTTOM) 72: 73: self.img_label=Tk.Label(frame, image=self.image) 74: self.img_label.pack(side=Tk.BOTTOM) 75: 76: stxt.window_create(Tk.END, align=Tk.BASELINE, padx=5, pady=5, window=frame) 77: self.img_label.bind('<Double-Button-1>', self.show) 78: 79: def show(self, event): 80: label = ImageLabel.id_original_size 81: if (label and label.winfo_exists()): 82: top = label.winfo_toplevel() 83: top.destroy() 84: top = Tk.Toplevel(self.img_label) 85: top.title(P.basename(self.image_file)) 86: top.geometry(GEO_SATE) 87: img = I.open(self.image_file) 88: self.timg = Itk.PhotoImage(img) 89: label=Tk.Label(top, image=self.timg, bg=ImageLabel.bg_var.get()) 90: label.pack() 91: ImageLabel.id_original_size = label 92: ImageLabel.image_file_now = self.image_file 93: 94: 95: class Frame(Tk.Frame): 96: """ The main class of this program. """ 97: 98: def __init__(self, master=None): 99: Tk.Frame.__init__(self, master) 100: self.master.title('BackGrounder') 101: self.master.geometry(GEO_MAIN) 102: self.cus_top = None 103: self.fout = None 104: 105: ### Menu 106: menu_bar = Tk.Menu(self, tearoff=0) 107: # File 108: menu_file = Tk.Menu(menu_bar, tearoff=0) 109: menu_bar.add_cascade(label="File", menu=menu_file, underline=0) 110: menu_file.add_command(label="Browse Dir.", command=self.browse, underline=0, accelerator = 'Ctrl-O') 111: menu_file.add_command(label="ReLoad", command=self.load_dir, underline=0, accelerator = 'Ctrl-R') 112: menu_file.add_command(label="Save As", command=self.save_image, underline=0, accelerator = 'Ctrl-S') 113: menu_file_type = Tk.Menu(menu_file, tearoff=0) 114: menu_file.add_cascade(label="File Type", menu=menu_file_type, underline=0) 115: menu_file.add_separator() 116: menu_file.add_command(label="Exit", command=self.exit, underline=0 , accelerator = 'Ctrl-Q') 117: 118: menu_bar.add_command(label="Back Ground", command=self.cus_bg, underline=0) 119: menu_bar.add_command(label="Help", command=self.show_info, underline=0) 120: 121: # short-cuts 122: self.master.bind('<Control-KeyPress-o>', self.browse) 123: self.master.bind('<Control-KeyPress-s>', self.save_image) 124: self.master.bind('<Control-KeyPress-r>', self.load_dir) 125: self.master.bind('<Control-KeyPress-q>', self.exit) 126: 127: # check buttons in menu_file_type 128: self.var_type = dict() 129: for i, image_type in enumerate(IMAGR_TYPES): 130: self.var_type[image_type] = Tk.IntVar() 131: menu_file_type.add_checkbutton(label=image_type, variable=self.var_type[image_type]) 132: menu_file_type.invoke(i) 133: 134: ImageLabel.bg_var = Tk.StringVar() 135: ImageLabel.bg_var.set('#FFFFFF') 136: 137: # add menu bar 138: try: 139: self.master.config(menu=menu_bar) # this required to show the menu bar 140: except AttributeError: 141: self.master.Tk.call(master, "config", "-menu", menu_bar) 142: 143: 144: self.once = False 145: self.stxt = S.ScrolledText(self, bg=self.cget('bg'), cursor=self.cget('cursor'), state=Tk.DISABLED) 146: self.stxt.pack(fill=Tk.BOTH, expand=1) 147: self.pack(fill=Tk.BOTH, expand=1) 148: 149: 150: def update(self, dir, types): 151: self.stxt.configure(state=Tk.NORMAL) 152: if self.once: 153: self.stxt.delete('1.0', Tk.END) 154: 155: self.once=True 156: pat = make_regexp(types) 157: 158: for f in os.listdir(dir): 159: if pat.search(f): 160: file = P.join(dir, f) 161: img = I.open(file) 162: ImageLabel(self.stxt, file, 163: Itk.PhotoImage(img.resize(get_size(img.size), I.NEAREST))) 164: 165: self.stxt.configure(state=Tk.DISABLED) 166: 167: 168: def browse(self, event=None): 169: self.dir = D.askdirectory() 170: if self.dir: 171: self.load_dir() 172: 173: def load_dir(self, event=None): 174: self.update(self.dir, self.var_type) 175: 176: 177: def show_info(self): 178: M.showinfo(u"使い方", u"メニューバーの File->Browse Dir. でディレクトリを選択してください。\n" 179: u"そのディレクトリに含まれる画像ファイルの一覧が表示されます。\n" 180: u"一覧にある画像をクリックすると、別窓でオリジナルサイズの画像が表示されます。\n\n" 181: u"透過型 GIF の場合は背景色をつけることができます。\n" 182: u"メニューバーの Back Ground をクリックすると\n" 183: u"赤、緑、青用の3つのスケールがある Window が現れるので、\n" 184: u"それで背景色を調節できます。\n\n" 185: u"背景色をつけた画像は File->SaveAs により保存することができます。" 186: ) 187: 188: def cus_bg(self): 189: if not (self.cus_top and self.cus_top.winfo_exists()): 190: self.cus_top = Tk.Toplevel(self) 191: self.cus_top.title('Create Back Ground') 192: self.cus_top.geometry(GEO_SCAL) 193: cusf = Tk.Frame(self.cus_top) 194: cusf.pack(fill=Tk.BOTH, padx=10, pady=10) 195: self.scale = dict() 196: for i, color in enumerate(('red', 'green', 'blue')): 197: l=Tk.Label(cusf, text=color+': ', anchor=Tk.W, fg=color, font=('Helvetica', '10', 'bold')) 198: l.grid(row=i, column=0, sticky=Tk.W) 199: self.scale[color] = Tk.Scale(cusf, orient=Tk.HORIZONTAL, length=300, from_=0, to=255, 200: command=self.customize_bg, tickinterval=50) 201: self.scale[color].set(255) 202: self.scale[color].grid(row=i, column=1) 203: 204: 205: def customize_bg(self, event): 206: ImageLabel.bg_var.set('#%02X%02X%02X' % 207: (self.scale['red'].get(), self.scale['green'].get(), self.scale['blue'].get())) 208: bg1 = ImageLabel.bg_var.get() 209: label = ImageLabel.id_original_size 210: if label and label.winfo_exists(): 211: label.configure(bg=bg1) 212: top = label.winfo_toplevel() 213: top.focus_set() 214: 215: def save_image(self, event=None): 216: self.fout = D.asksaveasfilename(initialdir=self.dir, initialfile=self.fout and P.basename(self.fout) or None) 217: if self.fout: 218: img=I.open(ImageLabel.image_file_now) 219: imgc = img.mode == 'RGB' and img or img.convert('RGB') 220: bg1 = Ic.getrgb(ImageLabel.bg_var.get()) # background color 221: ls=[] # a sequence to store image data 222: for c0 in imgc.getdata(): 223: if(c0==(255,255,255)): 224: ls.append(bg1) 225: else: 226: ls.append(c0) 227: 228: imgc.putdata(ls) 229: imgc.save(self.fout) 230: 231: def exit(self, event=None): 232: self.master.destroy() 233: 234: ##------------------------------------------------ 235: 236: if __name__ == '__main__': 237: f = Frame() 238: f.mainloop()
ご覧になるとわかるように7割以上 viewer.py と同じです。 プログラムが若干長いので、部分ごとに説明していきたいと思います。見出しのカッコ内の数字はコードの行数です。
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |