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 - modificare file BMP
Forum - C# / VB.NET - modificare file BMP

Pagine: [ 1 2 3 4 5 ] Precedente | Prossimo
Avatar
bernie (Normal User)
Pro


Messaggi: 117
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 14:31
Giovedì, 16/09/2021
Salve a tutti
ritorno dopo le ferie con i miei problemi....
Ho un bmp 8bpp lo carico , controllo che effettivamente sia 8bpp con una palette a 256.
A questo punto lo devo "stirare",prima in una direzione , lo salvo con nuovo nome  e poi stiro l'originale nell'altra dimensione .
Per fare ciò , uso le GDI+ quindi non posso usare un bmp con pixel indicizzati, il minimo che posso usare è Format16bppRgb555.
Però io ho bisogno che il mio bmp sia a 8 bpp, quindi lo clono e lo trasformo in Format8bppIndexed.
Fino qui tutto ok , però la palette cambia. Io dopo aver stirato la grafica in una dimensione , devo modificare la palette.
Qui iniziano i problemi . Dal mio punto di vista tutti i problemi sono dovuti al fatto che io converto il file in 8bpp, ma non converto la palette colore, quindi quando la vado a modificare , non ho una palette a 256colori  come l'originale , ma la palette dei 16bpp. Qualche suggerimento ?
Grazie  

PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 984
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 20:32
Giovedì, 16/09/2021
Quando carichi il bmp a 8bpp, dopo aver controllato che ha una palette a 256, la copi in un vettore. Converti a 16bpp, esegui tutti gli stiramenti che vuoi. Riconverti a 8bpp e riassoci la palette originale che ti eri salvato nel vettore.


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


Messaggi: 117
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 21:14
Giovedì, 16/09/2021
Carico la palette nel vettore usando MarshalCopy.
Creo una grafica a 16bpp e la uso per stirare la grafica a 8bpp.
La clono a 8bpp e gli carico la palette salvata sul vettore.
Corretto?

PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 984
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 8:22
Venerdì, 17/09/2021
Quasi.

carichi l'immagine e copi la palette in un vettore ColorPalette:

Codice sorgente - presumibilmente VB.NET

  1. Dim bmp8bpp As Bitmap = New Bitmap(FileName) ' in bmp8bpp l'immagine scelta
  2. Dim palette8bpp As Imaging.ColorPalette = bmp8bpp.Palette ' nel vettore palette8bpp, la palette dell'immagine scelta



converti ed esegui tutte le operazioni GDI+
riconverti in 8bpp
associ la palette originale:

Codice sorgente - presumibilmente Plain Text

  1. bmp8bppStirata.Palette = palette8bpp



Copiare i dati della bmp in un vettore con Marshal.Copy, non ti serve se non devi agire su di essi direttamente.


Ultima modifica effettuata da Carlo il 17/09/2021 alle 8:31


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


Messaggi: 117
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 14:05
Venerdì, 17/09/2021
Grazie Carlo
Ho fatto cosi'
Codice sorgente - presumibilmente VB.NET

  1. Dim origine As Bitmap = New Bitmap("C:\cerchio8bpp.bmp")
  2.         Dim palette_origine As Imaging.ColorPalette = origine.Palette
  3.         Dim modificato As New Bitmap(origine.Width, origine.Height * 4.4, Imaging.PixelFormat.Format16bppRgb555)
  4.         Using gr = Graphics.FromImage(modificato) 'layer grafico che permette la scrittura in newImage con le istruzioni GDI+
  5.             gr.SmoothingMode = SmoothingMode.HighQuality 'qualità delle trasformazioni grafiche
  6.             gr.InterpolationMode = InterpolationMode.HighQualityBicubic 'tipologia dell'algoritmo di ridimensionamento
  7.             gr.PixelOffsetMode = PixelOffsetMode.HighQuality 'precisione dei calcoli di un singolo pixel
  8.             gr.DrawImage(origine, New Rectangle(0, 0, origine.Width, origine.Height * 4.4)) 'nel layer grafico viene disegnata l'immagine in posizione 0,0 ridimensionata in width, height
  9.         End Using
  10.         'clono il bmp modificato per poterlo salavare a 8bpp
  11.         Dim clonemodificato As New Rectangle(0, 0, modificato.Width, modificato.Height)
  12.         Dim clonemodificato8bpp As Bitmap = modificato.Clone(clonemodificato, Imaging.PixelFormat.Format8bppIndexed)
  13.         clonemodificato8bpp.Palette = palette_origine
  14.         clonemodificato8bpp.Save("C:\cerchiomodificato8bpp.bmp", Imaging.ImageFormat.Bmp)
  15.         clonemodificato8bpp.Dispose()


Però il risultato non è corretto , l'immagine che carico è un cerchio nero su sfondo bianco , dopo la modifica , lo sfondo non è bianco ma grigio e questo crea dei problemi dopo quando devo modificare la palette rendendola a 8 livelli .
Allego la grafica che uso per test .
Grazie


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

Ultima modifica effettuata da bernie il 17/09/2021 alle 14:11
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 984
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 23:41
Venerdì, 17/09/2021
Hai ragione, la conversione a 8bpp, crea una palette ottimizzata e il bianco non è più nel livello originale.

