From bbedfe6d351cf36bf917946932de95299689ac4f Mon Sep 17 00:00:00 2001 From: Jojojoppe Date: Sun, 3 Aug 2025 17:47:27 +0200 Subject: [PATCH] RAW config is stored in config json --- negstation/widgets/open_raw_widget.py | 184 ++++++++++++++++++++------ negstation_layout.ini | 39 +++++- negstation_widgets.json | 13 ++ 3 files changed, 189 insertions(+), 47 deletions(-) diff --git a/negstation/widgets/open_raw_widget.py b/negstation/widgets/open_raw_widget.py index 5356b7c..8194263 100644 --- a/negstation/widgets/open_raw_widget.py +++ b/negstation/widgets/open_raw_widget.py @@ -1,6 +1,7 @@ import dearpygui.dearpygui as dpg import rawpy import numpy as np +import ast from PIL import Image from .pipeline_stage_widget import PipelineStageWidget @@ -42,6 +43,20 @@ class OpenRawWidget(PipelineStageWidget): "four_color_rgb": False, } + self.demosaic_combo_tag = dpg.generate_uuid() + self.color_space_combo_tag = dpg.generate_uuid() + self.output_bps_combo_tag = dpg.generate_uuid() + self.use_cam_wb_tag = dpg.generate_uuid() + self.auto_wb_tag = dpg.generate_uuid() + self.wb_r_slider_tag = dpg.generate_uuid() + self.wb_g_slider_tag = dpg.generate_uuid() + self.wb_b_slider_tag = dpg.generate_uuid() + self.bright_slider_tag = dpg.generate_uuid() + self.no_auto_bright_tag = dpg.generate_uuid() + self.gamma_slider_tag = dpg.generate_uuid() + self.half_size_tag = dpg.generate_uuid() + self.four_color_tag = dpg.generate_uuid() + self.manager.bus.subscribe( "process_full_res", self._on_process_full_res, True) @@ -60,90 +75,125 @@ class OpenRawWidget(PipelineStageWidget): dpg.add_file_extension(".*") with dpg.group(tag=self.config_group): + # -- Open / Reprocess buttons -- with dpg.group(horizontal=True): - dpg.add_button(label="Open File...", - callback=self._on_open_file) - dpg.add_button(label="Reprocess", - callback=self._process_and_publish) + dpg.add_button(label="Open File...", callback=self._on_open_file) + dpg.add_button(label="Reprocess", callback=self._process_and_publish) + # -- Demosaic combo -- dpg.add_combo( label="Demosaic", items=[alg.name for alg in rawpy.DemosaicAlgorithm], - default_value=rawpy.DemosaicAlgorithm.AHD.name, - callback=lambda s, a, u: self.rawconfig.__setitem__( - "demosaic_algorithm", rawpy.DemosaicAlgorithm[a]) + default_value=self.rawconfig["demosaic_algorithm"].name, + callback=lambda s,a,u: self.rawconfig.__setitem__( + "demosaic_algorithm", rawpy.DemosaicAlgorithm[a] + ), + tag=self.demosaic_combo_tag ) + + # -- Color space combo -- dpg.add_combo( label="Color Space", items=[cs.name for cs in rawpy.ColorSpace], - default_value=rawpy.ColorSpace.sRGB.name, - callback=lambda s, a, u: self.rawconfig.__setitem__( - "output_color", rawpy.ColorSpace[a]) + default_value=self.rawconfig["output_color"].name, + callback=lambda s,a,u: self.rawconfig.__setitem__( + "output_color", rawpy.ColorSpace[a] + ), + tag=self.color_space_combo_tag ) + + # -- Bits per sample -- dpg.add_combo( label="Output Bits", - items=["8", "16"], - default_value="16", - callback=lambda s, a, u: self.rawconfig.__setitem__( - "output_bps", int(a)) + items=["8","16"], + default_value=str(self.rawconfig["output_bps"]), + callback=lambda s,a,u: self.rawconfig.__setitem__( + "output_bps", int(a) + ), + tag=self.output_bps_combo_tag ) + + # -- Checkboxes & sliders -- dpg.add_checkbox( label="Use Camera WB", - default_value=True, - callback=lambda s, a, u: self.rawconfig.__setitem__( - "use_camera_wb", a) + default_value=self.rawconfig["use_camera_wb"], + callback=lambda s,a,u: self.rawconfig.__setitem__("use_camera_wb", a), + tag=self.use_cam_wb_tag ) dpg.add_checkbox( label="Auto WB", - default_value=False, - callback=lambda s, a, u: self.rawconfig.__setitem__( - "use_auto_wb", a) + default_value=self.rawconfig["use_auto_wb"], + callback=lambda s,a,u: self.rawconfig.__setitem__("use_auto_wb", a), + tag=self.auto_wb_tag ) dpg.add_slider_float( label="Manual WB R Gain", - default_value=1.0, min_value=0.1, max_value=4.0, - callback=lambda s, a, u: self.config.__setitem__( - "user_wb", (a, self.rawconfig["user_wb"][1], self.rawconfig["user_wb"][2], self.rawconfig["user_wb"][3])) + default_value=self.rawconfig["user_wb"][0], + min_value=0.1, max_value=4.0, + callback=lambda s,a,u: self.rawconfig.__setitem__( + "user_wb", (a, self.rawconfig["user_wb"][1], + self.rawconfig["user_wb"][2], self.rawconfig["user_wb"][3]) + ), + tag=self.wb_r_slider_tag ) dpg.add_slider_float( label="Manual WB G Gain", - default_value=1.0, min_value=0.1, max_value=4.0, - callback=lambda s, a, u: self.config.__setitem__( - "user_wb", (self.rawconfig["user_wb"][0], a, a, self.rawconfig["user_wb"][3])) + default_value=self.rawconfig["user_wb"][1], + min_value=0.1, max_value=4.0, + callback=lambda s,a,u: self.rawconfig.__setitem__( + "user_wb", (self.rawconfig["user_wb"][0], a, + self.rawconfig["user_wb"][2], self.rawconfig["user_wb"][3]) + ), + tag=self.wb_g_slider_tag ) dpg.add_slider_float( label="Manual WB B Gain", - default_value=1.0, min_value=0.1, max_value=4.0, - callback=lambda s, a, u: self.config.__setitem__( - "user_wb", (self.rawconfig["user_wb"][0], self.rawconfig["user_wb"][1], self.rawconfig["user_wb"][2], a)) + default_value=self.rawconfig["user_wb"][2], + min_value=0.1, max_value=4.0, + callback=lambda s,a,u: self.rawconfig.__setitem__( + "user_wb", (self.rawconfig["user_wb"][0], + self.rawconfig["user_wb"][1], a, + self.rawconfig["user_wb"][3]) + ), + tag=self.wb_b_slider_tag ) dpg.add_slider_float( label="Bright", - default_value=1.0, min_value=0.1, max_value=4.0, - callback=lambda s, a, u: self.rawconfig.__setitem__("bright", a) + default_value=self.rawconfig["bright"], + min_value=0.1, max_value=4.0, + callback=lambda s,a,u: self.rawconfig.__setitem__("bright", a), + tag=self.bright_slider_tag ) dpg.add_checkbox( label="No Auto Bright", - default_value=False, - callback=lambda s, a, u: self.rawconfig.__setitem__( - "no_auto_bright", a) + default_value=self.rawconfig["no_auto_bright"], + callback=lambda s,a,u: self.rawconfig.__setitem__( + "no_auto_bright", a + ), + tag=self.no_auto_bright_tag ) dpg.add_slider_float( label="Gamma", - default_value=1.0, min_value=0.1, max_value=3.0, - callback=lambda s, a, u: self.rawconfig.__setitem__("gamma", a) + default_value=self.rawconfig["gamma"], + min_value=0.1, max_value=3.0, + callback=lambda s,a,u: self.rawconfig.__setitem__("gamma", a), + tag=self.gamma_slider_tag ) dpg.add_checkbox( label="Half-size", - default_value=False, - callback=lambda s, a, u: self.rawconfig.__setitem__( - "half_size", a) + default_value=self.rawconfig["half_size"], + callback=lambda s,a,u: self.rawconfig.__setitem__( + "half_size", a + ), + tag=self.half_size_tag ) dpg.add_checkbox( label="4-color RGB", - default_value=False, - callback=lambda s, a, u: self.rawconfig.__setitem__( - "four_color_rgb", a) + default_value=self.rawconfig["four_color_rgb"], + callback=lambda s,a,u: self.rawconfig.__setitem__( + "four_color_rgb", a + ), + tag=self.four_color_tag ) with dpg.group(tag=self.busy_group, show=False): @@ -229,3 +279,53 @@ class OpenRawWidget(PipelineStageWidget): return self.manager.pipeline.publish( self.pipeline_stage_out_id, self.img_full, True) + + def get_config(self): + config = super().get_config() + config["raw_config"] = { k:str(v) for k, v in self.rawconfig.items() } + return config + + def set_config(self, config): + super().set_config(config) + raw_cfg = config.get("raw_config", {}) + if raw_cfg: + # parse each back into Python types + for k, v in raw_cfg.items(): + if k == "demosaic_algorithm": + # "DemosaicAlgorithm.AHD" → "AHD" + name = v.split(".", 1)[1] + self.rawconfig[k] = rawpy.DemosaicAlgorithm[name] + elif k == "output_color": + name = v.split(".", 1)[1] + self.rawconfig[k] = rawpy.ColorSpace[name] + elif k == "output_bps": + self.rawconfig[k] = int(v) + elif k in ("use_camera_wb","use_auto_wb", + "no_auto_bright","half_size","four_color_rgb"): + self.rawconfig[k] = (v == "True") + elif k in ("bright","gamma"): + self.rawconfig[k] = float(v) + elif k == "user_wb": + self.rawconfig[k] = tuple(ast.literal_eval(v)) + + # now that rawconfig is back to real types, update the UI + self._update_raw_ui() + + def _update_raw_ui(self): + """Push current self.rawconfig values back into all controls.""" + # combos want the enum.name or string + dpg.set_value(self.demosaic_combo_tag, self.rawconfig["demosaic_algorithm"].name) + dpg.set_value(self.color_space_combo_tag, self.rawconfig["output_color"].name) + dpg.set_value(self.output_bps_combo_tag, str(self.rawconfig["output_bps"])) + + # checkboxes & sliders + dpg.set_value(self.use_cam_wb_tag, self.rawconfig["use_camera_wb"]) + dpg.set_value(self.auto_wb_tag, self.rawconfig["use_auto_wb"]) + dpg.set_value(self.wb_r_slider_tag, self.rawconfig["user_wb"][0]) + dpg.set_value(self.wb_g_slider_tag, self.rawconfig["user_wb"][1]) + dpg.set_value(self.wb_b_slider_tag, self.rawconfig["user_wb"][2]) + dpg.set_value(self.bright_slider_tag, self.rawconfig["bright"]) + dpg.set_value(self.no_auto_bright_tag, self.rawconfig["no_auto_bright"]) + dpg.set_value(self.gamma_slider_tag, self.rawconfig["gamma"]) + dpg.set_value(self.half_size_tag, self.rawconfig["half_size"]) + dpg.set_value(self.four_color_tag, self.rawconfig["four_color_rgb"]) \ No newline at end of file diff --git a/negstation_layout.ini b/negstation_layout.ini index 3eb3bdd..21a609b 100644 --- a/negstation_layout.ini +++ b/negstation_layout.ini @@ -141,10 +141,10 @@ Collapsed=0 DockId=0x00000022,0 [Window][###103] -Pos=984,649 -Size=216,151 +Pos=984,19 +Size=216,679 Collapsed=0 -DockId=0x00000032,0 +DockId=0x0000003F,0 [Window][###139] Pos=984,600 @@ -224,6 +224,29 @@ Size=216,561 Collapsed=0 DockId=0x00000039,0 +[Window][###123] +Pos=984,634 +Size=216,166 +Collapsed=0 +DockId=0x0000003E,0 + +[Window][###102] +Pos=984,19 +Size=216,781 +Collapsed=0 +DockId=0x0000003D,0 + +[Window][###124] +Pos=984,700 +Size=216,100 +Collapsed=0 +DockId=0x00000040,0 + +[Window][###122] +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 @@ -240,7 +263,7 @@ DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,19 Siz 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=0xB7116FC5 + 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 @@ -270,7 +293,13 @@ DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,19 Siz 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 Selected=0xCF08B82F + 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 diff --git a/negstation_widgets.json b/negstation_widgets.json index 192203c..f2f7b11 100644 --- a/negstation_widgets.json +++ b/negstation_widgets.json @@ -39,6 +39,19 @@ "pipeline_config": { "stage_in": null, "stage_out": 2 + }, + "raw_config": { + "demosaic_algorithm": "DemosaicAlgorithm.AHD", + "output_color": "ColorSpace.sRGB", + "output_bps": "16", + "use_camera_wb": "True", + "use_auto_wb": "False", + "user_wb": "(1.0, 1.0, 1.0, 1.0)", + "bright": "1.0", + "no_auto_bright": "False", + "gamma": "1.0", + "half_size": "False", + "four_color_rgb": "False" } } },