1# Layer effect > Stroke 2# (fr) Effet de calque > Trait 3# (es) Efectos de capa > Trazo 4# (de) Ebeneneffekte > Strich 5from lazpaint import dialog 6 7try: 8 from tkinter import * 9except ImportError: 10 dialog.show_message("Please install tkinter. On Debian distributions, use the command: apt install python3-tk") 11 exit() 12 13from lazpaint import colors, image, layer, filters, tools, selection 14 15english = ["Layer is empty", "Radius", "Color", "Opacity", "Ok", "Cancel"] 16translation = dict(zip(english, dialog.translate_text(english))) 17 18if layer.is_empty(): 19 dialog.show_message(translation["Layer is empty"]) 20 exit() 21 22############ image processing 23 24FRIENDLY_NAME = dialog.get_script_name() 25MAX_RADIUS = 100 26MAX_OPACITY = 255 27 28source_layer_id = layer.get_id() 29source_layer_name = layer.get_name() 30 31chosen_radius = layer.get_registry("stroke-radius") 32if chosen_radius == None: 33 chosen_radius = image.get_registry("stroke-radius") 34if chosen_radius == None: 35 chosen_radius = 10 36 37stroke_layer_id = layer.get_registry("stroke-layer-id") 38if image.get_layer_index(stroke_layer_id) == None: 39 stroke_layer_id = None 40 41if stroke_layer_id is not None: 42 layer.select_id(stroke_layer_id) 43 chosen_opacity = layer.get_opacity() 44 overlay_color = colors.str_to_RGBA(layer.get_registry("overlay-color")) 45 layer.select_id(source_layer_id) 46else: 47 chosen_opacity = layer.get_opacity() 48 overlay_color = None 49 50if overlay_color is None: 51 overlay_color = colors.BLACK 52 53def create_stroke_layer(): 54 global stroke_layer_id 55 image.do_begin() 56 if stroke_layer_id != None: 57 layer.select_id(stroke_layer_id) 58 stroke_index = image.get_layer_index() 59 selection.select_all() 60 selection.delete() 61 layer.select_id(source_layer_id) 62 layer.duplicate() 63 image.move_layer_index(image.get_layer_index(), stroke_index+1) 64 layer.merge_over() 65 else: 66 layer.select_id(source_layer_id) 67 layer.duplicate() 68 layer.set_name(FRIENDLY_NAME + " - " + source_layer_name) 69 layer.set_registry("stroke-source-layer-id", source_layer_id) 70 stroke_layer_id = layer.get_id() 71 stroke_index = image.get_layer_index() 72 image.move_layer_index(stroke_index, stroke_index-1) 73 image.do_end() 74 75stroke_done = False 76opacity_done = False 77stroke_initial_color = None 78 79def apply_stroke(): 80 global stroke_done, opacity_done, stroke_initial_color 81 if opacity_done: 82 image.undo() 83 opacity_done = False 84 if stroke_done: 85 image.undo() 86 stroke_done = False 87 image.do_begin() 88 if chosen_radius > 0.5: 89 layer.duplicate() 90 disk_id = layer.get_id() 91 filters.blur(name=filters.BLUR_DISK, radius=chosen_radius-0.5) 92 filters.filter_function(red=overlay_color.red/255, green=overlay_color.green/255, blue=overlay_color.blue/255, alpha="min(alpha*"+str(chosen_radius*5)+",(1-alpha)*"+str(chosen_radius*5)+")", gamma_correction=False) 93 layer.select_id(stroke_layer_id) 94 else: 95 disk_id = None 96 filters.blur(name=filters.BLUR_CORONA, radius=chosen_radius+0.5) 97 filters.filter_function(red=overlay_color.red/255, green=overlay_color.green/255, blue=overlay_color.blue/255, alpha="min(alpha*"+str(chosen_radius)+",(1-alpha)*"+str(chosen_radius)+")", gamma_correction=False) 98 if disk_id is not None: 99 layer.select_id(disk_id) 100 layer.merge_over() 101 layer.set_registry("overlay-color", overlay_color) 102 stroke_initial_color = overlay_color 103 stroke_done = image.do_end() 104 apply_opacity() 105 106def apply_opacity(): 107 global opacity_done, chosen_opacity, overlay_color 108 if opacity_done: 109 image.undo() 110 opacity_done = False 111 image.do_begin() 112 layer.set_opacity(chosen_opacity) 113 if overlay_color != stroke_initial_color: 114 filters.filter_function(red=overlay_color.red/255, green=overlay_color.green/255, blue=overlay_color.blue/255, gamma_correction=False) 115 layer.set_registry("overlay-color", overlay_color) 116 opacity_done = image.do_end() 117 118######## interface 119 120def button_ok_click(): 121 global source_layer_id, chosen_radius, chosen_offset 122 layer.select_id(source_layer_id) 123 layer.set_registry("stroke-radius", chosen_radius) 124 layer.set_registry("stroke-layer-id", stroke_layer_id) 125 image.set_registry("stroke-radius", chosen_radius) 126 image.do_end() 127 exit() 128 129def button_cancel_click(): 130 if image.do_end(): 131 image.undo() 132 layer.select_id(source_layer_id) 133 exit() 134 135scale_radius_update_job = None 136 137def scale_radius_update_do(): 138 global scale_radius_update_job, chosen_radius, scale_radius 139 new_radius = scale_radius.get() 140 if new_radius != chosen_radius: 141 chosen_radius = new_radius 142 apply_stroke() 143 scale_radius_update_job = None 144 145def scale_radius_update(event): 146 global window, scale_radius_update_job 147 if scale_radius_update_job: 148 window.after_cancel(scale_radius_update_job) 149 scale_radius_update_job = window.after(500, scale_radius_update_do) 150 151scale_opacity_update_job = None 152 153def scale_opacity_update_do(): 154 global chosen_opacity 155 new_opacity = scale_opacity.get() 156 if new_opacity != chosen_opacity: 157 chosen_opacity = new_opacity 158 apply_opacity() 159 scale_opacity_update_job = None 160 161def scale_opacity_update(event): 162 global window, scale_opacity_update_job 163 if scale_opacity_update_job: 164 window.after_cancel(scale_opacity_update_job) 165 scale_opacity_update_job = window.after(100, scale_opacity_update_do) 166 167def button_color_click(): 168 global overlay_color, window 169 new_color = colors.show_dialog(overlay_color) 170 window.attributes('-topmost', True) 171 window.attributes('-topmost', False) 172 if new_color is not None and new_color != overlay_color: 173 overlay_color = new_color 174 apply_opacity() 175 176window = Tk() 177window.title(FRIENDLY_NAME) 178window.resizable(False, False) 179 180frame = Frame(window) 181frame.pack() 182 183label_radius = Label(frame, text=translation["Radius"]) 184label_radius.grid(column=0, row=0) 185scale_radius = Scale(frame, from_=0, to=MAX_RADIUS, orient=HORIZONTAL, command=scale_radius_update) 186scale_radius.grid(column=1, row=0, sticky=W+E, padx=10) 187scale_radius.set(chosen_radius) 188 189label_opacity = Label(frame, text=translation["Opacity"]) 190label_opacity.grid(column=0, row=1) 191scale_opacity = Scale(frame, from_=0, to=MAX_OPACITY, orient=HORIZONTAL, command=scale_opacity_update) 192scale_opacity.grid(column=1, row=1, sticky=W+E, padx=10) 193scale_opacity.set(chosen_opacity) 194 195label_color = Label(frame, text=translation["Color"]) 196label_color.grid(column=0, row=2) 197button_color = Button(frame, text=translation["Color"] + "...", command=button_color_click) 198button_color.grid(column=1, row=2) 199 200frame.columnconfigure(0, pad=20) 201frame.columnconfigure(1, minsize=250) 202frame.rowconfigure(0, pad=20) 203frame.rowconfigure(1, pad=20) 204frame.rowconfigure(2, pad=20) 205 206button_ok = Button(window, text=translation["Ok"], command=button_ok_click) 207button_ok.pack(side=RIGHT, padx=10, pady=10) 208button_cancel = Button(window, text=translation["Cancel"], command=button_cancel_click) 209button_cancel.pack(side=RIGHT, pady=10) 210 211image.do_begin() 212selection.deselect() 213create_stroke_layer() 214apply_stroke() 215 216window.update() 217window_width = window.winfo_width() 218screen_width = window.winfo_screenwidth() 219window.geometry('+%d+0' % (int((screen_width - window_width) / 2))) 220 221window.lift() 222window.attributes('-topmost',True) 223window.after_idle(window.attributes,'-topmost',False) 224 225window.mainloop() 226button_cancel_click() 227