Lettura dati Exif con ActionScript 3.0
di Giorgio Natili
Lettura dati Exif con ActionScript 3.0
Nella maggior parte delle fotocamere digitali si utilizzano file in formato Exif per memorizzare le immagini e attraverso questo formato sono disponibili moltissime informazioni; in questo modo tutti i software che si trattano immagini possono mostrare i dati rilevanti caricando solo pochi bytes. Il fatto positivo è che tutte le informazioni sull’immagine, inclusa la thumbnail, sono presenti nei primi 64 kbytes, memorizzate in image file directories (IFD) separate e ben organizzate. E’ per questo che non è necessario caricare l’immagine completa per mostrare la preview (se l’immagine è inferiore a 64 kbytes le informazioni si possono comunque ottenere e non è necessario chiudere il data stream prima del necessario).
Esistono già delle buone risorse sulla lettura di dati exif in ActionScript, alcuni ottimi esempi si trovano qui:
• http://code.shichiseki.jp/as3/ExifInfo/
• http://patrickshyu.com/2009/04/jpg-exif-metadata-in-actionscript-3/
Ho deciso di scrivere una soluzione personalizzata poiché la prima carica tutte l’ immagine prima di iniziare il parsing dei dati, mentre la seconda mi ha creato alcuni problemi con alcune immagini Motorola, e infine perché con alcune modifiche sono riuscito ad estrapolare anche informazioni su dati exif 1.1 mantenendo quindi una maggiore retro compatibilità.
Quello che manca e che vorrei migliorare è la visualizzazione delle thumbnails che non sono presenti in formato JPG, e la visualizzazione delle informazioni GPS che già vengono recuperate ma che non sono ben esposte.
Per evitare che si possa incorrerere nelle stesse problematiche da me riscontrate commenti ritengo opportuno approfondire alcuni argomenti prima di arrivare all’esplorazione del codice sorgente.
Innanzitutto per capire bene il formato e’ necessario leggere nel dettaglio le specifiche che si trovano qui http://www.exif.org/Exif2-2.PDF. Mi rendo conto che questo document non è così affascinante da leggere ma rappresenta l’unico modo per acquisire le informazioni necessarie per mettere in piedi una soluzione stabile e che contenga tutti i commenti necessari per far sì che altri possano estenderla e migliorarla.
E’ importante trovare un buon software capace di leggere dati exif per poter confrontare le informazioni recuperate dalla classe Exif (core di questa soluzione) e quelle ricuperate da un software professionale, in fase di sviluppo la scelta e’ stata ACDSEE (http://www.acdsee.com/).
Per testare adeguatamente la classe Exif e’ opportuno recuperare un discreto numero d’immagini campione e fortunatamente il sito ufficiale exif ne ha parecchie (a tal proposito ho incluso le immagini anche nell’applicazione di esempio) disponibili qui http://www.exif.org/samples.html.
L’ultimo passo prima di iniziare lo sviluppo e’ stato quello di trovare un “reader” esadecimale per veramente contare e parsare i dati binari di ogni immagine. Sviluppando il prototipo su Mac ho trovato 0xED (http://www.suavetech.com/0xed/0xed.html), per Windows una soluzione decisamente valida e’ Hex Workshop (http://www.hexworkshop.com/).
Prima di iniziare a scrivere le classi necessarie alla lettura dei dati Exif ho voluto studiare come altri avessero risolto il problema in altri linguaggi; le due soluzioni che ho trovato più interessanti sono questa in Java http://www.java2s.com/Open-Source/Java-Document/Web-Server/Jigsaw/org.w3c.tools.jpeg.htm e questa http://mediachest.sourceforge.net/mediautil/javadocs/mediautil/image/jpeg/package-summary.html, sempre scritta in Java.
Iniziamo con alcune nozioni di base necessarie per iniziare a lavorare con questo formato.
Il formato Exif si basa sul formato JPEG. Exif permette di inserire alcune informazioni sull’immagine, sulla fotocamera digitale e la thumbnail JPEG in conformità alle specifiche JPEG. E’ per questo che l’anteprima delle immagini puo’ essere velocemente e facilmente visualizzata senza aprire l’intero file attraverso molti software (primi tra tutti il Finder Mac e l’explorer di Windows).
Ogni file JPEG inizia con il valore binario '0xFFD8' e termina con il valore binario '0xFFD9'. Esistono diversi dati 0xFFXX binari nei dati JPEG, si chiamano “Marker”, e danno inizio ad una nuova parte delle informazioni JPEG. Il valore 0xFFD' indica il cosidetto SOI (Start of image), il valore 0xFFD9 indica il cosidetto EOI (End of image/fine immagine). L’identificazion di questi due Markers speciali serve per iniziare la lettura delle informazioni, non hanno dati successivi, e’ attraverso altri markers che si identifica dove si trovano gli altri dati da leggere.
Il marker 0xFFE0~0xFFEF si chiama “Application Marker” e non è necessario per decodificare immagini JPEG. Vengono utilizzati dalle applicazioni utente. Ad esempio, le fotocamere digitali più vecchie Olympus / Canon / Casio / Agfa usano JFIF (JPEG File Interchange Format) per memorizzare le immagini. JFIF utilizza un marker APP0 (0xFFE0) per inserire i dati di configurazione e la thumbnail della fotocamera digitale.
Il formato Exif contiene una thumbnail dell’immagine (tranne Ricoh RDC-300Z) che di solito si trova vicino alla seconda image file directory (IFD1). Esistono 3 formati per le thumbnails: quello JPEG (che poi usa YCbCr), quello RGB TIFF, e quello YCbCr TIFF. Sembrerebbe che, per Exif 2.1 e successivi, il formato ideale per la thumbnail sia JPEG con una dimensione di 160x120 pixels. Secondo le specifiche DCF, l’immagine thumbnail DEVE essere in formato JPG e la dimensione dell’immagine è fissata a 160x120 pixels. Se il Tag di valore di compressione (0x0103) in IFD1 è di ‘6’, il formato della thumbnail è JPEG. Quasi sempre con Exif si usa il formato JPEG per le thumbnail, in ogni caso, si può ottenere l’offset della thumbnail dal Tag JpegIFOffset (il cui valore esadecimale e’ 0x0201) contenuto nella seconda image file directory (IFD1) e le dimensioni della thumbnail tramite il Tag JpegIFByteCount (il cui valore esadecimale e’ 0x0202). I dati sono normalmente in formato JPEG, ed iniziano con il valore esadecimale 0xFFD8 e terminano con il valore 0xFFD9.
I seguenti termini ed annotazioni vengono usati nella documentazione exif e nella maggior parte delle risorse disponibili sull’argomento, conosendoli la lettura risulta di solito più facile e veloce:
• "Tag" è sinonimo di “field”,
• “.H” annesso ad un valore numerico indica un’annotazione esadecimale,
• se non altrimenti indicato, gli altri valori numerici sono scritti in base dieci,
• Il primo IFD di un file viene nominato “0th IFD,” il successivo “1st IFD”
• “Primary Image” si riferisce ai dati relativi all’immagine principale
• “Thumbnail” indica la “miniatura” dell’immagine che serve ad indicizzare la Primary Image
• “Exif” è un’abbreviazione di “Exchangeable image file format”, utilizzato in questo caso come termine generale sia per questo standard che per le versioni precedenti.
La letteratura e le nozioni su questo formato ovviamente non si esauriscono cosi’ brevemente, ritengo che queste basi siano pero’ sufficienti per capire la maggior parte dei meccanismi e dei commenti presenti nel sorgente, passiamo quindi ad una veloce analisi del codice.
La classe principale di questo pacchetto di lettura dei dati Exif si chiama come il formato stess (Exif), contiene tutti i valori uint che rappresentano gli exif tag come costanti della classe, diversi metodi per esporre i dati all’utente finale (ovvero lo sviluppatore che lo utilizzerà in un progetto) ed alcuni metodi utilizzabile per estrapolare le informazioni cotenute nel dato binario.
![]() |
La classe estende la classe URLStream e, per utilizzarla, e’ sufficiente crearne una istanze attraverso la quale e’ possibile caricare un file espresso attraverso un valido URLRequest.
Gli eventi inviati dalla classe Exif e che possono essere gestiti all’interno di un’applicazione sono:
• PARSE_COMPLETE
• PARSE_FAILED
• PARSING_ERRORS
• DATA_READY
• THUMBNAIL_READY
Il primo evento inizia a propagarsi quando i dati sono parsati completamente, il secondo indica che è avvenuto un grave errore (ad es. un jpg invalido o dato exif invalido, ecc.), il terzo si utilizza per intercettare errori non gravi (ad es. un tag che non viene registrato correttamente), il quarto indica che i dati exif sono stati parsati completamente e l’ultimo evento conferma che la thumbnail è pronta.
I metodi pubblici, le cosidette API, possono essere utilizzati per ottenere la thumbnail, il log degli errori, tutte le IFD ricuperate dalla classe e i dati caricati per estrapolare le informazioni memorizzate nei singoli tags.
L’utilizzo della classe è abbastanza semplice ma la logica interna è un po’ più complessa, infatti il “core” consiste in due metodi:
• exploreEntries
• parseTag
Il primo legge tutti gli inserimenti (i.e. tags) memorizzati in una IFD e collabora con il metodo parseTag per leggere i dati binari (utilizza quindi i metodi di lettura dei bytes definiti sia nella classe ByteArray che nella classe URLStream) come riportato nelle specifiche exif.
La classe Naming viene utilizzata all’interno di questi metodi per gestire diverse situazioni in cui il valore restituito (ad esempio il flash, l’orientamento, ecc.) non e’ di facile comprensione per un essere umano.
Di seguito ecco i tipi di dati che si usano in Exif (si possono vedere nelle prime righe del metodo exploreEntries):
• 1 = BYTE Un numero intero da 8 bit non firmato,
• 2 = ASCII Un byte da 8 bit contenente un codice ASCII da 7 bit. L’ultimo byte termina con NULL.,
• 3 = SHORT Un numero intero da 16 bit (2 byte) non firmato,
• 4 = LONG Un numero intero da 32 bit (4 byte) non firmato,
• 5 = RATIONAL Due LONG. Il primo LONG è il numeratore e il secondo LONG esprime il denominatore,
• 7 = UNDEFINED Un byte da 8 bit che può assumere qualsiasi valore a seconda della definizione del campo,
• 9 = SLONG Un numero intero da 32 bit (4 byte) firmato (l’annotazione complementare di 2),
• 10 = SRATIONAL Due SLONG. La prima SLONG è il numeratore e la seconda è il denominatore.
La classe Naming può essere passata alla classe Exif nel suo costruttore, in questo modo si può creare facilmente la propria versione localizzata di exif reader, eseguendo l’override dei metodi che inizializzano gli arrays utilizzati per memorizzare i valori di flash, orientamento, esposizione, ecc.
![]() |
Ogni volta che un IFD viene individuato nel file, la classe exif crea una istanze della classe IFD per far sì che si possano recuperare facilmente e creare magari classi helper personalizzate per estrapolare ulteriori informazioni o per soddisfare i bisogni di una specifica applicazione. Ogni volta che un tag exif valido viene definito individuato viene creata un’istanza della classe ExfTag e attraverso questa si puo estroplare il nome e il valore della tag attraverso il metodo pubblico getTagValue al quale e’ necessario passare come argomento una delle oltre 130 costanti definite nella classe Exif.
Dopo questa breve panoramica sulla logica interna del pacchetto vediamo come utilizzare il tutto all’interno di una applicazione.
Per utilizzare la classe Exif e’ sufficiente crearne un’istanza, definire gli event listeners e caricare un file
exif = new Exif();
exif.addEventListener(Exif.PARSING_ERRORS, onParsingErrors);
exif.addEventListener(Exif.DATA_READY, onExifDataRecovered);
exif.addEventListener(Exif.THUMBNAIL_READY, onThumbnailReady);
exif.load(new URLRequest(images.selectedItem.data));
I tre metod private utilizzati come event listeners popolano un’area di testo con il messaggio “error log”, visualizzano una lista di dati disponibili e caricano la thumnail; è quindi molto semplice ottenere il seguente risultato ovvero un reader di dati exif completo in ActionScript 3.0.
![]() |
Tutte queste classi sono disponibili in nabiro, una libreria ActionScript open source che contiene moltissimi componenti creati durante il percorso del nostro lavoro e pubblicata qui http://agile.gnstudio.com/nabiro.
L’applicazione di esempio e’ invece disponibile come allegato del tutorial.
Sono graditi commenti e qualsiasi riscontro o miglioria.


