Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - File bmp
Forum - C# / VB.NET - File bmp

Pagine: [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ] Precedente | Prossimo
Avatar
bernie (Normal User)
Pro


Messaggi: 107
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 17:06
Lunedì, 05/07/2021
Salve a tutti
dovrei creare un file bmp , monocanale , 4bpp  e fino a qui ci sono  
Codice sorgente - presumibilmente VB.NET

  1. Dim larghezza As Int16
  2.     Dim altezza As Int16
  3.     larghezza = TextBox1.Text
  4.     altezza = TextBox2.Text
  5.     Dim immagine As New Bitmap(larghezza, altezza, Imaging.PixelFormat.Format4bppIndexed)
  6.     immagine.SetResolution(360, 360)
  7.     immagine.Save("prova.bmp", Imaging.ImageFormat.Bmp)


Quello che dovrei fare adesso è assegnare ad ogni pixel un valore da 0 a 15 .
Avevo pensato a SetPixel , però quello associa un colore , e io sono in monocanale .
Qualche idea ?
Grazie

Ultima modifica effettuata da bernie il 05/07/2021 alle 17:07
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 972
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 22:47
Lunedì, 05/07/2021
SetPixel non lo puoi usare su una bmp a pixel indicizzati
I pixel indicizzati significa che l'immagine rispecchia un array di bytes con colori indicizzati e in base al numero dei bpp rappresentano più o meno pixel, per esempio un'immagine da 1bpp sarà composta da un vettore dove ogni byte rappresenta 8 pixel
Nel tuo caso 4bpp, ogni byte rappresenta due pixel adiacenti.
In base alla velocità operativa, hai due strade, una più lenta e facile, creare un'immagine a pixel non indicizzati usare setpixel con valori RGB, creati ad hoc per rispecchiare la tua palette e una volta creata l'immagine, convertirla a 4bpp.

La seconda nettamente più veloce ma più complicata, è usare LockBits e trattare l'immagine come un vettore.
Devi tenere in considerazione che il vettore conterrà tutti i bytes dell'immagine in sequenza, sarà tua cura calcolare quando la riga va accapo.
Ogni byte contiene il colore di due pixel, i colori usabili sono 0...15 o meglio &H0...&HF

Un esempio vale più di mille parole:
Codice sorgente - presumibilmente VB.NET

  1. Dim larghezza As Int16 = 800
  2. Dim altezza As Int16 = 600
  3.  
  4. Dim immagine As New Bitmap(larghezza, altezza, Imaging.PixelFormat.Format4bppIndexed)
  5. ' blocco i bit della bitmap  
  6. Dim area As Rectangle = New Rectangle(0, 0, immagine.Width, immagine.Height)
  7. Dim bmpData As System.Drawing.Imaging.BitmapData = immagine.LockBits(area, Drawing.Imaging.ImageLockMode.ReadWrite, immagine.PixelFormat)
  8.  
  9. ' puntatore all'indirizzo di memoria del primo byte.
  10. Dim ptr As IntPtr = bmpData.Scan0
  11.  
  12. ' un array che conterrà tutti i bytes della bitmap.
  13. Dim bytes As Integer = Math.Abs(bmpData.Stride) * immagine.Height ' calcolo dei bytes necessari
  14. Dim colorValues(bytes - 1) As Byte
  15. Dim dalbyte As Integer
  16.  
  17. ' nella prima riga dell'immagine scrivo una serie di punti bianchi e verdi
  18. For dalbyte = 0 To 399 ' ogni byte 2 pixel, la prima riga 0 399
  19.      colorValues(dalbyte) = &HFA ' due colori bianco e verde
  20. Next
  21. ' nella seconda riga dell'immagine scrivo una serie di punti bianchi e neri
  22. For dalbyte = 400 To 799 ' ogni byte 2 pixel, la seconda riga 400 799
  23.      colorValues(dalbyte) = &HF0 ' due colori bianco e nero
  24. Next
  25.  
  26. dalbyte = 6800 ' diciottesima riga
  27. For colore = 0 To 15
  28.      For dalbyte = dalbyte To dalbyte + 1199 ' per tre righe consecutive
  29.           colorValues(dalbyte) = colore + colore * 16 ' i 16 colori in un byte con 4bit ripetuti (&H00, &H11, &H22...&HFF)
  30.      Next
  31. Next
  32.  
  33. ' ripristino matrice su immagine
  34. System.Runtime.InteropServices.Marshal.Copy(colorValues, 0, ptr, bytes)
  35. immagine.UnlockBits(bmpData) ' sblocco bit
  36. immagine.Save("prova.bmp", Imaging.ImageFormat.Bmp)


Ultima modifica effettuata da Carlo il 19/07/2021 alle 10:15


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


