Visualizzazione e manipolazione di immagini con Tkinter in Python: una guida semplice

Python è un linguaggio di programmazione potente utilizzato in molti settori. Tra le sue librerie, Tkinter è la libreria GUI (interfaccia grafica utente) standard di Python, ampiamente utilizzata sia dai principianti che dagli esperti. In questo articolo, spiegheremo come visualizzare immagini e eseguire operazioni di base utilizzando Tkinter. Impareremo attraverso esempi concreti ed esercitazioni pratiche.

Indice

Panoramica di base di Tkinter

Tkinter è un toolkit GUI fornito come parte della libreria standard di Python. Funziona su Windows, macOS e Linux, ed è utile per creare interfacce semplici e intuitive. I vantaggi di Tkinter includono la facilità di installazione, l’ampia gamma di widget disponibili e il supporto della comunità. Utilizzando Tkinter, è possibile aggiungere facilmente elementi visivi ai programmi Python.

Come installare Tkinter

Tkinter è parte della libreria standard di Python e di solito viene installato automaticamente con Python. Tuttavia, su alcuni sistemi potrebbe essere necessario installarlo separatamente.

Installazione su Windows

Su Windows, Tkinter viene installato automaticamente insieme a Python. Non sono richiesti passaggi aggiuntivi.

Installazione su macOS

Su macOS, Tkinter è incluso con l’installazione di Python. Tuttavia, su versioni più vecchie di macOS, potrebbe essere necessario installare separatamente Python e Tkinter. In tal caso, è possibile utilizzare il seguente comando per l’installazione.

brew install python-tk

Installazione su Linux

Su Linux, potrebbe essere necessario installare Python e Tkinter separatamente. È possibile utilizzare il seguente comando per l’installazione.

sudo apt-get install python3-tk

Ora che Tkinter è installato, passiamo alla creazione di programmi utilizzando Tkinter.

Preparazione per la visualizzazione delle immagini

Per visualizzare un’immagine, utilizzeremo la libreria Tkinter e la libreria di elaborazione delle immagini Pillow (PIL). Pillow è un fork della Python Imaging Library (PIL) e risulta utile per aprire e manipolare le immagini. Segui i passaggi seguenti per installare Pillow e prepararti a visualizzare le immagini con Tkinter.

Installazione di Pillow

Prima di tutto, installa Pillow. Utilizza il seguente comando per installare Pillow.

pip install pillow

Configurazione di base

Il codice per importare Tkinter e Pillow e creare una finestra di base è il seguente.

import tkinter as tk  
from PIL import Image, ImageTk  

# Creazione della finestra principale  
root = tk.Tk()  
root.title("Visualizzazione Immagine")  

# Impostazione delle dimensioni della finestra  
root.geometry("800x600")  

# Caricamento dell'immagine  
image = Image.open("path/to/your/image.jpg")  
photo = ImageTk.PhotoImage(image)  

# Creazione di un widget Label per visualizzare l'immagine  
label = tk.Label(root, image=photo)  
label.pack()  

# Visualizzazione della finestra  
root.mainloop()

Questo codice crea una finestra Tkinter di base e visualizza l’immagine specificata. Successivamente, verrà fornita una spiegazione dettagliata di un esempio concreto di codice.

Esempio di codice per visualizzare un’immagine

Qui verrà mostrato un esempio concreto di codice per visualizzare un’immagine utilizzando Tkinter e Pillow.

Esempio di codice completo

import tkinter as tk  
from PIL import Image, ImageTk  

# Creazione della finestra principale  
root = tk.Tk()  
root.title("Visualizzazione Immagine")  

# Impostazione delle dimensioni della finestra  
root.geometry("800x600")  

# Caricamento dell'immagine  
image_path = "path/to/your/image.jpg"  
image = Image.open(image_path)  
photo = ImageTk.PhotoImage(image)  

# Creazione di un widget Label per visualizzare l'immagine  
label = tk.Label(root, image=photo)  
label.image = photo  # Necessario per mantenere il riferimento  
label.pack()  

# Visualizzazione della finestra  
root.mainloop()

