[RISOLTO]Creare Matrici di bit x Immagini B/W

E' utile a chi frequenta il forum saltuariamente, così se magari la discussione è andata in 2a o 3a pagina rischi di perdertela, così invece hai l'elenco di quelle che ti interessano sotto "Unread replies".

oooo finalmente l' ho capito! :smiley:
Grazie...
Tra poco torno sull' argomento perché sto facendo mille prove.

bhe' no, non e' il cruscotto dello scooter, ma un progetto molto molto piu' complesso, che comprende tante funzioni tra cui la visualizzazione di manometri analogici.
A fine progetto vi mostrero' il tutto finito.
Comunque perdonami ma il tuo ultimo suggerimento non sono riuscito a svilupparlo, perché fai riferimento probabilmente a funzioni del C++ (o altro linguaggio) che nell' ide di arduino (per ora conosco solo quello) non corrispondono....
Per ora sto lavorando con un array bidimenzionale ""const byte matrice[100][13]{....."" con la quale sembra che ci sto riuscendo.
Quando ho finito posto tutta la funzione cosi' mi dite se puo' essere ottimizzata.
Il difficile sara' inizializzare tutta la matrice la prima volta bit per bit per ottenere lo sfondo desiderato, ma poi ci arrivo, magari se c'e' qualche strumento da poter usare ditemelo, tipo ricavare la mappatura in bit di un' immagine di pari dimensioni, da un bitmap monocromatico o da un raster..booo
Altra domanda: ma per assegnare a tutta la matrice lo stesso valore si fa cosi? : const byte matrice[100][13]={0); ?

si si hai ragione, la logica l' avevo capita, ma poi non riuscivo a svilupparla con l' ide, soprattutto sulla creazione del mapper.
Lo so che l' ideale e' sganciarsi da arduino, ma per ora conosco bene quella e non ho tempo di studiarmi i comandi e le funzioni di altri linguaggi.
E' gia' tanto che dopo 20 anni mi sono rimesso a inciarmare nella programmazione (usavo il pascal).
Ripeto, la logica di sviluppo ce l' ho tutta, ma per ora resto ancorato ad arduino puramente per il fatto che non ho il tempo di "studiare". Ma prima o poi lo faro'!

Allora, ecco la funzione che ho creato. Gli passo le coordinate X e Y e la funzione mi dice se a quelle coordinate all' interno della matrice il pixel esiste o meno.
la matrice l' ho inizializzata (per ora vuota) cosi:
const byte matrice[100][13]={};
la funzione e' questa:

boolean matrici(byte y,byte x){  //funzione che da come risultato il valore del bit alle coordinate x,y
  boolean esiste;                      //per sapere se il pixel e' gia' esistente True
  byte val,xmat,xrest;
        xmat=x/8;                      //mi restituisce in numero del byte nella riga                
        val=matrice[y][xmat];          //mi restituisce il byte che contiene il bit richiesto
        xrest=x%xmat;                  //numero del bit da leggere nel byte
        esiste=bitRead(val,xrest);     
        return esiste;
}

Come vi sembra? e' ottimizzabile?
la velocita' di rinfresco non e' male, per ora ho provato con singolo manometro, ma poi ne vorrei mettere almeno 4.

perfetto....quindi e' come ti dicevo..la logica era quella... poi come svilupparla varia dal linguaggio (e dalle mie poche capacita'.. XD).
Quindi ho seguito la strada migliore? meglio di cosi' non posso fare? (semre riferito all' IDE).
TNX

lock:
per la matrice, ti conviene farti una matrice_init
dove ti fai un bel doppio ciclo e schiaffi dentro un po' di valori furbi
eventualmente anche 0x00 o 0xff

nel caso giocando sporco, e passando in toto il size di tutta la matrice
c'e' a corredo delle librerie base C, la funzioncina memset

da usarsi per cose bovine tipo cosi':

value= … 0x00 o 0xff o altro
memset(matrice,value,matrice_size);

(occhio che se sbagli il size, non perdona, asfalta)

