Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - File bmp
Forum - C# / VB.NET - File bmp - Pagina 4

Pagine: [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ] Precedente | Prossimo
Avatar
Carlo (Member)
Guru


Messaggi: 1087
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 18:48
Sabato, 17/07/2021
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

  1. Dim originale As New Bitmap("C:\greca.tiff")
  2.         Dim clonerettangolo As New Rectangle(0, 0, originale.Width, originale.Height)
  3.         Dim clone4bpp As Bitmap = originale.Clone(clonerettangolo, Imaging.PixelFormat.Format4bppIndexed)
  4.  
  5.         clone4bpp.Save("C:\1clonegreca4bpp.bmp", Imaging.ImageFormat.Bmp)
  6.         clone4bpp.Save("C:\1clonegreca4bpp.tiff", Imaging.ImageFormat.Tiff)
  7.  
  8.         'creo la palette scala di grigio
  9.         Dim palette As Imaging.ColorPalette = clone4bpp.Palette
  10.         For i = 0 To palette.Entries.Length - 1
  11.             palette.Entries(i) = Color.FromArgb(i * 17, i * 17, i * 17)
  12.         Next i
  13.  
  14.         'associo la palette creata alla bitmap 4bpp,
  15.         'i valori 0...15 ora corrispondono alla scala dal nero al bianco
  16.         clone4bpp.Palette = palette
  17.  
  18.         ' blocco i bit della bitmap per poter lavorare direttamente su un vettore di bytes
  19.         Dim area As Rectangle = New Rectangle(0, 0, clone4bpp.Width, clone4bpp.Height)
  20.         Dim bmpData As Imaging.BitmapData = clone4bpp.LockBits(area, Imaging.ImageLockMode.ReadWrite, clone4bpp.PixelFormat)
  21.  
  22.         ' puntatore all'indirizzo di memoria del primo byte.
  23.         Dim ptr As IntPtr = bmpData.Scan0
  24.  
  25.         ' un vettore che conterrà tutti i bytes della bitmap.
  26.         Dim bytes As Long = Math.Abs(bmpData.Stride) * clone4bpp.Height ' calcolo dei bytes necessari
  27.         Dim colorValues(bytes - 1) As Byte
  28.         ' nel vettore colorValues metto i dati dalla locazione ptr che rappresentano clone4bpp
  29.         System.Runtime.InteropServices.Marshal.Copy(ptr, colorValues, 0, bytes)
  30.  
  31.         'se è ex bianco(7) lo trasformo in bianco(15) altrimenti grigio(10)
  32.         For ind = 0 To bytes - 1
  33.             If colorValues(ind) = 119 Then ' &H77
  34.                 colorValues(ind) = 255 ' &HFF
  35.             Else
  36.                 colorValues(ind) = 170 ' &HAA
  37.             End If
  38.         Next
  39.         System.Runtime.InteropServices.Marshal.Copy(colorValues, 0, ptr, bytes)
  40.         clone4bpp.UnlockBits(bmpData) ' sblocco bit
  41.         clone4bpp.SetResolution(360, 360)
  42.         clone4bpp.Save("C:\clonegreca4bpp.bmp", Imaging.ImageFormat.Bmp)
  43.         clone4bpp.Save("C:\clonegreca4bpp.tiff", Imaging.ImageFormat.Tiff)
  44.         clone4bpp.Dispose()



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


in programmazione tutto è permesso
PM Quote
Avatar
bernie (Normal User)
Pro


Messaggi: 149
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 9:42
Domenica, 18/07/2021
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


PM Quote
Avatar
bernie (Normal User)
Pro


Messaggi: 149
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 10:53
Domenica, 18/07/2021
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.




PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 1087
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 1:20
Lunedì, 19/07/2021
Testo quotato

Postato originariamente da bernie:

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


Carlo ha allegato un file: Palette.zip (988840 bytes)
Clicca qui per scaricare il file

Ultima modifica effettuata da Carlo il 19/07/2021 alle 13:16


in programmazione tutto è permesso
PM Quote
Avatar
bernie (Normal User)
Pro


Messaggi: 149
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 22:42
Lunedì, 19/07/2021
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.

PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 1087
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 15:09
Martedì, 20/07/2021
Testo quotato

Postato originariamente da bernie:

Grazie Carlo
Alle domande direi che rispondo sì.


