-
Notifications
You must be signed in to change notification settings - Fork 43
/
export-scaled.py
executable file
·304 lines (253 loc) · 9.57 KB
/
export-scaled.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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#!/usr/bin/env python
# Export a copy of the current image, scaled to a different size.
# It's like "Save a copy" only it remembers to re-scale each time
# back to whatever scale you used on the last export --
# like if you want to keep a thumbnail or a
# smaller web version current as you're editing the master.
# Copyright 2012 by Akkana Peck, http://www.shallowsky.com/software/
# You may use and distribute this plug-in under the terms of the GPL v2
# or, at your option, any later GPL version.
from gimpfu import *
import gtk
import os
# Image original size
orig_width = 0
orig_height = 0
# The three gtk.Entry widgets we'll monitor:
percent_e = None
width_e = None
height_e = None
# A way to show errors to the user:
warning_label = None
# A way to turn off notifications while we're calculating
busy = False
# Doesn't work to compare entry against percent_e, etc.
# Must pass that info in a separate arg, darnit.
def entry_changed(entry, which) :
global percent_e, width_e, height_e, orig_width, orig_height, busy
if busy :
return
# Can't use get_value() or get_value_as_int() because they
# don't work before an update(), but update() will usually
# overwrite what the user typed. So define a function:
def get_num_value(spinbox) :
s = spinbox.get_text()
if not s :
return 0
try :
p = int(s)
return p
except ValueError :
try :
p = float(s)
return p
except ValueError :
return 0
if which == 'p' :
p = get_num_value(percent_e)
if not p : return
busy = True
w = int(orig_width * p / 100.)
width_e.set_text(str(w))
h = int(orig_height * p / 100.)
height_e.set_text(str(h))
busy = False
elif which == 'w' :
w = get_num_value(width_e)
if not w : return
busy = True
p = w * 100. / orig_width
percent_e.set_text(str(p))
h = int(orig_height * p / 100.)
height_e.set_text(str(h))
busy = False
elif which == 'h' :
h = get_num_value(height_e)
if not h : return
busy = True
p = h * 100. / orig_height
percent_e.set_text(str(p))
w = int(orig_width * p / 100.)
width_e.set_text(str(w))
busy = False
else :
print "I'm confused -- not width, height or percentage"
def python_export_scaled(img, drawable) :
global percent_e, width_e, height_e, orig_width, orig_height, warning_label
orig_filename = img.filename
orig_width = img.width
orig_height = img.height
# Do we already have defaults?
para = img.parasite_find('export-scaled')
if para :
[ init_filename, init_percent, init_width, init_height ] = \
para.data.split('\n')
else :
init_filename = orig_filename
init_percent = 100
init_width = img.width
init_height = img.height
chooser = gtk.FileChooserDialog(title=None,
action=gtk.FILE_CHOOSER_ACTION_SAVE,
buttons=(gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE,
gtk.RESPONSE_OK))
if init_filename :
chooser.set_current_name(os.path.basename(init_filename))
chooser.set_current_folder(os.path.dirname(init_filename))
vbox = gtk.VBox(spacing=8)
hbox = gtk.HBox(spacing=8)
l = gtk.Label("Export size:")
l.set_alignment(1, 0)
l.show()
hbox.pack_start(l)
l = gtk.Label("Percent")
l.set_alignment(1, 0)
hbox.pack_start(l)
l.show()
adj = gtk.Adjustment(float(init_percent), 1, 10000, 1, 10, 0)
percent_e = gtk.SpinButton(adj) #, 0, 0)
#percent_e = gtk.Entry()
#percent_e.set_width_chars(5)
#percent_e.set_text("100") # XXX Later, remember size from last time
percent_e.connect("changed", entry_changed, 'p');
percent_e.show()
hbox.pack_start(percent_e)
l = gtk.Label("%")
l.set_alignment(0, 1)
hbox.pack_start(l)
l.show()
l = gtk.Label("Width")
l.set_alignment(1, 0)
hbox.pack_start(l)
l.show()
adj = gtk.Adjustment(float(init_width), 1, 10000, 1, 10, 0)
width_e = gtk.SpinButton(adj)
#width_e = gtk.Entry()
#width_e.set_width_chars(7)
#width_e.set_text(str(img.width))
# XXX Later, remember size from previous run
width_e.connect("changed", entry_changed, 'w');
width_e.show()
hbox.pack_start(width_e)
l = gtk.Label("Height")
l.set_alignment(1, 0)
hbox.pack_start(l)
l.show()
adj = gtk.Adjustment(float(init_height), 1, 10000, 1, 10, 0)
height_e = gtk.SpinButton(adj)
#height_e = gtk.Entry()
#height_e.set_width_chars(7)
#height_e.set_text(str(img.height))
height_e.connect("changed", entry_changed, 'h');
hbox.pack_start(height_e)
height_e.show()
hbox.show()
vbox.pack_start(hbox)
warning_label = gtk.Label("")
warning_label.show()
vbox.pack_start(warning_label)
chooser.set_extra_widget(vbox)
# Oh, cool, we could have shortcuts to image folders,
# and maybe remove the stupid fstab shortcuts GTK adds for us.
#chooser.add_shortcut_folder(folder)
#chooser.remove_shortcut_folder(folder)
# Loop to catch errors/warnings:
while True :
response = chooser.run()
if response != gtk.RESPONSE_OK:
chooser.destroy()
return
percent = float(percent_e.get_text())
width = int(width_e.get_text())
height = int(height_e.get_text())
filename = chooser.get_filename()
if filename == orig_filename :
warning_label.set_text("Change the name or the directory -- don't overwrite original file!")
continue
# Whew, it's not the original filename, so now we can export.
#print "export from", orig_filename, "to", filename, \
# "at", width, "x", height
# Is there any point to pushing and popping the context?
#gimp.context_pop()
newimg = pdb.gimp_image_duplicate(img)
# If it's XCF, we don't need to flatten or process it further,
# just scale it:
base, ext = os.path.splitext(filename)
ext = ext.lower()
if ext == '.gz' or ext == '.bz2' :
base, ext = os.path.splitext(base)
ext = ext.lower()
if ext != '.xcf' :
newimg.flatten()
# XXX This could probably be smarter about flattening. Oh, well.
pdb.gimp_image_merge_visible_layers(copyimg, CLIP_TO_IMAGE)
newimg.scale(width, height)
# Find any image type settings parasites (e.g. jpeg settings)
# that got set during save, so we'll be able to use them
# next time.
def copy_settings_parasites(fromimg, toimg) :
for pname in fromimg.parasite_list() :
if pname[-9:] == '-settings' or pname[-13:] == '-save-options' :
para = fromimg.parasite_find(pname)
if para :
toimg.attach_new_parasite(pname, para.flags, para.data)
# Copy any settings parasites we may have saved from previous runs:
copy_settings_parasites(img, newimg)
# gimp-file-save insists on being passed a valid layer,
# even if saving to a multilayer format such as XCF. Go figure.
try :
# I don't get it. What's the rule for whether gimp_file_save
# will prompt for jpg parameters? Saving back to an existing
# file doesn't seem to help.
# run_mode=RUN_WITH_LAST_VALS is supposed to prevent prompting,
# but actually seems to do nothing. Copying the -save-options
# parasites is more effective.
dpy = chooser.get_display()
chooser.hide()
dpy.sync()
pdb.gimp_file_save(newimg, newimg.active_layer, filename, filename,
run_mode=RUN_WITH_LAST_VALS)
except RuntimeError, e :
#warning_label.set_text("Didn't save to " + filename
# + ":" + str(e))
markup = '<span foreground="red" size="larger" weight=\"bold">'
markup_end = '</span>'
warning_label.set_markup(markup + "Didn't save to " + filename
+ ":" + str(e) + markup_end)
gimp.delete(newimg)
chooser.show()
continue
chooser.destroy()
#gimp.context_pop()
copy_settings_parasites(newimg, img)
gimp.delete(newimg)
#gimp.Display(newimg)
# Save parameters as a parasite, even if saving failed,
# so we can default to them next time.
# Save: percent, width, height
# I have no idea what the flags are -- the doc doesn't say.
para = img.attach_new_parasite('export-scaled', 0,
'%s\n%d\n%d\n%d' % (filename, percent,
width, height))
# img.parasite_attach(para)
return
register(
"python_fu_export_scaled",
"Export a copy of the current image, scaled to a different size.",
"Export a copy of the current image, scaled to a different size.",
"Akkana Peck",
"Akkana Peck",
"2012",
"Export scaled...",
"*",
[
(PF_IMAGE, "image", "Input image", None),
(PF_DRAWABLE, "drawable", "Input drawable", None),
],
[],
python_export_scaled,
menu = "<Image>/File/Save/"
)
main()