Passa ai contenuti principali

Briciole di WPF: Ma quanti colori vuoi?!?!?

Questa briciola è dedicata alla structure Color presente nel namespace System.Windows.Media.

Di fatto si tratta della nuova struttura di colore introdotta da WPF che viene utilizzata dal presentation framework al posto della vecchia Color del namespace System.Drawing.

Ci sono due grandi differenze “esteriori” tra le due strutture.

La prima differenza è che la vecchia struttura può rappresentare 16.777.216 di colori essendo le sue componenti RGB rappresentate da 1 Byte ciascuno (256 possibili valori). Ogni terna di valori RGB ha, inoltre, 256 possibili valori di trasparenza.

La nuova struttura, invece, ha anche la possibilità di esprimere le componenti RGB (e Alfa) con dei valori di tipo Single (solo positivi o nulli) e, quindi, in linea teorica con un range di colori molto più ampio. La nuova struttura nasce con lo scopo di supportare lo standard scRGB (wiki docet).

La struttura Color di WPF mette ancora a disposizione dello sviluppatore le proprietà (A, R, G, B) che riportano il singolo canale espresso con un byte, ma forniscono anche delle proprietà (ScA, ScR, ScG, ScB) che esprimono le componenti del colore con dei valori di tipo Single.

I due insiemi di proprietà sono tra loro sincronizzati nel senso che se impostiamo uno dei canali “vecchi” otteniamo che il corrispondente canale “nuovo” ha il proprio valore aggiornato (con un valore tra 0 e 1. La conversione in questo verso avviene con una funzione di normalizzazione che possiamo ricavare utilizzando Reflector:

  1. Private Shared Function sRgbToScRgb(ByVal bval As Byte) As Single
  2.     Dim num As Single = (CSng(bval) / 255.0!)
  3.     If (num <= 0) Then
  4.         Return 0.0!
  5.     End If
  6.     If (num <= 0.04045) Then
  7.         Return (num / 12.92!)
  8.     End If
  9.     If (num < 1.0!) Then
  10.         Return CSng(Math.Pow(((num + 0.055) / 1.055), 2.4))
  11.     End If
  12.     Return 1.0!
  13. End Function

dove bval è il valore del canale “vecchio” e il ritorno della funzione è il valore del canale “nuovo”.

Quando impostiamo, invece, una delle proprietà dei nuovi canali, anche le corrispettive proprietà dei vecchi canali vengono aggiornate. Stavolta la funzione utilizzata per l’aggiornamento è la seguente:

  1. Private Shared Function ScRgbTosRgb(ByVal val As Single) As Byte
  2.     If (val <= 0) Then
  3.         Return 0
  4.     End If
  5.     If (val <= 0.0031308) Then
  6.         Return CByte((((255.0! * val) * 12.92!) + 0.5!))
  7.     End If
  8.     If (val < 1) Then
  9.         Return CByte(((255.0! * ((1.055! * CSng(Math.Pow(CDbl(val), 0.41666666666666669))) - 0.055!)) + 0.5!))
  10.     End If
  11.     Return 255
  12. End Function

In questo caso val è il valore del “nuovo” canale, mentre il ritorno della funzione è il valore del “vecchio” canale.

Altra differenza tra la nuova Color e la vecchia è che nella prima sono state rimosse le proprietà statiche che definivano i cosiddetti “colori noti” (ad esempio Color.Red). E’ stata, in questo senso, creata una nuova classe (interamente costituita da proprietà statiche ) Colors che contiene queste definizioni.

Se apriamo con Reflector la nuova structure Color osserviamo che anche il modo con cui internamente sono memorizzati i canali è cambiato.

Nella Color del namespace Drawing i canali sono memorizzati in un unico oggetto di tipo In64, mentre nella nuova structure abbiamo due strutture private ognuna delle quali ha 4 attributi (single o byte) che identificano i canali.

Commenti

Post popolari in questo blog

VB for Dummies: La serializzazione – parte 2

Questo post è la continuazione del precedente post sulla serializzazione. In particolare vedremo la serializzazione SOAP e quella JSON.   Serializzazione SOAP La serializzazione SOAP è demandata alla classe SOAPFormatter contenuta nel namespace System.Runtime.Serialization.Formatters.Soap contenuto nella libreria omonima. Il formatter SOAP risale alle primissime versioni del framework e, purtroppo, da un certo punto in poi, pur non essendo stato dichiarato obsoleto, non è stato portato avanti nello sviluppo e non supporta alcuni tipi di dati usatissimi nel mondo .NET quali i generici e i nullable. Per questo motivo, non possiamo serializzare in formato SOAP (utilizzando il SOAPFormatter) la nostra Fattura (vedi post precedente) poichè questa ha una proprietà di tipo List(Of DettagliFattura) (generico).   Serializzazione JSON Il formato di serializzazione JSON (maggiori info qui ) è un formato testuale molto in voga nelle applicazioni AJAX. Si trata di un mod...

Recensione: Windows Runtime via C#

Può sembrare strano che un VB-ista legga un libro su C#, ma come diceva Sun Tzu: “ Se conosci il tuo nemico, conosci te stesso ”. A parte gli scherzi, il libro vale la pena di essere letto a prescindere dal linguaggio .NET con cui si lavora. Oltre  290 pagine dedicate agli aspetti fondamentali dello sviluppo con Windows Runtime per le Windows Store App. I prerequisiti per poter leggere il libro sono la conoscenza di C# e di Visual Studio e gli autori non danno per scontato quasi nulla partendo dai concetti di base quali il type system e i suoi principi (argomento che di solito è saltato a piedi pari da chi si avvicina al mondo WinRT dal framework completo e che, se non compreso, può dare problemi nello sviluppo quotidiano). Tra i concetti che possiamo definire “core”, troviamo anche i capitoli dedicati all’app packaging e al process model, entrambi ben strutturati e chiari. Già solo questi tre capitoli iniziali giustificherebbero, in un certo qual modo, l’acquisto del libro, ...

Alla scoperta del Kinect : questione di profondità

Nei due precedenti post ( link e link ) abbiamo fatto conoscenza con “l’aggeggio” kinect e visto come sia possibile, in maniera molto semplice, gestire lo stream video proveniente dalla camera. In questo post diamo un’occhiata alla capacità che ha il Kinect di fornire frame in cui l’immagine non è la rappresentazione fedele della realtà che ci circonda ma la rappresentazione bidimensionale della distanza degli oggetti dai sensori di profondità. L’aggeggio, infatti, dispone di un sensore di profondità che è in grado di fornirci la distanza dei punti inquadrati da se stesso e, in più, è in grado di dirci a quale “player” fa riferimento ogni singolo pixel. Ma andiamo con ordine. Per abilitare la ricezione del depth stream è necessario: Istanziare la classe Runtime; Agganciare il gestore dell’evento DepthFrameReady; Inizializzare l’istanza della Runtime scegliendo una delle opzioni che abilitano il sensore di profondità; Aprire lo stream dei dati relativi alla pro...