Bene.
Testo quotato

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

  1. '---------------------- carica e cambia palette, sostituisce colori 4bpp -----------------
  2.         Dim clone4bpp As New Bitmap("C:\greca.tiff")
  3.         'Dim clonerettangolo As New Rectangle(0, 0, originale.Width, originale.Height)
  4.         'Dim clone4bpp As Bitmap = originale.Clone(clonerettangolo, Imaging.PixelFormat.Format4bppIndexed)
  5.  
  6.         'creo la palette scala di grigio
  7.         Dim palette As Imaging.ColorPalette = clone4bpp.Palette
  8.         For i = 0 To palette.Entries.Length - 1
  9.             palette.Entries(i) = Color.FromArgb(i * 17, i * 17, i * 17)
  10.         Next i
  11.  
  12.         'associo la palette creata alla bitmap 4bpp,
  13.         'i valori 0...15 ora corrispondono alla scala dal nero al bianco
  14.         clone4bpp.Palette = palette
  15.  
  16.         ' blocco i bit della bitmap per poter lavorare direttamente su un vettore di bytes
  17.         Dim area As Rectangle = New Rectangle(0, 0, clone4bpp.Width, clone4bpp.Height)
  18.         Dim bmpData As Imaging.BitmapData = clone4bpp.LockBits(area, Imaging.ImageLockMode.ReadWrite, clone4bpp.PixelFormat)
  19.  
  20.         ' puntatore all'indirizzo di memoria del primo byte.
  21.         Dim ptr As IntPtr = bmpData.Scan0
  22.  
  23.         ' un vettore che conterrà tutti i bytes della bitmap.
  24.         Dim bytes As Long = Math.Abs(bmpData.Stride) * clone4bpp.Height ' calcolo dei bytes necessari
  25.         Dim colorValues(bytes - 1) As Byte
  26.         ' nel vettore metto i dati che rappresentano clone4bpp
  27.         System.Runtime.InteropServices.Marshal.Copy(ptr, colorValues, 0, bytes)
  28.  
  29.         'se è ex bianco(7) lo trasformo in bianco(15) altrimenti grigio(10)
  30.         For ind = 0 To bytes - 1
  31.             ' scompongo il byte con i due pixel
  32.             Dim primosemibyte As Byte = colorValues(ind) \ 16
  33.             Dim secondosemibyte As Byte = colorValues(ind) - primosemibyte * 16
  34.             If primosemibyte = 7 Then ' pixel a sinistra
  35.                 primosemibyte = 15
  36.             Else
  37.                 primosemibyte = 10
  38.             End If
  39.             If secondosemibyte = 7 Then ' pixel a destra
  40.                 secondosemibyte = 15
  41.             Else
  42.                 secondosemibyte = 10
  43.             End If
  44.             colorValues(ind) = primosemibyte * 16 + secondosemibyte ' ricompongo il byte con i due pixel
  45.         Next
  46.         System.Runtime.InteropServices.Marshal.Copy(colorValues, 0, ptr, bytes)
  47.         clone4bpp.UnlockBits(bmpData) ' sblocco bit
  48.         clone4bpp.SetResolution(360, 360)
  49.         clone4bpp.Save("C:\clonegreca4bpp.bmp", Imaging.ImageFormat.Bmp)
  50.         clone4bpp.Save("C:\clonegreca4bpp.tiff", Imaging.ImageFormat.Tiff)
  51.         clone4bpp.Dispose()



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

  1. '---------------------- carica senza cambiare palette, sostituisce 1 colore 4bpp -----------------
  2.         Dim clone4bpp As New Bitmap("C:\greca.tiff")
  3.         'Dim clonerettangolo As New Rectangle(0, 0, originale.Width, originale.Height)
  4.         'Dim clone4bpp As Bitmap = originale.Clone(clonerettangolo, Imaging.PixelFormat.Format4bppIndexed)
  5.  
  6.         ''creo la palette scala di grigio
  7.         'Dim palette As Imaging.ColorPalette = clone4bpp.Palette
  8.         'For i = 0 To palette.Entries.Length - 1
  9.         '    palette.Entries(i) = Color.FromArgb(i * 17, i * 17, i * 17)
  10.         'Next i
  11.  
  12.         ''associo la palette creata alla bitmap 4bpp,
  13.         ''i valori 0...15 ora corrispondono alla scala dal nero al bianco
  14.         'clone4bpp.Palette = palette
  15.  
  16.         ' blocco i bit della bitmap per poter lavorare direttamente su un vettore di bytes
  17.         Dim area As Rectangle = New Rectangle(0, 0, clone4bpp.Width, clone4bpp.Height)
  18.         Dim bmpData As Imaging.BitmapData = clone4bpp.LockBits(area, Imaging.ImageLockMode.ReadWrite, clone4bpp.PixelFormat)
  19.  
  20.         ' puntatore all'indirizzo di memoria del primo byte.
  21.         Dim ptr As IntPtr = bmpData.Scan0
  22.  
  23.         ' un vettore che conterrà tutti i bytes della bitmap.
  24.         Dim bytes As Long = Math.Abs(bmpData.Stride) * clone4bpp.Height ' calcolo dei bytes necessari
  25.         Dim colorValues(bytes - 1) As Byte
  26.         ' nel vettore metto i dati che rappresentano clone4bpp
  27.         System.Runtime.InteropServices.Marshal.Copy(ptr, colorValues, 0, bytes)
  28.  
  29.         'se è grigio(9) lo trasformo in rosso(4)
  30.         For ind = 0 To bytes - 1
  31.             ' scompongo il byte con i due pixel
  32.             Dim primosemibyte As Byte = colorValues(ind) \ 16
  33.             Dim secondosemibyte As Byte = colorValues(ind) - primosemibyte * 16
  34.             If primosemibyte = 9 Then ' pixel a sinistra
  35.                 primosemibyte = 4
  36.             End If
  37.             If secondosemibyte = 9 Then ' pixel a destra
  38.                 secondosemibyte = 4
  39.             End If
  40.             colorValues(ind) = primosemibyte * 16 + secondosemibyte ' ricompongo il byte con i due pixel
  41.         Next
  42.         System.Runtime.InteropServices.Marshal.Copy(colorValues, 0, ptr, bytes)
  43.         clone4bpp.UnlockBits(bmpData) ' sblocco bit
  44.         clone4bpp.SetResolution(360, 360)
  45.         clone4bpp.Save("C:\GrayToRed4bpp.bmp", Imaging.ImageFormat.Bmp)
  46.         clone4bpp.Dispose()



Il file è grande per vedere il risultato va zoomato.

Ultima modifica effettuata da Carlo il 20/07/2021 alle 17:02


in programmazione tutto è permesso
PM Quote
Avatar
bernie (Normal User)
Pro


Messaggi: 149
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 21:48
Martedì, 20/07/2021
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.


PM Quote
Avatar
bernie (Normal User)
Pro


Messaggi: 149
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 7:10
Mercoledì, 21/07/2021
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à.


PM Quote
Pagine: [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ] Precedente | Prossimo