Spiegazione del codice

  • import tkinter as tk: Importa il modulo Tkinter.
  • from PIL import Image, ImageTk: Importa i moduli Image e ImageTk dalla libreria Pillow.
  • root = tk.Tk(): Crea la finestra principale.
  • root.title("Visualizzazione Immagine"): Imposta il titolo della finestra.
  • root.geometry("800x600"): Imposta le dimensioni della finestra a 800×600 pixel.
  • image_path = "path/to/your/image.jpg": Specifica il percorso del file dell’immagine da visualizzare.
  • image = Image.open(image_path): Carica il file immagine.
  • photo = ImageTk.PhotoImage(image): Converte l’immagine in un formato visualizzabile con Tkinter.
  • label = tk.Label(root, image=photo): Crea un widget Label per visualizzare l’immagine.
  • label.image = photo: Mantiene il riferimento all’immagine per evitare problemi di visualizzazione.
  • label.pack(): Dispone il widget Label nella finestra.
  • root.mainloop(): Avvia il ciclo principale e visualizza la finestra.

Eseguendo questo codice, l’immagine specificata verrà visualizzata all’interno della finestra Tkinter. Successivamente, spiegheremo come ridimensionare l’immagine.

Come ridimensionare un’immagine

Spiegheremo come ridimensionare un’immagine utilizzando Tkinter e Pillow. Il ridimensionamento è utile per adattare l’immagine alle dimensioni della finestra o alle esigenze dell’utente.

Esempio di codice per ridimensionare un’immagine

Il codice seguente ridimensiona un’immagine a dimensioni specifiche prima di visualizzarla.

import tkinter as tk  
from PIL import Image, ImageTk  

# Creazione della finestra principale  
root = tk.Tk()  
root.title("Ridimensionamento Immagine")  

# Impostazione delle dimensioni della finestra  
root.geometry("800x600")  

# Caricamento dell'immagine  
image_path = "path/to/your/image.jpg"  
image = Image.open(image_path)  

# Ridimensionamento dell'immagine (es.: 400x300 pixel)  
resized_image = image.resize((400, 300), Image.ANTIALIAS)  
photo = ImageTk.PhotoImage(resized_image)  

# Creazione di un widget Label per visualizzare l'immagine ridimensionata  
label = tk.Label(root, image=photo)  
label.image = photo  # Necessario per mantenere il riferimento  
label.pack()  

# Visualizzazione della finestra  
root.mainloop()

Spiegazione del codice

  • image = Image.open(image_path): Carica il file immagine.
  • resized_image = image.resize((400, 300), Image.ANTIALIAS): Ridimensiona l’immagine a 400×300 pixel. Image.ANTIALIAS viene utilizzato per un ridimensionamento di alta qualità.
  • photo = ImageTk.PhotoImage(resized_image): Converte l’immagine ridimensionata in un formato visualizzabile con Tkinter.
  • label = tk.Label(root, image=photo): Crea un widget Label per visualizzare l’immagine.
  • label.image = photo: Mantiene il riferimento all’immagine.
  • label.pack(): Dispone il widget Label nella finestra.
  • root.mainloop(): Avvia il ciclo principale e visualizza la finestra.

Eseguendo questo codice, l’immagine ridimensionata verrà visualizzata all’interno della finestra Tkinter. Successivamente, spiegheremo come ruotare e riflettere un’immagine.

Rotazione e riflessione delle immagini

Oltre a visualizzare le immagini, è possibile ruotarle o rifletterle utilizzando Tkinter e Pillow. Vedremo come farlo attraverso esempi concreti di codice.

Esempio di codice per ruotare un’immagine

Il codice seguente ruota un’immagine di 90 gradi e la visualizza.

import tkinter as tk  
from PIL import Image, ImageTk  

# Creazione della finestra principale  
root = tk.Tk()  
root.title("Rotazione Immagine")  

# Impostazione delle dimensioni della finestra  
root.geometry("800x600")  

# Caricamento dell'immagine  
image_path = "path/to/your/image.jpg"  
image = Image.open(image_path)  

# Rotazione dell'immagine di 90 gradi  
rotated_image = image.rotate(90)  
photo = ImageTk.PhotoImage(rotated_image)  

# Creazione di un widget Label per visualizzare l'immagine ruotata  
label = tk.Label(root, image=photo)  
label.image = photo  # Necessario per mantenere il riferimento  
label.pack()  

# Visualizzazione della finestra  
root.mainloop()

Esempio di codice per riflettere un’immagine

Il codice seguente mostra come riflettere un’immagine orizzontalmente o verticalmente.

import tkinter as tk  
from PIL import Image, ImageTk  

# Creazione della finestra principale  
root = tk.Tk()  
root.title("Riflessione Immagine")  