Mi era sfuggito questo suggerimento . Utile per inizializzarla in qualche modo, ma nel mio caso non la posso usare, visto che la matrice a me serve come sfondo di un dispaly, quindi devo impostarla io a monte.
E qui viene il difficile.
O faccio tutto a mano la prima volta....un casino davvero..
O trovo un modo per buttare nella matrice le stesse coordinate che la libreria grafica usa per spedire i dati al display e creo la matrice (che funzionera' come controllo per lo sfondo) nello stesso momento che creo la crafica con i comandi che uso per la normale scrittura su display, ad esempio quando do un comando di tracciare un cerchio vado a prelevare le coordinate che la libreria spedisce al display e le memorizzo nella matrice....un casino ancora peggiore e per me credo impossibile da perseguire.

OPPURE adotto un altro sistema per farmi gli sfondi: ho un programma che da una immagine mi crea il bitmapper nel formato .c che posso passare direttamente all' IDE. Il problema pero' e' che lo crea a colori, quindi nel formato RGB565, ed io ho la necessita di trasformarlo in Booleano (diciamo Bianco e Nero ma in realta' e' Vero o Falso, poi assegno io i 2 valori di colore).
Non so se esiste qualche programmino in Windows che posso usare, altrimenti posso usare arduino e creo il file su SD, leggo le singole celle a colori, se c'e' il nero (0x0000) scrivo 0 sul file, se non c'e' ( qualunque altro valore) scrivo 1 sul file.
Oppure sparo i codici in seriale e dal monitor me li copio...
Ad ogni modo in queso caso mi risulterebbe piu' utile utilizzare un array unico, come da te cosigliato all' inizio, piuttosto che la matrice che ho usato io (che ho provato e funziona alla grande). Cosi' mi allineo al normale uso dei bitmapper.

Sono riuscito a ricavare in Windows da un' immagine B/W il suo corrisponde bitmapper binario, pero' riesco a ricavare tutti gli 0 e 1 attaccati.
in pratica in questo modo:
00001101010101000101111001110001010011
0010110101010101111110010101001011010101
.......
per poterlo incollare nell' ide devo assegnargli il preffisso Bx e separarli da 1 virgola ogni gruppo da 8.
come posso fare in modo semiautomatico? sto diventando matto.

Deltoz:
come posso fare in modo semiautomatico? sto diventando matto.

Forse QUESTO link ti può aiutare ???

Guglielmo

X Lock :
Si dopo svariato tentativi con programmini vari, tra cui anche Gimp, che pero' trasforma in .c o .h ma utilizzando l' RGB quindi non 1 bit per ogni pixel, sempre in Gimp salvando in .PBM riesco ad ottenere la inconversione in bit ma come ho descritto sopra.
allora ho deciso di scaricarmi il pacchetto Visual Studio Express...installato...e stavo tentando....ma non riesco, devo perderci un po di tempo per prendere dimestichezza, ma ora non riesco.
Ho trovato un sorgente in c# in rete che trasforma un' immagine BW in una sequenza di 0 e 1, come Gimp, pero' avendo il sorgente volevo modificarlo per aggiungerci appunto il prefisso "B" ( e non Bx, ho letto in una guida che e' il formattatore binario in Arduino), raggrupparli x 8 e aggiungerci la ",".....ma non ci sono riuscito, mi da errore...booo, se magari ve lo posso passare potete darci uno sguardo?

X Guglielmo:
Ottimo, e' quello che cerco, ma caricando un' immagine in BW mi restituisce tutti 0xFF...non corrisponde, non so perché.
Certo avere un programmino mio sarebbe l' ideale.

Deltoz:
X Guglielmo:
Ottimo, e' quello che cerco, ma caricando un' immagine in BW mi restituisce tutti 0xFF...non corrisponde, non so perché.
Certo avere un programmino mio sarebbe l' ideale.

Gli devi passare il tipo giusto di file : "To convert an image from bitmap file (.jpg/.png/.gif, RGB/Grayscale)"

Guglielmo

gpb01:

Deltoz:
X Guglielmo:
Ottimo, e' quello che cerco, ma caricando un' immagine in BW mi restituisce tutti 0xFF...non corrisponde, non so perché.
Certo avere un programmino mio sarebbe l' ideale.

Gli devi passare il tipo giusto di file : "To convert an image from bitmap file (.jpg/.png/.gif, RGB/Grayscale)"

Guglielmo

OK, non prendeva il BW. Comunque passandogli una immagine 99x99 mi crea un file dicendo che le misure sono 104x99 :astonished:....bhooo mo provo a caricarlo e vodo che succede...

lock:

Deltoz:
Si dopo svariato tentativi con programmini vari, tra cui anche Gimp, che pero' trasforma in .c o .h ma utilizzando l' RGB quindi non 1 bit per ogni pixel

andrebbe ritoccato il plug-in, o aggiunto un plug-in esterno
io per una vecchia versione di Photoshop mi ero fatto una cosa simile
per lo stesso scopo: avevo un monitor a tubo catodico ad 1 bit di colore

oppure ti fai andare bene quanto sputa fuori gimp
e lo ritocchi in post produzione

ovvero ti scrivi un programmino che si legge quanto sputa fuori gimp
e risputa fuori il tutto come va bene a te
ovvero incameri triplette RGB alla volta, e te le filtri

una cosa brutale tipo if ({R,G,B} > soglia) --> pixel=On, else pixel=Off

Si si.... sulla logica e' ok...ma poi non riesco a svilupparla praticamente in visual o altro...

ora dovendo lavorare con l' array no creato una nuova funzione, e alla fine sto lavorando come il normale bitmapper.

boolean immaginebin(byte y,byte x, word larga, byte dimcella){ //da come risultato in valore del bit alle coordinate date. 
                                                              //alla funzione vengono passate le coordinate xy,la largherra dell' immagine e la dimensione delle celle
  boolean esiste;                      //per sapere se il pixel e' gia' esistente True
  byte cella,miobit,rest,val;
  miobit=(y*larga)+x;                    //mi restituisce il n di bit corrispondente alle coordinate date 
  cella=miobit/dimcella;
  val=immagine2[cella];      //mi restituisce il valore della cella contenente il bit richiesto
  rest=miobit%dimcella;                //mi restituisce il numero del bit nella cella
  esiste=bitRead(val,rest);          // e' il valore booleano del bit richiesto
  return esiste;
}

Ed in effetti credo sia proprio come le indicazioni iniziali che mi davate, ma poi avevo preso la direzione dell' array 2D.
Ora pero' mi sta venendo un dubbio.
I bit dei singoli byte vengono presi in considerazione rispetto alla loro posizione (primo a sx e' il successivo del primo a dx del byte precedente) oppure del loro valore binario (il primo bit sarebbe il primo a dx)....
perché se fosse la seconda che ho detto allora quando calcolo il resto devo invertire il tutto, perché il bit 7 corrispondera' alla posizione 0 che a me serve..
spero si capisca come mi sono spiegato :smiley:

OK, trovata la soluzione a tutto.
Utilizzando il Visual C# ho modificato un programmino trovato in rete, gli passo l' immagine da convertire e ottengo direttamente l' immagine in binario come serve a me. Ecco cosa mi restituisce:

// Immagine creata automaticamente da Bitmap
// Dimensione Immagine :240 X 240
const byte immagine[]={
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000011,B11111111,B11111111,B11100000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000011,B11111100,B00000000,B00000000,B00011111,B11100000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B11111100,B00000000,B00000000,B00100000,B00000000,B00011111,B10000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
........................................
.........................................

Poi ho rielaborato la funzione che mi verifica il bit desiderato all' interno dell' immagine binaria:

boolean get_from_image_bin(byte x,byte y, word larghezza, byte dimcella){ //restituisce come risultato il valore del bit alle coordinate date 
                                                               //alla funzione vengono passate le coordinate xy,la largherra dell' immagine e la dimensione delle celle
  static boolean esiste;                                              //per sapere se il pixel e' gia' esistente True
  static word cella,miobit;
  static byte resto,val;
  miobit=(y*larghezza)+x;                                      //n di bit corrispondente alle coordinate date 
  cella=miobit/dimcella;                                       //numero progressibo del Byte, numero di cella
  val=immagine[cella];                                         //valore della cella contenente il bit richiesto
  resto=map(miobit%dimcella,0,7,7,0);                          //numero del bit nella cella
  esiste=bitRead(val,resto);                                   // e' il valore booleano del bit richiesto
  return esiste;
}

e ho creato la funzione per la visualizzazione dell' immagine completa :

void visualizzaimmagine(word x, word y, word larghezza, word altezza){  //visualizza l' immagine partendo dal punto XY sul dispay, gli vengono passate anche le misure dell' immagine
  boolean ok;
  word i,j;
  for (i=0;i<altezza;i++){                        //per tutta l' altezza dell' immagine
    for (j=0;j<larghezza;j++){                     //per tutta la larghezza dell' immagine
      ok=get_from_image_bin(j,i,larghezza,8);        //ricavo il pixel desiderato dalla funzione di ricerca
      if (ok==true){
        myGLCD.drawPixel(j+x,i+y);            //Traccio il pixel nel punto richiesto con l' offset richiesto
      }
    }
  }
}

e il gioco e' fatto. Una volta visualizzato lo sfondo posso fare qualunque controllo sulla visualizzazione di altre cose sopra lo sfondo e spostarle a mio piacimento senza perderlo.
Nel caso del manometro la lancetta si sposterà, passera' sopra lo sfondo ma non lo cancellera'....
Testato e funzionante...

lock:

Deltoz:
preffisso Bx

questo NON fa parte dell'ANSI C

Vero. Ma nel core di Arduino c'è un file binary.h in cui sono dichiarate costanti tipo B00000000, B00000001 ecc... da 0 a 255

leo72:

lock:

Deltoz:
preffisso Bx

questo NON fa parte dell'ANSI C

Vero. Ma nel core di Arduino c'è un file binary.h in cui sono dichiarate costanti tipo B00000000, B00000001 ecc... da 0 a 255

Esatto, il prefisso "B" e' il formattatore binario. E' utile nel mio caso perché se volessi variare un singolo bit dell' immagine faccio subito....

Esiste anche un altro formato, supportato dal compilatore avr-gcc, quello che usa il prefisso 0b.
0b00000001 è equivalente a B00000001

lock:

Deltoz:
Nel caso del manometro la lancetta si sposterà, passera' sopra lo sfondo ma non lo cancellera'

Soluzione adottata ?

Traccio prima lo sfondo come descritto sopra.
Ho creato una funzione che disegna la lancetta tracciando i singoli pixel, a questa funzione gli passo il "centro", la lunghezza, l' offset dal centro e i gradi dell' angolo che deve formare con l' asse X.
Poi con un semplice calcolo trigonometrico sfruttando il seno e coseno vado a tracciare tutti i punti.
Memorizzo il vecchio angolo, quando devo tracciare la nuova posizione vado prima a cancellare la vecchia, nel cancellare la vecchia faccio il confronto con i pixel dell' immagine di sfondo e cancello solo dove non c'e' lo sfondo (monocromatico con 2 colori a scelta mia e variabili). Anche nel tracciare la nuova lancetta potrei verificare se il pixel esiste gia'...devo vedere la differenza in termini di velocita.

Ad ogni modo tutto questo sbattimento lo si potrebbe evitare sfruttando la possibilita' di alcuni display di interrogarli per sapere il colore di un dato pixel, utilizzando l' RD... ma ormai il mio progetto e' bello che assemblato e per ora non ho percorso questa strada, ma per il prossimo lo usero' di certo, ampliando le possibilita' di utilizzo.
Sembra anche abbastanza veloce, devo ottimizzare alcune cosette e sono a posto.

Piccolo quesito.
Ma se carico l' array in memoria flash con il comando: byte immagine[] PROGMEM={.......}; poi devo usare comandi diversi per leggerle i byte all' interno? non posso piu' usare il comando " val=immagine[cella]; " ???
devo usare "val=pgm_read_byte_near(immagine + cella)" ?? per forza?

After getting the data into Flash memory, it requires special methods (functions), also defined in the pgmspace.h library, to read the data from program memory back into SRAM, so we can do something useful with it.

esatto, il calcolo trigonometrico usato e' proprio quello.
per quanto riguarda la bitmap sto combattendo un attimo per l' uso del PROGMEM, e ricombinare il tutto visto che lo avevo prima sviluppato per le matrici normali, poi con l' array di byte.....

A questo punto se la bitmap in Flash la lavoro a 16bit , ovviamente riadattando i calcoli che ho fatto nella funzione, dovrebbe lavorare piu' velocemente giusto?

Domani posto il sorgente c#.