Preparare e convertire automaticamente le foto per Waveshare PhotoPainter e display e-paper

Il problema che volevo risolvere

Uso un Waveshare PhotoPainter originale da 7,3 pollici, con display e-paper a 7 colori e risoluzione 800×480. :-D

È un oggetto che mi piace parecchio, soprattutto per utilizzarlo come cornice fotografica, ma dopo averci caricato un po’ di fotografie mi sono scontrato con un problema abbastanza pratico: preparare bene le immagini richiede molto più lavoro di quanto sembri.

Il display ha soltanto 800×480 pixel. Proprio per questo non voglio sprecarne neanche uno.

Con una fotografia orizzontale il problema è relativamente semplice. Con le fotografie verticali, invece, bisogna decidere cosa sacrificare: ritagliare aggressivamente la foto, lasciare dello spazio ai lati oppure trovare un compromesso.

E se le fotografie diventano 50, 100 o diverse centinaia, fare tutto manualmente diventa rapidamente noioso.

Da questa esigenza è nato PhotoPainter Cropper & Converter.

È un piccolo tool che gira interamente nel browser e che ho realizzato per:

  • caricare interi gruppi di fotografie;
  • scegliere velocemente il ritaglio di ogni foto;
  • adattarle esattamente alla risoluzione dello schermo;
  • gestire meglio le fotografie verticali;
  • ricordare i crop già effettuati;
  • convertire automaticamente le immagini nella palette del display e-paper;
  • generare i BMP pronti per PhotoPainter;
  • scaricare tutto in un unico ZIP.

La cosa importante è che tutta l’elaborazione avviene localmente nel browser: le fotografie non vengono inviate a nessun server.

Il tool è disponibile direttamente qui:

PhotoPainter Cropper & Converter

Prima di tutto: capire come convertiva le immagini PhotoPainter

Il primo problema non era realizzare l’interfaccia di crop.

Quella era la parte relativamente semplice.

Il problema vero era riuscire a generare un’immagine che il PhotoPainter interpretasse esattamente nello stesso modo di quella prodotta dagli strumenti che utilizzavo normalmente.

Ho quindi fatto un po’ di reverse engineering del processo di conversione, cercando di replicarne il comportamento.

Nel mio caso il display di riferimento è:

1
2
3
Waveshare PhotoPainter originale / 7.3" HAT (F)
Risoluzione: 800x480
Palette: ACeP 7 colori

La palette utilizzata dal tool è composta da:

1
2
3
4
5
6
7
Nero
Bianco
Verde
Blu
Rosso
Giallo
Arancione

Naturalmente una fotografia normale contiene milioni di possibili colori, mentre questo display può rappresentarne soltanto sette.

Serve quindi una fase di quantizzazione.

Nel tool ho replicato la conversione utilizzando il dithering Floyd–Steinberg.

In pratica, per ogni pixel viene cercato il colore più vicino disponibile nella palette del display. L’errore introdotto da questa approssimazione viene poi distribuito sui pixel vicini.

La distribuzione utilizzata è quella classica:

1
2
        X   7/16
3/16 5/16 1/16

Il risultato finale non aumenta ovviamente il numero reale di colori del pannello, ma sfrutta la disposizione dei pixel per ottenere una resa visiva molto più convincente rispetto a una semplice conversione al colore più vicino.

Dopo la quantizzazione, il tool genera direttamente un BMP 24 bit bottom-up, nel formato utilizzato dalla pipeline che volevo replicare.

Ho confrontato il risultato su decine e successivamente centinaia di fotografie e, nei miei test, sono riuscito ad arrivare allo stesso risultato della conversione originale, fino ad ottenere immagini con i pixel risultanti identici.

A quel punto potevo finalmente eliminare dal mio workflow la conversione manuale e inglobare tutto nello stesso strumento.

Dal crop alla conversione, tutto dentro una pagina HTML

La prima versione del mio workflow non era nemmeno un’applicazione web.

Avevo due script Python separati:

  1. uno script con interfaccia Tkinter per ritagliare manualmente le fotografie;
  2. uno script che effettuava la conversione nel BMP richiesto dal display.

