Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Sono molte le cose che non hai considerato.
1) il file che hai allegato ha una palette a 16 colori standard HalfTone:
0=nero, 1=blu,...7=bianco,... 10=rossoscuro, ecc ecc
2) se crei una tua palette con scala di grigio, quello che prima era bianco diventa grigio di livello 7
3) quando blocchi i bit, poi devi mettere i bytes della bitmap nel vettore, altrimenti il vettore conterrà solo zeri
4) il vettore lo devi scorrere tutto, non solo la prima riga
5) quando vai a caccia del colore da variare devi considerare che a 4bpp nel byte ci sono due pixel:
se il livello che cerchi è il 7 (bianco nella tua tiff) in Hex due pixel &H77=119
6) quando hai trovato il livello che vuoi variare, se vuoi mettere un grigio di livello 10, devi inserire &HAA=170
Ora non so se la palette nel tiff ti va bene, o se la devi uniformare ai tuoi livelli di grigio....
Ho correttto il tuo programma che ora sostituisce il 7 (bianco vecchia palette) con il 15 (bianco nuova palette) e mette un 10 dove non c'era il bianco (7)
Spero di non averti confuso le idee, ma purtroppo quando si lavora su bytes che rappresentano immagini, bisogna impegnarsi un po'
Codice sorgente - presumibilmente VB.NET
Dim originale AsNew Bitmap("C:\greca.tiff")
Dim clonerettangolo AsNew Rectangle(0, 0, originale.Width, originale.Height)
Dim clone4bpp As Bitmap = originale.Clone(clonerettangolo, Imaging.PixelFormat.Format4bppIndexed)
La risoluzione orizzontale usando questo metodo è di due pixel, nel senso che il pixel 0 e 1, saranno sempre dello stesso livello, lo stesso per il pixel 2 e 3, 4 e 5, e così via.
Per ovviare, bisogna ogni volta che si legge un byte, spezzarlo in due semibyte, modificare il semibyte voluto e risalvare la coppia modificata...
Ultima modifica effettuata da Carlo il 17/07/2021 alle 20:46
No , non mi hai fatto confusione , anzi ....
Per quanto riguarda il punto 4 , quella è stata una dimenticanza....
Quello che non ho capito è "System.Runtime.InteropServices.Marshal.Copy(ptr, colorValues, 0, bytes)" bisogna che me lo studio.
Anche il colore del pixel , ma quello inizio a capirlo ( spero )
Ovviamente adesso inizierò ad adattare la tua correzione alle mie necessità e poi staremo a vedere se ho capito .
Per il momento grazie .
Se volessi alzare l'asticella , continuo a postare qui o devo aprire un altro post?
Grazie
Marshal.Copy , in base a come vengono disposti i parametri copia i dati della memoria in un vettore oppure li copia dal vettore alla memoria.
Quindi la prima chiamata , copia dalla memoria a partire dal prt ,nel vettore dove effettuare la copia , inizio,lunghezza dei dati da copiare
Nella seconda chiamata, copia i dati dal vettore iniziando da 0, nella memoria iniziando da prt , per la lunghezza dei dati .
Inizio a capire , bisogna vedere se sarò in grado di utilizzarlo al meglio ....
Nel caso che volessi provare a farlo "Ora non so se la palette nel tiff ti va bene, o se la devi uniformare ai tuoi livelli di grigio...."
considerando che potrei non sapere che file mi arriva , io pensavo ( probabilmente sbagliando) che clonarlo a 4bpp a prescindere da come mi arriva il file , mi doveva uniformare , ma così non è . Ho fato prove con 3 differenti tipi di file ,bitmap, greyscale 4bpp e greyscale 8bpp. il bitmap funziona , il greyscale 8bpp funziona ( e io mi aspettavo di no ) mentre il greyscale 4 bpp mi riempie completamente il bmp. Questo non lo capisco, in teoria doveva funzionare , essendo a 4bpp.
Non capisco.
Marshal.Copy , in base a come vengono disposti i parametri copia i dati della memoria in un vettore oppure li copia dal vettore alla memoria.
Quindi la prima chiamata , copia dalla memoria a partire dal prt ,nel vettore dove effettuare la copia , inizio,lunghezza dei dati da copiare
Nella seconda chiamata, copia i dati dal vettore iniziando da 0, nella memoria iniziando da prt , per la lunghezza dei dati .
Inizio a capire , bisogna vedere se sarò in grado di utilizzarlo al meglio ....
Forse ti ha portato fuori strada che negli esempi precedenti il primo Marshal.Copy non c'era.
Ma non serviva perché l'immagine veniva creata ex novo, si partiva con una bitmap vuota e un vettore con tutti zeri.
Invece nell'ultimo esempio parti da un'immagine caricata da HDD, quando dichiari il vettore è vuoto, ci devi mettere i dati della bitmap caricata se vuoi modificare leggendo i valori.
Marshal.Copy, permette di scrivere o leggere byte o blocchi di bytes in memoria e copiarli in vettori o in altre zone di memoria, ma tutto rigorosamente managed (gestito), non puoi fare danni.
Testo quotato
Postato originariamente da bernie: Nel caso che volessi provare a farlo "Ora non so se la palette nel tiff ti va bene, o se la devi uniformare ai tuoi livelli di grigio...."
considerando che potrei non sapere che file mi arriva , io pensavo ( probabilmente sbagliando) che clonarlo a 4bpp a prescindere da come mi arriva il file , mi doveva uniformare , ma così non è . Ho fato prove con 3 differenti tipi di file ,bitmap, greyscale 4bpp e greyscale 8bpp. il bitmap funziona , il greyscale 8bpp funziona ( e io mi aspettavo di no ) mentre il greyscale 4 bpp mi riempie completamente il bmp. Questo non lo capisco, in teoria doveva funzionare , essendo a 4bpp.
Non capisco.
Non capisco cosa ti sfugge, ma mi sembra di capire che non hai chiara la funzione della palette Le immagini indicizzate, hanno un numero ridotto di colori, ma i colori visualizzabili sono scelti comunque da una collezione di 16.777.216 colori.
prendiamo un'immagine 4bpp, per un pixel si possono definire valori 0...15, ma questi valori non si sa che colore rappresentano, finquando non vai a leggere la palette che contiene i valori RGB associati ai valori 0...15.
Ho scritto due righe che ti fanno aprire files BMP, TIF, TIFF, leggono la palette e la usa per disegnare dei quadratini colorati, il risultato viene mostrato su una picturebox. Con questo programma (progetto VS allegato) puoi scoprire la palette dei file che ti vengono inviati.
Una volta che conosci la palette sei in grado di sapere che valore RGB ha un colore, per esempio il bianco (255,255,255), che nella palette HalfTone è assegnato al 7.
In base alle tue esigenze, devi decidere quanto automatizzare l'interpretazione della palette, tutto è fattibile.
Domande:
Sai come sono memorizzati i dati in ram e cosa sono i bit?
Sai quanti bit ci sono in un byte?
Sai cos'è una word, dword, qword?
Sai cos'è il sistema numerico binario?
Sai cos'è il sistema numerico esadecimale?
Sai come sono codificati i colori RGB e ARGB?
Se a una qualsiasi di queste domande rispondi, no, prima di proseguire devi studiarle, sono concetti molto semplici e è sufficiente una conoscenza di base per proseguire, puoi anche chiedere qui, ti risponderò con piacere.
Per quanto riguarda cambiare post, per ora mi sembra che siamo in tema, anzi se guardi il mio primo esempio della mia prima risposta, vedrai che ci siamo mossi di poco o niente...
Grazie Carlo Alle domande direi che rispondo sì. Al momento la situazione è questa, il mio sistema accetta bitmap a 1 bpp, a 8 bpp e a 4 bpp. Lui però usa una "palette" da 3bpp. Quando gli arrivano 8bpp li converte lui, quando gli arriva 1bpp, lo prende così. A questo punto anche se lo accetta non so bene come si comporta con 4bpp. Per me è più comodo lavorare a 4bpp, in quanto il bmp rimane più piccolo. Devo capire cosa succede se gli mando un bmp a 4bpp, lo rimappa come fosse un 8bpp o lo tiene così ? Questo è il dubbio adesso.
Postato originariamente da bernie: Al momento la situazione è questa, il mio sistema accetta bitmap a 1 bpp, a 8 bpp e a 4 bpp. Lui però usa una "palette" da 3bpp. Quando gli arrivano 8bpp li converte lui, quando gli arriva 1bpp, lo prende così. A questo punto anche se lo accetta non so bene come si comporta con 4bpp. Per me è più comodo lavorare a 4bpp, in quanto il bmp rimane più piccolo. Devo capire cosa succede se gli mando un bmp a 4bpp, lo rimappa come fosse un 8bpp o lo tiene così ? Questo è il dubbio adesso.
Ribene, mentre ti togli il dubbio, ti propongo un aggiornamento al codice che divide il byte in semibyte e modifica i pixel contenuti singolarmente. Ho scelto il metodo matematico, ma la stessa cosa si può fare mascherando i bit oppure facendo scorrere i bit>>4 a destra per ricavare il semibyte a sinistra, facendo scorrere i bit<<4 a sinistra poi bit>>4 a destra per ricavare il semibyte a destra, è più veloce, se ti interessa prova o chiedi..
Codice sorgente - presumibilmente VB.NET
'---------------------- carica e cambia palette, sostituisce colori 4bpp -----------------
Dim clone4bpp AsNew Bitmap("C:\greca.tiff")
'Dim clonerettangolo As New Rectangle(0, 0, originale.Width, originale.Height)
'Dim clone4bpp As Bitmap = originale.Clone(clonerettangolo, Imaging.PixelFormat.Format4bppIndexed)
'creo la palette scala di grigio
Dim palette As Imaging.ColorPalette= clone4bpp.Palette
For i = 0 To palette.Entries.Length- 1
palette.Entries(i)= Color.FromArgb(i * 17, i * 17, i * 17)
Next i
'associo la palette creata alla bitmap 4bpp,
'i valori 0...15 ora corrispondono alla scala dal nero al bianco
clone4bpp.Palette= palette
' blocco i bit della bitmap per poter lavorare direttamente su un vettore di bytes
Dim area As Rectangle =New Rectangle(0, 0, clone4bpp.Width, clone4bpp.Height)
Dim bmpData As Imaging.BitmapData= clone4bpp.LockBits(area, Imaging.ImageLockMode.ReadWrite, clone4bpp.PixelFormat)
' puntatore all'indirizzo di memoria del primo byte.
Dim ptr As IntPtr = bmpData.Scan0
' un vettore che conterrà tutti i bytes della bitmap.
Dim bytes AsLong= Math.Abs(bmpData.Stride)* clone4bpp.Height' calcolo dei bytes necessari
Dim colorValues(bytes - 1)AsByte
' nel vettore metto i dati che rappresentano clone4bpp
Per saggiare la precisione, nel tuo file: greca.tiff, ci sono dei pixel grigi con valore=9
Il codice seguente sostituisce il valore 9 (grigio) con il valore 4 (rosso), senza cambiare la palette.
Codice sorgente - presumibilmente VB.NET
'---------------------- carica senza cambiare palette, sostituisce 1 colore 4bpp -----------------
Dim clone4bpp AsNew Bitmap("C:\greca.tiff")
'Dim clonerettangolo As New Rectangle(0, 0, originale.Width, originale.Height)
'Dim clone4bpp As Bitmap = originale.Clone(clonerettangolo, Imaging.PixelFormat.Format4bppIndexed)
''creo la palette scala di grigio
'Dim palette As Imaging.ColorPalette = clone4bpp.Palette
'For i = 0 To palette.Entries.Length - 1
' palette.Entries(i) = Color.FromArgb(i * 17, i * 17, i * 17)
'Next i
''associo la palette creata alla bitmap 4bpp,
''i valori 0...15 ora corrispondono alla scala dal nero al bianco
'clone4bpp.Palette = palette
' blocco i bit della bitmap per poter lavorare direttamente su un vettore di bytes
Dim area As Rectangle =New Rectangle(0, 0, clone4bpp.Width, clone4bpp.Height)
Dim bmpData As Imaging.BitmapData= clone4bpp.LockBits(area, Imaging.ImageLockMode.ReadWrite, clone4bpp.PixelFormat)
' puntatore all'indirizzo di memoria del primo byte.
Dim ptr As IntPtr = bmpData.Scan0
' un vettore che conterrà tutti i bytes della bitmap.
Dim bytes AsLong= Math.Abs(bmpData.Stride)* clone4bpp.Height' calcolo dei bytes necessari
Dim colorValues(bytes - 1)AsByte
' nel vettore metto i dati che rappresentano clone4bpp
Grazie Carlo Purtroppo non avrò accesso al mio PC fino a fine settimana. Sembra che il sistema riconosca i bmp a 4 bit e non li rimappa come fa con quelli a 8 bpp. A questo punto non mi resta che eliminare il quarto bit in maniera da avere una palette da 8 livelli.
Mi sono reso conto adesso di essere stato un po' criptico, vedo di spiegarmi meglio. Quando genero il bmp, lo genero direttamente a 4bpp e assegno il valore che voglio, questo è ok . Quando invece devo usare un bmp 1bpp lo devo convertire a 4bpp e assegnare il valore che voglio. Con i bmp 8bpp devo rimappare la palette originale su una a 8 livelli ( alcune volte a 5 livelli) . Quindi a memoria, direi che tutte queste cose le avevamo viste . A questo punto penso che rimango un altro punto da chiarire e poi dovrei essere quasi in dirittura d'arrivo. Stavo pensando, visto l'ingente numero di esempi volevo trovare il modo di salvare la discussione per future necessità.