123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- # Layer effect > Inner light
- # (fr) Effet de calque > Lumière 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 = "innerlight"
- OPPOSITE_REGISTRY_NAME = "innershadow"
- DEFAULT_ANGLE = 315
- DEFAULT_COLOR = colors.WHITE
- 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()
|