Topic: Immagini e "contesti" grafici  (Letto 754 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 381
  • Punti reputazione: 0
    • Mostra profilo
Immagini e "contesti" grafici
« il: Ottobre 20, 2018, 11:13 »
Domanda forse un po' strana :

Che Voi sappiate esiste la possibilità di definire un oggetto immagine utilizzabile direttamente (senza specifiche istruzioni di caricamento) nei vari contesti grafici disponibili (pyTk, pyGtk, wxPyton, etc.)?

Un paio di giorni di ricerche in tal senso non hanno avuto esito e niente del poco che conosco è in tal senso ma data la notevole quantità di gestori presenti in python ed il grande numero di librerie esistenti (per lo più a me ignote) mi hanno spinto a porre la domanda.

Grazie dell'attenzione :)

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 3.154
  • Punti reputazione: 9
    • Mostra profilo
Re:Immagini e "contesti" grafici
« Risposta #1 il: Ottobre 20, 2018, 13:46 »
Mah, più che strana, non la capisco.
Naturalmente tutti i vari framework hanno una classe "immagine" (wx.Bitmap, QPixmap, Tkinter.Image...) che fa da interfaccia a un'immagine, e permette di gestire varie operazioni. Tra queste, naturalmente, anche caricarci dentro un'immagine proveniente da un file e/o salvare in un file.
Non capisco che cosa intendi per "oggetto immagine utilizzabile direttamente". In genere puoi certamente creare immagini "vuote" con una certa geometria, ma più che altro puoi disegnare su un canvas e poi salvare il canvas come un'immagine.

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 381
  • Punti reputazione: 0
    • Mostra profilo
Re:Immagini e "contesti" grafici
« Risposta #2 il: Ottobre 20, 2018, 16:33 »
Ciao @RicPol :)
Mah, più che strana, non la capisco.
Naturalmente tutti i vari framework hanno ...

C'è qualcosa di più "strano" di ciò che non si capisce? ... Cerchiamo di spiegare allora! ;)

Sto cominciando, lentamente, a costruirmi un "cassettino degli attrezzi", man mano che capisco qualcosa. Due cose che amo, quando costruisco una interfaccia grafica, è usare icone e tooltip, per contro odio visceralmente districarmi tra la miriade di files che la qual cosa richiederebbe, perciò concentro tutto in un modulo (non lo faccio a mano) di risorse contenente un dizionario per la memorizzazione di immagini e stringhe, oltre una piccola classe per la distribuzione a richiesta.

Al momento, le immagini vengono memorizzate convertite in base64 e restituite nello stesso modo, il processo richiedente si incarica, quindi, della riconversione da base64 ad immagine, in pytk (unico gestore usato al momento) uso istruzioni di questo tipo:
self.icoSSet = tk.PhotoImage(data = ids.getIco('sset'))

nel costruire una GUI

Sto per mettere in cantiere un piccolo progettino e nello avviarne la costruzione del modulo di risorse mi sono chiesto se fosse possibile predisporre una immagine usabile direttamente in tutti i vari contesti grafici (lo immagino che ognuno di tali contesti abbia metodi propri) i modo da "alleggerire" il codice di costruzione delle interfacce grafiche, solitamente ipertrofico.

Spero che, ora, sia più comprensibile il motivo della domanda.

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 3.154
  • Punti reputazione: 9
    • Mostra profilo
