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: # --- 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

def process_grayscale_image(
    img: np.ndarray,
    path: Path,
    image_processor: 'ImageProcessor',
    temp_folder: Path
) -> Tuple[Path, int, int]:
    """Adjust grayscale values and save the processed image."""
    try:
        adjusted, modal_black, modal_white = adjust_values(img)
        relative_parent = path.parent.relative_to(Config.INPUT_FOLDER)
        out_path = temp_folder / relative_parent / f"{path.stem}.png"
        out_path.parent.mkdir(parents=True, exist_ok=True)

        Image.fromarray(adjusted).convert('L').save(out_path, format='PNG', compress_level=5)

        subfolder = relative_parent.as_posix()
        filename = path.name

        if modal_black:
            image_processor.black_results[subfolder].append((filename, modal_black))
        if modal_white != 255:
            image_processor.white_results[subfolder].append((filename, modal_white))

        return out_path, modal_black, modal_white
    except (ValueError, OSError) as e:
        log_error(f"Error processing grayscale image {path}: {e}")
        return path, 0, 255

def process_color_image(
    img: np.ndarray,
    path: Path,
    image_processor: 'ImageProcessor',
    temp_folder: Path,
    diff_threshold: int = Config.COLORDIFF_THRESHOLD,
    fraction_threshold: float = Config.FRACTION_COLORED_PIXELS_THRESHOLD
) -> Tuple[Path, bool]:
    """Process an image to determine if it's color or grayscale and handle accordingly."""
    try:
        if is_color_image(img, diff_threshold, fraction_threshold):
            # Save color image as PNG
            relative_path = path.relative_to(Config.INPUT_FOLDER).with_suffix('.png')
            out_path = temp_folder / relative_path
            out_path.parent.mkdir(parents=True, exist_ok=True)
            Image.fromarray(img).save(out_path, format='PNG', compress_level=5)

            subfolder = path.parent.relative_to(Config.INPUT_FOLDER).as_posix()
            image_processor.color_results[subfolder].append(path.name)

            return out_path, False

        # Handle grayscale image
        gray_image = ImageOps.grayscale(Image.fromarray(img))
        gray_array = np.array(gray_image)
        out_path, modal_black, modal_white = process_grayscale_image(
            gray_array, path, image_processor, temp_folder
        )
        return out_path, modal_black != 0
    except (OSError, ValueError) as e:
        log_error(f"Error processing image {path}: {e}")
        return path, False