# Impostazione delle dimensioni della finestra  
root.geometry("800x600")  

# Caricamento dell'immagine  
image_path = "path/to/your/image.jpg"  
image = Image.open(image_path)  

# Riflessione orizzontale dell'immagine  
flipped_image = image.transpose(Image.FLIP_LEFT_RIGHT)  
photo = ImageTk.PhotoImage(flipped_image)  

# Creazione di un widget Label per visualizzare l'immagine riflessa  
label = tk.Label(root, image=photo)  
label.image = photo  # Necessario per mantenere il riferimento  
label.pack()  

# Visualizzazione della finestra  
root.mainloop()

Spiegazione del codice

  • rotated_image = image.rotate(90): Ruota l’immagine di 90 gradi. È possibile impostare un angolo di rotazione arbitrario.
  • flipped_image = image.transpose(Image.FLIP_LEFT_RIGHT): Riflette l’immagine orizzontalmente. Per rifletterla verticalmente, utilizza Image.FLIP_TOP_BOTTOM.
  • photo = ImageTk.PhotoImage(rotated_image) o photo = ImageTk.PhotoImage(flipped_image): Converte l’immagine in un formato visualizzabile con Tkinter.
  • label = tk.Label(root, image=photo): Crea un widget Label per visualizzare l’immagine.
  • label.image = photo: Mantiene il riferimento all’immagine.
  • label.pack(): Dispone il widget Label nella finestra.
  • root.mainloop(): Avvia il ciclo principale e visualizza la finestra.

Ora abbiamo imparato a ruotare e riflettere le immagini. Successivamente, spiegheremo come gestire gli eventi del mouse sulle immagini.

Gestione degli eventi del mouse

Con Tkinter, è possibile gestire eventi del mouse sulle immagini. Mostreremo come catturare eventi del mouse come clic e trascinamento e implementare azioni in base a questi eventi.

Gestione degli eventi di clic sull’immagine

Il codice seguente mostra come ottenere le coordinate del punto in cui si è cliccato sull’immagine e visualizzare il testo in quella posizione.

import tkinter as tk  
from PIL import Image, ImageTk  

# Creazione della finestra principale  
root = tk.Tk()  
root.title("Gestione degli Eventi del Mouse sull'Immagine")  

# Impostazione delle dimensioni della finestra  
root.geometry("800x600")  

# Caricamento dell'immagine  
image_path = "path/to/your/image.jpg"  
image = Image.open(image_path)  
photo = ImageTk.PhotoImage(image)  

# Creazione di un widget Canvas per visualizzare l'immagine  
canvas = tk.Canvas(root, width=800, height=600)  
canvas.pack()  
canvas.create_image(0, 0, anchor=tk.NW, image=photo)  

# Funzione di gestione dell'evento di clic  
def on_click(event):  
    # Ottiene le coordinate del punto in cui si è cliccato  
    x, y = event.x, event.y  
    # Visualizza il testo alle coordinate cliccate  
    canvas.create_text(x, y, text=f"({x}, {y})", fill="red")  

# Associa l'evento di clic alla funzione di gestione  
canvas.bind("<Button-1>", on_click)  

# Visualizzazione della finestra  
root.mainloop()

Spiegazione del codice

  • canvas = tk.Canvas(root, width=800, height=600): Crea un widget Canvas.
  • canvas.create_image(0, 0, anchor=tk.NW, image=photo): Visualizza l’immagine sul canvas.
  • def on_click(event): Definisce la funzione di gestione dell’evento di clic. Utilizza event.x e event.y per ottenere le coordinate.
  • canvas.create_text(x, y, text=f"({x}, {y})", fill="red"): Visualizza il testo con le coordinate al punto cliccato.
  • canvas.bind("<Button-1>", on_click): Associa l’evento di clic sinistro alla funzione on_click.

Gestione degli eventi di trascinamento sull’immagine

Il codice seguente mostra come gestire gli eventi di trascinamento del mouse per disegnare un percorso sul canvas.

import tkinter as tk  
from PIL import Image, ImageTk  

# Creazione della finestra principale  
root = tk.Tk()  
root.title("Gestione degli Eventi di Trascinamento")  

# Impostazione delle dimensioni della finestra  
root.geometry("800x600")  

# Caricamento dell'immagine  
image_path = "path/to/your/image.jpg"  
image = Image.open(image_path)  
photo = ImageTk.PhotoImage(image)  

