Compare 1 and 2 which is better? Which produces better image quality 1: ef adjust_grayscale_values(img: np.ndarray) -> tuple[np.ndarray, int, int]:
"""Adjust the values of a grayscale image."""
try:
# Calculate modal white value in the range [250, 255]
hist_white, bins_white = np.histogram(img[img >= 250], bins=6, range=(250, 256))
modal_white = int(bins_white[np.argmax(hist_white)])

    # Calculate modal black value in the range [0, 55]
    hist_black, bins_black = np.histogram(img[img < 56], bins=56, range=(0, 56))
    modal_black = int(bins_black[np.argmax(hist_black)])

    # Convert image to float for processing
    adjusted = img.astype(np.float64)

    # Create a mask for extreme original values (0 and 255)
    mask = (img == 0) | (img == 255)

    # Exclude extreme values from the white adjustment
    white_adjust_mask = ~mask

    # Scale image if modal white is not at maximum intensity
    if modal_white != 255:
        adjusted[white_adjust_mask] *= 255.0 / modal_white
        adjusted = np.clip(adjusted, 0, 255)

    # After white value adjustment, identify new extreme values
    new_extremes = (adjusted == 0) | (adjusted == 255)

    # Combine masks to exclude all extreme values from black adjustment
    total_extremes = mask | new_extremes
    black_adjust_mask = ~total_extremes

    # Adjust image based on modal black value
    if modal_black:
        adjusted[black_adjust_mask] = (
            adjusted[black_adjust_mask] - modal_black
        ) * (255.0 / (255 - modal_black))
        adjusted = np.clip(adjusted, 0, 255)

        gamma = 1.0 - (modal_black / 255.0)
        adjusted[black_adjust_mask] = (
            np.power(adjusted[black_adjust_mask] / 255.0, gamma) * 255
        )

    # Round to nearest integer and then convert to uint8
    adjusted = np.rint(adjusted).astype(np.uint8)

    return adjusted, modal_black, modal_white

except ValueError as e:
    log_error_message(f"Error adjusting values for image: {e}")
    return img, 0, 255 2: 

def create_adjustment_lut(modal_black: int, modal_white: int, gamma: float) -> np.ndarray:
"""Create a lookup table for grayscale value adjustments."""
lut = np.arange(256, dtype=np.float64)

# White adjustment
if modal_white != 255:
    lut *= 255.0 / modal_white

# Black adjustment
if modal_black > 0:
    lut = (lut - modal_black) * (255.0 / (255 - modal_black))

# Gamma correction
lut = np.power(lut / 255.0, gamma) * 255

return np.clip(np.round(lut), 0, 255).astype(np.uint8)

def adjust_grayscale_values(img: np.ndarray) -> Tuple[np.ndarray, int, int]:
"""Adjust the values of a grayscale image using a LUT."""
try:
# Calculate modal white value in the range [250, 255]
hist_white, bins_white = np.histogram(img[img >= 250], bins=6, range=(250, 256))
modal_white = int(bins_white[np.argmax(hist_white)])

    # Calculate modal black value in the range [0, 55]
    hist_black, bins_black = np.histogram(img[img < 56], bins=56, range=(0, 56))
    modal_black = int(bins_black[np.argmax(hist_black)])

    # Calculate gamma based on modal black value
    gamma = 1.0 - (modal_black / 255.0)

    # Create the adjustment LUT
    lut = create_adjustment_lut(modal_black, modal_white, gamma)

    # Apply the LUT to the image
    adjusted = lut[img]

    # Preserve original extreme values (0 and 255)
    mask = (img == 0) | (img == 255)
    adjusted[mask] = img[mask]

    return adjusted, modal_black, modal_white

except ValueError as e:
    log_error_message(f"Error adjusting values for image: {e}")
    return img, 0, 255