Re:Immagini e "contesti" grafici
« Risposta #3 il: Ottobre 20, 2018, 19:17 »
Mah, veramente continua a essere tutto un po' sfocato.
Vuoi fare un programma con gui desktop, e fin qui ci siamo. Vuoi metterci delle immagini per le icone e va benissimo (a dire il vero i "tooltip" che citi di solito non hanno immagini, quindi qui non so bene a cosa ti riferisci, ma poco male). Però non vuoi usare un file fisico separato per l'immagine, e d'accordo. Quindi serializzi l'immagine in base64, e perché no.
Tutto ciò che viene dopo è un po' un mistero. Primo, ti chiedi se i vari framework supportano una cosa del genere? Mah, dovresti vedere sulla documentazione. Per esempio le wx hanno un loro meccanismo di serializzazione (se ben ricordo basato su base64 ma non è l'unico modo ovviamente). Credo che le qt sicuramente sì. Ma dopo tutto, che ti importa? Se hai encodato l'immagine in base64, puoi decodarla e passarla al framework come uno stream di bytes al posto del file, no? Non so, vado a naso ma l'api è la stessa (a meno di idiosincrasie specifiche del framework che dovresti controllare sulla documentazione, ma insomma...).
Secondo, parli di "gestore" ma che cosa sarebbe un "gestore" di preciso? Vuoi dire "un gui framework"? E vuoi dire che intendi usare più di un gui framework (chesso, le wx e le qt) *contemporaneamente* nello stesso progetto? Apperò... la vedo veramente ma veramente ma veramente ma veramente... avventurosa.
Terzo, parli di "pytk" ma io davvero, mica lo so che cosa è "pytk". Se cerco trovo questo https://pypi.org/project/pytk/ e mi auguro che davvero tu non intenda questa cosa qui... un progetto semiabbandonato (ultima release, aprile 2017... capirai) e praticamente che non ha mai superato lo stato di bozza. Guarda, il mio consiglio qui sarebbe: scegliti un gui framework serio e importante e testato e ben sviluppato, a scelta tra le wx e le qt (in pratica non c'è molto altro che risponda ai requisiti). Sceglilo in base a una serie di motivi che NON sono "supporta le immagini serializzate", ma più complessivo, basato sull'architettura, sulle feature, etc. E poi usa quello e attieniti a quello, e non cambiare più. Già imparare a usare bene UN gui framework è un lavoraccio immane... figuriamoci usarne due o tre... nessuno fa una cosa del genere, se proprio non ne ha un preciso e specifico bisogno.
Quarto (e qui proprio mi sono perso), parli di "contesti grafici" ma che cosa è un "contesto grafico"? Vuoi dire che vorresti usare, per dire, la stessa icona in due finestre diverse, o in due menu diversi, o cose del genere? Boh, ma certo, questo è sempre possibile, a prescindere da come tu voglia persistere le immagini (come file o serializzate). Voglio dire, questa è programmazione a oggetti... una volta che hai l'istanza di una immagine, puoi usarla un po' dove ti pare. Ma forse intendevi altro, non so...

Detto questo, nella mia esperienza la serializzazione delle immagini in una gui desktop non è che sia proprio una svolta decisiva nel processo di semplificazione del progetto, diciamo. Anzi per molte ragioni spesso si preferisce proprio lasciarle come file... basta un minimo di organizzazione (la classica directory "imgs" e qualche nome di file ben scelto...) e non c'è poi un grande problema . Però intendiamoci, non è che serializzarle sia sbagliato, eh. E' solo che non lo vedo fare tanto spesso.

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 381
  • Punti reputazione: 0
    • Mostra profilo
Re:Immagini e "contesti" grafici
« Risposta #4 il: Ottobre 21, 2018, 08:14 »
Mah, veramente continua a essere tutto un po' sfocato.
....
Tutto ciò che viene dopo è un po' un mistero. Primo, ti chiedi se i vari framework supportano una cosa del genere?
No, non è quella la domanda, do abbastanza per scontato che i vari framework abbiano i loro metodi per poter visualizzare una immagine decodificandola da base64. mi chiedevo, date le estese librerie, se esista un oggetto "immagine" tale da poter essere utilizzato direttamente in tutti i framework così com'è, senza ulteriori passaggi.

... Ovviamente, ho presente che i vari frameworks hanno meccanismi propri, studiarseli è assiomatico.

