Topic: Salvare il Canvas in un'immagine png  (Letto 139 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline maurotramonti

  • python unicellularis
  • *
  • Post: 3
  • Punti reputazione: 0
    • Mostra profilo
Salvare il Canvas in un'immagine png
« il: Febbraio 06, 2020, 16:05 »
Salve a tutti, sono nuovo del forum. Sto sviluppando un'applicazione che replica le funzionalità di Paint in Python e vorrei sapere se qualcuno di voi conosce un metodo per salvare il Canvas in un'immagine. Grazie in anticipo a tutti.  :)

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 255
  • Punti reputazione: 0
    • Mostra profilo
Re:Salvare il Canvas in un'immagine png
« Risposta #1 il: Febbraio 06, 2020, 19:33 »
Ciao @Mauro

Mai provato ma la domanda mi ha incuriosito e fatta una ricerca ho trovato un esempio per python 2.7. Adattando il codice funziona.

Nell'esempio viene usato PIL per convertire in immagine un grafo tracciato in un canvas, è il primo adattamento da farsi per farlo funzionare in una versione 3.x di python, trasformare l0import
import Image, ImageDraw

in
from PIL import Image, ImageDraw

poi, se non stai usando windows,attento alla istruzione
os.startfile(filename)

che dovrebbe aprire il file jpg prodotto, per il resto lo ho eseguito ed è funzionale

Ciao

[Edit] ... letto meglio il codice che ho proposto : l'immagine vien disegnata tanto nel canvas quanto in una immagine on memoria da PIL ed è pil che salva l'immagine ... il che non credo sia ciò che Ti serve, chiedo venia per la segnalazione "zoppa"
« Ultima modifica: Febbraio 06, 2020, 19:52 da nuzzopippo »

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 255
  • Punti reputazione: 0
    • Mostra profilo
Re:Salvare il Canvas in un'immagine png
« Risposta #2 il: Febbraio 07, 2020, 09:20 »
Allora ...

Piccato di aver dato una risposta non pertinente, ieri sera ho dato una guardata in giro per vedere cosa c'è sull'argomento ... non posso dire di aver trovato tecniche strabilianti per trasformare i contenuti di un canvas in immagini, in ogni caso quanto trovato fa ricorso alla libreria PIL.

Fondamentalmente, le tecniche che ho trovato sono due :

una effettua uno screenshot di una parte dello schermo tramite la funzione ImageDraw di PIL, se ho capito bene disponibile solo per windows, in questa pagina un esempio, metodo che può essere riprodotto in ambienti linux tramite la libreria pyscreenshot, un esempio più ampio in tal senso lo ho trovato su stackoverflow, non ho testato tali mezzi ma segnalo.

La seconda tecnica utilizza il metodo "postscript" dei canvas, lo trovi verso il basso nella docs che, se ho compreso bene, può creare un file postscript dei soli item e non di eventuali immagini inserite (leggi la docs), per poi aprirlo tramite Image di PIL e salvarlo nel formato voluto.
... Tale metodo lo ho provato, sulla base di un esempio su stackoverflow utilizzando il canvas dei colori di questo codice che ho già utilizzato per altre problematiche.
L'immagine viene creata, ma contiene solo l'immagine della parte visibile del canvas, di dimensioni molto ridotte, oltre tutto ... se vuoi "vedere", copiati il codice, poi altera gli import in questo modo :

import tkinter as tk
from tkinter import font as fnt
import lst_nomi as lc
from PIL import Image
import io

quindi nella classe "defColor" definisci il metodo

    def __save_colors(self, pan):
        ps = pan.postscript(colormode='color')
        img = Image.open(io.BytesIO(ps.encode('utf-8')))
        img.save('exampled_colors.jpg')

per richiamarlo alla fine del metodo "__populate_colors" in questo modo
...
            except:
                pass
        pan.configure(scrollregion=(0, 0, dim_x, posy))
        self.__save_colors(pan)


per funzionare funziona ma ...

Al momento trovo le metodologie ora indicate poco soddisfacenti (parzialità immagine), forse c'è da approfondire e comprenderle meglio, o, forse, è più efficace la prima tecnica segnalata, in ogni caso c'è da lavorarci su.

Ciao :)
« Ultima modifica: Febbraio 07, 2020, 09:21 da nuzzopippo »

Offline maurotramonti

  • python unicellularis
  • *
  • Post: 3
  • Punti reputazione: 0
    • Mostra profilo
Re:Salvare il Canvas in un'immagine png
« Risposta #3 il: Febbraio 07, 2020, 14:21 »
Grazie per le risposte, alla fine ho risolto usando PIL. Però c'è un altro problema: non posso eliminare il file .ps una volt convertito, mi dice "file occupato da un altro processo" anche se ho usato Image.close()

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 255
  • Punti reputazione: 0
    • Mostra profilo
Re:Salvare il Canvas in un'immagine png
« Risposta #4 il: Febbraio 07, 2020, 14:44 »
Però c'è un altro problema: non posso eliminare il file .ps una volt convertito, mi dice "file occupato da un altro processo" anche se ho usato Image.close()

Difficile indovinare "perché" senza vedere il codice, potrebbe dipendere da vari fattori, potresti riprodurre il problema in un breve esempio e postare l'errore?

Offline maurotramonti

  • python unicellularis
  • *
  • Post: 3
  • Punti reputazione: 0
    • Mostra profilo
Re:Salvare il Canvas in un'immagine png
« Risposta #5 il: Febbraio 07, 2020, 15:10 »
Allora praticamente ho risolto in questo modo: visto che il file non era disponibile fino al termine della funziona save() ho fatto così:


    def save(self):
        name = asksaveasfile(mode='w', defaultextension='.ps')
        path = name.name.replace("/","\\")
        ps = self.canvas.postscript(file = path, colormode='color')
        im = Image.open(path)
        im.save(path.replace(".ps",".png"))
        im.close()
        self.path = path
        self.needUnlink = True



Ogni volta che il mouse viene trascinato sul Canvas, verifica se la variabile needUnlink è su True e cancella quel file, ormai inutilizzato:


        if self.needUnlink:
            os.unlink(self.path)
            self.needUnlink = False

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 255
  • Punti reputazione: 0
    • Mostra profilo
Re:Salvare il Canvas in un'immagine png
« Risposta #6 il: Febbraio 07, 2020, 16:09 »
Hai provato a mettere la scittura dell'immagine in un blocco with?

Poi, per avere il nomefile nella notazione di windows dovrebbe essere sufficiente richiedere un os.path.abspath (credo senza certezza assoluta, non uso windows)

Se Ti va, prova un po' questa variante della Tua funzione e fai sapere:

    def save(self):
        name = asksaveasfile(mode='w', defaultextension='.ps')
        path = os.path.abspath(name)
        ps = self.canvas.postscript(file = path, colormode='color')
        with Image.open(path) as im:
        im.save(path.replace(".ps",".png"))
try:
os.remove(path)
Except OSError as e:
# messaggio di errore


Ciao :)
« Ultima modifica: Febbraio 07, 2020, 16:12 da nuzzopippo »