 |
| Global Moderator |
 |
Joined: May 16, 2010 Posts: 16023
|
This script works great in Gimp-2.6 but doesn't show in the menus for Gimp-2.7. I am wondering if someone could tell me how to fix the script so it will work in Gimp-2.7? # GIMPFU START ############################################# import string as _string import math import gimp import gimpcolor from gimpenums import * pdb = gimp.pdb
import gettext t = gettext.translation('gimp20-python', gimp.locale_directory, fallback=True) _ = t.ugettext
class error(RuntimeError): pass class CancelError(RuntimeError): pass
PF_INT8 = PDB_INT8 PF_INT16 = PDB_INT16 PF_INT32 = PDB_INT32 PF_INT = PF_INT32 PF_FLOAT = PDB_FLOAT PF_STRING = PDB_STRING PF_VALUE = PF_STRING #PF_INT8ARRAY = PDB_INT8ARRAY #PF_INT16ARRAY = PDB_INT16ARRAY #PF_INT32ARRAY = PDB_INT32ARRAY #PF_INTARRAY = PF_INT32ARRAY #PF_FLOATARRAY = PDB_FLOATARRAY #PF_STRINGARRAY = PDB_STRINGARRAY PF_COLOR = PDB_COLOR PF_COLOUR = PF_COLOR PF_REGION = PDB_REGION PF_DISPLAY = PDB_DISPLAY PF_IMAGE = PDB_IMAGE PF_LAYER = PDB_LAYER PF_CHANNEL = PDB_CHANNEL PF_DRAWABLE = PDB_DRAWABLE PF_VECTORS = PDB_VECTORS #PF_SELECTION = PDB_SELECTION #PF_BOUNDARY = PDB_BOUNDARY #PF_PATH = PDB_PATH #PF_STATUS = PDB_STATUS
PF_TOGGLE = 1000 PF_BOOL = PF_TOGGLE PF_SLIDER = 1001 PF_SPINNER = 1002 PF_ADJUSTMENT = PF_SPINNER
PF_FONT = 1003 PF_FILE = 1004 PF_BRUSH = 1005 PF_PATTERN = 1006 PF_GRADIENT = 1007 PF_RADIO = 1008 PF_TEXT = 1009 PF_PALETTE = 1010 PF_FILENAME = 1011 PF_DIRNAME = 1012 PF_OPTION = 1013
_type_mapping = { PF_INT8 : PDB_INT8, PF_INT16 : PDB_INT16, PF_INT32 : PDB_INT32, PF_FLOAT : PDB_FLOAT, PF_STRING : PDB_STRING, #PF_INT8ARRAY : PDB_INT8ARRAY, #PF_INT16ARRAY : PDB_INT16ARRAY, #PF_INT32ARRAY : PDB_INT32ARRAY, #PF_FLOATARRAY : PDB_FLOATARRAY, #PF_STRINGARRAY : PDB_STRINGARRAY, PF_COLOR : PDB_COLOR, PF_REGION : PDB_REGION, PF_DISPLAY : PDB_DISPLAY, PF_IMAGE : PDB_IMAGE, PF_LAYER : PDB_LAYER, PF_CHANNEL : PDB_CHANNEL, PF_DRAWABLE : PDB_DRAWABLE, PF_VECTORS : PDB_VECTORS,
PF_TOGGLE : PDB_INT32, PF_SLIDER : PDB_FLOAT, PF_SPINNER : PDB_INT32,
PF_FONT : PDB_STRING, PF_FILE : PDB_STRING, PF_BRUSH : PDB_STRING, PF_PATTERN : PDB_STRING, PF_GRADIENT : PDB_STRING, PF_RADIO : PDB_STRING, PF_TEXT : PDB_STRING, PF_PALETTE : PDB_STRING, PF_FILENAME : PDB_STRING, PF_DIRNAME : PDB_STRING, PF_OPTION : PDB_INT32, }
_obj_mapping = { PF_INT8 : int, PF_INT16 : int, PF_INT32 : int, PF_FLOAT : float, PF_STRING : str, #PF_INT8ARRAY : list, #PF_INT16ARRAY : list, #PF_INT32ARRAY : list, #PF_FLOATARRAY : list, #PF_STRINGARRAY : list, PF_COLOR : gimpcolor.RGB, PF_REGION : int, PF_DISPLAY : gimp.Display, PF_IMAGE : gimp.Image, PF_LAYER : gimp.Layer, PF_CHANNEL : gimp.Channel, PF_DRAWABLE : gimp.Drawable, PF_VECTORS : gimp.Vectors,
PF_TOGGLE : bool, PF_SLIDER : float, PF_SPINNER : int,
PF_FONT : str, PF_FILE : str, PF_BRUSH : str, PF_PATTERN : str, PF_GRADIENT : str, PF_RADIO : str, PF_TEXT : str, PF_PALETTE : str, PF_FILENAME : str, PF_DIRNAME : str, PF_OPTION : int, }
_registered_plugins_ = {}
def register(proc_name, blurb, help, author, copyright, date, label, imagetypes, params, results, function, menu=None, domain=None, on_query=None, on_run=None): '''This is called to register a new plug-in.'''
# First perform some sanity checks on the data def letterCheck(str): allowed = _string.letters + _string.digits + '_' + '-' for ch in str: if not ch in allowed: return 0 else: return 1
if not letterCheck(proc_name): raise error, "procedure name contains illegal characters"
for ent in params: if len(ent) < 4: raise error, ("parameter definition must contain at least 4 " "elements (%s given: %s)" % (len(ent), ent))
if type(ent[0]) != int: raise error, "parameter types must be integers"
if not letterCheck(ent[1]): raise error, "parameter name contains illegal characters"
for ent in results: if len(ent) < 3: raise error, ("result definition must contain at least 3 elements " "(%s given: %s)" % (len(ent), ent))
if type(ent[0]) != type(42): raise error, "result types must be integers"
if not letterCheck(ent[1]): raise error, "result name contains illegal characters"
plugin_type = PLUGIN
if (not proc_name[:7] == 'python-' and not proc_name[:7] == 'python_' and not proc_name[:10] == 'extension-' and not proc_name[:10] == 'extension_' and not proc_name[:8] == 'plug-in-' and not proc_name[:8] == 'plug_in_' and not proc_name[:5] == 'file-' and not proc_name[:5] == 'file_'): proc_name = 'python-fu-' + proc_name
# if menu is not given, derive it from label need_compat_params = False if menu is None and label: fields = label.split('/') if fields: label = fields.pop() menu = '/'.join(fields) need_compat_params = True
if need_compat_params and plugin_type == PLUGIN: file_params = [(PDB_STRING, "filename", "The name of the file", ""), (PDB_STRING, "raw-filename", "The name of the file", "")]
if menu is None: pass elif menu[:6] == '<Load>': params[0:0] = file_params elif menu[:7] == '<Image>' or menu[:6] == '<Save>': params.insert(0, (PDB_IMAGE, "image", "Input image", None)) params.insert(1, (PDB_DRAWABLE, "drawable", "Input drawable", None)) if menu[:6] == '<Save>': params[2:2] = file_params
_registered_plugins_[proc_name] = (blurb, help, author, copyright, date, label, imagetypes, plugin_type, params, results, function, menu, domain, on_query, on_run)
def _query(): for plugin in _registered_plugins_.keys(): (blurb, help, author, copyright, date, label, imagetypes, plugin_type, params, results, function, menu, domain, on_query, on_run) = _registered_plugins_[plugin]
def make_params(params): return [(_type_mapping[x[0]], x[1], _string.replace(x[2], "_", "")) for x in params]
params = make_params(params) # add the run mode argument ... params.insert(0, (PDB_INT32, "run-mode", "Interactive, Non-Interactive"))
results = make_params(results)
if domain: try: (domain, locale_dir) = domain gimp.domain_register(domain, locale_dir) except ValueError: gimp.domain_register(domain)
gimp.install_procedure(plugin, blurb, help, author, copyright, date, label, imagetypes, plugin_type, params, results)
if menu: gimp.menu_register(plugin, menu) if on_query: on_query()
def _get_defaults(proc_name): import gimpshelf (blurb, help, author, copyright, date, label, imagetypes, plugin_type, params, results, function, menu, domain, on_query, on_run) = _registered_plugins_[proc_name]
key = "python-fu-save--" + proc_name
if gimpshelf.shelf.has_key(key): return gimpshelf.shelf[key] else: # return the default values return [x[3] for x in params]
def _set_defaults(proc_name, defaults): import gimpshelf
key = "python-fu-save--" + proc_name gimpshelf.shelf[key] = defaults
def _run(proc_name, params): run_mode = params[0] func = _registered_plugins_[proc_name][10]
if run_mode == RUN_NONINTERACTIVE: return apply(func, params[1:])
script_params = _registered_plugins_[proc_name][8]
min_args = 0 if len(params) > 1: for i in range(1, len(params)): param_type = _obj_mapping[script_params[i - 1][0]] if not isinstance(params[i], param_type): break
min_args = i
if len(script_params) > min_args: start_params = params[:min_args + 1]
if run_mode == RUN_WITH_LAST_VALS: default_params = _get_defaults(proc_name) params = start_params + default_params[min_args:] else: params = start_params else: run_mode = RUN_NONINTERACTIVE
if run_mode == RUN_INTERACTIVE: try: res = _interact(proc_name, params[1:]) except CancelError: return else: res = apply(func, params[1:])
gimp.displays_flush()
return res
def main(): '''This should be called after registering the plug-in.''' gimp.main(None, None, _query, _run)
def fail(msg): '''Display and error message and quit''' gimp.message(msg) raise error, msg
def N_(message): return message # GIMPFU END ###############################################
#----------------------------------------------------------- # This is a hack for gimpfu._interact function. # This is to accomodate custom widget placement and functinality # # [... Hoppefully some more advanced programmer will teach me how # to override imported function rather than pasting the hole module here. # ...]
def _interact(proc_name, start_params): (blurb, help, author, copyright, date, label, imagetypes, plugin_type, params, results, function, menu, domain, on_query, on_run) = _registered_plugins_[proc_name]
def run_script(run_params): params = start_params + tuple(run_params) _set_defaults(proc_name, params) return apply(function, params)
params = params[len(start_params):]
# short circuit for no parameters ... if len(params) == 0: return run_script([])
import pygtk pygtk.require('2.0')
import gimpui import gtk # import pango
defaults = _get_defaults(proc_name) defaults = defaults[len(start_params):]
class EntryValueError(Exception): pass
def warning_dialog(parent, primary, secondary=None): dlg = gtk.MessageDialog(parent, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, primary) if secondary: dlg.format_secondary_text(secondary) dlg.run() dlg.destroy()
def error_dialog(parent, proc_name): import sys, traceback
exc_str = exc_only_str = _('Missing exception information')
try: etype, value, tb = sys.exc_info() exc_str = ''.join(traceback.format_exception(etype, value, tb)) exc_only_str = ''.join(traceback.format_exception_only(etype, value)) finally: etype = value = tb = None
title = _("An error occured running %s") % proc_name dlg = gtk.MessageDialog(parent, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, title) dlg.format_secondary_text(exc_only_str)
alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0) alignment.set_padding(0, 0, 12, 12) dlg.vbox.pack_start(alignment) alignment.show()
expander = gtk.Expander(_("_More Information")); expander.set_use_underline(True) expander.set_spacing(6) alignment.add(expander) expander.show()
scrolled = gtk.ScrolledWindow() scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolled.set_size_request(-1, 200) expander.add(scrolled) scrolled.show()
label = gtk.Label(exc_str) label.set_alignment(0.0, 0.0) label.set_padding(6, 6) label.set_selectable(True) scrolled.add_with_viewport(label) label.show()
def response(widget, id): widget.destroy()
dlg.connect("response", response) dlg.set_resizable(True) dlg.show()
# define a mapping of param types to edit objects ... class StringEntry(gtk.Entry): def __init__(self, default=''): gtk.Entry.__init__(self) self.set_text(str(default))
def get_value(self): return self.get_text()
class TextEntry(gtk.ScrolledWindow): def __init__ (self, default=''): gtk.ScrolledWindow.__init__(self) self.set_shadow_type(gtk.SHADOW_IN)
self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.set_size_request(100, -1)
self.view = gtk.TextView() self.add(self.view) self.view.show()
self.buffer = self.view.get_buffer()
self.set_value(str(default))
def set_value(self, text): self.buffer.set_text(text)
def get_value(self): return self.buffer.get_text(self.buffer.get_start_iter(), self.buffer.get_end_iter())
class IntEntry(StringEntry): def get_value(self): try: return int(self.get_text()) except ValueError, e: raise EntryValueError, e.args
class FloatEntry(StringEntry): def get_value(self): try: return float(self.get_text()) except ValueError, e: raise EntryValueError, e.args
# class ArrayEntry(StringEntry): # def get_value(self): # return eval(self.get_text(), {}, {})
def precision(step): # calculate a reasonable precision from a given step size if math.fabs(step) >= 1.0 or step == 0.0: digits = 0 else: digits = abs(math.floor(math.log10(math.fabs(step)))); if digits > 20: digits = 20 return int(digits)
class SliderEntry(gtk.HScale): # bounds is (upper, lower, step) def __init__(self, default=0, bounds=(0, 100, 5)): step = bounds[2] self.adj = gtk.Adjustment(default, bounds[0], bounds[1], step, 10 * step, 0) gtk.HScale.__init__(self, self.adj) self.set_digits(precision(step))
def get_value(self): return self.adj.value
class SpinnerEntry(gtk.SpinButton): # bounds is (upper, lower, step) def __init__(self, default=0, bounds=(0, 100, 5)): step = bounds[2] self.adj = gtk.Adjustment(default, bounds[0], bounds[1], step, 10 * step, 0) gtk.SpinButton.__init__(self, self.adj, step, precision(step))
class ToggleEntry(gtk.ToggleButton): def __init__(self, default=0): gtk.ToggleButton.__init__(self)
self.label = gtk.Label(_("No")) self.add(self.label) self.label.show()
self.connect("toggled", self.changed)
self.set_active(default)
def changed(self, tog): if tog.get_active(): self.label.set_text(_("Yes")) else: self.label.set_text(_("No"))
def get_value(self): return self.get_active()
class RadioEntry(gtk.VBox): def __init__(self, default=0, items=((_("Yes"), 1), (_("No"), 0))): gtk.VBox.__init__(self, homogeneous=False, spacing=2)
button = None
for (label, value) in items: button = gtk.RadioButton(button, label) self.pack_start(button) button.show()
button.connect("toggled", self.changed, value)
if value == default: button.set_active(True) self.active_value = value
def changed(self, radio, value): if radio.get_active(): self.active_value = value
def get_value(self): return self.active_value
class ComboEntry(gtk.ComboBox): def __init__(self, default=0, items=()): store = gtk.ListStore(str) for item in items: store.append([item])
gtk.ComboBox.__init__(self, model=store)
cell = gtk.CellRendererText() self.pack_start(cell) self.set_attributes(cell, text=0)
self.set_active(default)
def get_value(self): return self.get_active()
def FileSelector(default=''): if default and default.endswith('/'): selector = DirnameSelector if default == '/': default = '' else: selector = FilenameSelector return selector(default)
class FilenameSelector(gtk.FileChooserButton): def __init__(self, default='', save_mode=False): gtk.FileChooserButton.__init__(self, _("Python-Fu File Selection")) self.set_action(gtk.FILE_CHOOSER_ACTION_OPEN) if default: self.set_filename(default)
def get_value(self): return self.get_filename()
class DirnameSelector(gtk.FileChooserButton): def __init__(self, default=''): gtk.FileChooserButton.__init__(self, _("Python-Fu Folder Selection")) self.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) if default: self.set_filename(default)
def get_value(self): return self.get_filename()
_edit_mapping = { PF_INT8 : IntEntry, PF_INT16 : IntEntry, PF_INT32 : IntEntry, PF_FLOAT : FloatEntry, PF_STRING : StringEntry, #PF_INT8ARRAY : ArrayEntry, #PF_INT16ARRAY : ArrayEntry, #PF_INT32ARRAY : ArrayEntry, #PF_FLOATARRAY : ArrayEntry, #PF_STRINGARRAY : ArrayEntry, PF_COLOR : gimpui.ColorSelector, PF_REGION : IntEntry, # should handle differently ... PF_IMAGE : gimpui.ImageSelector, PF_LAYER : gimpui.LayerSelector, PF_CHANNEL : gimpui.ChannelSelector, PF_DRAWABLE : gimpui.DrawableSelector, PF_VECTORS : gimpui.VectorsSelector,
PF_TOGGLE : ToggleEntry, PF_SLIDER : SliderEntry, PF_SPINNER : SpinnerEntry, PF_RADIO : RadioEntry, PF_OPTION : ComboEntry,
PF_FONT : gimpui.FontSelector, PF_FILE : FileSelector, PF_FILENAME : FilenameSelector, PF_DIRNAME : DirnameSelector, PF_BRUSH : gimpui.BrushSelector, PF_PATTERN : gimpui.PatternSelector, PF_GRADIENT : gimpui.GradientSelector, PF_PALETTE : gimpui.PaletteSelector, PF_TEXT : TextEntry }
if on_run: on_run()
tooltips = gtk.Tooltips()
dialog = gimpui.Dialog(proc_name, 'python-fu', None, 0, None, proc_name, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
dialog.set_alternative_button_order((gtk.RESPONSE_OK, gtk.RESPONSE_CANCEL))
dialog.set_transient()
vbox = gtk.VBox(False, 12) vbox.set_border_width(12) dialog.vbox.pack_start(vbox) vbox.show()
if blurb: if domain: try: (domain, locale_dir) = domain trans = gettext.translation(domain, locale_dir, fallback=True) except ValueError: trans = gettext.translation(domain, fallback=True) blurb = trans.ugettext(blurb) box = gimpui.HintBox(blurb) vbox.pack_start(box, expand=False) #box.show()
table = gtk.Table(len(params), 8, False) table.set_row_spacings(6) table.set_col_spacings(6) vbox.pack_start(table, expand=False) table.show()
def response(dlg, id): if id == gtk.RESPONSE_OK: dlg.set_response_sensitive(gtk.RESPONSE_OK, False) dlg.set_response_sensitive(gtk.RESPONSE_CANCEL, False)
params = []
try: for wid in edit_wids: params.append(wid.get_value()) except EntryValueError: warning_dialog(dialog, _("Invalid input for '%s'") % wid.desc) else: try: dialog.res = run_script(params) except Exception: dlg.set_response_sensitive(gtk.RESPONSE_CANCEL, True) error_dialog(dialog, proc_name) raise
gtk.main_quit()
dialog.connect("response", response)
edit_wids = []
# ADD WIDGETS MANUALLY
# Image Width --------------------- pf_type = params[0][0] name = params[0][1] desc = params[0][2] def_val = defaults[0] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 1, 2, 1, 2, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val, params[0][4]) label.set_mnemonic_widget(wid) table.attach(wid, 2,3, 1,2, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid) # Image Height --------------------- pf_type = params[1][0] name = params[1][1] desc = params[1][2] def_val = defaults[1] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 3, 4, 1, 2, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val, params[1][4]) label.set_mnemonic_widget(wid) table.attach(wid, 4,5, 1,2, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Font Range --------------------- pf_type = params[2][0] name = params[2][1] desc = params[2][2] def_val = defaults[2] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 1, 2, 3, 4, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val, params[2][4]) label.set_mnemonic_widget(wid) table.attach(wid, 2,5, 3,4, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid) # Lower Limit --------------------- pf_type = params[3][0] name = params[3][1] desc = params[3][2] def_val = defaults[3] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 1, 2, 4, 5, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val,params[3][4]) label.set_mnemonic_widget(wid) table.attach(wid, 2,3, 4,5, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid) # Upper Limit --------------------- pf_type = params[4][0] name = params[4][1] desc = params[4][2] def_val = defaults[4] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 3, 4, 4, 5, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val,params[4][4]) label.set_mnemonic_widget(wid) table.attach(wid, 4,5, 4,5, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Iterations --------------------- pf_type = params[5][0] name = params[5][1] desc = params[5][2] def_val = defaults[5] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 6, 7, 3, 4, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val, params[5][4]) label.set_mnemonic_widget(wid) table.attach(wid, 7,9, 3,4, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Custom ------------------------- pf_type = params[6][0] name = params[6][1] desc = params[6][2] def_val = defaults[6] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 6, 7, 4, 5, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val, params[6][4]) label.set_mnemonic_widget(wid) table.attach(wid, 7,9, 4,5, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# BG color --------------------- pf_type = params[7][0] name = params[7][1] desc = params[7][2] def_val = defaults[7] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 6, 7, 1, 2, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val) label.set_mnemonic_widget(wid) table.attach(wid, 7,9, 1,2, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Base Text color --------------------- pf_type = params[8][0] name = params[8][1] desc = params[8][2] def_val = defaults[8] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 1, 2, 6, 7, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val) label.set_mnemonic_widget(wid) table.attach(wid, 2,4, 6,7, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Text Color Variation --------------------- pf_type = params[9][0] name = params[9][1] desc = params[9][2] def_val = defaults[9] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 1, 4, 7, 8, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val,params[9][4]) label.set_mnemonic_widget(wid) table.attach(wid, 1,4, 8,9, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Base Text Size --------------------- pf_type = params[10][0] name = params[10][1] desc = params[10][2] def_val = defaults[10] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 1, 2, 11, 12, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val,params[10][4]) label.set_mnemonic_widget(wid) table.attach(wid, 2,3, 11,12, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Text Size Variation --------------------- pf_type = params[11][0] name = params[11][1] desc = params[11][2] def_val = defaults[11] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 1, 4, 12, 13, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val,params[11][4]) label.set_mnemonic_widget(wid) table.attach(wid, 1,4, 13,14, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Text Rotation Note ------------------------- label = gtk.Label("(Deafult Rotation is 0)") label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 6, 9, 11, 12, xoptions=gtk.FILL) label.show() # Text Rotation Variation --------------------- pf_type = params[12][0] name = params[12][1] desc = params[12][2] def_val = defaults[12] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 6, 9, 12, 13, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val,params[12][4]) label.set_mnemonic_widget(wid) table.attach(wid, 6,9, 13,14, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Base Text Opacity --------------------- pf_type = params[13][0] name = params[13][1] desc = params[13][2] def_val = defaults[13] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 6, 7, 6, 7, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val,params[13][4]) label.set_mnemonic_widget(wid) table.attach(wid, 7,9, 6,7, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Text Opacity Variation --------------------- pf_type = params[14][0] name = params[14][1] desc = params[14][2] def_val = defaults[14] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 6, 9, 7, 8, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val,params[14][4]) label.set_mnemonic_widget(wid) table.attach(wid, 6,9, 8,9, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Text Options --------------------- pf_type = params[15][0] name = params[15][1] desc = params[15][2] def_val = defaults[15] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 1, 2, 15, 16, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val,params[15][4]) label.set_mnemonic_widget(wid) table.attach(wid, 2,4, 15,16, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Text Input --------------------- pf_type = params[16][0] name = params[16][1] desc = params[16][2] def_val = defaults[16] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 5, 6, 15, 16, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val) label.set_mnemonic_widget(wid) table.attach(wid, 6,9, 15,16, yoptions=gtk.FILL) tooltips.set_tip(wid.view, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Random Seed --------------------- pf_type = params[17][0] name = params[17][1] desc = params[17][2] def_val = defaults[17] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 1, 2, 17, 18, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val, params[17][4]) label.set_mnemonic_widget(wid) table.attach(wid, 2,3, 17,18, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Flatten flag --------------------- pf_type = params[18][0] name = params[18][1] desc = params[18][2] def_val = defaults[18] label = gtk.Label(desc) label.set_use_underline(True) label.set_alignment(0.0, 0.5) table.attach(label, 4, 5, 17, 18, xoptions=gtk.FILL) label.show() wid = _edit_mapping[pf_type](def_val) label.set_mnemonic_widget(wid) table.attach(wid, 5,9, 17,18, yoptions=0) tooltips.set_tip(wid, desc, None) wid.show() wid.desc = desc edit_wids.append(wid)
# Horizontal Separator 1 --------------------- separator = gtk.HSeparator() table.attach(separator, 1, 9, 2, 3, xoptions=gtk.FILL) separator.show() # Horizontal Separator 2 --------------------- separator = gtk.HSeparator() table.attach(separator, 1, 9, 5, 6, xoptions=gtk.FILL) separator.show()
# Horizontal Separator 3 --------------------- separator = gtk.HSeparator() table.attach(separator, 1, 9, 10, 11, xoptions=gtk.FILL) separator.show()
# Horizontal Separator 4 --------------------- separator = gtk.HSeparator() table.attach(separator, 1, 9, 14, 15, xoptions=gtk.FILL) separator.show()
# Horizontal Separator 5 --------------------- separator = gtk.HSeparator() table.attach(separator, 1, 9, 16, 17, xoptions=gtk.FILL) separator.show()
# Vertical Separator 1 --------------------- separator = gtk.VSeparator() table.attach(separator, 5, 6, 3, 5, xoptions=gtk.FILL) separator.show()
# Vertical Separator 2 --------------------- separator = gtk.VSeparator() table.attach(separator, 5, 6, 6, 10, xoptions=gtk.FILL) separator.show()
# Vertical Separator 3 --------------------- separator = gtk.VSeparator() table.attach(separator, 5, 6, 11, 14, xoptions=gtk.FILL) separator.show()
# Widgets Interaction ---------------------------
#get installed fonts number num_fonts, font_list = pdb.gimp_fonts_get_list("")
def callback_limitsToggle(widget, data=None): val = edit_wids[2].get_active() if val==0: edit_wids[3].set_sensitive(0) edit_wids[4].set_sensitive(0) else: edit_wids[3].set_sensitive(1) edit_wids[4].set_sensitive(1)
def callback_customToggle(widget, data=None): val = edit_wids[5].get_active() if val==0: edit_wids[6].set_sensitive(0) else: edit_wids[6].set_sensitive(1)
def callback_setMin(widget, data=None): limit = edit_wids[4].get_value() edit_wids[3].set_range(1,limit) if edit_wids[3].get_value()>= limit: edit_wids[3].set_value(limit)
def callback_textToggle(widget, data=None): val = edit_wids[15].get_active() if val==0: edit_wids[16].set_sensitive(0) else: edit_wids[16].set_sensitive(1)
handler_1 = edit_wids[4].connect('output',callback_setMin,None) handler_2 = edit_wids[5].connect('changed',callback_customToggle,None) handler_3 = edit_wids[2].connect('changed',callback_limitsToggle,None) handler_4 = edit_wids[15].connect('changed',callback_textToggle,None) # Dialog DEFAULTS: #set range for font range maximum limit edit_wids[4].set_range(1,num_fonts+1)
#Disable font range limit and 'custom' spinners: if edit_wids[2].get_active() == 0: edit_wids[3].set_sensitive(0) edit_wids[4].set_sensitive(0)
if edit_wids[5].get_active() == 0: edit_wids[6].set_sensitive(0)
if edit_wids[15].get_active()==0: edit_wids[16].set_sensitive(0)
# TABLE POPULATION LOOP [from original code] ## for i in range(len(params)): ## pf_type = params[i][0] ## name = params[i][1] ## desc = params[i][2] ## def_val = defaults[i] ## ## label = gtk.Label(desc) ## label.set_use_underline(True) ## label.set_alignment(0.0, 0.5) ## table.attach(label, 1, 2, i, i+1, xoptions=gtk.FILL) ## label.show() ## ## if pf_type in (PF_SPINNER, PF_SLIDER, PF_RADIO, PF_OPTION): ## wid = _edit_mapping[pf_type](def_val, params[i][4]) ## else: ## wid = _edit_mapping[pf_type](def_val) ## ## label.set_mnemonic_widget(wid) ## ## table.attach(wid, 2,3, i,i+1, yoptions=0) ## ## if pf_type != PF_TEXT: ## tooltips.set_tip(wid, desc, None) ## else: ## #Attach tip to TextView, not to ScrolledWindow ## tooltips.set_tip(wid.view, desc, None) ## wid.show() ## ## wid.desc = desc ## edit_wids.append(wid) ##
# END OF TABLE POPULATION LOOP
progress_vbox = gtk.VBox(False, 6) vbox.pack_end(progress_vbox, expand=False) progress_vbox.show()
progress = gimpui.ProgressBar() progress_vbox.pack_start(progress) progress.show()
# progress_label = gtk.Label() # progress_label.set_alignment(0.0, 0.5) # progress_label.set_ellipsize(pango.ELLIPSIZE_MIDDLE)
# attrs = pango.AttrList() # attrs.insert(pango.AttrStyle(pango.STYLE_ITALIC, 0, -1)) # progress_label.set_attributes(attrs)
# progress_vbox.pack_start(progress_label) # progress_label.show()
tooltips.enable() dialog.show()
gtk.main()
if hasattr(dialog, 'res'): res = dialog.res dialog.destroy() return res else: dialog.destroy() raise CancelError
# HERE STARTS THE PLUGIN ------------------------------------------
##Word Art v1.0 - 2011.01 ##Gimp Python plugin
## Below code is ##Copyright (C) 2011 Andrei Roslovtsev ~ www.byes-and-pixels.com ## ##This program is free software; you can redistribute it and/or ##modify it under the terms of the GNU General Public License ##as published by the Free Software Foundation version 2 ##of the License. ## ##This program is distributed in the hope that it will be useful, ##but WITHOUT ANY WARRANTY; without even the implied warranty of ##MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ##GNU General Public License for more details. ## ##You should have received a copy of the GNU General Public License ##along with this program; if not, write to the Free Software ##Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
# This plugin creates random text art based on specified parameters: # Iterates through installed fonts on a given machine, # randomizes position, color, opacity rotation of text layers, # Allows to use font names as strings or a user input. # # # Note: # Developed and tested with Python 2.6 only. # # Version:1.0 # 2011.01 # Andrei Roslovtsev # www.bytes-and-pixels.com # [email protected]
#----------------------------------------------------------- import sys, re, random as r
def make_poster(img_w,img_h,fonts,l_limit, u_limit,iterations,custom,bg_col,base_tc,tc_var,base_ts, ts_var,tr_var,base_to,to_var,txt_mode,in_text,seed,flatten_flag):
#set variables num_fonts, font_list = pdb.gimp_fonts_get_list("") r.seed(seed) txt_size = base_ts text_col = base_tc # randomization helpers ts_min,ts_max,tc_min1,tc_max1,tc_min2,tc_max2,tc_min3,tc_max3 = 0,0,0,0,0,0,0,0
strings = [] #populate strings if txt_mode == 1: strings = in_text.split('\n') else: for font in range(num_fonts): strings.append(font_list[font]) #font range and iterations params f_start,f_end,i,i_end = 0,0,0,0 j_end,cur_font=0,0
if txt_mode == 1: #Check strings for blanks and clean them up for item in strings: if item=='': strings.remove(item) else: regex = re.search('\w',item) if regex == None: strings.remove(item)
try: #check if strings list is empty and go to except if len(strings) == 0: raise Exception('You didn\'t provide any text') # Create new image image = pdb.gimp_image_new(img_w, img_h, 0) pdb.gimp_image_set_filename(image, "Word_art")
layer1 = pdb.gimp_layer_new(image, img_w, img_h, 1, 'BG', 100, 0) pdb.gimp_image_add_layer(image, layer1, 0) display = pdb.gimp_display_new(image) pdb.gimp_context_set_background(bg_col) gimp.pdb.gimp_edit_fill(layer1, 1)
# reset colors to B&W pdb.gimp_context_set_default_colors()
# Select the range and number of iterations if fonts == 0: f_start = 0 f_end = num_fonts if fonts == 1: f_start = int(l_limit-1) #adjust to zero based value f_end = int(u_limit-1) #adjust to zero based value
cur_font = f_start if iterations == 0: i_end = num_fonts if fonts == 1: i_end = f_end - f_start + 1 if iterations == 1: i_end = custom
#setup j - strings iterator------------ if txt_mode == 0 and fonts == 1: j = int(l_limit-1) #adjust to zero based value j_end = int(u_limit-1) #adjust to zero based value else: j = 0 j_end = len(strings)
#setup cur_font - font iterator if fonts == 1: cur_font = f_start
#remenber initial j value j_init = j
# --------------------- Start the main loop -------------------------------- while i < i_end:
#setup strings iterator to loop if txt_mode == 1: if j==j_end: j=j_init else: if j>j_end: j=j_init
#setup font iterator to loop if cur_font>f_end: cur_font=f_start
# Text Layers -------------------------------------------- layer_n = pdb.gimp_text_layer_new(image, strings[j], font_list[cur_font], txt_size, 0) pdb.gimp_image_add_layer(image, layer_n, 0) pdb.gimp_text_layer_set_color(layer_n, text_col) #randomize stuff: #calulate variation limits # text size ts_min=base_ts - ts_var if ts_min<8: ts_min=8 ts_max = base_ts + ts_var txt_size = r.randint(ts_min,ts_max) #text color tc_min1 = clamp(base_tc[0] - tc_var,0,255) tc_min2 = clamp(base_tc[1] - tc_var,0,255) tc_min3 = clamp(base_tc[2] - tc_var,0,255) tc_max1 = clamp(base_tc[0] + tc_var,0,255) tc_max2 = clamp(base_tc[1] + tc_var,0,255) tc_max3 = clamp(base_tc[2] + tc_var,0,255)
#rotation var rot = 0 if tr_var > 0: rot = r.randint(tr_var*-1,tr_var)
#opacity var op = base_to if to_var > 0: op = clamp(r.randint(base_to-to_var,base_to+to_var),0,100) text_col = (r.randint(tc_min1,tc_max1),r.randint(tc_min2,tc_max2),r.randint(tc_min3,tc_max3))
txt_x = r.randint(-10,img_w) txt_y = r.randint(-10,img_h) layer_n.set_offsets(txt_x, txt_y-2)
if rot <> 0: layer_n = pdb.gimp_drawable_transform_rotate_default(layer_n, math.radians(rot), 1, 0, 0, 1, 0)
if op < 100: pdb.gimp_layer_set_opacity(layer_n, op)
i=i+1 j=j+1 cur_font = cur_font + 1
# Flatten Image routine --------------------------------------------- if flatten_flag == 1: pdb.gimp_image_flatten(image)
except Exception as inst: pdb.gimp_message(inst)
def clamp(x,minimum, maximum): return max(minimum, min(x, maximum)) #--------------------------------------------------------------------- register( "Word_Art", N_("Create a poster art from text strings"), "Create a random poster art from text strings - b&p_word_art_01_v1.0.py", "Andrei Roslovtsev", "www.bytes-and-pixels.com", "2011", N_("_Word Art"), #"RGB*, GRAY*", "", [ (PF_SPINNER, "img_w", "Image Width:", 640, (1, 20000, 1)), (PF_SPINNER, "img_h", "Image Height:", 480, (1, 20000, 1)), (PF_OPTION,"fonts", "Font Range:", 0, ["All fonts","Limited fonts"]), (PF_SPINNER, "l_limit", "Lower Limit:", 0,(1,2000,1)), (PF_SPINNER, "u_limit", "Upper Limit:", 0,(1,2000,1)), (PF_OPTION,"iterations", "Iterations:", 0, ["Font number","Custom"]), (PF_SPINNER, "custom", "Custom:", 0,(0,2000,1)), (PF_COLOR, "bg_col", "Background Color:", (250, 250, 250) ), (PF_COLOR, "base_tc", "Base Text Color:", (140, 155, 175) ), (PF_SLIDER, "tc_var", "Text color variation:", 50, (0, 255, 1)), (PF_SPINNER, "base_ts", "Base Text Size (px):", 24, (1, 2000, 1)), (PF_SLIDER, "ts_var", "Text size variation (px):", 100, (0, 1000, 1)), (PF_SLIDER, "tr_var", "Text rotation variation (degrees):", 10, (0, 180, 1)), (PF_SPINNER, "base_to", "Base Text Opacity (%):", 80, (1, 100, 1)), (PF_SLIDER, "to_var", "Text opacity variation (%):", 20, (0, 100, 1)), (PF_OPTION,"txt_mode", "Text Options:", 1, ["Font names","User input"]), (PF_TEXT, "in_text", "Text:", "Python\nGimp\nPyGTK\nCool Plugins"), (PF_SPINNER, "seed", "Random Seed:", 1000, (1, 2000, 1)), (PF_TOGGLE, "flatten_flag", "Flatten Image", 0) ], [], make_poster, #menu="<Image>/File/Create/Buttons", menu="<Image>/Filters/Word Art", domain=("gimp20-python", gimp.locale_directory) )
main()
_________________
|
|