Go Down

Topic: [RISOLTO]Creare Matrici di bit x Immagini B/W (Read 15211 times) previous topic - next topic

Deltoz


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.

Deltoz

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.

gpb01


come posso fare in modo semiautomatico? sto diventando matto.


Forse QUESTO link ti può aiutare ???

Guglielmo
Search is Your friend ... or I am Your enemy !

Deltoz

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. 

gpb01


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
Search is Your friend ... or I am Your enemy !

Deltoz

#20
Mar 10, 2014, 05:15 pm Last Edit: Mar 11, 2014, 01:41 am by Deltoz Reason: 1


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  :smiley-eek:....bhooo mo provo a caricarlo e vodo che succede...


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...

Deltoz

ora dovendo lavorare con l' array no creato una nuova funzione, e alla fine sto lavorando come il normale bitmapper.
Code: [Select]
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 :D

Deltoz

#22
Mar 11, 2014, 01:37 am Last Edit: Mar 11, 2014, 01:40 am by Deltoz Reason: 1
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:
Code: [Select]
// 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:
Code: [Select]
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 :
Code: [Select]
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...

leo72



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

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....

leo72

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

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.

Deltoz

#27
Mar 11, 2014, 06:26 pm Last Edit: Mar 11, 2014, 06:44 pm by Deltoz Reason: 1
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?
Quote
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.

Deltoz

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#.

Deltoz

l'ho spiegato prima, io la lancetta la traccio pixel per pixel con il calcolo trigonometrico (generatore punti-linea). Avendo le coordinate di ogni punto, lo confronto con il suo corrispondente nel mapper (chiaramente con cero offset). La dimensione del mapper e' uguale all' area del  quadrato che contiene la circonferenza del manometro.
Fammi sistemare il codice e lo posto.

Go Up