# Creazione di un widget Canvas per visualizzare l'immagine  
canvas = tk.Canvas(root, width=800, height=600)  
canvas.pack()  
canvas.create_image(0, 0, anchor=tk.NW, image=photo)  

# Funzione di gestione dell'evento di trascinamento  
def on_drag(event):  
    # Ottiene le coordinate del punto in cui si sta trascinando  
    x, y = event.x, event.y  
    # Disegna un piccolo cerchio per mostrare il percorso di trascinamento  
    canvas.create_oval(x-2, y-2, x+2, y+2, fill="blue", outline="blue")  

# Associa l'evento di trascinamento alla funzione di gestione  
canvas.bind("<B1-Motion>", on_drag)  

# Visualizzazione della finestra  
root.mainloop()

Spiegazione del codice

  • def on_drag(event): Definisce la funzione di gestione dell’evento di trascinamento. Utilizza event.x e event.y per ottenere le coordinate.
  • canvas.create_oval(x-2, y-2, x+2, y+2, fill="blue", outline="blue"): Disegna un piccolo cerchio alle coordinate specificate per mostrare il percorso di trascinamento.
  • canvas.bind("<B1-Motion>", on_drag): Associa l’evento di trascinamento sinistro alla funzione on_drag.

Ora che sappiamo come gestire eventi del mouse come clic e trascinamento, possiamo applicare queste conoscenze per creare un semplice editor di immagini.

Esempio applicativo: creazione di un editor di immagini

Applicando le conoscenze acquisite, creeremo un semplice editor di immagini utilizzando Tkinter e Pillow. Questo editor permetterà di visualizzare, ridimensionare, ruotare, riflettere un’immagine e disegnare su di essa utilizzando eventi del mouse.

Esempio di codice per un editor di immagini di base

Il seguente codice implementa le funzionalità di base di un editor di immagini.

import tkinter as tk  
from tkinter import filedialog  
from PIL import Image, ImageTk  

class ImageEditor:  
    def __init__(self, root):  
        self.root = root  
        self.root.title("Editor di Immagini Semplice")  
        self.root.geometry("800x600")  

        self.canvas = tk.Canvas(root, width=800, height=600)  
        self.canvas.pack()  

        self.menu = tk.Menu(root)  
        root.config(menu=self.menu)  

        file_menu = tk.Menu(self.menu)  
        self.menu.add_cascade(label="File", menu=file_menu)  
        file_menu.add_command(label="Apri", command=self.open_image)  
        file_menu.add_command(label="Salva", command=self.save_image)  

        edit_menu = tk.Menu(self.menu)  
        self.menu.add_cascade(label="Modifica", menu=edit_menu)  
        edit_menu.add_command(label="Ridimensiona", command=self.resize_image)  
        edit_menu.add_command(label="Ruota", command=self.rotate_image)  
        edit_menu.add_command(label="Rifletti", command=self.flip_image)  

        self.image = None  
        self.photo = None  

        self.canvas.bind("<B1-Motion>", self.paint)  

    def open_image(self):  
        file_path = filedialog.askopenfilename()  
        if file_path:  
            self.image = Image.open(file_path)  
            self.photo = ImageTk.PhotoImage(self.image)  
            self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)  

    def save_image(self):  
        file_path = filedialog.asksaveasfilename(defaultextension=".jpg")  
        if file_path and self.image:  
            self.image.save(file_path)  

    def resize_image(self):  
        if self.image:  
            self.image = self.image.resize((400, 300), Image.ANTIALIAS)  
            self.photo = ImageTk.PhotoImage(self.image)  
            self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)  

    def rotate_image(self):  
        if self.image:  
            self.image = self.image.rotate(90)  
            self.photo = ImageTk.PhotoImage(self.image)  
            self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)  

    def flip_image(self):  
        if self.image:  
            self.image = self.image.transpose(Image.FLIP_LEFT_RIGHT)  
            self.photo = ImageTk.PhotoImage(self.image)  
            self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)  

    def paint(self, event):  
        if self.image:  
            x, y = event.x, event.y  
            self.canvas.create_oval(x-2, y-2, x+2, y+2, fill="blue", outline="blue")  

if __name__ == "__main__":  
    root = tk.Tk()  
    app = ImageEditor(root)  
    root.mainloop()

