Non so di preciso come funziona so che di default da 8bpp a 4bpp è molto grossolano, ci dovrebbero essere delle istruzioni per rimappare la palette e quantizzarla per ottenere risultati molto raffinati, in GDI+ c'è anche colorMatrix.
La cosa si può fare anche a mano usando le conoscenze di base.
Apri un nuovo progetto WinForm e nel form metti due picturebox affiancate.
La prima parte del codice crea un'immagine con una sfumatura da 256 livelli di grigio e i dati sono contenuti nel vettore
colorValues
La seconda parte del codice crea un'immagine vuota con palette a 16 livelli di grigio e i dati sono contenuti nel vettore vuoto
levelValues
La terza parte del codice legge
colorValues e lo usa per scrivere con palette scalata in
levelValues
La quarta parte del codice mette i dati contenuti nei vettori creati in bmp8bpp e bmp4bpp, per mostrarli su due picturebox
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim bmp8bpp As New Bitmap(255, 255, Imaging.PixelFormat.Format8bppIndexed) ' immagine 8bpp
' blocco i bit della bitmap
Dim area8 As Rectangle = New Rectangle(0, 0, bmp8bpp.Width, bmp8bpp.Height)
Dim bmpData8 As System.Drawing.Imaging.BitmapData = bmp8bpp.LockBits(area8, Drawing.Imaging.ImageLockMode.ReadWrite, bmp8bpp.PixelFormat)
' creo una palette con 256 livelli di grigio
Dim palette256 As Imaging.ColorPalette = bmp8bpp.Palette
For i = 0 To palette256.Entries.Length - 1
palette256.Entries(i) = Color.FromArgb(i, i, i)
Next i
' associo la palette creata alla bitmap 8bpp,
' i valori 0...255 ora corrispondono alla scala dal nero al bianco
bmp8bpp.Palette = palette256
Dim ptr8 As IntPtr = bmpData8.Scan0 ' puntatore all'indirizzo di memoria del primo byte.
Dim bytes8 As Integer = Math.Abs(bmpData8.Stride) * bmp8bpp.Height ' calcolo dei bytes necessari
Dim colorValues(bytes8 - 1) As Byte ' un array che conterrà tutti i bytes della bitmap.
' creo una sfumatura
For colonna = 0 To bmp8bpp.Width
For riga = 0 To Math.Abs(bmpData8.Stride) - 2
Dim ind As Integer = colonna + riga * Math.Abs(bmpData8.Stride) 'calcolo l'indice
' per semplificare l'esempio, la bitmap è larga 256 pixel,
' la colonna viene usata anche per impostare il colore
colorValues(ind) = colonna ' il valore di colonna come valore del byte di grigio 0...255
Next
Next
' dichiaro bmp4bpp
Dim bmp4bpp As New Bitmap(255, 255, Imaging.PixelFormat.Format4bppIndexed)
' blocco i bit della bitmap
Dim area4 As Rectangle = New Rectangle(0, 0, bmp4bpp.Width, bmp4bpp.Height)
Dim bmpData4 As System.Drawing.Imaging.BitmapData = bmp4bpp.LockBits(area4, Drawing.Imaging.ImageLockMode.ReadWrite, bmp4bpp.PixelFormat)
' creo una palette con 16 livelli di grigio
Dim palette16 As Imaging.ColorPalette = bmp4bpp.Palette
For i = 0 To palette16.Entries.Length - 1
palette16.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
bmp4bpp.Palette = palette16
Dim ptr4 As IntPtr = bmpData4.Scan0
Dim bytes4 As Long = Math.Abs(bmpData4.Stride) * bmp4bpp.Height ' calcolo dei bytes necessari
Dim levelValues(bytes4 - 1) As Byte
' nel vettore che rappresenta bmp4bpp ci copio i dati dal vettore che rappresenta bmp8bpp, scalati
' scorro tutto il vettore colorValues che rappresenta bmp8bpp
For ind = 0 To bytes8 - 1
' il vettore levelValues che rappresenta bmp4bpp è lungo la metà rispetto a colorValues
' il valore di un pixel di colorValues, in un byte replicato per due pixel
levelValues(ind \ 2) = (colorValues(ind) \ 16) + (colorValues(ind) \ 16) * 16
Next
' ripristino vettore su immagine
System.Runtime.InteropServices.Marshal.Copy(colorValues, 0, ptr8, bytes8)
bmp8bpp.UnlockBits(bmpData8) ' sblocco bit
PictureBox1.Width = bmp8bpp.Width
PictureBox1.Height = bmp8bpp.Height
PictureBox1.Image = bmp8bpp
' ripristino vettore su immagine
System.Runtime.InteropServices.Marshal.Copy(levelValues, 0, ptr4, bytes4)
bmp4bpp.UnlockBits(bmpData4) ' sblocco bit
PictureBox2.Left = PictureBox1.Left + PictureBox1.Width + 20
PictureBox2.Width = bmp4bpp.Width
PictureBox2.Height = bmp4bpp.Height
PictureBox2.Image = bmp4bpp
End Sub
End Class
niente di nuovo.
se ti servono più info su:
levelValues(ind \ 2) = (colorValues(ind) \ 16) + (colorValues(ind) \ 16) * 16
chiedi