Layer.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. from gi.repository import Gtk, GLib
  2. import PF2.VectorMask as VectorMask
  3. import cv2
  4. class Layer:
  5. def __init__(self, base, name, on_change):
  6. print("init", name)
  7. self.mask = VectorMask.VectorMask()
  8. self.tools = []
  9. self.tool_map = {}
  10. self.name = name
  11. self.enabled = True
  12. self.selected_tool = 0
  13. self.editable = not base
  14. self.opacity = 1.0
  15. self.blend_mode = "additive"
  16. if(not self.editable):
  17. self.blend_mode = "overlay"
  18. self.selector_row = None
  19. self.tool_box = Gtk.FlowBox()
  20. self.tool_box.set_selection_mode(Gtk.SelectionMode.NONE)
  21. self.tool_box.set_orientation(1)
  22. self.tool_stack = Gtk.Stack()
  23. self.tool_stack.set_transition_type(6)
  24. self.tool_stack.set_homogeneous(False)
  25. self.layer_changed = on_change
  26. def add_tool(self, tool):
  27. print("add tool", tool)
  28. self.tool_box.add(tool.tool_button)
  29. self.tool_stack.add(tool.widget)
  30. self.tool_map[tool.tool_button] = tool
  31. tool.tool_button.connect("clicked", self.on_tool_button_clicked)
  32. tool.connect_on_change(self.on_tool_change)
  33. self.tools += [tool,]
  34. if(len(self.tools) == 1):
  35. tool.tool_button.set_active(True)
  36. def on_tool_change(self, tool, prop):
  37. self.layer_changed(self)
  38. def on_tool_button_clicked(self, sender):
  39. if(sender.get_active()):
  40. self.tool_stack.set_visible_child(self.tool_map[sender].widget)
  41. for key in self.tool_map:
  42. if(key != sender):
  43. key.set_active(False)
  44. elif(self.tool_stack.get_visible_child() == self.tool_map[sender].widget):
  45. sender.set_active(True)
  46. def get_layer_dict(self):
  47. layerDict = {}
  48. # Get tool values
  49. toolDict = {}
  50. for tool in self.tools:
  51. toolDict[tool.id] = tool.get_properties_as_dict()
  52. layerDict["tools"] = toolDict
  53. layerDict["name"] = self.name
  54. layerDict["mask"] = self.mask.get_vector_mask_dict()
  55. layerDict["enabled"] = self.enabled
  56. layerDict["opacity"] = self.opacity
  57. layerDict["blend-mode"] = self.blend_mode
  58. return layerDict
  59. def set_from_layer_dict(self, dict):
  60. print("set_from_layer_dict", dict)
  61. # Load Tool Data
  62. for tool in self.tools:
  63. if(tool.id in dict["tools"]):
  64. GLib.idle_add(tool.load_properties, dict["tools"][tool.id])
  65. # The base layer only has tools.
  66. if(self.editable):
  67. # Load Mask Vectors
  68. self.mask.set_from_vector_mask_dict(dict["mask"])
  69. # Load Layer Name
  70. self.name = dict["name"]
  71. # Load Enabled State
  72. self.enabled = dict["enabled"]
  73. # Load Opacity Fraction
  74. self.opacity = dict["opacity"]
  75. # Load Blend Mode
  76. self.blend_mode = dict["blend-mode"]
  77. def render_layer(self, baseImage, image, callback=None):
  78. # Only process if the layer is enabled
  79. if(self.enabled and self.opacity != 0.0):
  80. layer = None
  81. if(self.blend_mode == "overlay"):
  82. # We are passed a base image (original)
  83. # Make a copy of this to pass through the tools
  84. layer = baseImage.copy()
  85. else: # if(self.blend_mode == "additive"):
  86. # Layer is additive, make copy of current working image
  87. layer = image.copy()
  88. # Process the Layer
  89. ntools = len(self.tools)
  90. count = 1
  91. for tool in self.tools:
  92. if (callback != None):
  93. # For showing progress
  94. callback(tool.name, ntools, count - 1)
  95. # Call the tool's image processing function
  96. layer = tool.on_update(layer)
  97. count += 1
  98. # Base layer needs no mask processing
  99. if(not self.editable):
  100. image = layer
  101. # Here we would blend with the mask
  102. else:
  103. mask_map = self.mask.get_mask_map()
  104. height, width = layer.shape[:2]
  105. mask_map = cv2.resize(mask_map, (width, height), interpolation=cv2.INTER_AREA)
  106. mask_map = mask_map * self.opacity
  107. inverted_map = (mask_map * -1) + 1
  108. for i in range(0,3):
  109. image[0:, 0:, i] = (layer[0:, 0:, i] * mask_map) + (image[0:, 0:, i] * inverted_map)
  110. return image
  111. def show_all(self):
  112. self.tool_box.show_all()
  113. self.tool_stack.show_all()
  114. for tool in self.tools:
  115. tool.widget.show_all()
  116. tool.tool_button.show_all()
  117. def reset_tools(self):
  118. for tool in self.tools:
  119. tool.reset()
  120. def set_size(self, width, height):
  121. self.mask.set_dimentions(width, height)
  122. def set_opacity(self, opacity):
  123. self.opacity = opacity
  124. self.on_tool_change(None, None)
  125. def set_enabled(self, enabled):
  126. self.enabled = enabled
  127. self.on_tool_change(None, None)
  128. def set_blending_mode(self, mode):
  129. self.blend_mode = mode
  130. self.on_tool_change(None, None)