# Layer effect > Inner shadow # (fr) Effet de calque > Ombre intérieure from lazpaint import dialog try: from tkinter import Tk, Frame, Label, Scale, HORIZONTAL, Button, RIGHT, W, E except ImportError: dialog.show_message("Please install tkinter. On Debian distributions, use the command: apt install python3-tk") exit() from lazpaint import colors, image, layer, filters, tools, selection import math translation = dialog.translate_dict(["Layer is empty", "Radius", "Angle", "Opacity", "Ok", "Cancel", "Run this script again to update effect"]) if layer.is_empty(): dialog.show_message(translation["Layer is empty"]) exit() ############ image processing FRIENDLY_NAME = dialog.get_script_name() REGISTRY_NAME = "innershadow" OPPOSITE_REGISTRY_NAME = "innerlight" DEFAULT_ANGLE = 135 DEFAULT_COLOR = colors.BLACK MAX_RADIUS = 200 MAX_OPACITY = 255 MAX_ANGLE = 360 source_layer_id = layer.get_registry(REGISTRY_NAME+"-source-layer-id") if source_layer_id is not None: layer.select_id(source_layer_id) else: source_layer_id = layer.get_id() source_layer_name = layer.get_name() chosen_radius = layer.get_registry(REGISTRY_NAME+"-radius") if chosen_radius == None: chosen_radius = layer.get_registry(OPPOSITE_REGISTRY_NAME+"-radius") if chosen_radius == None: chosen_radius = image.get_registry(REGISTRY_NAME+"-radius") if chosen_radius == None: chosen_radius = image.get_registry(OPPOSITE_REGISTRY_NAME+"-radius") if chosen_radius == None: chosen_radius = 20 chosen_angle = layer.get_registry(REGISTRY_NAME+"-angle") if chosen_angle == None: chosen_angle = layer.get_registry(OPPOSITE_REGISTRY_NAME+"-angle") if chosen_angle is not None: chosen_angle = (chosen_angle+180) % 360 if chosen_angle == None: chosen_angle = image.get_registry(REGISTRY_NAME+"-angle") if chosen_angle == None: chosen_angle = image.get_registry(OPPOSITE_REGISTRY_NAME+"-angle") if chosen_angle is not None: chosen_angle = (chosen_angle+180) % 360 if chosen_angle == None: chosen_angle = DEFAULT_ANGLE shadow_layer_id = layer.get_registry(REGISTRY_NAME+"-layer-id") if image.get_layer_index(shadow_layer_id) == None: shadow_layer_id = None if shadow_layer_id is not None: layer.select_id(shadow_layer_id) chosen_opacity = layer.get_opacity() overlay_color = colors.str_to_RGBA(layer.get_registry("overlay-color")) layer.select_id(source_layer_id) else: chosen_opacity = layer.get_opacity()*2/3 overlay_color = None if overlay_color is None: overlay_color = DEFAULT_COLOR def create_shadow_layer(): global shadow_layer_id image.do_begin() if shadow_layer_id != None: layer.select_id(shadow_layer_id) layer.remove() layer.select_id(source_layer_id) layer.duplicate() layer.rasterize() layer.set_name(FRIENDLY_NAME+" - "+source_layer_name) layer.set_registry(REGISTRY_NAME+"-source-layer-id", source_layer_id) shadow_layer_id = layer.get_id() layer.set_registry("overlay-color", overlay_color) layer.set_opacity(chosen_opacity) image.do_end() blur_done = False opacity_done = False def apply_blur(): global blur_done, opacity_done if opacity_done: image.undo() opacity_done = False if blur_done: image.undo() blur_done = False image.do_begin() if chosen_radius == 0: filters.filter_function(alpha=0, gamma_correction=False) else: layer.duplicate() layer.set_opacity(255) filters.filter_function(red="alpha", green="alpha", blue="alpha", alpha=1, gamma_correction=False) mask_layer_id = layer.get_id() layer.select_id(shadow_layer_id) filters.filter_function(red=overlay_color.red/255, green=overlay_color.green/255, blue=overlay_color.blue/255, gamma_correction=False) tools.choose(tools.MOVE_LAYER) offset = (math.sin(chosen_angle*math.pi/180)*chosen_radius, -math.cos(chosen_angle*math.pi/180)*chosen_radius) tools.mouse([(0,0), (offset[0],offset[1])]) layer.select_id(mask_layer_id) layer.duplicate() mask_layer_id2 = layer.get_id() layer.select_id(mask_layer_id) tools.choose(tools.MOVE_LAYER) tools.mouse([(offset[0]/2,offset[1]/2), (0,0)]) colors.linear_negative() layer.set_blend_op(layer.BLEND_MASK) layer.merge_over() mask_layer_id = mask_layer_id2 filters.blur(radius=chosen_radius) layer.select_id(mask_layer_id) layer.set_blend_op(layer.BLEND_MASK) layer.merge_over() blur_done = image.do_end() apply_opacity() def apply_opacity(): global opacity_done if opacity_done: image.undo() opacity_done = False image.do_begin() layer.set_opacity(chosen_opacity) opacity_done = image.do_end() ######## interface def button_ok_click(): global source_layer_id, chosen_radius, chosen_angle layer.select_id(source_layer_id) layer.set_registry(REGISTRY_NAME+"-radius", chosen_radius) layer.set_registry(REGISTRY_NAME+"-angle", chosen_angle) layer.set_registry(REGISTRY_NAME+"-layer-id", shadow_layer_id) image.set_registry(REGISTRY_NAME+"-radius", chosen_radius) image.set_registry(REGISTRY_NAME+"-angle", chosen_angle) image.do_end() exit() def button_cancel_click(): if image.do_end(): image.undo() layer.select_id(source_layer_id) exit() scale_radius_update_job = None def scale_radius_update_do(): global scale_radius_update_job, chosen_radius, scale_radius new_radius = scale_radius.get() if new_radius != chosen_radius: chosen_radius = new_radius apply_blur() scale_radius_update_job = None def scale_radius_update(event): global window, scale_radius_update_job if scale_radius_update_job: window.after_cancel(scale_radius_update_job) scale_radius_update_job = window.after(800, scale_radius_update_do) scale_angle_update_job = None def scale_angle_update_do(): global scale_angle_update_job, chosen_angle, scale_angle new_angle = scale_angle.get() if new_angle != chosen_angle: chosen_angle = new_angle apply_blur() scale_angle_update_job = None def scale_angle_update(event): global window, scale_angle_update_job if scale_angle_update_job: window.after_cancel(scale_angle_update_job) scale_angle_update_job = window.after(800, scale_angle_update_do) scale_opacity_update_job = None def scale_opacity_update_do(): global chosen_opacity new_opacity = scale_opacity.get() if new_opacity != chosen_opacity: chosen_opacity = new_opacity apply_opacity() scale_opacity_update_job = None def scale_opacity_update(event): global window, scale_opacity_update_job if scale_opacity_update_job: window.after_cancel(scale_opacity_update_job) scale_opacity_update_job = window.after(100, scale_opacity_update_do) window = Tk() window.title(FRIENDLY_NAME) window.resizable(False, False) frame = Frame(window) frame.pack() label_radius = Label(frame, text=translation["Radius"]) label_radius.grid(column=0, row=0) scale_radius = Scale(frame, from_=0, to=MAX_RADIUS, orient=HORIZONTAL, command=scale_radius_update) scale_radius.grid(column=1, row=0, sticky=W+E, padx=10) scale_radius.set(chosen_radius) label_angle = Label(frame, text=translation["Angle"]) label_angle.grid(column=0, row=1) scale_angle = Scale(frame, from_=0, to=MAX_ANGLE, orient=HORIZONTAL, command=scale_angle_update) scale_angle.grid(column=1, row=1, sticky=W+E, padx=10) scale_angle.set(chosen_angle) label_opacity = Label(frame, text=translation["Opacity"]) label_opacity.grid(column=0, row=2) scale_opacity = Scale(frame, from_=0, to=MAX_OPACITY, orient=HORIZONTAL, command=scale_opacity_update) scale_opacity.grid(column=1, row=2, sticky=W+E, padx=10) scale_opacity.set(chosen_opacity) label_info = Label(frame, text=translation["Run this script again to update effect"], background="lemon chiffon", foreground="black", borderwidth=1, relief="solid") label_info.grid(column=0, rows=3, columnspan=2) frame.columnconfigure(0, pad=20) frame.columnconfigure(1, minsize=250) frame.rowconfigure(0, pad=20) frame.rowconfigure(1, pad=20) frame.rowconfigure(2, pad=20) button_ok = Button(window, text=translation["Ok"], command=button_ok_click) button_ok.pack(side=RIGHT, padx=10, pady=10) button_cancel = Button(window, text=translation["Cancel"], command=button_cancel_click) button_cancel.pack(side=RIGHT, pady=10) image.do_begin() selection.deselect() create_shadow_layer() apply_blur() window.update() window_width = window.winfo_width() screen_width = window.winfo_screenwidth() window.geometry('+%d+0' % (int((screen_width - window_width) / 2))) window.lift() window.attributes('-topmost',True) window.after_idle(window.attributes,'-topmost',False) window.mainloop() button_cancel_click()