-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaligner.py
executable file
·173 lines (145 loc) · 5.79 KB
/
aligner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/usr/bin/env python
# Copyright (c) 2012 David Zwarg
# http://www.zwarg.com/
#
# An image alignment tool. This tool will allow one to cycle through
# a folder full of images, and nudge each image individually.
#
# Pass in a directory full of images with the -i command line option.
#
# Commands:
# next image: Page_Down
# prev image: Page_Up
# nugde: arrow keys (Left, Right, Down, Up)
# quit: Esc
import pygtk
import gtk
from optparse import OptionParser
import glob
import os
class Aligner:
"""
Create a class for the main application.
"""
def __init__(self, folder):
"""
Intialize the Aligner class. Load the image files, create
the window and context, and show the first image.
@param folder: The folder name from where to load images.
"""
self.changed = False
self.files = glob.glob( folder + '/*.jpg' )
if len(self.files) < 2:
raise IOError('No files found in the input folder.')
self.files.sort()
self.index = 0
self.image = gtk.Image()
self.image.set_from_file( self.files[self.index] )
self.image.show()
self.status = gtk.Statusbar()
context = self.status.get_context_id("statusbar")
self.status.push( context, self.files[self.index] )
self.status.show()
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.connect("destroy", self.destroy)
self.window.connect("key_press_event", self.keypress)
vbox = gtk.VBox(False,1)
self.window.add(vbox)
vbox.show()
vbox.pack_start(self.image, False, 0)
vbox.pack_start(self.status, False, 0)
self.window.show()
def destroy(self, widget, data=None):
"""
Quit the application.
"""
gtk.main_quit()
def keypress(self, widget, data):
"""
Respond to a key press event.
"""
context = self.status.get_context_id("statusbar")
keyname = gtk.gdk.keyval_name(data.keyval)
if keyname == 'Left':
self.wrap( self.files[self.index], -1, 0 )
elif keyname == 'Right':
self.wrap( self.files[self.index], 1, 0 )
elif keyname == 'Up':
self.wrap( self.files[self.index], 0, -1 )
elif keyname == 'Down':
self.wrap( self.files[self.index], 0, 1 )
elif keyname == 'Page_Down':
if self.changed:
pixbuf = self.image.get_pixbuf()
pixbuf.save(self.files[self.index], "jpeg", {"quality":"100"})
self.changed = False
if self.index == len(self.files) - 1:
self.index = 0
else:
self.index += 1
self.status.pop(context)
self.status.push(context,self.files[self.index])
self.image.set_from_file( self.files[self.index] )
self.image.show()
elif keyname == 'Page_Up':
if self.changed:
pixbuf = self.image.get_pixbuf()
pixbuf.save(self.files[self.index], "jpeg", {"quality":"100"})
self.changed = False
if self.index == 0:
self.index = len(self.files) - 1
else:
self.index -= 1
self.status.pop(context)
self.status.push(context,self.files[self.index])
self.image.set_from_file( self.files[self.index] )
self.image.show()
elif keyname == 'Escape':
gtk.main_quit()
else:
print 'Unrecognized keycode/keyname: %d/%s' % (data.hardware_keycode, keyname)
def wrap(self, img, x, y):
"""
Wrap an image pixel data around it's edge.
@param img: The image. Seems to be ignored.
@param x: The amount to shift in the X coordinate.
@param y: The amount to shift in the Y coordinate.
"""
pixbuf0 = self.image.get_pixbuf()
pixbuf1 = gtk.gdk.Pixbuf( gtk.gdk.COLORSPACE_RGB, False, 8, pixbuf0.get_width(), pixbuf0.get_height() )
# twiddle the bits
if x == 0:
if y < 0:
pixbuf0.copy_area( x, 1, pixbuf0.get_width(), pixbuf0.get_height()-1, pixbuf1, x, 0 )
pixbuf0.copy_area( x, 0, pixbuf0.get_width(), 1, pixbuf1, x, pixbuf0.get_height()-1 )
else: # y > 0:
pixbuf0.copy_area( x, 0, pixbuf0.get_width(), pixbuf0.get_height()-1, pixbuf1, x, 1 )
pixbuf0.copy_area( x, pixbuf0.get_height()-1, pixbuf0.get_width(), 1, pixbuf1, x, 0 )
elif x < 0:
pixbuf0.copy_area( 0, y, 1, pixbuf0.get_height(), pixbuf1, pixbuf0.get_width()-1, y )
pixbuf0.copy_area( 1, y, pixbuf0.get_width()-1, pixbuf0.get_height(), pixbuf1, 0, y )
else: # x > 0:
pixbuf0.copy_area( 0, y, pixbuf0.get_width()-1, pixbuf0.get_height(), pixbuf1, 1, y )
pixbuf0.copy_area( pixbuf0.get_width()-1, y, 1, pixbuf0.get_height(), pixbuf1, 0, y )
self.changed = True;
self.image.set_from_pixbuf( pixbuf1 )
self.image.show()
def main(self):
"""
The main loop for this class
"""
gtk.main()
if __name__ == "__main__":
oParser = OptionParser()
oParser.add_option("-i","--input",dest="input", help="specify an input folder")
(options, args) = oParser.parse_args()
if options.input is None:
print "Please provide an input folder with -i or --input"
exit(1)
input = os.path.abspath(options.input)
if not os.path.exists(input):
print "The provided input folder does not exist."
exit(1)
align = Aligner(input)
align.main()