Oppure

Loading
16/09/21 12:31
bernie
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
aaa
16/09/21 18:32
Carlo
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
16/09/21 19:14
bernie
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?
aaa
17/09/21 6:22
Carlo
Quasi.

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

Dim bmp8bpp As Bitmap = New Bitmap(FileName) ' in bmp8bpp l'immagine scelta
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:

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 17/09/21 6:31
in programmazione tutto è permesso
17/09/21 12:05
bernie
Grazie Carlo
Ho fatto cosi'
Dim origine As Bitmap = New Bitmap("C:\cerchio8bpp.bmp")
        Dim palette_origine As Imaging.ColorPalette = origine.Palette
        Dim modificato As New Bitmap(origine.Width, origine.Height * 4.4, Imaging.PixelFormat.Format16bppRgb555)
        Using gr = Graphics.FromImage(modificato) 'layer grafico che permette la scrittura in newImage con le istruzioni GDI+
            gr.SmoothingMode = SmoothingMode.HighQuality 'qualità delle trasformazioni grafiche
            gr.InterpolationMode = InterpolationMode.HighQualityBicubic 'tipologia dell'algoritmo di ridimensionamento
            gr.PixelOffsetMode = PixelOffsetMode.HighQuality 'precisione dei calcoli di un singolo pixel
            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
        End Using
        'clono il bmp modificato per poterlo salavare a 8bpp
        Dim clonemodificato As New Rectangle(0, 0, modificato.Width, modificato.Height)
        Dim clonemodificato8bpp As Bitmap = modificato.Clone(clonemodificato, Imaging.PixelFormat.Format8bppIndexed)
        clonemodificato8bpp.Palette = palette_origine
        clonemodificato8bpp.Save("C:\cerchiomodificato8bpp.bmp", Imaging.ImageFormat.Bmp)
        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
Ultima modifica effettuata da bernie 17/09/21 12:11
aaa
17/09/21 21:41
Carlo
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
Dim Originale As New Bitmap("cerchio8bpp.bmp")
Dim paletteOriginale As Imaging.ColorPalette = Originale.Palette
Dim areaOriginale As New Rectangle(0, 0, Originale.Width, Originale.Height)
Dim bmpDataOriginale As Imaging.BitmapData = Originale.LockBits(areaOriginale, Imaging.ImageLockMode.ReadWrite, Originale.PixelFormat)
Dim ptrOriginale As IntPtr = bmpDataOriginale.Scan0 ' conterrà l'indirizzo di memoria
Dim bytesOriginale As Integer = Math.Abs(bmpDataOriginale.Stride) * Originale.Height
Dim levelValuesOriginale(bytesOriginale - 1) As Byte
System.Runtime.InteropServices.Marshal.Copy(ptrOriginale, levelValuesOriginale, 0, bytesOriginale)

Dim ZoomH As Single = 5 ' solo interi, per i decimali bisogna pensarci un po'
Dim ZoomW As Single = 1 ' solo interi, per i decimali bisogna pensarci un po'

Dim Stirata As New Bitmap(Originale.Width * ZoomW, Originale.Height * ZoomH, Imaging.PixelFormat.Format8bppIndexed)
Stirata.Palette = Originale.Palette
Dim areaStirata As New Rectangle(0, 0, Stirata.Width, Stirata.Height)
Dim bmpDataStirata As Imaging.BitmapData = Stirata.LockBits(areaStirata, Imaging.ImageLockMode.ReadWrite, Stirata.PixelFormat)
Dim ptrStirata As IntPtr = bmpDataStirata.Scan0 ' conterrà l'indirizzo di memoria
Dim bytesStirata As Integer = Math.Abs(bmpDataStirata.Stride) * Stirata.Height
Dim levelValuesStirata(bytesStirata - 1) As Byte

' lettura e scrittura con zoom impostato
For rig = 0 To Originale.Height - 1
    Dim limite As UInt32 = rig * bmpDataOriginale.Stride
    Dim rig2 As Single = rig * ZoomH
    For col = 0 To Originale.Width - 1
        Dim indOriginale = col + limite
        Dim livello As Byte = levelValuesOriginale(indOriginale)
        Dim col2 As Single = col * ZoomW
        For H = 0 To ZoomH - 1
            For W = 0 To ZoomW - 1
                Dim indStirata As UInt32 = col2 + W + (rig2 + H) * bmpDataStirata.Stride ' calcolo l'indice
                levelValuesStirata(indStirata) = livello
            Next
        Next
    Next
Next

System.Runtime.InteropServices.Marshal.Copy(levelValuesStirata, 0, ptrStirata, bytesStirata)
Stirata.UnlockBits(bmpDataStirata) 'sblocco bit
Stirata.Save("zoom.bmp", Imaging.ImageFormat.Bmp)
Ultima modifica effettuata da Carlo 18/09/21 9:05
in programmazione tutto è permesso
18/09/21 13:49
bernie
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
aaa
18/09/21 16:04
Carlo
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