Successivamente ho deciso di riunire tutto.

L’attuale PhotoPainter Cropper & Converter è quindi scritto in HTML, CSS e JavaScript ed è contenuto in un unico file statico.

Non richiede installazione.

Non richiede Python.

Non richiede un backend.

Non richiede l’upload delle fotografie.

Può essere pubblicato come una normale pagina statica oppure aperto direttamente dal computer.

Non è limitato al mio PhotoPainter

Anche se il progetto è nato principalmente per il mio PhotoPainter 800×480 a 7 colori, ho cercato di non legarlo esclusivamente a quel modello.

All’apertura è possibile scegliere il dispositivo di destinazione.

Tra i profili presenti ci sono, ad esempio:

  • Waveshare PhotoPainter (B), 800×480, Spectra 6;
  • Waveshare PhotoPainter originale / 7.3” HAT (F), 800×480, ACeP 7 colori;
  • Waveshare 5.65” e-Paper (F), 600×448;
  • Waveshare 4.01” e-Paper HAT (F), 640×400;
  • Waveshare 4”/3.6” e-Paper HAT+ (E), 600×400;
  • Waveshare 13.3” e-Paper HAT+ (E), 1600×1200;
  • alcuni display Waveshare bianco/nero/rosso;
  • bianco/nero/giallo;
  • bianco e nero;
  • display in scala di grigi.

Ho aggiunto inoltre dei profili generici, nei quali è possibile indicare manualmente larghezza e altezza e scegliere la tipologia di palette:

1
2
3
4
5
6
7
Bianco/Nero
Bianco/Nero/Rosso
Bianco/Nero/Giallo
4 livelli di grigio
16 livelli di grigio
6 colori Spectra 6 / E6
7 colori ACeP

Quindi il cropper può essere utilizzato anche con altri display, purché il formato di output sia adatto al proprio workflow.

Il crop in batch

Il workflow che utilizzo normalmente parte da una cartella contenente tutte le fotografie che voglio preparare.

Dal tool posso selezionare direttamente la cartella oppure aggiungere le immagini separatamente.

A quel punto si passa all’editor.

Per ogni fotografia viene visualizzato il rettangolo corrispondente esattamente al rapporto d’aspetto del display scelto.

Nel mio caso:

1
800 / 480 = 1,666...

Posso quindi spostare e ridimensionare velocemente l’inquadratura fino a ottenere la composizione che voglio.

Questo è particolarmente utile quando preparo tante foto insieme: non voglio che sia un algoritmo a decidere automaticamente quale sia la parte importante della fotografia.

Se ci sono delle persone, ad esempio, voglio essere io a decidere chi deve rimanere al centro.

Mi è capitato anche di utilizzare la stessa fotografia in raccolte differenti con crop diversi. Per una raccolta destinata ai nonni, ad esempio, posso tranquillamente scegliere un’inquadratura maggiormente concentrata sui bambini piuttosto che sugli adulti.

È una piccola cosa, ma quando si preparano centinaia di immagini fa la differenza.

Le fotografie verticali e il riempimento sfocato

Questo è probabilmente l’aspetto che personalmente trovo più utile.

Una fotografia verticale e un display 800×480 orizzontale hanno rapporti d’aspetto completamente diversi.

Posso ovviamente ingrandire la fotografia fino a riempire lo schermo, ma in quel modo rischio di perdere una quantità enorme dell’immagine originale.

Oppure posso mantenere un’inquadratura più ampia.

A quel punto, però, alcune aree del frame rimangono fuori dalla fotografia.

Il tool permette di gestirle in due modi:

1
2
white
blur

Con white viene utilizzato semplicemente uno sfondo bianco.

Con blur, invece, viene generato uno sfondo utilizzando la fotografia stessa, ingrandita e fortemente sfocata, mentre la parte selezionata rimane nitida in primo piano.

È lo stesso tipo di effetto che si vede spesso nei player video o nelle applicazioni social quando un contenuto verticale deve essere mostrato all’interno di uno spazio orizzontale.

