Я хочу контролировать 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
Я потратил весь день, пытаясь решить эту проблему, и сейчас нахожусь моему разуму конец. Вот что я пробовал на данный момент:
- Увеличение размера изображения: я увеличил масштаб изображений и применил различные методы повторной выборки, такие как изображение. LANCZOS, чтобы улучшить четкость, но это не имело большого значения.
- Настройка разрешения вручную: я настроил параметры разрешения при сохранении изображений использую Pillow, но по умолчанию оно по-прежнему равно 72 точек на дюйм, что приводит к появлению пиксельных изображений низкого качества на дисплее Retina.
- Применение круговых масок: я создал круговые маски со сглаживанием для сглаживания краев, но они по-прежнему выглядят грубыми и пикселизированными.
- CustomTkinter: я тестировал CustomTkinter, который предлагает гибкость, и использую объект круга работал лучше, но при использовании Pillow для изображений мне не удалось преодолеть ограничение 72 DPI.
- API Mac (Quartz с pyobjc): я даже изучал API-интерфейсы macOS, такие как Quartz, через пакет pyobjc, надеясь, что это поможет мне напрямую управлять рендерингом с высоким разрешением, но изображения все равно выглядели неправильно.
Подробнее здесь: https://stackoverflow.com/questions/790 ... le-how-can