Spiegazione del codice

  • La classe ImageEditor implementa le principali funzionalità dell’editor di immagini.
  • Il metodo __init__ configura la finestra, il canvas e il menu.
  • Il metodo open_image apre un file immagine e lo visualizza nel canvas.
  • Il metodo save_image salva l’immagine corrente su file.
  • Il metodo resize_image ridimensiona l’immagine.
  • Il metodo rotate_image ruota l’immagine di 90 gradi.
  • Il metodo flip_image riflette l’immagine orizzontalmente.
  • Il metodo paint gestisce l’evento di trascinamento, disegnando un cerchio blu sul canvas.

Partendo da questo editor di immagini di base, è possibile aggiungere ulteriori funzionalità per creare uno strumento di editing delle immagini più avanzato. Passiamo ora ad alcuni esercizi pratici per approfondire la comprensione di quanto appreso.

Esercizi e soluzioni

Di seguito vengono proposti alcuni esercizi per verificare le conoscenze acquisite e le relative soluzioni. Questi esercizi ti aiuteranno a consolidare la comprensione della visualizzazione e manipolazione delle immagini con Tkinter e Pillow.

Esercizio 1: Ridimensionamento dell’immagine

Aggiungi una funzione per ridimensionare l’immagine a una dimensione specifica (es.: larghezza di 300 pixel e altezza di 200 pixel) e visualizzarla.

Soluzione

Aggiungi la seguente funzione al codice per ridimensionare l’immagine.

def resize_image(self):  
    if self.image:  
        self.image = self.image.resize((300, 200), Image.ANTIALIAS)  
        self.photo = ImageTk.PhotoImage(self.image)  
        self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)

Esercizio 2: Salvataggio dell’immagine

Consenti all’utente di specificare il nome del file durante il salvataggio dell’immagine.

Soluzione

Aggiungi la seguente funzione al codice per il salvataggio dell’immagine.

def save_image(self):  
    file_path = filedialog.asksaveasfilename(defaultextension=".jpg")  
    if file_path and self.image:  
        self.image.save(file_path)

Esercizio 3: Rotazione dell’immagine con angolo specifico

Aggiungi una funzione per ruotare l’immagine di un angolo arbitrario specificato dall’utente (es.: 45 gradi).

Soluzione

Aggiungi la seguente funzione al codice per ruotare l’immagine.

def rotate_image(self):  
    if self.image:  
        angle = int(input("Inserisci l'angolo di rotazione: "))  
        self.image = self.image.rotate(angle)  
        self.photo = ImageTk.PhotoImage(self.image)  
        self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)

Esercizio 4: Visualizzazione di più immagini in sequenza

Aggiungi una funzione che consenta di caricare e visualizzare più immagini in sequenza.

Soluzione

Aggiungi la seguente funzione al codice per visualizzare più immagini.

def open_image(self):  
    file_paths = filedialog.askopenfilenames()  
    if file_paths:  
        for file_path in file_paths:  
            self.image = Image.open(file_path)  
            self.photo = ImageTk.PhotoImage(self.image)  
            self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo)  
            self.root.update()  # Aggiorna la finestra per mostrare l'immagine successiva  
            self.root.after(1000)  # Intervallo di 1 secondo tra le immagini

Esercizio 5: Cambiare il colore del disegno durante gli eventi del mouse

Permetti all’utente di specificare il colore del disegno durante il trascinamento del mouse.

Soluzione

Aggiungi la seguente funzione al codice per cambiare il colore del disegno.

def paint(self, event):  
    if self.image:  
        x, y = event.x, event.y  
        color = input("Inserisci il colore del disegno: ")  
        self.canvas.create_oval(x-2, y-2, x+2, y+2, fill=color, outline=color)

Questi esercizi ti aiuteranno a consolidare la comprensione delle operazioni di visualizzazione e manipolazione delle immagini utilizzando Tkinter e Pillow. Infine, riepiloghiamo i punti principali trattati.

Conclusione

In questo articolo, abbiamo imparato a utilizzare la libreria Tkinter di Python per visualizzare e manipolare immagini. Abbiamo iniziato con le basi di Tkinter, per poi passare a utilizzare la libreria Pillow per il caricamento, il ridimensionamento, la rotazione, la riflessione delle immagini e la gestione degli eventi del mouse. Infine, abbiamo applicato queste conoscenze creando un semplice editor di immagini, sviluppando così abilità pratiche. Con queste basi, è possibile creare applicazioni di elaborazione delle immagini più avanzate. Prova a mettere in pratica ciò che hai imparato in vari progetti!

Indice