1) si può riordinare tutto, riportando il bianco al livello 255
2) si può usare ColorMatch, per creare la BMP8bpp a mano
3) si può ritornare al metodo del vettore/LockBits se le trasformazioni non sono impegnative

Lo zoom orizzontale e/o verticale, non è impegnativo.
Un codice senza pretesa di funzionare in tutte le situazioni e con zoom di soli interi
Codice sorgente - presumibilmente VB.NET

  1. Dim Originale As New Bitmap("cerchio8bpp.bmp")
  2. Dim paletteOriginale As Imaging.ColorPalette = Originale.Palette
  3. Dim areaOriginale As New Rectangle(0, 0, Originale.Width, Originale.Height)
  4. Dim bmpDataOriginale As Imaging.BitmapData = Originale.LockBits(areaOriginale, Imaging.ImageLockMode.ReadWrite, Originale.PixelFormat)
  5. Dim ptrOriginale As IntPtr = bmpDataOriginale.Scan0 ' conterrà l'indirizzo di memoria
  6. Dim bytesOriginale As Integer = Math.Abs(bmpDataOriginale.Stride) * Originale.Height
  7. Dim levelValuesOriginale(bytesOriginale - 1) As Byte
  8. System.Runtime.InteropServices.Marshal.Copy(ptrOriginale, levelValuesOriginale, 0, bytesOriginale)
  9.  
  10. Dim ZoomH As Single = 5 ' solo interi, per i decimali bisogna pensarci un po'
  11. Dim ZoomW As Single = 1 ' solo interi, per i decimali bisogna pensarci un po'
  12.  
  13. Dim Stirata As New Bitmap(Originale.Width * ZoomW, Originale.Height * ZoomH, Imaging.PixelFormat.Format8bppIndexed)
  14. Stirata.Palette = Originale.Palette
  15. Dim areaStirata As New Rectangle(0, 0, Stirata.Width, Stirata.Height)
  16. Dim bmpDataStirata As Imaging.BitmapData = Stirata.LockBits(areaStirata, Imaging.ImageLockMode.ReadWrite, Stirata.PixelFormat)
  17. Dim ptrStirata As IntPtr = bmpDataStirata.Scan0 ' conterrà l'indirizzo di memoria
  18. Dim bytesStirata As Integer = Math.Abs(bmpDataStirata.Stride) * Stirata.Height
  19. Dim levelValuesStirata(bytesStirata - 1) As Byte
  20.  
  21. ' lettura e scrittura con zoom impostato
  22. For rig = 0 To Originale.Height - 1
  23.     Dim limite As UInt32 = rig * bmpDataOriginale.Stride
  24.     Dim rig2 As Single = rig * ZoomH
  25.     For col = 0 To Originale.Width - 1
  26.         Dim indOriginale = col + limite
  27.         Dim livello As Byte = levelValuesOriginale(indOriginale)
  28.         Dim col2 As Single = col * ZoomW
  29.         For H = 0 To ZoomH - 1
  30.             For W = 0 To ZoomW - 1
  31.                 Dim indStirata As UInt32 = col2 + W + (rig2 + H) * bmpDataStirata.Stride ' calcolo l'indice
  32.                 levelValuesStirata(indStirata) = livello
  33.             Next
  34.         Next
  35.     Next
  36. Next
  37.  
  38. System.Runtime.InteropServices.Marshal.Copy(levelValuesStirata, 0, ptrStirata, bytesStirata)
  39. Stirata.UnlockBits(bmpDataStirata) 'sblocco bit
  40. Stirata.Save("zoom.bmp", Imaging.ImageFormat.Bmp)


Ultima modifica effettuata da Carlo il 18/09/2021 alle 11:05


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


Messaggi: 117
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 15:49
Sabato, 18/09/2021
Ho provato l'esempio di Carlo e funziona , però, come input ho una immagine greyscale , mentre dopo l'eleborazione mi ritrovo con una immagine colorscale .
Ho cercato in rete , ma non ho trovato niente .
Mi sembra di ricordare che Carlo disse che VB.Net non gestisce greyscale . Mi sbaglio ?
Grazie

PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 984
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 18:04
Sabato, 18/09/2021
L'immagine che hai postatao cerchio8bpp.bmp è scala di colore

Anche se con Photoschop la converto in scala di grigio, al caricamento risulta sempre scala di colore.

hai un'immagine in scala di grigio?

Imaging.PixelFormat.Format16bppGrayScale (non supportato in .Net)


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


Messaggi: 117
Iscritto: 23/10/2019

Segnala al moderatore
Postato alle 18:21
Sabato, 18/09/2021
Quella immagine dovrebbe essere greyscale, almeno, l'originale è greyscale.

Credo che non ci sia soluzione, mi serve come out un bmp 8bpp greyscale.

Infatti tutti gli esempi che ho trovato in rete, non convertono in greyscale, ma rendono una immagine RGB grigia, e non sono neanche convinto che la conversione con i tre canali uguali sia corretta, visto che l'occhio umano ha sensibilità diversa in base al canale ( è molto più sensibile al verde che al blu)

Se .Net non supporta greyscale, quale linguaggio lo supporta?
Grazie

PM Quote
Pagine: [ 1 2 3 4 5 ] Precedente | Prossimo