Individuare i colori dei pixel di una immagine
Indice
- 1 Individuare i valori RGBA dei pixel di una immagine mediante le risorse native di Gambas
- 1.1 con la proprietà .Pixels della Classe Image
- 1.2 con la proprietà .Data della Classe Image e le funzioni di dereferenziazione
- 1.3 con la proprietà .Data della Classe Image ed i Memory Stream
- 1.4 puntando all'area di memoria della variabile di tipo Image
- 1.5 individuando il colore di ciascun pixel mediante le sue coordinate x ed y
- 2 Individuare i valori RGBA dei pixel di una immagine mediante le risorse del API di SDL2
- 3 Note
Individuare i valori RGBA dei pixel di una immagine mediante le risorse native di Gambas
Per individuare i colori dei pixel di una immagine mediante le sole risorse native di Gambas, sono possibili almeno quattro modalità.
Si raccomanda la lettura - per le informazioni generali sulla gestione dei pixel in Gambas - della seguente pagina della documentazione ufficiale: Image Management In Gambas.
con la proprietà .Pixels della Classe Image
La proprietà .Pixels della Classe Image ritorna un vettore di tipo Integer[ ] contenente in ciascun elemento il valore (dunque a 32 bit) del colore di un pixel dell'immagine.
Esempio:
Public Sub Form_Open() Dim im As Image Dim i As Integer im = Image.Load("/percorso/del/file/immagine") For Each i In im.Pixels Print Hex(i, 8) Next End
con la proprietà .Data della Classe Image e le funzioni di dereferenziazione
La proprietà .Data della Classe Image ritorna un Puntatore all'area di memoria dell'Oggetto "Image", contenente ii dati della variabile di tipo Image. E' dunque coì possibile per mezzo delle funzioni di dereferenziazione, native di Gambas, leggere all'interno dell'area puntata dal predetto Puntatore.
Nell'esempio che segue abbiamo una semplice immagine formata da 2 x 2 pixel dei seguenti colori: blu, giallo, rosso e verde. Saranno mostrati i valori in rappresentazione esadecimale dei quattro pixel.
Public Sub Button1_Click() Dim im As Image Dim i As Integer im = Image.Load("/percorso/del/file/immagine") For i = 0 To (im.W * im.H * 4) - 1 Step 4 Print Hex(Int@(im.Data + i), 8) Next End
con la proprietà .Data della Classe Image ed i Memory Stream
Questo esempio è simile al precedente, ma si userà la risorsa dei Memory Stream per leggere all'interno dell'area puntata dal predetto Puntatore. Sarà possibile altresì scrivervi modificando quindi il colore di uno o di più pixel dell'immagine.
Nell'esempio che segue abbiamo una semplice immagine formata da 2 x 2 pixel dei seguenti colori: blu, giallo, rosso e verde. Si procederà con il vedere quei quattro pixel e cambiando, poi, il colore del pixel rosso nel colore blu:
Public Sub Form_Open() With PictureBox1 .X = 50 .Y = 50 .W = 40 .H = 40 .Stretch = True End With End Public Sub Button1_Click() Dim im As Image Dim st As Stream Dim fo, b As Byte Dim j As Integer Dim s As String im = Image.Load("/percorso/del/file/immagine") fo = Len(im.Format) ' Viene dereferenziato il "Puntatore", mostrando così tutti i valori dei colori dei pixel della variabile immagine: st = Memory im.Data For Read Write For j = 0 To (im.H * im.W * fo) - 1 ' La dimensione in byte effettiva di un'immagine si ottiene moltiplicando i pixel per la quantità di byte che compongono un singolo pixel (formato dei pixel) Read #st, b If j Mod 4 = 0 Then Print "------------------" Print j;; b;; Hex(b, 2) Next Print "------------------" ' Viene modificato il colore del pixel che occupa 4 byte a partire dal 9° byte: Seek #st, 8 ' Viene impostato il colore blu (se il formato è diverso dal "BGR", allora il primo byte è relativo al valore "alfa" !): s = Right("FF0000FF", fo * 2) Write #st, Val("&" & s) As Integer ' Vengono nuovamente letti i valori dei colori dopo la modifica del terzo pixel: Seek #st, 0 For j = 0 To (im.H * im.W * fo) - 1 Read #st, b If j Mod 4 = 0 Then Print "------------------" Print j;; b;; Hex(b, 2) Next st.Close ' Mostra l'immagine come modificata: PictureBox1.Picture = im.Picture End
puntando all'area di memoria della variabile di tipo Image
Nel paragrafo precedente abbiamo visto come Gambas mediante la proprietà .Data della Classe Image consenta di puntare alla sub-area di memoria di una variabile di tipo Image, e di leggere i valori corrispondenti ai colori dei pixel dell'immagine.
L'accesso a tale sub-area di memoria dell'area principale di memoria di una variabile di tipo Image può essere effettuato anche direttamente mediante i Puntatori e la dereferenzianzione dei medesimi.
Sappiamo, come già detto, che i valori dei colori dei pixel di una variabile di tipo Image sono contenuti in una specifica area di memoria riservata, il cui indirizzo è indicato al 16° byte dell'area di memoria principale della predetta variabile di tipo Image.
Mostriamo un esempio pratico, nel quale è possibile vedere gli otto byte - iniziando da 16° - che rappresentano il valore dell'indirizzo dell'area di memoria contenente i valori dei pixel della variabile di tipo Image appositamente creata:
Public Sub Form_Open() Dim im As Image Dim p As Pointer Dim st As Stream Dim j, b As Byte im = New Image(2,2, Color.Red) p = Object.Address(im) st = Memory p For Read For j = 0 To 23 Read #st, b Print j;; Hex(b) Next st.Close End
Individuato l'indirizzo dell'area di memoria riservata contenente i valori dei pixel della variabile di tipo Image, affinché possano essere letti i valori dei colori dei pixel dell'immagine, tale indirizzo dovrà essere dereferenziato come Puntatore ad un Intero.
Mostriamo un esempio, nel quale sarà creata una semplice immagine di 2x2 pixel di colore rosso. Si provvederà mediante la procedura descritta a mostrare i dati grezzi dell'immagine, ossia i valori dei colori dei pixel.
Public Sub Form_Open() Dim im As Image Dim p1, p2 As Pointer Dim st As Stream Dim j As Byte ' Creiamo ed istanziamo la variabile di tipo "Image": im = New Image(2,2, Color.Red) ' Otteniamo innanzitutto un Puntatore all'area di memoria dell'immagine appena creata": p1 = Object.Address(im) ' Accediamo all'altra area di memoria, quella contenente i valori dei colori dei pixel dell'immagine, ' dereferenziando il suo Puntatore presente a cominciare dal 16° byte dell'area di memoria principale: p2 = Pointer@(p1 + 16) ' Viene dereferenziato il Puntatore all'area di memoria contenente i valori dei colori dei pixel dell'immagine: For j = 0 To 3 Print j;; Hex(Int@(p2)) ' Si saltano 4 byte, poiché il colore di ogni pixel è individuato da 32bit: p2 = p2 + 4 Next End
individuando il colore di ciascun pixel mediante le sue coordinate x ed y
Questa modalità prevede l'individuazione del colore di ciascun pixel dell'immagine identificandolo attraverso le sue coordinate x ed y con la sintassi:
Image[x, y]
Esempio:
Public Sub Form_Open() Dim x, y As Byte Dim im As Image im = Image.Load("/percorso/del/file/immagine") For x = 0 To im.W - 1 For y = 0 To im.h - 1 Print Hex$(im[x, y], 6) Next Next ' Volendo usare un solo ciclo, potremo anche fare così, impostando in un vettore le coordinate dei pixel dell'immagine: ' Dim vett As Byte[] = [0, 0, 1, 1, 0, 1, 0, 1] ' Dim j As Byte ' Dim im As Image ' ' im = Image.Load("/percorso/del/file/immagine") ' ' For j = 0 To im.W * im.H - 1 ' Print Hex$(im[vett[j], vett[j + 4]], 6) ' Next End
Per analogia con questa modalità segnaliamo anche la seguente pagina della WIKI.
Individuare i valori RGBA dei pixel di una immagine mediante le risorse del API di SDL2
Con alcune risorse del API di SDL2 è possibile conoscere i valori RGBA dei pixel di una immagine.
Per poter fruire in Gambas delle risorse di SDL, è necessario installare e richiamare le seguenti librerie dinamiche condivise:
- "libSDL2-2.0.so.0.2.0"
- "libSDL2_image-2.0.o.0.0.0"
Mostriamo un semplice esempio pratico:
Library "libSDL2-2.0:0.2.0" Public Struct SDL_Rect x As Integer y As Integer w As Integer h As Integer End Struct Public Struct SDL_Surface flags As Integer format As Pointer w As Integer h As Integer pitch As Integer pixels As Pointer userdata As Pointer locked As Integer lock_data As Pointer clip_rect As Struct SDL_Rect map As Pointer refcount As Integer End Struct Public Struct SDL_PixelFormat format As Integer palette As Pointer BitsPerPixel As Byte BytesPerPixel As Byte Rmask As Integer Gmask As Integer BMask As Integer AMask As Integer Rloss As Byte Gloss As Byte Bloss As Byte Aloss As Byte Rshift As Byte Gshift As Byte Bshift As Byte Ashift As Byte refcount As Integer next_ As Pointer End Struct Private Const SDL_INIT_VIDEO As Integer = &20 ' int SDL_Init(Uint32 flags) ' Initialize the SDL library. Private Extern SDL_Init(flags As Integer) As Integer ' void SDL_Quit(void) ' Clean up all initialized subsystems. Private Extern SDL_Quit() Library "libSDL2_image-2.0:0" ' SDL_Surface * IMG_Load(const char *file) ' Load an image from an SDL data source. Private Extern IMG_Load(_file As String) As SDL_Surface Public Sub Main() Dim immagine As String Dim imago As SDL_Surface Dim pxfmt As SDL_PixelFormat Dim dati As Pointer Dim i As Integer Dim r, g, b, a As Byte immagine = "/percorso/del/file/immagine" SDL_Init(SDL_INIT_VIDEO) ' Carica un'immagine: imago = IMG_Load(immagine) If IsNull(imago) Then Error.Raise("Impossibile caricare un'immagine !") ' Assegna il membro di tipo Puntatore della Struttura "SDL_Surface" alla variabile di tipo della Struttura "SDL_PixelFormat", ' affinché possa essere utilizzato comodamente il membro ".BytesPerPixel" della predetta Struttura "SDL_PixelFormat": pxfmt = imago.format Print "Formato immagine: "; pxfmt.BitsPerPixel; " bit per pixel" dati = imago.pixels For i = 0 To (imago.w * imago.h * 4) - 1 Step 4 r = Byte@(dati + i) g = Byte@(dati + i + 1) b = Byte@(dati + i + 2) a = Byte@(dati + i + 3) Print "r: "; Hex(r, 2), i; "\ng: "; Hex(g, 2); "\nb: "; Hex(b, 2); "\na: "; Hex(a, 2) Print "\n" Sleep 0.3 Next ' Libera la libreria "SDL2" e va in chiusura: SDL_Quit() End
Note
[1] Per analogia di argomento si segnala anche la pagina: Individuare il colore di un determinato pixel.