Pillow/Python по умолчанию имеет разрешение 72 DPI на дисплее Retina — выглядит ужасно. Как я могу добиться более высоко ⇐ Python

Программы на Python
Anonymous
Pillow/Python по умолчанию имеет разрешение 72 DPI на дисплее Retina — выглядит ужасно. Как я могу добиться более высоко

Сообщение Anonymous »

У меня возникла проблема при отображении изображений с помощью Pillow на дисплее Retina. У меня есть папка с изображениями размером 150x150 пикселей, и когда я пытаюсь отобразить их с помощью круглой маски, они кажутся пикселизированными и низкого качества из-за значения по умолчанию 72 DPI. Если я попытаюсь использовать изображения большего размера, они просто займут слишком много места на моем экране и не будут использовать возможности дисплея Retina.
Я хочу контролировать DPI или масштабировать эти изображения. должным образом соответствовать моему дисплею Retina (у которого более высокое разрешение). Вот фрагмент соответствующего кода и скриншот:
введите здесь описание изображения

Код: Выделить всё

# Constants for general settings
WINDOW_MIN_WIDTH = 700
WINDOW_MIN_HEIGHT = 350
GRID_COLUMNS = 9  # Number of columns for the grid layout
IMAGE_DIAMETER = 132  # Diameter for the circular images
border_width = 4
DEFAULT_THEME = "blue"
APPEARANCE_MODE = "dark"
IMAGE_BRIGHTNESS = 0.5

#.... Omitted a bunch of code which is more about how to find the images using os pointless for this dpi issue

def create_circular_image(self, image_path, diameter, border_width):
"""
Create a circular image with a border and anti-aliasing for smoother edges.
"""
try:
# Load the image and ensure it's square
img = Image.open(image_path)
square_size = min(img.width, img.height)
img = img.crop((0, 0, square_size, square_size))

# Resize with high-quality resampling to reduce pixelation
img = img.resize((diameter, diameter), Image.LANCZOS)

# Apply a circular mask with anti-aliasing
mask = Image.new("L", img.size, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0, diameter, diameter), fill=255)
img.putalpha(mask)

# Determine the group (subdirectory) and border color
group = os.path.basename(os.path.dirname(image_path))
ring_color = GROUP_COLORS.get(group, "white")  # Default to white if not found

# Create a new border with anti-aliasing
new_diameter = diameter + 2 * border_width
bordered_img = Image.new("RGBA", (new_diameter, new_diameter), ring_color)
border_mask = Image.new("L", (new_diameter, new_diameter), 0)
border_draw = ImageDraw.Draw(border_mask)
border_draw.ellipse((0, 0, new_diameter, new_diameter), fill=255, outline=0)

# Calculate the position to center the circular image within the bordered frame
img_pos = ((new_diameter - img.width) // 2, (new_diameter - img.height) // 2)

# Apply the circular mask to ensure smooth edges
bordered_img.paste(img, img_pos, mask)
bordered_img.putalpha(border_mask)

# Convert to CTkImage for high DPI support
ctk_image = CTkImage(light_image=bordered_img, dark_image=bordered_img, size=(new_diameter, new_diameter))

return ctk_image

#... Omitted more until I reference the actual creation for the buttons which calls that function

def create_phenotype_controls(self, image_paths):
"""
Create controls for images and sliders.
"""
phenotype_names = self.extract_phenotypes_from_paths(image_paths)

for idx, (image_path, phenotype_name) in enumerate(itertools.zip_longest(image_paths, phenotype_names)):
frame = ctk.CTkFrame(self.grid_frame)
frame.grid(row=idx // GRID_COLUMNS, column=idx % GRID_COLUMNS, padx=2.5, pady=2.5)

# Create circular image
image = self.create_circular_image(image_path, IMAGE_DIAMETER, border_width)
image_widget = ctk.CTkButton(frame, image=image, text="",command=lambda idx=idx: self.toggle_phenotype(idx),fg_color="gray12")  # Ensure no text
image_widget.pack(padx=0,pady=0, fill="both")  # Fill the available space

self.buttons.append(image_widget)  # Store the button reference

#... Omitted last bit of code here
Кажется, я не могу найти способ правильно настроить DPI в Pillow для работы с моим дисплеем Retina и избежать пикселизации при применении круговых масок. Есть ли у кого-нибудь решение или обходной путь для достижения более высокого разрешения рендеринга изображений на дисплее Retina с помощью Pillow?
Я потратил весь день, пытаясь решить эту проблему, и сейчас нахожусь моему разуму конец. Вот что я пробовал на данный момент:
  • Увеличение размера изображения: я увеличил масштаб изображений и применил различные методы повторной выборки, такие как изображение. LANCZOS, чтобы улучшить четкость, но это не имело большого значения.
  • Настройка разрешения вручную: я настроил параметры разрешения при сохранении изображений использую Pillow, но по умолчанию оно по-прежнему равно 72 точек на дюйм, что приводит к появлению пиксельных изображений низкого качества на дисплее Retina.
  • Применение круговых масок: я создал круговые маски со сглаживанием для сглаживания краев, но они по-прежнему выглядят грубыми и пикселизированными.
  • CustomTkinter: я тестировал CustomTkinter, который предлагает гибкость, и использую объект круга работал лучше, но при использовании Pillow для изображений мне не удалось преодолеть ограничение 72 DPI.
  • API Mac (Quartz с pyobjc): я даже изучал API-интерфейсы macOS, такие как Quartz, через пакет pyobjc, надеясь, что это поможет мне напрямую управлять рендерингом с высоким разрешением, но изображения все равно выглядели неправильно.
Несмотря на все эти попытки, мне не удается отображать изображения с таким же качеством, как на дисплее Retina моего Mac M2. Это расстраивает, потому что создается впечатление, что Pillow просто не может правильно обрабатывать настройки высокого разрешения. Удалось ли кому-нибудь обойти это ограничение или существует лучший подход к отображению изображений с высоким разрешением с помощью Python на дисплее Retina?

Подробнее здесь: https://stackoverflow.com/questions/790 ... le-how-can

Вернуться в «Python»