Messaggi: 107
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 8:37
Martedì, 06/07/2021
Ciao Carlo
Grazie per l'esempio, purtroppo credo di essermi spiegato male .
Parlando di monocanale , si intende un file dove non c'è colore , ma livelli di grigio ,greyscale . quando apri questo tipo di file in photoshop e vai col cursore sul singolo pixel , ti indica un numero che varia da 0 a 100%. Se il file è a 8bpp il "peso" del pixel varia da 0 a 255 .
Mi dispiace averti fatto perdere del tempo per colpa delle mie incorrette spiegazioni .

PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 972
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 10:40
Martedì, 06/07/2021
OK, ma l'esempio resta valido.
Ho usato i valori 0...15, che in un file 4bpp di default usano la palette HalfTone, ma la palette la puoi cambiare come vuoi, anche usare 16 livelli di grigio.

Per un aiuto senza ambiguità, vorrei sapere cosa devi fare, se lavori in tandem con Photoshop, oppure hai dei files 4bpp da modificare via codice, cerca di espormi con cosa lavori e cosa vuoi ottenere, le possibilità sono sconfinate, usare quella giusta ti risparmia inutili complicazioni.

Avevo capito che il file 4bpp lo vuoi creare ex novo, e l'esempio è l'inizio per fare questo, ma poi bisogna sapere che esigenze di scrittura hai, se il file è uno è non devi variarne il contenuto dinamicamente e velocemente, la strada più semplice resta quella di partire con una bmp a pixel non indicizzati, usare una tua scala di 16 grigi, disegnare quello che vuoi con setpixel o tutte le istruzioni grafiche disponibili e poi convertire il file a 4bpp prima di salvare, la palette grayscale viene creata automaticamente.

Ultima modifica effettuata da Carlo il 06/07/2021 alle 10:42


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


Messaggi: 107
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 12:12
Martedì, 06/07/2021
Vorrei creare dei files da passare ad un sistema grafico .
Questo sistema accetta bmp monocanale( quindi solo 1 colore) 4 bpp ,8bpp scala di grigio .
Se creo il file
Codice sorgente - presumibilmente C# / VB.NET

  1. Dim immagine As New Bitmap(larghezza, altezza, Imaging.PixelFormat.Format4bppIndexed)


il sistema lo accetta senza problemi , anche se uso 8bpp.
Allego una immagine che il sistema accetta dove il gradiente va dal 100% allo 0% .
Quello che  vorrei fare è riuscire a creare immagini decidendo il gradiente dell'immagine ( tutta l'immagine deve avere lo stesso valore di gradiente ) .
L'immagine una volta creata non necessita di essere modificata al volo, viene solo caricata in una cartella e il sistema la va a leggere.
Spero di essere stato più chiaro questa volta . Ti ringrazio per l'aiuto e scusa se a volte non riesco a spiegarmi bene .




bernie ha allegato un file: prova2Grayscale.zip (462263 bytes)
Clicca qui per scaricare il file

Ultima modifica effettuata da bernie il 06/07/2021 alle 12:13
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 972
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 23:29
Martedì, 06/07/2021
Usare 4bpp, considerato che un byte contiene i valori di due pixel, complica i calcoli, se 8bpp va bene invece tutto è in discesa perché ogni byte rappresenta un pixel e il valore contenuto nel byte rappresenta un livello di grigio da 0 a 255 (sfumature ottime). :rofl:
Per il lavoro che vuoi fare tu credo che LockBit e lavorare sui bytes dell'immagine sia il metodo con il risultato migliore, perché lavorare su sfumature usando bmp a 16 o più bit, quando poi si converte a 8bpp, per matenere la qualità bisogna lavorare su l'ottimizzazione della palette o introdurre un dither (complicazioni inutili).

