Saltar a contenido

Ajustar imagenes

En el caso de cargar una imagen grande, se visualizará solo parte de ella. En ese caso, ajustaremos el tamaño de las imagen, una vez cargada en la memoria RAM, para que quepa en la ventana:

Visor04.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from PIL import Image, ImageTk


class App:
    def __init__(self, ventana):
        self.ventana = ventana
        self.ventana.title('Visor de imágenes')
        self.ventana.geometry('800x600')

        # Añadir un panel para botones
        self.panelBotones = tk.Frame(self.ventana)
        self.panelBotones.pack()

        # Añadir un botón "Salir"
        self.btnSalir = tk.Button(self.panelBotones, text='Salir', command=self.ventana.destroy)
        self.btnSalir.pack(side='left')

        # Añadir un botón "Abrir"
        self.btnAbrir = tk.Button(self.panelBotones, text='Abrir', command=self.abrir)
        self.btnAbrir.pack(side='left')

        # Añadir un panel para mostrar la imagen
        self.panelImagen = tk.Label(self.ventana)
        self.panelImagen.pack()

    def abrir(self):
        tipos_archivos= [
                        ("Todos", "*.*"),
                        ("JPEG" , ".jpg"),
                        ("PNG"  , ".png"),
                        ("GIF"  , ".gif")
                                      ]
        self.archivo = filedialog.askopenfilename(
                                  defaultextension=".jpg",
                                  filetypes=tipos_archivos
                                  )

        if not self.archivo:
            return

        try:
            self.imagen = Image.open(self.archivo)
        except:
            messagebox.showerror("Error", "Error abriendo archivo")

        self.ajustar()
        self.mostrar()

    def ajustar(self):
        ancho_imagen = self.imagen.width
        alto_imagen = self.imagen.height
        ancho_panel = ventana.winfo_width()
        alto_panel = ventana.winfo_height() - self.panelBotones.winfo_height()
        zoom_ancho = 1
        zoom_alto = 1
        if ancho_imagen > ancho_panel:
            zoom_ancho = ancho_panel/ancho_imagen
        if alto_imagen > alto_panel:
            zoom_alto = alto_panel/alto_imagen
        zoom = min(zoom_ancho,zoom_alto)
        if zoom < 1:
            dimensiones = (
                int(ancho_imagen*zoom),
                int(alto_imagen*zoom)
                )
            self.imagen = self.imagen.resize(dimensiones)

    def mostrar(self):
        self.tk_imagen = ImageTk.PhotoImage(self.imagen)
        self.panelImagen.configure(image=self.tk_imagen)

ventana = tk.Tk()
App(ventana)
ventana.mainloop()

Como paso previo a mostrar la imagen, invocamos la función ajustar(). Las dimensiones de una imagen se obtienen con:

ancho_imagen = self.imagen.width
alto_imagen = self.imagen.height

Las dimensiones de la ventana:

ancho_ventana = ventana.winfo_width()
alto_ventana = ventana.winfo_height()

Las dimensiones del Frame que usamos como panel de botones:

ancho_panel = panelBotones.winfo_width()
alto_panel = panelBotones.winfo_height()

El area restante para mostrar la imagen tiene las dimensiones:

ancho = ancho_ventana
alto = alto_ventana - alto_panel

Para el cálculo del zoom a aplicar, comparamos las dimensiones de la imagen y del espacio disponible. Una vez calculado el nuevo tamaño, ajustamos la imagen con:

imagen.resize(dimensiones)

siendo el argumento una tupla de dos valores, ancho y alto. El método resize() crea un nuevo objeto, por lo que tenemos que sobreescribir la variable:

imagen = imagen.resize(dimensiones)