diff --git a/configuration.py b/configuration.py index dec107d..5e3dd72 100644 --- a/configuration.py +++ b/configuration.py @@ -398,7 +398,14 @@ class Configuration: @property def resolution_threshold_for_jpg(self) -> int: """Gets the pixel dimension threshold for using JPG for 8-bit images.""" - return self._core_settings.get('RESOLUTION_THRESHOLD_FOR_JPG', 4096) + value = self._core_settings.get('RESOLUTION_THRESHOLD_FOR_JPG', 4096) + log.info(f"CONFIGURATION_DEBUG: resolution_threshold_for_jpg property returning: {value} (type: {type(value)})") + # Ensure it's an int, as downstream might expect it. + # The .get() default is an int, but if the JSON had null or a string, it might be different. + if not isinstance(value, int): + log.warning(f"CONFIGURATION_DEBUG: RESOLUTION_THRESHOLD_FOR_JPG was not an int, got {type(value)}. Defaulting to 4096.") + return 4096 + return value @property def respect_variant_map_types(self) -> list: diff --git a/processing/pipeline/orchestrator.py b/processing/pipeline/orchestrator.py index 5cdd88b..993dcc9 100644 --- a/processing/pipeline/orchestrator.py +++ b/processing/pipeline/orchestrator.py @@ -286,6 +286,8 @@ class PipelineOrchestrator: 'supplier': context.effective_supplier or 'UnknownSupplier', } + # Log the value being read for the threshold before creating the input object + log.info(f"ORCHESTRATOR_DEBUG: Reading RESOLUTION_THRESHOLD_FOR_JPG from config for SaveVariantsInput: {getattr(context.config_obj, 'RESOLUTION_THRESHOLD_FOR_JPG', None)}") save_input = SaveVariantsInput( image_data=current_image_data, # Use potentially scaled data internal_map_type=internal_map_type, @@ -300,7 +302,7 @@ class PipelineOrchestrator: png_compression_level=context.config_obj.png_compression_level, jpg_quality=context.config_obj.jpg_quality, output_filename_pattern=context.config_obj.output_filename_pattern, - resolution_threshold_for_jpg=getattr(context.config_obj, "RESOLUTION_THRESHOLD_FOR_JPG", None) # Added + resolution_threshold_for_jpg=getattr(context.config_obj, "resolution_threshold_for_jpg", None) # Corrected case ) saved_data = self._save_stage.execute(save_input) # Log saved_data for merge tasks diff --git a/processing/pipeline/stages/prepare_processing_items.py b/processing/pipeline/stages/prepare_processing_items.py index cee6c2e..16f068e 100644 --- a/processing/pipeline/stages/prepare_processing_items.py +++ b/processing/pipeline/stages/prepare_processing_items.py @@ -56,10 +56,15 @@ class PrepareProcessingItemsStage(ProcessingStage): # --- Add merged tasks --- - merged_tasks_attr_name = 'merged_image_tasks' # Check attribute name if different - if hasattr(context, merged_tasks_attr_name) and getattr(context, merged_tasks_attr_name): - merged_tasks_list = getattr(context, merged_tasks_attr_name) - if isinstance(merged_tasks_list, list): + # --- Add merged tasks from global configuration --- + # merged_image_tasks are expected to be loaded into context.config_obj + # by the Configuration class from app_settings.json. + + merged_tasks_list = getattr(context.config_obj, 'merged_image_tasks', None) + + if merged_tasks_list and isinstance(merged_tasks_list, list): + log.debug(f"Asset '{asset_name_for_log}': Found {len(merged_tasks_list)} merge tasks in global config.") + for task_idx, task_data in enumerate(merged_tasks_list): for task_idx, task_data in enumerate(merged_tasks_list): if isinstance(task_data, dict): task_key = f"merged_task_{task_idx}" @@ -71,10 +76,14 @@ class PrepareProcessingItemsStage(ProcessingStage): log.info(f"Asset '{asset_name_for_log}': Identified and adding Merge Task: Key='{merge_def.task_key}', OutputType='{task_data.get('output_map_type', 'N/A')}'") items_to_process.append(merge_def) else: - log.warning(f"Asset '{asset_name_for_log}': Item at index {task_idx} in '{merged_tasks_attr_name}' is not a dictionary. Skipping. Item: {task_data}") - log.debug(f"Asset '{asset_name_for_log}': Added {len(merged_tasks_list)} potential MergeTaskDefinition items.") - else: - log.warning(f"Asset '{asset_name_for_log}': Attribute '{merged_tasks_attr_name}' is not a list. Skipping merge tasks.") + log.warning(f"Asset '{asset_name_for_log}': Item at index {task_idx} in config_obj.merged_image_tasks is not a dictionary. Skipping. Item: {task_data}") + # The log for "Added X potential MergeTaskDefinition items" will be covered by the final log. + elif merged_tasks_list is None: + log.debug(f"Asset '{asset_name_for_log}': 'merged_image_tasks' not found in config_obj. No global merge tasks to add.") + elif not isinstance(merged_tasks_list, list): + log.warning(f"Asset '{asset_name_for_log}': 'merged_image_tasks' in config_obj is not a list. Skipping global merge tasks. Type: {type(merged_tasks_list)}") + else: # Empty list + log.debug(f"Asset '{asset_name_for_log}': 'merged_image_tasks' in config_obj is empty. No global merge tasks to add.") if not items_to_process: diff --git a/processing/pipeline/stages/supplier_determination.py b/processing/pipeline/stages/supplier_determination.py index 27a1a5e..15f5e5d 100644 --- a/processing/pipeline/stages/supplier_determination.py +++ b/processing/pipeline/stages/supplier_determination.py @@ -55,6 +55,13 @@ class SupplierDeterminationStage(ProcessingStage): # Optionally clear the error flag if previously set and now resolved. if 'supplier_error' in context.status_flags: del context.status_flags['supplier_error'] + + # merged_image_tasks are loaded from app_settings.json into Configuration object, + # not from supplier-specific presets. + # Ensure the attribute exists on context for PrepareProcessingItemsStage, + # which will get it from context.config_obj. + if not hasattr(context, 'merged_image_tasks'): + context.merged_image_tasks = [] return context \ No newline at end of file diff --git a/processing/utils/image_saving_utils.py b/processing/utils/image_saving_utils.py index 01ec7a1..9147fc5 100644 --- a/processing/utils/image_saving_utils.py +++ b/processing/utils/image_saving_utils.py @@ -80,6 +80,7 @@ def save_image_variants( logger.debug(f"SaveImageVariants: Resolutions: {image_resolutions}, File Type Defs: {file_type_defs.keys()}, Output Formats: 8bit={output_format_8bit}, 16bit_pri={output_format_16bit_primary}, 16bit_fall={output_format_16bit_fallback}") logger.debug(f"SaveImageVariants: PNG Comp: {png_compression_level}, JPG Qual: {jpg_quality}") logger.debug(f"SaveImageVariants: Output Tokens: {output_filename_pattern_tokens}, Output Pattern: {output_filename_pattern}") + logger.debug(f"SaveImageVariants: Received resolution_threshold_for_jpg: {resolution_threshold_for_jpg}") # Log received threshold # 2. Determine Target Bit Depth target_bit_depth = 8 # Default @@ -173,9 +174,29 @@ def save_image_variants( # Determine final extension for this variant, considering JPG threshold final_variant_ext = current_output_ext - if target_bit_depth == 8 and resolution_threshold_for_jpg is not None and \ - max(target_w_res, target_h_res) > resolution_threshold_for_jpg and \ - current_output_ext == 'png': # Only convert if current 8-bit is PNG + + # --- Start JPG Threshold Logging --- + logger.debug(f"SaveImageVariants: JPG Threshold Check for {base_map_type} {res_key}:") + logger.debug(f" - target_bit_depth: {target_bit_depth}") + logger.debug(f" - resolution_threshold_for_jpg: {resolution_threshold_for_jpg}") + logger.debug(f" - target_w_res: {target_w_res}, target_h_res: {target_h_res}") + logger.debug(f" - max(target_w_res, target_h_res): {max(target_w_res, target_h_res)}") + logger.debug(f" - current_output_ext: {current_output_ext}") + + cond_bit_depth = target_bit_depth == 8 + cond_threshold_not_none = resolution_threshold_for_jpg is not None + cond_res_exceeded = False + if cond_threshold_not_none: # Avoid comparison if threshold is None + cond_res_exceeded = max(target_w_res, target_h_res) > resolution_threshold_for_jpg + cond_is_png = current_output_ext == 'png' + + logger.debug(f" - Condition (target_bit_depth == 8): {cond_bit_depth}") + logger.debug(f" - Condition (resolution_threshold_for_jpg is not None): {cond_threshold_not_none}") + logger.debug(f" - Condition (max(res) > threshold): {cond_res_exceeded}") + logger.debug(f" - Condition (current_output_ext == 'png'): {cond_is_png}") + # --- End JPG Threshold Logging --- + + if cond_bit_depth and cond_threshold_not_none and cond_res_exceeded and cond_is_png: final_variant_ext = 'jpg' logger.info(f"SaveImageVariants: Overriding 8-bit PNG to JPG for {base_map_type} {res_key} due to resolution {max(target_w_res, target_h_res)}px > threshold {resolution_threshold_for_jpg}px.")