layer_shadow.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. # Layer 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
  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. source_layer_id = layer.get_id()
  16. source_layer_name = layer.get_name()
  17. chosen_radius = layer.get_registry("shadow-radius")
  18. if chosen_radius == None:
  19. chosen_radius = image.get_registry("shadow-radius")
  20. if chosen_radius == None:
  21. chosen_radius = 10
  22. chosen_offset = layer.get_registry("shadow-offset")
  23. if chosen_offset == None or len(chosen_offset) != 2:
  24. chosen_offset = image.get_registry("shadow-offset")
  25. if chosen_offset == None or len(chosen_offset) != 2:
  26. chosen_offset = (10, 10)
  27. shadow_layer_id = layer.get_registry("shadow-layer-id")
  28. if image.get_layer_index(shadow_layer_id) == None:
  29. shadow_layer_id = None
  30. def create_shadow_layer():
  31. global shadow_layer_id
  32. image.do_begin()
  33. if shadow_layer_id != None:
  34. layer.select_id(shadow_layer_id)
  35. layer.remove()
  36. layer.select_id(source_layer_id)
  37. layer.duplicate()
  38. layer.set_name("Shadow of "+source_layer_name)
  39. shadow_layer_id = layer.get_id()
  40. shadow_index = image.get_layer_index()
  41. image.move_layer_index(shadow_index, shadow_index-1)
  42. colors.lightness(shift=-1)
  43. opacity = layer.get_opacity()
  44. layer.set_opacity(opacity*2/3)
  45. image.do_end()
  46. blur_done = False
  47. offset_done = False
  48. def apply_blur():
  49. global blur_done, offset_done
  50. if offset_done:
  51. image.undo()
  52. offset_done = False
  53. if blur_done:
  54. image.undo()
  55. blur_done = False
  56. image.do_begin()
  57. filters.blur(radius=chosen_radius)
  58. blur_done = image.do_end()
  59. apply_offset()
  60. def apply_offset():
  61. global offset_done
  62. if offset_done:
  63. image.undo()
  64. offset_done = False
  65. image.do_begin()
  66. tools.choose(tools.MOVE_LAYER)
  67. tools.mouse([(0,0), chosen_offset])
  68. offset_done = image.do_end()
  69. ######## interface
  70. def button_ok_click():
  71. global source_layer_id, chosen_radius, chosen_offset
  72. layer.select_id(source_layer_id)
  73. layer.set_registry("shadow-radius", chosen_radius)
  74. layer.set_registry("shadow-offset", chosen_offset)
  75. layer.set_registry("shadow-layer-id", shadow_layer_id)
  76. image.set_registry("shadow-radius", chosen_radius)
  77. image.set_registry("shadow-offset", chosen_offset)
  78. image.do_end()
  79. exit()
  80. def button_cancel_click():
  81. if image.do_end():
  82. image.undo()
  83. layer.select_id(source_layer_id)
  84. exit()
  85. scale_radius_update_job = None
  86. def scale_radius_update_do():
  87. global scale_radius_update_job, chosen_radius, scale_radius
  88. new_radius = scale_radius.get()
  89. if new_radius != chosen_radius:
  90. chosen_radius = new_radius
  91. apply_blur()
  92. scale_radius_update_job = None
  93. def scale_radius_update(event):
  94. global window, scale_radius_update_job
  95. if scale_radius_update_job:
  96. window.after_cancel(scale_radius_update_job)
  97. scale_radius_update_job = window.after(500, scale_radius_update_do)
  98. scale_offset_update_job = None
  99. def scale_offset_update_do():
  100. global chosen_offset
  101. new_offset = (scale_offset_x.get(), scale_offset_y.get())
  102. if new_offset != chosen_offset:
  103. chosen_offset = new_offset
  104. apply_offset()
  105. scale_offset_update_job = None
  106. def scale_offset_update(event):
  107. global window, scale_offset_update_job
  108. if scale_offset_update_job:
  109. window.after_cancel(scale_offset_update_job)
  110. scale_offset_update_job = window.after(100, scale_offset_update_do)
  111. window = Tk()
  112. window.title("Layer shadow")
  113. window.resizable(False, False)
  114. frame = Frame(window)
  115. frame.pack()
  116. label_radius = Label(frame, text="Radius:")
  117. label_radius.grid(column=0, row=0)
  118. scale_radius = Scale(frame, from_=0, to=MAX_RADIUS, orient=HORIZONTAL, command=scale_radius_update)
  119. scale_radius.grid(column=1, row=0, columnspan=2, sticky=W+E, padx=10)
  120. scale_radius.set(chosen_radius)
  121. label_offset = Label(frame, text="Offset:")
  122. label_offset.grid(column=0, row=1)
  123. scale_offset_x = Scale(frame, from_=-MAX_OFFSET, to=MAX_OFFSET, orient=HORIZONTAL, command=scale_offset_update)
  124. scale_offset_x.grid(column=1, row=1, sticky=W+E, padx=10)
  125. scale_offset_x.set(chosen_offset[0])
  126. scale_offset_y = Scale(frame, from_=-MAX_OFFSET, to=MAX_OFFSET, orient=HORIZONTAL, command=scale_offset_update)
  127. scale_offset_y.grid(column=2, row=1, sticky=W+E, padx=10)
  128. scale_offset_y.set(chosen_offset[1])
  129. frame.columnconfigure(0, pad=20)
  130. frame.columnconfigure(1, weight=1)
  131. frame.columnconfigure(2, weight=1)
  132. frame.rowconfigure(0, pad=20)
  133. frame.rowconfigure(1, pad=20)
  134. button_ok = Button(window, text="Ok", command=button_ok_click)
  135. button_ok.pack(side=RIGHT, padx=10, pady=10)
  136. button_cancel = Button(window, text="Cancel", command=button_cancel_click)
  137. button_cancel.pack(side=RIGHT, pady=10)
  138. image.do_begin()
  139. create_shadow_layer()
  140. apply_blur()
  141. window.update()
  142. window_width = window.winfo_width()
  143. screen_width = window.winfo_screenwidth()
  144. window.geometry('+%d+0' % (int((screen_width - window_width) / 2)))
  145. window.mainloop()
  146. button_cancel_click()