Nell'esempio ho usato una bmp a 8bpp larga 256 pixel, così la sfumatura corrisponde con le colonne.
Poi sarai tu che deciderai come ottenere le sfumature, è sufficiente che nel vettore inserisci al giusto indice i valori 0...255.
La riga 31, calcola l'indice del pixel alla coordinata di colonna e riga che vuoi scrivere.
Codice sorgente - presumibilmente VB.NET

  1. Imports System.Drawing.Imaging
  2.  
  3. Public Class Form1
  4.     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
  5.  
  6.         Dim larghezza As Int16 = 255 ' 256 colonne per semplificare la creazione della sfumatura
  7.         Dim altezza As Int16 = 200 ' a piacere
  8.         Dim immagine As New Bitmap(larghezza, altezza, Imaging.PixelFormat.Format8bppIndexed)
  9.  
  10.         ' creo una palette con 256 livelli di grigio
  11.         Dim palette As ColorPalette = immagine.Palette
  12.         For i = 0 To palette.Entries.Length - 1
  13.             palette.Entries(i) = Color.FromArgb(i, i, i)
  14.         Next i
  15.         ' associo la palette creata alla bitmap 8bpp,
  16.         ' i valori 0...255 ora corrispondono alla scala dal nero al bianco
  17.         immagine.Palette = palette
  18.         ' blocco i bit della bitmap per poter lavorare direttamente su un vettore di bytes
  19.         Dim area As Rectangle = New Rectangle(0, 0, immagine.Width, immagine.Height)
  20.         Dim bmpData As System.Drawing.Imaging.BitmapData = immagine.LockBits(area, Drawing.Imaging.ImageLockMode.ReadWrite, immagine.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 Integer = Math.Abs(bmpData.Stride) * immagine.Height ' calcolo dei bytes necessari
  27.         Dim colorValues(bytes - 1) As Byte
  28.         ' disegno delle righe vericali, ogni riga un grigio progressivo
  29.         For colonna = 0 To 255
  30.             For riga = 0 To immagine.Height - 1
  31.                 Dim ind As Integer = colonna + riga * (larghezza + 1) 'calcolo l'indice
  32.                 ' per semplificare l'esempio, la bitmap è larga 256 pixel,
  33.                 ' la colonna viene usata anche per impostare il colore
  34.                 colorValues(ind) = colonna ' il valore di colonna come valore del byte di grigio 0...255
  35.             Next
  36.         Next
  37.  
  38.         ' ripristino vettore su immagine
  39.         System.Runtime.InteropServices.Marshal.Copy(colorValues, 0, ptr, bytes)
  40.         immagine.UnlockBits(bmpData) ' sblocco bit
  41.         immagine.Save("prova8bpp.bmp", Imaging.ImageFormat.Bmp)
  42.     End Sub
  43.  
  44. End Class



Fai sapere se l'immagine è accettata e se riesci a creare le sfumature che vuoi. :k:

Ultima modifica effettuata da Carlo il 06/07/2021 alle 23:57


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


Messaggi: 107
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 12:21
Mercoledì, 07/07/2021
Ciao Carlo
ho provato il tuo esempio e il sistema riconosce il bmp valido.
Ho poi modificato in maniera da avere tutto il bmp con lo stesso valore di "colorValues" scusa ma riesco sempre a spiegarmi da schifo e il file di esempio che ho postato è stato ancora più fuorviante ....scusa.
Comunque il bmp deve essere flat , colore solido. Per ottenere ciò , ho semplicemente messo un valore fisso in "colorValues(ind)", fino qui tutto ok .
Adesso ho provato ad ingrandire il bmp e mi va sempre in errore "System.IndexOutOfRangeException: 'Indice oltre i limiti della matrice.'"nella riga di "colorValues(ind)=200"
dovrebbe significare che l'indice "ind" è oltre i limiti della matrice, quello che non capisco è perchè con dimensioni del bmp di 255X200pixel non ho problemi , mentre con 3000X200 si .
Effettivamente ind raggiunge il valore di 9603200 mentre i bytes necessari sono solo 600000.
Ho fatto varie prove modificando la forma di calcolare ind , non mi da più nessun errore , purtroppo , anche cambiando il valore di colorValue , il bmp non cambia .











Ultima modifica effettuata da bernie il 07/07/2021 alle 12:23
PM Quote
Avatar
bernie (Normal User)
Pro


Messaggi: 107
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 14:11
Mercoledì, 07/07/2021
Credo di aver risolto , probabilmente non è elegante , ma dopo varie prove sembra funzionare .
Ho lasciato il calcolo di ind come nel tuo esempio.
Prima di andare a scrivere il il valore nel pixel indicizzato , controllo che ind non sia maggiore del numero totale di pixel , se maggiore lo setto come il numero dei pixel.
Forse non elegante , ma sembra funzionare .

PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 972
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 16:04
Mercoledì, 07/07/2021
Quando dichiari la larghezza dell'immagine devi inserire un numero disparo, perché per avere un'immagine larga 3000 pixel = 0...2999, oppure bisogna aggiustare i calcoli dell'indice.

Ma per avere un'immagine a tono continuo, non ti serve più calcolare l'indice perché il vettore lo devi riempire tutto con lo stesso valore 0...255, è sufficiente un unico ciclo che scansiona tutto il vettore:
Codice sorgente - presumibilmente C# / VB.NET

  1. For ind = 0 To bytes - 1 ' la lunghezza del vettore
  2.      colorValues(ind) = 200 ' un valore qualsiasi 0...255
  3. Next



Per il tono continuo è semplice usare anche il 4bpp, hai tutte le info per modificare il codice, se ti serve prova. :k:

Ultima modifica effettuata da Carlo il 07/07/2021 alle 23:25


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