SYSTEM: You are a Python programmer tasked with refactoring code. You are proficient in Python 3.12 and use modern features where appropriate. Your code is clear, easy to read, and free of unnecessary verbosity. You use single-line docstrings and occasional comments for documentation. Often, the code you receive is just one part of a larger program. USER: # --- Resize Images ---

def resize_image(input_path: Path, output_path: Path) -> Path:
    """Resize an image using ImageMagick."""
    output_path = output_path.with_suffix('.png')
    
    identify_command = [
        str(Config.IMAGEMAGICK),
        str(input_path),
        '-format', '%wx%h',
        'info:'
    ]
    try:
        result = subprocess.run(
            identify_command, 
            stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE, 
            text=True, 
            check=True
        )
        current_width, current_height = map(int, result.stdout.strip().split('x'))
    except subprocess.CalledProcessError as e:
        log_error(f"ImageMagick identify failed for {input_path}: {e.stderr.strip()}")
        return output_path

    resize_mode = app.RESIZE_MODE.get()
    maintain_aspect = app.maintain_aspect_ratio.get()
    
    if resize_mode == "Fit":
        target_width = int(app.RESIZE_WIDTH.get() or 0)
        target_height = int(app.RESIZE_HEIGHT.get() or 0)
        
        if maintain_aspect:
            if target_width == 0 and target_height > 0:
                target_width = int(target_height * current_width / current_height)
            elif target_height == 0 and target_width > 0:
                target_height = int(target_width * current_height / current_width)
        
        resize_arg = f'{target_width}x{target_height}!'
    else:  # Shortest Side
        target_size = int(app.RESIZE_SIDE.get())
        resize_arg = f'{target_size}x{target_size}^'

    is_upscaling = (
        (resize_mode == "Fit" and (target_width > current_width or target_height > current_height)) or
        (resize_mode == "Shortest Side" and target_size > min(current_width, current_height))
    )

    command = [
        str(Config.IMAGEMAGICK),
        str(input_path),
    ]
    
    if is_upscaling:
        command += [
            '-filter', 'LanczosSharp',
            '-distort', 'Resize', resize_arg,
        ]
    else:
        command += [
            '-colorspace', 'RGB',
            '-filter', 'Lanczos2Sharp',
            '-resize', resize_arg,
            '-colorspace', 'sRGB',
        ]
    
    command += [
        '-define', 'png:compression-level=5',
        str(output_path)
    ]
    
    try:
        result = subprocess.run(
            command,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            check=True
        )
        if result.stderr:
            log_error(f"ImageMagick: {result.stderr.strip()}")
    except subprocess.CalledProcessError as e:
        log_error(f"ImageMagick resize failed for {input_path}: {e.stderr.strip()}")
    
    return output_path

def resize_images(input_folder: Path, output_folder: Path, image_processor: 'ImageProcessor'):
    """Resize images in the input folder and save them to the output folder."""
    try:
        check_imagemagick()
    except FileNotFoundError as e:
        log_error(str(e))
        return

    tasks = [input_path for input_path in input_folder.rglob('*') 
             if input_path.is_file() and input_path.suffix.lower() in Config.IMAGE_EXTENSIONS]

    if not tasks:
        log_error(f"No image files found in '{input_folder}'")
        return

    with create_temp_folder() as temp_folder:
        try:
            run_with_thread_pool(tasks, process_file, time.time(), len(tasks), image_processor, temp_folder, True)
        finally:
            pass

# --- Processing ---

def process_file(
    path: Path,
    start_time,
    total_files,
    image_processor: 'ImageProcessor',
    temp_folder: Path,
    resize=False,
    auto_correct_and_resize=False
) -> None:
    """Process a single image file."""
    if shared_state.stop_event.is_set():
        return

    if not is_valid_image(path):
        log_error(f"Invalid image file: {path}")
        with shared_state.processed_files_lock:
            shared_state.processed_files_count += 1
        update_status(start_time, shared_state.processed_files_count, total_files)
        return

    try:
        img = np.array(open_and_convert_image(path))
    except (OSError, ValueError) as e:
        log_error(f"Error reading image {path}: {e}")
        with shared_state.processed_files_lock:
            shared_state.processed_files_count += 1
        update_status(start_time, shared_state.processed_files_count, total_files)
        return

    relative_path = path.relative_to(Config.INPUT_FOLDER)
    temp_output_path = temp_folder / relative_path.with_suffix('.png')
    temp_output_path.parent.mkdir(parents=True, exist_ok=True)

    is_color = is_color_image(img)

    if auto_correct_and_resize:
        if is_color:
            intermediate_path, _ = process_color_image(img, path, image_processor, temp_folder)
        else:
            intermediate_path, _, _ = process_grayscale_image(img, path, image_processor, temp_folder)
        temp_output_path = resize_image(intermediate_path, temp_output_path)
    elif resize:
        temp_output_path = resize_image(path, temp_output_path)
    else:
        if is_color:
            temp_output_path, _ = process_color_image(img, path, image_processor, temp_folder)
        else:
            temp_output_path, _, _ = process_grayscale_image(img, path, image_processor, temp_folder)

    final_output_path = Config.OUTPUT_FOLDER / relative_path.with_suffix(
        '.jpg' if app.RESIZE_FORMAT.get() == 'jpg' else '.png'
    )
    final_output_path.parent.mkdir(parents=True, exist_ok=True)

    if app.RESIZE_FORMAT.get() == 'jpg':
        convert_png_to_jpg(temp_output_path, final_output_path)
    else:
        shutil.move(str(temp_output_path), str(final_output_path))

    with shared_state.processed_files_lock:
        shared_state.processed_files_count += 1
    update_status(start_time, shared_state.processed_files_count, total_files)

