Formati RGB in colore .NET

Ho controllato la documentazione su Colore (sto scrivendo un programma C #) Impostando un colore su Colore

Se vedi lì, imposta un colore basato su valori di 8 bit di RGB. In altre parole, suppongo che sia un formato RGB-888 … credo.

Sto usando nella mia fotocamera un formato RGB-565 (5 bit per R, B e 6 per G) C’è un modo per impostare Colore su un colore basato su questo formato e non su 888? O devo farlo manualmente da solo?

Ho recentemente scritto il codice per fare esattamente questo, basato sul convertitore di formato di colore generico del progetto ScummVM .

La risposta è su una domanda diversa qui su StackOverflow, e anche se la domanda non è in realtà un duplicato, penso, la risposta è, quindi mi limiterò a collegarmi ad esso:

Lavorare con un’immagine digitale con profondità di 10 bit

Intendiamoci, non sono sicuro di come il moltiplicatore di ciascun fattore funzioni nel formato 5-6-5. Il componente a 6 bit è semplicemente più preciso? In tal caso, il sistema di conversione automatico farà il lavoro.

Ad ogni modo, con il codice linkato sopra, questo esempio dovrebbe soddisfare perfettamente le tue esigenze. Qui viene utilizzato per convertire un formato RGBA 5-5-5-1 personalizzato:

//bytes 84 21 ==> 0x8421 (BE) ==bin==> 1000 0100 0010 0001 ==split==> 10000 10000 10000 1 ==dec==> 16 16 16 1 (RGBA) ==adjust==> 128 128 128 255 // values in constructor are: bytes per pixel, amount of bits and amount to shift for getting R, G, B and A components, and data endianness. private static PixelFormatter SixteenBppFormatter = new PixelFormatter(2, 5, 11, 5, 6, 5, 1, 1, 0, false); protected static Byte[] Convert16bTo32b(Byte[] imageData, Int32 startOffset, Int32 width, Int32 height, ref Int32 stride) { Int32 newImageStride = width * 4; ; Byte[] newImageData = new Byte[height * newImageStride]; for (Int32 y = 0; y < height; y++) { for (Int32 x = 0; x < width; x++) { Int32 sourceOffset = y * stride + x * 2; Int32 targetOffset = y * newImageStride + x * 4; Color c = SixteenBppFormatter.GetColor(imageData, startOffset + sourceOffset); PixelFormatter.Format32BitArgb.WriteColor(newImageData, targetOffset, c); } } stride = newImageStride; return newImageData; } 

Tutto quello che devi fare è definire il tuo PixelFormatter con la corretta distribuzione dei bit per il formato 5-6-5.

Dovrai infatti esaminare Bitmap.LockBits() per ottenere i dati originali a 16 bit dall'immagine e per scrivere quei dati in una nuova immagine ARGB a 32 bit. La mia funzione BuildImage menzionata in questa risposta dovrebbe mostrare come gestire la scrittura. Il metodo di lettura è in realtà molto più semplice:

 ///  /// Gets the raw bytes from an image. ///  /// The image to get the bytes from. /// Stride of the retrieved image data. /// The raw bytes of the image public static Byte[] GetImageData(Bitmap sourceImage, out Int32 stride) { BitmapData sourceData = sourceImage.LockBits(new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), ImageLockMode.ReadOnly, sourceImage.PixelFormat); stride = sourceData.Stride; Byte[] data = new Byte[stride * sourceImage.Height]; Marshal.Copy(sourceData.Scan0, data, 0, data.Length); sourceImage.UnlockBits(sourceData); return data; } 

Prendi nota, in tutte le situazioni in cui modifichi i byte immagine grezza, la differenza tra "passo" e "larghezza". In molti formati, una riga di pixel in un'immagine viene riempita al successivo multiplo di quattro byte, quindi non è ansible leggerla ed elaborarla come array assumendo che si tratti di tutti i dati dell'immagine; quei byte di padding lo incasineranno molto velocemente. Come mostrato nel mio codice di esempio per convertire il mio formato 16bpp in ARGB, è necessario eseguire questa operazione riga per riga, e per riga assicurarsi di utilizzare solo i dati che si trovano ancora nell'intervallo (larghezza * byte per pixel).

Ho notato che per tutte le funzioni che possono cambiare il passo, si consiglia di darlo come parametro ref .