diff --git a/negative_raw.nef.xmp b/negative_raw.nef.xmp new file mode 100644 index 0000000..32353c0 --- /dev/null +++ b/negative_raw.nef.xmp @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + darktable + exported + format + nef + + + + + darktable|exported + darktable|format|nef + + + + + diff --git a/negstation/negstation.py b/negstation/negstation.py index 9e170f7..973307c 100644 --- a/negstation/negstation.py +++ b/negstation/negstation.py @@ -82,6 +82,16 @@ class EditorManager: instance.create() instance.set_config(config) + def _on_drag(self, sender, app_data, user_data): + self.bus.publish_deferred("mouse_dragged", { + "button": ( + "right" + if app_data[0] == 0 + else ("left" if app_data[0] == 1 else ("middle")) + ), + "delta": (app_data[1], app_data[2]) + }) + def setup(self): self._discover_and_register_widgets( f"{os.path.dirname(os.path.realpath(__file__))}/widgets" @@ -110,6 +120,11 @@ class EditorManager: callback=lambda s, a, ud: self._add_widget(ud), user_data=widget_name, ) + + with dpg.handler_registry() as self.handler_registry: + dpg.add_mouse_drag_handler(callback=self._on_drag, threshold=1.0, button=0) + dpg.add_mouse_drag_handler(callback=self._on_drag, threshold=1.0, button=1) + dpg.add_mouse_drag_handler(callback=self._on_drag, threshold=1.0, button=2) def run(self): self.setup() diff --git a/negstation/widgets/orientation_widget.py b/negstation/widgets/orientation_widget.py new file mode 100644 index 0000000..dc10b4e --- /dev/null +++ b/negstation/widgets/orientation_widget.py @@ -0,0 +1,121 @@ +import dearpygui.dearpygui as dpg +import numpy as np + +from .pipeline_stage_widget import PipelineStageWidget + + +class OrientationStage(PipelineStageWidget): + name = "Orient Image" + register = True + has_pipeline_in = True + has_pipeline_out = True + + def __init__(self, manager, logger): + super().__init__(manager, logger, default_stage_out="oriented_image") + + self.rotation = 0 + self.mirror_h = False + self.mirror_v = False + + self.rotation_combo_tag = dpg.generate_uuid() + self.mirror_h_tag = dpg.generate_uuid() + self.mirror_v_tag = dpg.generate_uuid() + + self.last_image = None + + def create_pipeline_stage_content(self): + dpg.add_combo( + label="Rotation", + items=["0°", "90°", "180°", "270°"], + default_value="0°", + callback=self._on_rotation_change, + tag=self.rotation_combo_tag + ) + + dpg.add_checkbox( + label="Mirror Horizontal", + default_value=False, + callback=self._on_mirror_h_change, + tag=self.mirror_h_tag + ) + + dpg.add_checkbox( + label="Mirror Vertical", + default_value=False, + callback=self._on_mirror_v_change, + tag=self.mirror_v_tag + ) + + def _on_rotation_change(self, sender, value, user_data): + degree_map = { + "0°": 0, + "90°": 90, + "180°": 180, + "270°": 270 + } + self.rotation = degree_map.get(value, 0) + self.on_pipeline_data(self.last_img) + + def _on_mirror_h_change(self, sender, value, user_data): + self.mirror_h = value + self.on_pipeline_data(self.last_img) + + def _on_mirror_v_change(self, sender, value, user_data): + self.mirror_v = value + self.on_pipeline_data(self.last_img) + + def on_pipeline_data(self, img): + if img is None: + return + + self.last_img = img + img_out = img.copy() + + # Apply rotation + if self.rotation == 90: + img_out = np.rot90(img_out, k=3) + elif self.rotation == 180: + img_out = np.rot90(img_out, k=2) + elif self.rotation == 270: + img_out = np.rot90(img_out, k=1) + + # Apply mirroring + if self.mirror_h: + img_out = np.fliplr(img_out) + if self.mirror_v: + img_out = np.flipud(img_out) + + self.publish_stage(img_out) + + def get_config(self): + config = super().get_config() + config["orientation"] = { + "rotation": self.rotation, + "mirror_h": str(self.mirror_h), + "mirror_v": str(self.mirror_v), + } + return config + + def set_config(self, config): + super().set_config(config) + orient_cfg = config.get("orientation", {}) + + self.rotation = int(orient_cfg.get("rotation", 0)) + self.mirror_h = orient_cfg.get("mirror_h", "False") == "True" + self.mirror_v = orient_cfg.get("mirror_v", "False") == "True" + + self._update_ui() + + def _update_ui(self): + # Update rotation combo + reverse_map = { + 0: "0°", + 90: "90°", + 180: "180°", + 270: "270°" + } + dpg.set_value(self.rotation_combo_tag, reverse_map.get(self.rotation, "0°")) + + # Update checkboxes + dpg.set_value(self.mirror_h_tag, self.mirror_h) + dpg.set_value(self.mirror_v_tag, self.mirror_v) \ No newline at end of file diff --git a/negstation/widgets/pipeline_stage_widget.py b/negstation/widgets/pipeline_stage_widget.py index 9a5bb12..7fb7683 100644 --- a/negstation/widgets/pipeline_stage_widget.py +++ b/negstation/widgets/pipeline_stage_widget.py @@ -64,7 +64,8 @@ class PipelineStageWidget(BaseWidget): tag=self.stage_out_input, ) dpg.add_separator() - self.create_pipeline_stage_content() + with dpg.group(): + self.create_pipeline_stage_content() def create_pipeline_stage_content(self): """Must be implemented by the widget, creates the content of the window""" @@ -176,5 +177,4 @@ class PipelineStageWidget(BaseWidget): group_x, group_y = dpg.get_item_pos(self.pipeline_config_group_tag) self.window_height = win_h - group_h - group_y - 12 self.window_width = win_w - 7 - self.window_offset_y = group_h + group_y + 3 self.on_resize(win_w, win_h) diff --git a/negstation/widgets/stage_viewer_widget.py b/negstation/widgets/stage_viewer_widget.py index fce6661..5041a38 100644 --- a/negstation/widgets/stage_viewer_widget.py +++ b/negstation/widgets/stage_viewer_widget.py @@ -1,6 +1,5 @@ import dearpygui.dearpygui as dpg import numpy as np -from PIL import Image from .pipeline_stage_widget import PipelineStageWidget @@ -13,25 +12,96 @@ class PipelineStageViewer(PipelineStageWidget): def __init__(self, manager, logger): super().__init__(manager, logger, default_stage_in="pipeline_out") self.texture_tag = dpg.generate_uuid() + self.drawlist = None self.img = None - self.needs_update = False self.registry = manager.texture_registry + self.needs_update = False + self.canvas_handler = None + self.scaled_size = (0, 0) + self.image_position = (0, 0) + + self.manager.bus.subscribe("mouse_dragged", self._on_mouse_drag, False) def create_pipeline_stage_content(self): + # Create an empty dynamic texture dpg.add_dynamic_texture( 1, 1, [0, 0, 0, 0], tag=self.texture_tag, parent=self.registry ) - self.image_item = dpg.add_image(self.texture_tag) + + # Add drawlist + with dpg.drawlist(width=-1, height=-1) as self.drawlist: + pass + + # Register click handler + with dpg.item_handler_registry() as self.canvas_handler: + dpg.add_item_clicked_handler(callback=self.on_canvas_click) + dpg.bind_item_handler_registry(self.drawlist, self.canvas_handler) + + def on_canvas_click(self, sender, app_data, user_data): + mouse_x, mouse_y = dpg.get_mouse_pos(local=False) + canvas_x, canvas_y = dpg.get_item_rect_min(self.drawlist) + local_x = mouse_x - canvas_x + local_y = mouse_y - canvas_y + + img_x, img_y = self.image_position + img_w, img_h = self.scaled_size + + if ( + local_x >= img_x + and local_x < img_x + img_w + and local_y >= img_y + and local_y < img_y + img_h + ): + # calculate the image coordinate + x = int((local_x - img_x) * self.img.shape[1] / img_w) + y = int((local_y - img_y) * self.img.shape[0] / img_h) + self.manager.bus.publish_deferred( + "img_clicked", + { + "stage_id": self.pipeline_stage_in_id, + "pos": (x, y), + "button": ( + "right" + if app_data[0] == 0 + else ("left" if app_data[0] == 1 else ("middle")) + ), + }, + ) + + def _on_mouse_drag(self, data): + mouse_x, mouse_y = dpg.get_mouse_pos(local=False) + canvas_x, canvas_y = dpg.get_item_rect_min(self.drawlist) + local_x = mouse_x - canvas_x + local_y = mouse_y - canvas_y + + img_x, img_y = self.image_position + img_w, img_h = self.scaled_size + + if ( + local_x >= img_x + and local_x < img_x + img_w + and local_y >= img_y + and local_y < img_y + img_h + ): + # calculate the image coordinate + x = int((local_x - img_x) * self.img.shape[1] / img_w) + y = int((local_y - img_y) * self.img.shape[0] / img_h) + self.manager.bus.publish_deferred( + "img_dragged", + { + "stage_id": self.pipeline_stage_in_id, + "pos": (x, y), + "button": data['button'], + "delta": data['delta'] + }, + ) def on_resize(self, width, height): self.needs_update = True def on_pipeline_data(self, img): - # Resize if needed if img is None: return - h, w, _ = img.shape - self.img = img self.needs_update = True @@ -39,15 +109,13 @@ class PipelineStageViewer(PipelineStageWidget): pass def update_texture(self, img: np.ndarray): - """Only call from update function""" - # TODO show a smaller version of the image to speed things up if img is None: - dpg.configure_item(self.image_item, show=False) return h, w, _ = img.shape flat = img.flatten().tolist() + # Replace texture if dpg.does_item_exist(self.texture_tag): dpg.delete_item(self.texture_tag) dpg.add_dynamic_texture( @@ -59,25 +127,32 @@ class PipelineStageViewer(PipelineStageWidget): ) win_w, win_h = self.window_width, self.window_height - avail_w = win_w - avail_h = win_h - - scale = min(avail_w / w, avail_h / h) # , 1.0) + scale = min(win_w / w, win_h / h) disp_w = int(w * scale) disp_h = int(h * scale) - x_off = (avail_w - disp_w) / 2 - y_off = self.window_offset_y + x_off = (win_w - disp_w) / 2 + y_off = (win_h - disp_h) / 2 - dpg.configure_item( - self.image_item, - texture_tag=self.texture_tag, - pos=(x_off, y_off), - width=disp_w, - height=disp_h, - show=True + self.scaled_size = (disp_w, disp_h) + self.image_position = (x_off, y_off) + + # Clear old drawings + dpg.delete_item(self.drawlist, children_only=True) + + # Draw image + dpg.draw_image( + self.texture_tag, + pmin=(x_off, y_off), + pmax=(x_off + disp_w, y_off + disp_h), + uv_min=(0, 0), + uv_max=(1, 1), + parent=self.drawlist, ) + # Resize drawlist + dpg.configure_item(self.drawlist, width=win_w, height=win_h) + def update(self): if self.needs_update: self.needs_update = False diff --git a/negstation_layout.ini b/negstation_layout.ini index 3763de2..3d66ba1 100644 --- a/negstation_layout.ini +++ b/negstation_layout.ini @@ -19,7 +19,7 @@ DockId=0x00000007,0 Pos=0,19 Size=270,691 Collapsed=0 -DockId=0x00000035,1 +DockId=0x00000041,1 [Window][###59] Pos=0,494 @@ -46,9 +46,9 @@ DockId=0x0000000E,0 [Window][###23] Pos=0,19 -Size=270,691 +Size=270,693 Collapsed=0 -DockId=0x00000035,0 +DockId=0x00000041,0 [Window][###29] Pos=0,19 @@ -60,7 +60,7 @@ DockId=0x00000012,0 Pos=198,19 Size=602,425 Collapsed=0 -DockId=0x00000033,0 +DockId=0x00000014,0 [Window][###49] Pos=0,495 @@ -72,7 +72,7 @@ DockId=0x0000000C,0 Pos=246,19 Size=554,379 Collapsed=0 -DockId=0x00000033,0 +DockId=0x00000014,0 [Window][###60] Pos=0,19 @@ -82,15 +82,15 @@ DockId=0x00000012,1 [Window][###107] Pos=939,19 -Size=261,534 +Size=261,781 Collapsed=0 DockId=0x00000011,0 [Window][###35] Pos=272,19 -Size=700,588 +Size=698,591 Collapsed=0 -DockId=0x00000033,0 +DockId=0x00000014,0 [Window][###43] Pos=0,490 @@ -111,16 +111,16 @@ Collapsed=0 DockId=0x00000013,1 [Window][###87] -Pos=0,712 -Size=270,88 +Pos=272,646 +Size=710,154 Collapsed=0 -DockId=0x00000036,1 +DockId=0x00000046,0 [Window][###111] -Pos=974,666 -Size=226,134 +Pos=974,19 +Size=226,641 Collapsed=0 -DockId=0x00000015,0 +DockId=0x0000004B,0 [Window][###96] Pos=984,19 @@ -159,10 +159,10 @@ Collapsed=0 DockId=0x00000029,0 [Window][###121] -Pos=984,630 -Size=216,170 +Pos=984,596 +Size=216,204 Collapsed=0 -DockId=0x0000002A,0 +DockId=0x0000004E,0 [Window][###129] Pos=939,555 @@ -171,14 +171,14 @@ Collapsed=0 DockId=0x00000016,0 [Window][###97] -Pos=984,19 -Size=216,560 +Pos=972,19 +Size=228,560 Collapsed=0 DockId=0x0000002F,0 [Window][###113] -Pos=984,581 -Size=216,219 +Pos=972,581 +Size=228,219 Collapsed=0 DockId=0x00000030,0 @@ -192,7 +192,7 @@ DockId=0x00000036,0 Pos=0,19 Size=270,567 Collapsed=0 -DockId=0x00000035,1 +DockId=0x00000041,1 [Window][###82] Pos=272,601 @@ -207,10 +207,10 @@ Collapsed=0 DockId=0x00000031,0 [Window][###95] -Pos=974,19 -Size=226,645 +Pos=0,700 +Size=270,100 Collapsed=0 -DockId=0x00000014,0 +DockId=0x00000042,0 [Window][###120] Pos=984,582 @@ -232,9 +232,9 @@ DockId=0x0000003E,0 [Window][###102] Pos=984,19 -Size=216,613 +Size=216,467 Collapsed=0 -DockId=0x0000003D,0 +DockId=0x00000051,0 [Window][###124] Pos=984,700 @@ -247,70 +247,199 @@ Pos=987,597 Size=216,100 Collapsed=0 -[Docking][Data] -DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,19 Size=1200,781 Split=X - DockNode ID=0x00000037 Parent=0x7C6B3D9B SizeRef=982,781 Split=X - DockNode ID=0x0000002D Parent=0x00000037 SizeRef=982,781 Split=X - DockNode ID=0x0000002B Parent=0x0000002D SizeRef=937,781 Split=X - DockNode ID=0x00000027 Parent=0x0000002B SizeRef=982,781 Split=X - DockNode ID=0x00000023 Parent=0x00000027 SizeRef=982,781 Split=X - DockNode ID=0x0000001B Parent=0x00000023 SizeRef=972,781 Split=X - DockNode ID=0x00000017 Parent=0x0000001B SizeRef=898,781 Split=X - DockNode ID=0x00000009 Parent=0x00000017 SizeRef=270,581 Split=Y Selected=0x3BEDC6B0 - DockNode ID=0x0000000B Parent=0x00000009 SizeRef=196,474 Split=Y Selected=0x3BEDC6B0 - DockNode ID=0x0000000D Parent=0x0000000B SizeRef=196,99 Split=Y Selected=0x99D84869 - DockNode ID=0x00000012 Parent=0x0000000D SizeRef=196,423 Selected=0x0F59680E - DockNode ID=0x00000013 Parent=0x0000000D SizeRef=196,156 Split=Y Selected=0xB4AD3310 - DockNode ID=0x0000001F Parent=0x00000013 SizeRef=270,469 Split=Y Selected=0xD36850C8 - DockNode ID=0x00000035 Parent=0x0000001F SizeRef=270,691 Selected=0xB4AD3310 - DockNode ID=0x00000036 Parent=0x0000001F SizeRef=270,88 Selected=0x8773D56E - DockNode ID=0x00000020 Parent=0x00000013 SizeRef=270,154 Selected=0x0531B3D5 - DockNode ID=0x0000000E Parent=0x0000000B SizeRef=196,373 Selected=0x3BEDC6B0 - DockNode ID=0x0000000C Parent=0x00000009 SizeRef=196,105 Selected=0x4F81AB74 - DockNode ID=0x0000000A Parent=0x00000017 SizeRef=700,581 Split=X - DockNode ID=0x00000003 Parent=0x0000000A SizeRef=299,581 Split=Y Selected=0x52849BCC - DockNode ID=0x00000005 Parent=0x00000003 SizeRef=299,473 Split=Y Selected=0x52849BCC - DockNode ID=0x00000007 Parent=0x00000005 SizeRef=299,86 Selected=0x52849BCC - DockNode ID=0x00000008 Parent=0x00000005 SizeRef=299,385 Selected=0xBD79B41E - DockNode ID=0x00000006 Parent=0x00000003 SizeRef=299,106 Selected=0x84DD78D1 - DockNode ID=0x00000004 Parent=0x0000000A SizeRef=499,581 Split=Y - DockNode ID=0x00000001 Parent=0x00000004 SizeRef=800,379 Split=Y Selected=0x7FF1E0B5 - DockNode ID=0x0000000F Parent=0x00000001 SizeRef=602,588 Split=Y Selected=0x977476CD - DockNode ID=0x00000033 Parent=0x0000000F SizeRef=710,580 CentralNode=1 Selected=0x977476CD - DockNode ID=0x00000034 Parent=0x0000000F SizeRef=710,199 Selected=0x4F935A1E - DockNode ID=0x00000010 Parent=0x00000001 SizeRef=602,191 Selected=0x083320CE - DockNode ID=0x00000002 Parent=0x00000004 SizeRef=800,200 Selected=0x1834836D - DockNode ID=0x00000018 Parent=0x0000001B SizeRef=300,781 Selected=0x7E9438EA - DockNode ID=0x0000001C Parent=0x00000023 SizeRef=226,781 Split=Y Selected=0x714F2F7B - DockNode ID=0x0000001D Parent=0x0000001C SizeRef=216,344 Split=Y Selected=0x714F2F7B - DockNode ID=0x00000021 Parent=0x0000001D SizeRef=216,579 Split=Y Selected=0x714F2F7B - DockNode ID=0x00000019 Parent=0x00000021 SizeRef=216,391 Selected=0x714F2F7B - DockNode ID=0x0000001A Parent=0x00000021 SizeRef=216,388 Split=Y Selected=0x7E9438EA - DockNode ID=0x00000014 Parent=0x0000001A SizeRef=216,645 Selected=0x36EF55AB - DockNode ID=0x00000015 Parent=0x0000001A SizeRef=216,134 Selected=0x7E9438EA - DockNode ID=0x00000022 Parent=0x0000001D SizeRef=216,200 Selected=0x0D80EC84 - DockNode ID=0x0000001E Parent=0x0000001C SizeRef=216,435 Selected=0x7740BFE4 - DockNode ID=0x00000024 Parent=0x00000027 SizeRef=216,781 Split=Y Selected=0xCF08B82F - DockNode ID=0x00000025 Parent=0x00000024 SizeRef=216,579 Split=Y Selected=0xCF08B82F - DockNode ID=0x00000031 Parent=0x00000025 SizeRef=216,628 Selected=0x052342BF - DockNode ID=0x00000032 Parent=0x00000025 SizeRef=216,151 Split=Y Selected=0xCF08B82F - DockNode ID=0x0000003B Parent=0x00000032 SizeRef=216,634 Split=Y Selected=0xCF08B82F - DockNode ID=0x0000003F Parent=0x0000003B SizeRef=216,679 Selected=0xCF08B82F - DockNode ID=0x00000040 Parent=0x0000003B SizeRef=216,100 Selected=0x30E0C534 - DockNode ID=0x0000003C Parent=0x00000032 SizeRef=216,145 Split=Y Selected=0x82C01924 - DockNode ID=0x0000003D Parent=0x0000003C SizeRef=216,613 Selected=0xF268919F - DockNode ID=0x0000003E Parent=0x0000003C SizeRef=216,166 Selected=0x82C01924 - DockNode ID=0x00000026 Parent=0x00000024 SizeRef=216,200 Selected=0x032CD220 - DockNode ID=0x00000028 Parent=0x0000002B SizeRef=216,781 Split=Y Selected=0xB5C8EB4F - DockNode ID=0x00000029 Parent=0x00000028 SizeRef=216,609 Selected=0xB5C8EB4F - DockNode ID=0x0000002A Parent=0x00000028 SizeRef=216,170 Selected=0xF8004A44 - DockNode ID=0x0000002C Parent=0x0000002D SizeRef=261,781 Split=Y Selected=0xC8700185 - DockNode ID=0x00000011 Parent=0x0000002C SizeRef=142,534 Selected=0x3A881EEF - DockNode ID=0x00000016 Parent=0x0000002C SizeRef=142,245 Selected=0xC8700185 - DockNode ID=0x0000002E Parent=0x00000037 SizeRef=216,781 Split=Y Selected=0x4C2F06CB - DockNode ID=0x0000002F Parent=0x0000002E SizeRef=216,560 Selected=0x4C2F06CB - DockNode ID=0x00000030 Parent=0x0000002E SizeRef=216,219 Selected=0x04546B8A - DockNode ID=0x00000038 Parent=0x7C6B3D9B SizeRef=216,781 Split=Y Selected=0x88A8C2FF - DockNode ID=0x00000039 Parent=0x00000038 SizeRef=216,561 Selected=0x88A8C2FF - DockNode ID=0x0000003A Parent=0x00000038 SizeRef=216,218 Selected=0xC56063F4 +[Window][###46] +Pos=0,700 +Size=270,100 +Collapsed=0 +DockId=0x00000042,1 + +[Window][###53] +Pos=0,19 +Size=270,679 +Collapsed=0 +DockId=0x00000041,1 + +[Window][###83] +Pos=272,612 +Size=698,188 +Collapsed=0 +DockId=0x00000044,0 + +[Window][###89] +Pos=272,605 +Size=710,195 +Collapsed=0 +DockId=0x00000015,0 + +[Window][###119] +Pos=984,653 +Size=216,147 +Collapsed=0 +DockId=0x0000004A,0 + +[Window][###36] +Pos=272,19 +Size=710,625 +Collapsed=0 +DockId=0x00000014,0 + +[Window][###48] +Pos=0,714 +Size=270,86 +Collapsed=0 +DockId=0x00000036,1 + +[Window][###56] +Pos=0,19 +Size=270,693 +Collapsed=0 +DockId=0x00000041,1 + +[Window][###93] +Pos=0,714 +Size=270,86 +Collapsed=0 +DockId=0x00000036,0 + +[Window][###133] +Pos=974,645 +Size=226,155 +Collapsed=0 +DockId=0x00000048,0 + +[Window][###110] +Pos=974,19 +Size=226,624 +Collapsed=0 +DockId=0x00000047,0 + +[Window][###109] +Pos=60,60 +Size=216,263 +Collapsed=0 + +[Window][###131] +Pos=60,60 +Size=141,100 +Collapsed=0 + +[Window][###128] +Pos=60,60 +Size=141,100 +Collapsed=0 + +[Window][###50] +Pos=0,700 +Size=270,100 +Collapsed=0 +DockId=0x00000042,1 + +[Window][###58] +Pos=0,19 +Size=270,679 +Collapsed=0 +DockId=0x00000041,1 + +[Window][###104] +Pos=984,19 +Size=216,575 +Collapsed=0 +DockId=0x0000004D,0 + +[Window][###156] +Pos=984,451 +Size=216,200 +Collapsed=0 +DockId=0x00000050,0 + +[Window][###136] +Pos=984,488 +Size=216,163 +Collapsed=0 +DockId=0x00000052,0 + +[Docking][Data] +DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,19 Size=1200,781 Split=X + DockNode ID=0x00000037 Parent=0x7C6B3D9B SizeRef=982,781 Split=X + DockNode ID=0x0000002D Parent=0x00000037 SizeRef=970,781 Split=X + DockNode ID=0x0000002B Parent=0x0000002D SizeRef=937,781 Split=X + DockNode ID=0x00000027 Parent=0x0000002B SizeRef=982,781 Split=X + DockNode ID=0x00000023 Parent=0x00000027 SizeRef=982,781 Split=X + DockNode ID=0x0000001B Parent=0x00000023 SizeRef=972,781 Split=X + DockNode ID=0x00000017 Parent=0x0000001B SizeRef=898,781 Split=X + DockNode ID=0x00000009 Parent=0x00000017 SizeRef=270,581 Split=Y Selected=0x3BEDC6B0 + DockNode ID=0x0000000B Parent=0x00000009 SizeRef=196,474 Split=Y Selected=0x3BEDC6B0 + DockNode ID=0x0000000D Parent=0x0000000B SizeRef=196,99 Split=Y Selected=0x99D84869 + DockNode ID=0x00000012 Parent=0x0000000D SizeRef=196,423 Selected=0x0F59680E + DockNode ID=0x00000013 Parent=0x0000000D SizeRef=196,156 Split=Y Selected=0xB4AD3310 + DockNode ID=0x0000001F Parent=0x00000013 SizeRef=270,469 Split=Y Selected=0xD36850C8 + DockNode ID=0x00000035 Parent=0x0000001F SizeRef=270,693 Split=Y Selected=0xD36850C8 + DockNode ID=0x00000041 Parent=0x00000035 SizeRef=270,679 Selected=0x068DEF00 + DockNode ID=0x00000042 Parent=0x00000035 SizeRef=270,100 Selected=0x89CD1AA0 + DockNode ID=0x00000036 Parent=0x0000001F SizeRef=270,86 Selected=0xB9AFA00B + DockNode ID=0x00000020 Parent=0x00000013 SizeRef=270,154 Selected=0x0531B3D5 + DockNode ID=0x0000000E Parent=0x0000000B SizeRef=196,373 Selected=0x3BEDC6B0 + DockNode ID=0x0000000C Parent=0x00000009 SizeRef=196,105 Selected=0x4F81AB74 + DockNode ID=0x0000000A Parent=0x00000017 SizeRef=698,581 Split=X + DockNode ID=0x00000003 Parent=0x0000000A SizeRef=299,581 Split=Y Selected=0x52849BCC + DockNode ID=0x00000005 Parent=0x00000003 SizeRef=299,473 Split=Y Selected=0x52849BCC + DockNode ID=0x00000007 Parent=0x00000005 SizeRef=299,86 Selected=0x52849BCC + DockNode ID=0x00000008 Parent=0x00000005 SizeRef=299,385 Selected=0xBD79B41E + DockNode ID=0x00000006 Parent=0x00000003 SizeRef=299,106 Selected=0x84DD78D1 + DockNode ID=0x00000004 Parent=0x0000000A SizeRef=499,581 Split=Y + DockNode ID=0x00000001 Parent=0x00000004 SizeRef=800,379 Split=Y Selected=0x7FF1E0B5 + DockNode ID=0x0000000F Parent=0x00000001 SizeRef=602,588 Split=Y Selected=0x977476CD + DockNode ID=0x00000033 Parent=0x0000000F SizeRef=710,580 Split=Y Selected=0x977476CD + DockNode ID=0x00000043 Parent=0x00000033 SizeRef=710,591 Split=Y Selected=0x4EE4732B + DockNode ID=0x00000045 Parent=0x00000043 SizeRef=710,625 Split=Y Selected=0xD0D40C1D + DockNode ID=0x00000014 Parent=0x00000045 SizeRef=710,584 CentralNode=1 Selected=0xD0D40C1D + DockNode ID=0x00000015 Parent=0x00000045 SizeRef=710,195 Selected=0x38436B0F + DockNode ID=0x00000046 Parent=0x00000043 SizeRef=710,154 Selected=0x8773D56E + DockNode ID=0x00000044 Parent=0x00000033 SizeRef=710,188 Selected=0x72F373AE + DockNode ID=0x00000034 Parent=0x0000000F SizeRef=710,199 Selected=0x4F935A1E + DockNode ID=0x00000010 Parent=0x00000001 SizeRef=602,191 Selected=0x083320CE + DockNode ID=0x00000002 Parent=0x00000004 SizeRef=800,200 Selected=0x1834836D + DockNode ID=0x00000018 Parent=0x0000001B SizeRef=300,781 Selected=0x7E9438EA + DockNode ID=0x0000001C Parent=0x00000023 SizeRef=226,781 Split=Y Selected=0x714F2F7B + DockNode ID=0x0000001D Parent=0x0000001C SizeRef=216,344 Split=Y Selected=0x714F2F7B + DockNode ID=0x00000021 Parent=0x0000001D SizeRef=216,579 Split=Y Selected=0x714F2F7B + DockNode ID=0x00000019 Parent=0x00000021 SizeRef=216,391 Selected=0x714F2F7B + DockNode ID=0x0000001A Parent=0x00000021 SizeRef=216,388 Split=Y Selected=0x7E9438EA + DockNode ID=0x0000004B Parent=0x0000001A SizeRef=226,641 Selected=0x7E9438EA + DockNode ID=0x0000004C Parent=0x0000001A SizeRef=226,138 Split=Y Selected=0x499CCA81 + DockNode ID=0x00000047 Parent=0x0000004C SizeRef=226,624 Selected=0x43F4115A + DockNode ID=0x00000048 Parent=0x0000004C SizeRef=226,155 Selected=0x499CCA81 + DockNode ID=0x00000022 Parent=0x0000001D SizeRef=216,200 Selected=0x0D80EC84 + DockNode ID=0x0000001E Parent=0x0000001C SizeRef=216,435 Selected=0x7740BFE4 + DockNode ID=0x00000024 Parent=0x00000027 SizeRef=216,781 Split=Y Selected=0xCF08B82F + DockNode ID=0x00000025 Parent=0x00000024 SizeRef=216,579 Split=Y Selected=0xCF08B82F + DockNode ID=0x00000031 Parent=0x00000025 SizeRef=216,628 Selected=0x052342BF + DockNode ID=0x00000032 Parent=0x00000025 SizeRef=216,151 Split=Y Selected=0xCF08B82F + DockNode ID=0x0000003B Parent=0x00000032 SizeRef=216,634 Split=Y Selected=0xCF08B82F + DockNode ID=0x0000003F Parent=0x0000003B SizeRef=216,679 Selected=0xCF08B82F + DockNode ID=0x00000040 Parent=0x0000003B SizeRef=216,100 Selected=0x30E0C534 + DockNode ID=0x0000003C Parent=0x00000032 SizeRef=216,145 Split=Y Selected=0x82C01924 + DockNode ID=0x0000003D Parent=0x0000003C SizeRef=216,613 Split=Y Selected=0xF268919F + DockNode ID=0x00000049 Parent=0x0000003D SizeRef=216,632 Split=Y Selected=0xF268919F + DockNode ID=0x0000004F Parent=0x00000049 SizeRef=216,430 Split=Y Selected=0xF268919F + DockNode ID=0x00000051 Parent=0x0000004F SizeRef=216,467 Selected=0xF268919F + DockNode ID=0x00000052 Parent=0x0000004F SizeRef=216,163 Selected=0x817C45F1 + DockNode ID=0x00000050 Parent=0x00000049 SizeRef=216,200 Selected=0x5725A6EC + DockNode ID=0x0000004A Parent=0x0000003D SizeRef=216,147 Selected=0x4EE4732B + DockNode ID=0x0000003E Parent=0x0000003C SizeRef=216,166 Selected=0x82C01924 + DockNode ID=0x00000026 Parent=0x00000024 SizeRef=216,200 Selected=0x032CD220 + DockNode ID=0x00000028 Parent=0x0000002B SizeRef=216,781 Split=Y Selected=0xB5C8EB4F + DockNode ID=0x00000029 Parent=0x00000028 SizeRef=216,609 Selected=0xB5C8EB4F + DockNode ID=0x0000002A Parent=0x00000028 SizeRef=216,170 Split=Y Selected=0xF8004A44 + DockNode ID=0x0000004D Parent=0x0000002A SizeRef=216,575 Selected=0x7D28643F + DockNode ID=0x0000004E Parent=0x0000002A SizeRef=216,204 Selected=0xF8004A44 + DockNode ID=0x0000002C Parent=0x0000002D SizeRef=261,781 Split=Y Selected=0xC8700185 + DockNode ID=0x00000011 Parent=0x0000002C SizeRef=142,534 Selected=0x3A881EEF + DockNode ID=0x00000016 Parent=0x0000002C SizeRef=142,245 Selected=0xC8700185 + DockNode ID=0x0000002E Parent=0x00000037 SizeRef=228,781 Split=Y Selected=0x4C2F06CB + DockNode ID=0x0000002F Parent=0x0000002E SizeRef=216,560 Selected=0x4C2F06CB + DockNode ID=0x00000030 Parent=0x0000002E SizeRef=216,219 Selected=0x04546B8A + DockNode ID=0x00000038 Parent=0x7C6B3D9B SizeRef=216,781 Split=Y Selected=0x88A8C2FF + DockNode ID=0x00000039 Parent=0x00000038 SizeRef=216,561 Selected=0x88A8C2FF + DockNode ID=0x0000003A Parent=0x00000038 SizeRef=216,218 Selected=0xC56063F4 diff --git a/negstation_widgets.json b/negstation_widgets.json index f2f7b11..740e68a 100644 --- a/negstation_widgets.json +++ b/negstation_widgets.json @@ -3,7 +3,8 @@ "0": "opened_image", "1": "inverted_image", "2": "opened_raw", - "3": "monochrome" + "3": "monochrome", + "4": "oriented_image" }, "widgets": [ { @@ -19,7 +20,7 @@ "widget_type": "PipelineStageViewer", "config": { "pipeline_config": { - "stage_in": 3, + "stage_in": 4, "stage_out": null } } @@ -28,7 +29,7 @@ "widget_type": "InvertStage", "config": { "pipeline_config": { - "stage_in": 2, + "stage_in": 3, "stage_out": 1 } } @@ -63,7 +64,7 @@ "widget_type": "MonochromeStage", "config": { "pipeline_config": { - "stage_in": 1, + "stage_in": 2, "stage_out": 3 } } @@ -72,7 +73,7 @@ "widget_type": "HistogramWidget", "config": { "pipeline_config": { - "stage_in": 3, + "stage_in": 4, "stage_out": null } } @@ -81,10 +82,24 @@ "widget_type": "ExportStage", "config": { "pipeline_config": { - "stage_in": 3, + "stage_in": 4, "stage_out": null } } + }, + { + "widget_type": "OrientationStage", + "config": { + "pipeline_config": { + "stage_in": 1, + "stage_out": 4 + }, + "orientation": { + "rotation": 0, + "mirror_h": "False", + "mirror_v": "False" + } + } } ] } \ No newline at end of file