layerfx_shadow.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. # Layer effect > Drop shadow
  2. from lazpaint import dialog
  3. try:
  4. from tkinter import *
  5. except ImportError:
  6. dialog.show_message("Please install tkinter.")
  7. exit()
  8. from lazpaint import colors, image, layer, filters, tools, selection
  9. if layer.is_empty():
  10. dialog.show_message("Layer is empty")
  11. exit()
  12. ############ image processing
  13. MAX_RADIUS = 100
  14. MAX_OFFSET = 100
  15. MAX_OPACITY = 255
  16. source_layer_id = layer.get_registry("shadow-source-layer-id")
  17. if source_layer_id is not None:
  18. layer.select_id(source_layer_id)
  19. else:
  20. source_layer_id = layer.get_id()
  21. source_layer_name = layer.get_name()
  22. chosen_radius = layer.get_registry("shadow-radius")
  23. if chosen_radius == None:
  24. chosen_radius = image.get_registry("shadow-radius")
  25. if chosen_radius == None:
  26. chosen_radius = 10
  27. chosen_offset = layer.get_registry("shadow-offset")
  28. if chosen_offset == None or len(chosen_offset) != 2:
  29. chosen_offset = image.get_registry("shadow-offset")
  30. if chosen_offset == None or len(chosen_offset) != 2:
  31. chosen_offset = (10, 10)
  32. shadow_layer_id = layer.get_registry("shadow-layer-id")
  33. if image.get_layer_index(shadow_layer_id) == None:
  34. shadow_layer_id = None
  35. if shadow_layer_id is not None:
  36. layer.select_id(shadow_layer_id)
  37. chosen_opacity = layer.get_opacity()
  38. overlay_color = colors.str_to_RGBA(layer.get_registry("overlay-color"))
  39. layer.select_id(source_layer_id)
  40. else:
  41. chosen_opacity = layer.get_opacity()*2/3
  42. overlay_color = None
  43. if overlay_color is None:
  44. overlay_color = colors.BLACK
  45. def create_shadow_layer():
  46. global shadow_layer_id
  47. image.do_begin()
  48. if shadow_layer_id != None:
  49. layer.select_id(shadow_layer_id)
  50. layer.remove()
  51. layer.select_id(source_layer_id)
  52. layer.duplicate()
  53. layer.set_name("Shadow of "+source_layer_name)
  54. layer.set_registry("shadow-source-layer-id", source_layer_id)
  55. shadow_layer_id = layer.get_id()
  56. shadow_index = image.get_layer_index()
  57. image.move_layer_index(shadow_index, shadow_index-1)
  58. filters.filter_function(red=overlay_color.red/255, green=overlay_color.green/255, blue=overlay_color.blue/255, gamma_correction=False)
  59. layer.set_registry("overlay-color", overlay_color)
  60. layer.set_opacity(chosen_opacity)
  61. image.do_end()
  62. blur_done = False
  63. offset_done = False
  64. def apply_blur():
  65. global blur_done, offset_done
  66. if offset_done:
  67. image.undo()
  68. offset_done = False
  69. if blur_done:
  70. image.undo()
  71. blur_done = False
  72. image.do_begin()
  73. filters.blur(radius=chosen_radius)
  74. blur_done = image.do_end()
  75. apply_offset()
  76. def apply_offset():
  77. global offset_done
  78. if offset_done:
  79. image.undo()
  80. offset_done = False
  81. image.do_begin()
  82. tools.choose(tools.MOVE_LAYER)
  83. tools.mouse([(0,0), chosen_offset])
  84. layer.set_opacity(chosen_opacity)
  85. offset_done = image.do_end()
  86. ######## interface
  87. def button_ok_click():
  88. global source_layer_id, chosen_radius, chosen_offset
  89. layer.select_id(source_layer_id)
  90. layer.set_registry("shadow-radius", chosen_radius)
  91. layer.set_registry("shadow-offset", chosen_offset)
  92. layer.set_registry("shadow-layer-id", shadow_layer_id)
  93. image.set_registry("shadow-radius", chosen_radius)
  94. image.set_registry("shadow-offset", chosen_offset)
  95. image.do_end()
  96. exit()
  97. def button_cancel_click():
  98. if image.do_end():
  99. image.undo()
  100. layer.select_id(source_layer_id)
  101. exit()
  102. scale_radius_update_job = None
  103. def scale_radius_update_do():
  104. global scale_radius_update_job, chosen_radius, scale_radius
  105. new_radius = scale_radius.get()
  106. if new_radius != chosen_radius:
  107. chosen_radius = new_radius
  108. apply_blur()
  109. scale_radius_update_job = None
  110. def scale_radius_update(event):
  111. global window, scale_radius_update_job
  112. if scale_radius_update_job:
  113. window.after_cancel(scale_radius_update_job)
  114. scale_radius_update_job = window.after(500, scale_radius_update_do)
  115. scale_offset_update_job = None
  116. def scale_offset_update_do():
  117. global chosen_offset
  118. new_offset = (scale_offset_x.get(), scale_offset_y.get())
  119. if new_offset != chosen_offset:
  120. chosen_offset = new_offset
  121. apply_offset()
  122. scale_offset_update_job = None
  123. def scale_offset_update(event):
  124. global window, scale_offset_update_job
  125. if scale_offset_update_job:
  126. window.after_cancel(scale_offset_update_job)
  127. scale_offset_update_job = window.after(100, scale_offset_update_do)
  128. scale_opacity_update_job = None
  129. def scale_opacity_update_do():
  130. global chosen_opacity
  131. new_opacity = scale_opacity.get()
  132. if new_opacity != chosen_opacity:
  133. chosen_opacity = new_opacity
  134. apply_offset()
  135. scale_opacity_update_job = None
  136. def scale_opacity_update(event):
  137. global window, scale_opacity_update_job
  138. if scale_opacity_update_job:
  139. window.after_cancel(scale_opacity_update_job)
  140. scale_opacity_update_job = window.after(100, scale_opacity_update_do)
  141. window = Tk()
  142. window.title("Layer shadow")
  143. window.resizable(False, False)
  144. frame = Frame(window)
  145. frame.pack()
  146. label_radius = Label(frame, text="Radius:")
  147. label_radius.grid(column=0, row=0)
  148. scale_radius = Scale(frame, from_=0, to=MAX_RADIUS, orient=HORIZONTAL, command=scale_radius_update)
  149. scale_radius.grid(column=1, row=0, sticky=W+E, padx=10)
  150. scale_radius.set(chosen_radius)
  151. label_offset = Label(frame, text="Offset:")
  152. label_offset.grid(column=0, row=1)
  153. scale_offset_x = Scale(frame, from_=-MAX_OFFSET, to=MAX_OFFSET, orient=HORIZONTAL, command=scale_offset_update)
  154. scale_offset_x.grid(column=1, row=1, sticky=W+E, padx=10)
  155. scale_offset_x.set(chosen_offset[0])
  156. scale_offset_y = Scale(frame, from_=-MAX_OFFSET, to=MAX_OFFSET, orient=HORIZONTAL, command=scale_offset_update)
  157. scale_offset_y.grid(column=1, row=2, sticky=W+E, padx=10)
  158. scale_offset_y.set(chosen_offset[1])
  159. label_opacity = Label(frame, text="Opacity:")
  160. label_opacity.grid(column=0, row=3)
  161. scale_opacity = Scale(frame, from_=0, to=MAX_OPACITY, orient=HORIZONTAL, command=scale_opacity_update)
  162. scale_opacity.grid(column=1, row=3, sticky=W+E, padx=10)
  163. scale_opacity.set(chosen_opacity)
  164. frame.columnconfigure(0, pad=20)
  165. frame.columnconfigure(1, minsize=250)
  166. frame.rowconfigure(0, pad=20)
  167. frame.rowconfigure(1, pad=20)
  168. frame.rowconfigure(2, pad=20)
  169. frame.rowconfigure(3, pad=20)
  170. button_ok = Button(window, text="Ok", command=button_ok_click)
  171. button_ok.pack(side=RIGHT, padx=10, pady=10)
  172. button_cancel = Button(window, text="Cancel", command=button_cancel_click)
  173. button_cancel.pack(side=RIGHT, pady=10)
  174. image.do_begin()
  175. selection.deselect()
  176. create_shadow_layer()
  177. apply_blur()
  178. window.update()
  179. window_width = window.winfo_width()
  180. screen_width = window.winfo_screenwidth()
  181. window.geometry('+%d+0' % (int((screen_width - window_width) / 2)))
  182. window.mainloop()
  183. button_cancel_click()