Riguardo al "gestore", : gui framework dici? Gui framework sia! (anche se morirei strangolato provando a pronunciarlo ... e non credo Tu non l'abbia inteso ;) ), pytk è un arcaismo che ho visto quale futura speranza tempo fa e s'è perso nelle circonvoluzioni, ogni tanto esce a salutare ma stava li come mero esempio, niente più.

Il fatto che attualmente stia vedendo tkinter non significa che lo userò in futuro, essendo fornito di base con python è uno strumento da conoscere ed eventualmente da utilizzare in caso si faccia qualcosa per altri (mi è già capitato di doverlo fare, in tl caso utilizzo il minimo profilo possibile, su macchine non sotto il mio controllo), per me, ammesso decida di utilizzare una interfaccia grafica, quasi certamente userò un altro framework che ancora non ho identificato, lo farò tra un anno o due ... dal che deriva che ciò che faccio oggi deve prevedere l'evenienza.

... una volta che hai l'istanza di una immagine, puoi usarla un po' dove ti pare. Ma forse intendevi altro, non so...       

beh ... sbaglierò ma dipende un po' dall'istanza, credo, istruzioni del genere istanzierebbero una immagine

from PIL import Image
from io import BytesIO
import base64

data['img'] = '''R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw=='''

im = Image.open(BytesIO(base64.b64decode(data))

ma assegnandola direttamente ad un widget tkinter avremmo:
_tkinter.TclError: image "<PIL.PngImagePlugin.PngImageFile image mode=RGBA size=22x22 at 0x7F7E7876A898>" doesn't exist


Detto questo, nella mia esperienza la serializzazione delle immagini in una gui desktop non è che sia proprio una svolta decisiva nel processo di semplificazione del progetto, diciamo. Anzi per molte ragioni spesso si preferisce proprio lasciarle come file... basta un minimo di organizzazione (la classica directory "imgs" e qualche nome di file ben scelto...) e non c'è poi un grande problema . Però intendiamoci, non è che serializzarle sia sbagliato, eh. E' solo che non lo vedo fare tanto spesso.
Su questo hai ragione, non è una faccenda "importante", solo un mio vezzo, non mi piace avere molti files sparsi in giro, anche se in direttrici dedicate, e preferisco "serializzare", non è un fattore che guida le mie scelte.

Per altro, hai posto la cosa ma ho sorvolato, le immagini (icone in effetti) non necessariamente ma frequeentemente, le utilizzo in abinamento con i tooltip, semplici stringhe di testo visualizzate da un altro "attrezzo" (classe) ... quindi li gestsco assieme, di solito sono legati, sono nominati casualmente nel primo post ma non inferiscono con l'argomento.

Ciao :)

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 3.154
  • Punti reputazione: 9
    • Mostra profilo
Re:Immagini e "contesti" grafici
« Risposta #5 il: Ottobre 21, 2018, 15:58 »
> Riguardo al "gestore", : gui framework dici?

Mah guarda, non sono "io" che lo dico. Tutti li chiamano gui framework. E la ragione per cui tutti li chiamano gui framework è che... spoiler alert... si chiamano gui framework. Tra l'altro, capisco se avessi usato un sinonimo anche vago, ma "gestore" (manager) in programmazione a oggetti significa proprio un'altra cosa, con la conseguente perdita di tempo a cercare di capire quello che hai in mente. Boh.

>  se esista un oggetto "immagine" tale da poter essere utilizzato direttamente in tutti i framework così com'è, senza ulteriori passaggi.

Uhm... boh? No? Ma soprattutto, perché dovrebbe esistere? Voglio, dire, certo che "qualcosa" alla base esiste: un file jpg, per dire, può essere usato da tutti. O magari (forse, dovrei vedere) un oggetto file-like, tipo uno stream di bytes che contiene le stesse informazioni. Ma che senso avrebbe una classe "Image" che wrappa un'immagine e che può essere usata così com'è in tutti i gui framework? Allora potresti chiederti se per caso esiste una classe Button che disegna un pulsante e che puoi inserire dentro tutti i framework. E proseguendo il ragionamento, perché non anche una classe Menu, e una classe Frame... e perché poi avere framework diversi? Non sarebbe meglio avere un solo framework?

Del resto, sempre cercando di indovinare quello che hai in mente, forse ho capito l'idea su cui ti sei fissato: pytk in effetti è un vago tentativo di fare una "facade" che astrae le funzionalità di gui framework diversi. Guarda, un progetto analogo più noto era questo http://anygui.sourceforge.net/, per quel che è durato. Il problema alla radice di progetti del genere è sempre quello: perché? Cioè, l'idea sarebbe: scrivo una gui in python in modo tale che lo stesso codice sia applicabile indifferentemente a wxPython, Tkinter, PyQt... Ok, bello, ma... chi se ne frega? Cioè, se l'idea è facilitare la distribuzione del codice... guarda, lascia stare, è inutile.
Piuttosto, usa UN gui framework che ti piace, studiatelo, e scrivi la tua gui con quello.

> ... pytk è un arcaismo...
> ... tkinter non significa che lo userò in futuro ...

Ok, ma capisci che così è sempre tutto vago.

>  istruzioni del genere istanzierebbero una immagine

Quel codice non è python valido, quindi non è molto chiaro che cosa dovrebbe fare.

> ma assegnandola direttamente ad un widget tkinter

... e però chiaramente *non* posti il codice con cui la "assegni" a un widget tkinter, e *non* dici che cosa intendi per "assegnarla". Occhei, anche qui, lucidiamo la sfera di cristallo e proviamo a indovinare. Se il codice che hai postato funzionasse, dovrebbe creare (suppongo) una istanza di PIL.Image a partire da uno stream di bytes. E questo, credo, in effetti è possibile. Dopo di che, però, perché dovresti pensare che una Tkinter.Image, per dire, dovrebbe accettare come sorgente una PIL.Image? O una Tkinter.Label, per dire, dovrebbe accettare una PIL.Image come parametro? E a maggior ragione, una wx.Image, o una immagine Qt...?
Quello che ti suggerivo era di provare a caricare una Tkinter.Image (per dire) invece che direttamente con un file immagine, con uno stream di bytes. Ma chi ha mai parlato di PIL in tutto questo? Che c'entra? Da dove spunta fuori adesso PIL? Mah, il mistero si infittisce.

Se posso azzardare, la mia impressione è che ti sei fissato su un dettaglio completamente insignificante ma nel frattempo hai le idee molto confuse almeno su due aspetti basilari:
- primo, non è né necessario né utile perseguire un'architettura di "gui framework intercambiabili", qualsiasi cosa voglia dire questo. Studia UN gui framework e scrivi la tua gui con quello. E' già fin troppo complicato così.
- secondo, dovresti forse studiarti un gui framework qualsiasi anche se poi finisci per non usarlo, solo per chiarirti le idee su come funziona l'architettura di un sistema del genere. E forse anche per chiarirti qualcosa sulla programmazione a oggetti. C'è differenza tra un file-immagine ("pippo.jpg"), una classe Image (da qualunque libreria/framework tu la importi) che gestisce l'immagine eventualmente persistendola nel file, e l'immagine che decora un pulsante, un menu, un'icona o un altro elemento visibile della gui.

Offline nuzzopippo

  • python neanderthalensis
  • ****
  • Post: 381
  • Punti reputazione: 0
    • Mostra profilo
Re:Immagini e "contesti" grafici
« Risposta #6 il: Ottobre 22, 2018, 08:37 »
> Riguardo al "gestore", : gui framework dici?

Mah guarda, non sono "io" che lo dico. ...
@Ric, Ti rigrazio della pazienza che dimostri alle mie improprietà ... i termini inglesi semplicemente non si fermano nella mia mente e le mie "interpretazioni" lasciano a desiderare, ci sbatto il grugno sin troppo spesso.

>  se esista un oggetto "immagine" tale da poter essere utilizzato direttamente in tutti i framework così com'è, senza ulteriori passaggi.

Uhm... boh? No? Ma soprattutto, perché dovrebbe esistere? Voglio, dire, certo ...
Ecco, questo è risposta alla mia domanda, argomentazioni più che ragionevoli, non inaspettate.

Dato l'unico linguaggio di riferimento (python) avevo considerato potesse, a sua volta, essere ragionevole pensare all'esistenza di una interfaccia unificante le immagini, bene o male utilizzate ovunque nei vari con gui framework :) così pare non sia, lascerò perdere.