Nel mio caso lo preferisco nettamente alle bande vuote.

Soprattutto su un piccolo display 800×480 permette di sfruttare l’intera superficie mantenendo comunque visibile una porzione più grande della fotografia originale.

Il raggio della sfocatura viene inoltre calcolato proporzionalmente alla larghezza del display, quindi non è legato rigidamente agli 800 pixel del mio PhotoPainter.

L’altra cosa che mi serviva: ricordare tutti i crop

Dopo aver preparato parecchie fotografie mi sono accorto di un altro problema.

Immaginiamo di avere una raccolta di 100 fotografie.

Le preparo tutte, le converto e le metto sul PhotoPainter.

Passano quattro mesi.

Nel frattempo trovo altre venti fotografie e voglio aggiungerle alla raccolta.

Potrei naturalmente elaborare soltanto quelle nuove, ma magari riguardando le vecchie mi accorgo che su alcune vorrei modificare leggermente l’inquadratura.

Senza conservare lo stato precedente dovrei praticamente ricominciare da capo.

Per questo, insieme a ogni fotografia, PhotoPainter Cropper genera un piccolo file:

1
<nome>_ppcrop.txt

Al suo interno vengono memorizzate le informazioni necessarie per ricostruire il ritaglio.

Il formato contiene dati come:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
image_name=
image_w=
image_h=

rect_x1=
rect_y1=
rect_x2=
rect_y2=

rect_nx1=
rect_ny1=
rect_nx2=
rect_ny2=

target_w=
target_h=
ratio=
fill_mode=
device=

Oltre alle coordinate assolute salvo anche le coordinate normalizzate rispetto alla dimensione dell’immagine.

Questo permette al programma di recuperare la selezione anche quando le dimensioni dell’immagine non coincidono più esattamente con quelle memorizzate, purché siano disponibili le coordinate normalizzate.

Quando seleziono nuovamente una cartella, il programma associa automaticamente:

1
2
foto.jpg
foto_ppcrop.txt

e ripristina l’inquadratura precedente.

Questa, nel mio utilizzo, è diventata una delle funzioni più importanti.

Posso conservare insieme:

1
2
IMG_1234.jpg
IMG_1234_ppcrop.txt

e considerare il file TXT quasi come un piccolo file di progetto della fotografia.

La foto originale rimane intatta.

Il TXT descrive semplicemente come voglio visualizzarla sul PhotoPainter.

Lavorare velocemente con la tastiera

Un’altra esigenza nata dall’elaborazione di molte fotografie era evitare di dover cliccare continuamente sui pulsanti.

Il crop può quindi essere controllato quasi interamente dalla tastiera.

Le scorciatoie principali sono:

1
2
3
4
5
6
7
8
9
10
11
12
13
Frecce       sposta il crop
Shift+Frecce spostamento più rapido

+ / - ridimensiona il crop
Shift ridimensionamento più rapido

Invio conferma e passa alla foto successiva
Tab conferma e passa alla foto successiva
A conferma e passa alla foto successiva

Esc salta la fotografia

F alterna sfondo bianco / sfocato

È possibile utilizzare anche la rotellina del mouse per cambiare la dimensione del ritaglio.

Nella parte inferiore dell’editor è inoltre presente una barra con le miniature.

In questo modo posso vedere dove mi trovo nella raccolta, quali immagini ho già confermato e tornare rapidamente su una fotografia precedente.

Quando bisogna sistemare cento foto, queste piccole scorciatoie fanno risparmiare parecchio tempo.

Esportazione

Una volta completata la selezione si passa alla fase di esportazione.

Per ogni fotografia confermata il programma genera tre elementi:

1
2
3
<nome>_ppcrop.txt
<nome>_pp.jpg
<nome>_pp_scale_output.bmp

Il JPG contiene il risultato del crop.

Il BMP contiene invece l’immagine convertita nella palette del display selezionato con dithering Floyd–Steinberg.

È possibile scaricare i singoli file oppure generare direttamente:

1
photopainter_export.zip

All’interno dello ZIP viene mantenuta questa struttura:

1
2
3
4
5
6
7
8
9
10
11
foto1_ppcrop.txt
foto2_ppcrop.txt
foto3_ppcrop.txt

_export_photopainter_jpg/
├── foto1_pp.jpg
├── foto1_pp_scale_output.bmp
├── foto2_pp.jpg
├── foto2_pp_scale_output.bmp
├── foto3_pp.jpg
└── foto3_pp_scale_output.bmp

I file _ppcrop.txt possono poi essere riportati nella stessa cartella delle fotografie originali.

Al caricamento successivo il tool li riconoscerà e ripristinerà i crop.

Nessuna fotografia viene caricata online

Visto il tipo di dati che normalmente passo a questo strumento, per me era importante anche questo aspetto.

Le fotografie sono spesso foto personali e familiari.

PhotoPainter Cropper & Converter non necessita di inviarle da nessuna parte.

Il browser legge i file locali, effettua il crop, crea il canvas, esegue la quantizzazione, costruisce il BMP e infine crea anche lo ZIP.

Tutto avviene lato client.

Persino la generazione dello ZIP è implementata direttamente nella pagina, senza appoggiarsi a un servizio esterno.

Questo significa che posso utilizzare il programma anche semplicemente aprendo localmente il file HTML.

Un singolo file HTML

Alla fine il progetto è diventato volutamente molto semplice da distribuire.

Tutto è contenuto in un unico:

1
index.html

Al suo interno ci sono:

1
2
3
4
5
6
7
8
9
10
11
HTML
CSS
JavaScript
profili dei dispositivi
palette colori
editor Canvas
gestione dei file di stato
Floyd-Steinberg dithering
encoder BMP
generazione ZIP
traduzioni dell'interfaccia

L’interfaccia è disponibile in:

1
2
3
4
Italiano
English
Español
Français

Il browser prova a scegliere automaticamente la lingua, che può comunque essere cambiata dall’interfaccia.

Questa scelta rende il progetto molto semplice da pubblicare: non c’è un’applicazione da installare o un servizio da mantenere.

È semplicemente una pagina statica.

Provare PhotoPainter Cropper & Converter

Il tool è pubblicato qui:

https://5m1.ovh/PhotoPainterCropper/index.html

La procedura completa è:

  1. aprire PhotoPainter Cropper & Converter;
  2. scegliere il proprio display e-paper;
  3. caricare la cartella contenente le fotografie;
  4. includere gli eventuali _ppcrop.txt di una sessione precedente;
  5. iniziare il crop;
  6. posizionare e ridimensionare l’inquadratura;
  7. scegliere, quando necessario, tra riempimento bianco e sfocato;
  8. confermare le fotografie;
  9. passare all’esportazione;
  10. generare JPG e BMP;
  11. scaricare lo ZIP;
  12. conservare i file _ppcrop.txt insieme alle immagini originali.

Il codice sorgente sarà disponibile anche su GitHub:

[DA VERIFICARE: inserire URL repository GitHub]

Conclusioni

Questo progetto è nato semplicemente perché avevo un problema che continuava a ripresentarsi.

Volevo scegliere le mie fotografie preferite, visualizzarle sul PhotoPainter sfruttando al massimo quei 800×480 pixel e non perdere ogni volta tempo tra crop, fotografie verticali, conversioni e lavorazioni già fatte mesi prima.

Prima ho automatizzato il crop.

Poi la conversione.

Poi ho aggiunto il riempimento sfocato.

Poi mi sono accorto che avevo bisogno di ricordare le selezioni.

Alla fine tutto è finito in una singola pagina HTML che ormai utilizzo per elaborare intere raccolte di fotografie.

È esattamente il genere di progetto per cui esiste GeeGeek: qualcosa che mi serviva, che ho costruito per risolvere un mio problema concreto e che, una volta arrivato a funzionare come volevo, tanto vale condividere.

Se volete provarlo, lo trovate qui:

PhotoPainter Cropper & Converter

Spero possa essere utile anche a qualcun altro che utilizza un PhotoPainter, un display Waveshare o più in generale una cornice e-paper e si è trovato davanti allo stesso problema.