def process_folder(folder: Path, image_processor: 'ImageProcessor', auto_correct_and_resize=False) -> None:
    """Process all images in a folder."""
    image_processor.reset_results()

    if auto_correct_and_resize:
        try:
            check_imagemagick()
        except FileNotFoundError as e:
            log_error(str(e))
            return

    tasks = [path for path in folder.rglob('*') 
             if path.is_file() and path.suffix.lower() in Config.IMAGE_EXTENSIONS]

    if not tasks:
        log_error(f"No image files found in '{folder}'")
        return

    with create_temp_folder() as temp_folder:
        try:
            run_with_thread_pool(tasks, process_file, time.time(), len(tasks), image_processor, temp_folder, False, auto_correct_and_resize)
        finally:
            pass

# --- Logging ---

def log_errors(error_queue):
    """Log errors from the error queue."""
    error_dict = defaultdict(list)
    while not error_queue.empty():
        file_path, error_messages = error_queue.get()
        error_dict[file_path].extend(error_messages)

    if error_dict:
        shared_state.log_message_queue.put("UPDATE_LOG")
        for file_path in sorted(error_dict.keys()):
            shared_state.log_message_queue.put(f"{file_path.resolve()}")
            shared_state.log_message_queue.put("")
            for error_message in sorted(error_dict[file_path]):
                log_error(error_message)
            shared_state.log_message_queue.put("")

def log_and_execute(choice: str, label: str, function: callable, *args):
    """Log the execution of a function and run it in a separate thread."""
    def run_in_thread():
        start_time = time.time()
        separator = '-' * Config.SEPARATOR_LENGTH
        shared_state.log_message_queue.put(f"{separator}\n{label}\n{separator}\n")

        try:
            total_files = function(*args)
        except FileNotFoundError as e:
            log_error(str(e))
            total_files = 0
        except (OSError, ValueError) as e:
            log_error(f"An error occurred during '{label}': {e}")
            total_files = 0

        end_time = time.time()
        execution_time = end_time - start_time
        
        shared_state.log_message_queue.put("")
        image_processor.write_results_to_files(Config.OUTPUT_FOLDER, choice)
        
        app.after(0, app.update_final_status, execution_time)
        app.after(0, app.update_text_area)

    thread = threading.Thread(target=run_in_thread)
    thread.start()

# --- ImageProcessor Class ---

class ImageProcessor:
    """Class to handle image processing results."""
    def __init__(self):
        self.white_results = defaultdict(list)
        self.black_results = defaultdict(list)
        self.color_results = defaultdict(list)

    def write_results_to_files(self, output_folder: Path, choice: str):
        """Write processing results to files."""
        results_map = {
            '2': ("2. Analyze Images", "Modal Value Black", "Modal Value White"),
            '3': ("3. Find Color Images", "Filename"),
            '5': ("5. Automatic Color Correction", "Modal Value Black", "Modal Value White"),
            '6': ("6. Automatic Color Correction + Resize", "Modal Value Black", "Modal Value White")
        }
        headers = results_map.get(choice)
        if headers:
            if choice == '3':
                self._write_results("Color", self.color_results, headers[0], headers[1])
            else:
                self._write_results("Black", self.black_results, headers[0], headers[1])
                self._write_results("White", self.white_results, headers[0], headers[2])
                self._write_results("Color", self.color_results, headers[0], "Filename")

    def _write_results(self, file_path: str, results: Dict[str, List[Tuple[str, int]]], header: str,
                       value_name: str):
        """Write results to a specific file."""
        separator = '-' * Config.SEPARATOR_LENGTH
        content = f"{separator}\n{header}\n{separator}\n"
        if results:
            for subfolder, subfolder_results in sorted(results.items()):
                full_subfolder_path = Config.INPUT_FOLDER / subfolder
                content += f"\n{full_subfolder_path}\n\n"
                if value_name == "Filename":
                    subfolder_results.sort()
                    content += '\n'.join(f" - {filename}" for filename in subfolder_results)
                else:
                    subfolder_results.sort(key=lambda x: x[1], reverse=True)
                    content += '\n'.join(
                        f" - {filename}, {value_name}: {value}" for filename, value in subfolder_results)
                content += "\n"
        shared_state.tab_messages[file_path].append(content)

    def reset_results(self):
        """Reset all results."""
        self.white_results = defaultdict(list)
        self.black_results = defaultdict(list)
        self.color_results = defaultdict(list)