Sono penosamente consapevole di aver tanto da imparare, grazie dei consigli.

Un particolare OT :
>  istruzioni del genere istanzierebbero una immagine
Quel codice non è python valido, quindi non è molto chiaro che cosa dovrebbe fare.
> ma assegnandola direttamente ad un widget tkinter
... e però chiaramente *non* posti il codice con cui la "assegni" a un widget tkinter, ...

Quel codice, era un esempio generico (mancava anche una parentesi) buttato li per non postare un bel po' di codice per esemplificare che una generica istanza ad immagine non fosse necessariamente accettabile da un widget tkinter.

Mi ha incuriosito il "non è python valido", eseguendo nello IDLE questo codice:

Python 3.6.6 (default, Sep 12 2018, 18:26:19)
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "copyright", "credits" or "license()" for more information.
imdata = '''
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAA
CYQAAAmEBwTBV+gAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAALeSURBVHjatZ
XNahRBEMer5yP7lUyMQYjBgBJI1Iirou4hlyB5AR9APUsuBlSIL5B4Ex8hD+DBgwcVvHhRMXoQUVyCo
Pm6iHF3vnqmp63qnWlmdkcR1GKqZ3t6+lf/rurpZVJK+B9mUbO8vPxMRPGsbdty5vhcfezguJUkCUak
oKx3MabcMAz9Gy8wsb+1sx23P7z3JU6pVCufVtfWFhTYd72FTrcLzsgITM+ehNPNs/B0YxMSmQAZo4Z
AoOOkUBMWL07Dq5cv4N2bjTEhBKBPasWccwjDEJJGQ00Yshksnj8GQKI1jGkgUw2gegYWOhmuULsG04
ujjkPRemDLgOqQBdoyoE4LQoGpu0hBODdzDdZRVN5Ago3gJ683gdJcZpJc9kowf2oKEqHVFsDU0WAaD
KMYLsxO0mQNwk4KzFxSppRHiYA4jjW4VHGM0QMuwDSNAZmIzqBaNaflx6RWe7niSAgER/Do+dtCKvLb
XWFT5ZdaczhHkmLsq/ugYrIYo3uo+NyJ6Z5M3YJOTV51IpUwYtCzouJECA3e3d2GWsPJB9OWYgmsA31
jBuzt7YBIlSaGkUtFDvL44QOt7E+NUpiZ0a/4bywvQzBWzPE/smKOqZL9dn1pCSYOT/wSwMMQ7qysQB
AEqoCHxscHT7coirK+Loof+HD75i011sUDavXu2gB8dPQAGEaHCqcZRcUlYM/zIEJVgvY1BnFdt2zdw
NJCE7xSqdDc3ysmEKWIwDzkZeDC+SDxXqvXAQpgBJSBeRypIzXgoUpHv3lhQGPqC2XptjXyuyLm/B4w
dqM/Fd1OF77v79OBr/r9Fng+hD4VT4JlmtDBd2n1jDHTwoY+lftHj0zND48Mn8nYvu/bV65dZdkexb7
+J9GKPRfLENIzVG0Cjzid0i7V1UJ1CcK3Pn/9chkAKgRttVrQbDZnHMepVavVOhalYdt2Lc2rj+nxMJ
Dbbrc/rq+vE4jldyL6j58Q3BDGwSeCEgAAAABJRU5ErkJggg==
'''
from PIL import Image
from io import BytesIO
import base64
img = Image.open(BytesIO(base64.b64decode(imdata)))
img.save('test.png')

Viene correttamente eseguito e salvata l'immagine (un discetto) e proseguendo con

import tkinter as tk
btSSet = tk.Button(None,
           image=img
       )
Traceback (most recent call last):
  File "<pyshell#11>", line 2, in <module>
    image=img
  File "/usr/lib/python3.6/tkinter/__init__.py", line 2366, in __init__
    Widget.__init__(self, master, 'button', cnf, kw)
  File "/usr/lib/python3.6/tkinter/__init__.py", line 2296, in __init__
    (widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: image "<PIL.PngImagePlugin.PngImageFile image mode=RGBA size=22x22 at 0x7F8101F4AC50>" doesn't exist
 

(spero che venga mostrato correttamente, nella anteprima le indicazioni copiate dallo IDL non vengono esposte come codice, ho tolto i tripli '>' ma non sembra cambiare)
Si ha il messaggio segnalato.
Ovviamente, suppongo Tu riferissi alla incompletezza del codice del precedente post ed alla raffazzonata esemplificazione fatta, ho cercato di far di meglio senza creare papiri ma, se c'è altro che occorre sapere, son tutto orecchi.

Ciao e grazie :)

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 3.154
  • Punti reputazione: 9
    • Mostra profilo
Re:Immagini e "contesti" grafici
« Risposta #7 il: Ottobre 22, 2018, 11:32 »
> i termini inglesi semplicemente non si fermano nella mia mente
Beh, auguri per i tuoi progressi con l'informatica in generale, allora. Direi che ti conviene abituarti a pensare in Inglese, aiuta abbastanza.

> Mi ha incuriosito il "non è python valido", eseguendo nello IDLE questo codice:
Sì, solo che *questo* codice *non* è il codice che avevi postato prima. La differenza è tra codice non valido e codice valido. Se provi a far girare il codice che avevi postato prima, così come l'avevi postato, lo vedi.
Poi certo, non è che proprio non ci sono arrivato lo stesso a capire che cosa volevi fare. Ma non è che uno possa sempre unire i puntini nel modo giusto.
E il motivo per cui alla fine hai quell'errore, è quello che già ti spiegavo. Semplicemente Tkinter non accetta una istanza di PIL.Image come argomento per un Button (o per qualsiasi altra cosa, per quel che vale). Una PIL.Image non è una "chiave universale" che puoi inserire dove vuoi. PIL è una libreria di manipolazione delle immagini. Fa tante belle cose ed è molto utilizzata nel mondo python, ma non è in nessun modo e non vuole essere un "provider universale di immagini" per altre librerie.
Se una libreria (per esempio un gui framework) decide di fornire un adapter per PIL.Image, naturalmente può farlo e allora tu potrai usare una istanza di PIL.Image dentro *quella* libreria. Ma è una decisione consapevole dell'autore della libreria. Sul momento non mi vengono esempi di librerie che fanno questo, ma ce ne saranno.
Viceversa, se PIL decidesse di fornire un adapter verso un'altra libreria, allora potresti usare questo nella tua libreria "cliente". E guarda caso qualcosa del genere esiste: https://pillow.readthedocs.io/en/5.3.x/reference/ImageTk.html e https://pillow.readthedocs.io/en/5.3.x/reference/ImageQt.html. Quindi PIL mette a disposizione degli adapter verso Tkinter e verso le Qt... ma per esempio non verso le wx. Perché? E che ne so? Perché l'autore di PIL non aveva voglia, suppongo. E del resto, mica è un obbligo.
Quindi curiosamente la risposta all'errore del tuo codice è che tutto funzionerebbe se usassi PIL.ImageTk invece di PIL.Imge. Ma questo è solo perché PIL mette a disposizione quelle classi, bontà sua. Non è un protocollo obbligatorio. E certe cose si scoprono solo leggendo la documentazione (di PIL e di Tkinter, in questo caso).

Uhm. Ho questa immagine mentale che forse tu pensi che tutto questo debba funzionare come quando vai in un paese straniero e non sai la lingua: però ti esprimi a gesti e bene o male ti fai capire lo stesso perché "scusi dov'è il bagno?" è un'esigenza comune a tutti. Così, tu pensi che "un'immagine" è pur sempre "un'immagine", e quindi tutte le librerie devono "bene o male" capire che cosa voglio fare quando gli metto davanti una PIL.Image o qualcosa del genere... Ma purtroppo l'informatica non funziona esattamente così.