1+ using System ;
2+ using System . Numerics ;
3+
4+ namespace ImageSharp
5+ {
6+ /// <summary>
7+ /// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255.
8+ /// The color components are stored in alpha, red, green, and blue order.
9+ /// </summary>
10+ /// <remarks>
11+ /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
12+ /// as it avoids the need to create new values for modification operations.
13+ /// </remarks>
14+ public class Argb : IPackedPixel < uint > , IEquatable < Argb >
15+ {
16+ const int BlueShift = 0 ;
17+ const uint BlueMask = 0xFFFFFF00 ;
18+ const int GreenShift = 8 ;
19+ const uint GreenMask = 0xFFFF00FF ;
20+ const int RedShift = 16 ;
21+ const uint RedMask = 0xFF00FFFF ;
22+ const int AlphaShift = 24 ;
23+ const uint AlphaMask = 0x00FFFFFF ;
24+
25+ /// <summary>
26+ /// The maximum byte value.
27+ /// </summary>
28+ readonly static Vector4 MaxBytes = new Vector4 ( 255 ) ;
29+
30+ /// <summary>
31+ /// The half vector value.
32+ /// </summary>
33+ readonly static Vector4 Half = new Vector4 ( 0.5F ) ;
34+
35+ /// <summary>
36+ /// Initializes a new instance of the <see cref="Color"/> struct.
37+ /// </summary>
38+ /// <param name="r">The red component.</param>
39+ /// <param name="g">The green component.</param>
40+ /// <param name="b">The blue component.</param>
41+ /// <param name="a">The alpha component.</param>
42+ public Argb ( byte r , byte g , byte b , byte a = 255 )
43+ {
44+ PackedValue = Pack ( r , g , b , a ) ;
45+ }
46+
47+ /// <summary>
48+ /// Initializes a new instance of the <see cref="Color"/> struct.
49+ /// </summary>
50+ /// <param name="r">The red component.</param>
51+ /// <param name="g">The green component.</param>
52+ /// <param name="b">The blue component.</param>
53+ /// <param name="a">The alpha component.</param>
54+ public Argb ( float r , float g , float b , float a = 1 )
55+ {
56+ PackedValue = Pack ( r , g , b , a ) ;
57+ }
58+
59+ /// <summary>
60+ /// Initializes a new instance of the <see cref="Color"/> struct.
61+ /// </summary>
62+ /// <param name="vector">
63+ /// The vector containing the components for the packed vector.
64+ /// </param>
65+ public Argb ( Vector3 vector )
66+ {
67+ PackedValue = Pack ( ref vector ) ;
68+ }
69+
70+ /// <summary>
71+ /// Initializes a new instance of the <see cref="Color"/> struct.
72+ /// </summary>
73+ /// <param name="vector">
74+ /// The vector containing the components for the packed vector.
75+ /// </param>
76+ public Argb ( Vector4 vector )
77+ {
78+ PackedValue = Pack ( ref vector ) ;
79+ }
80+
81+ /// <summary>
82+ /// Initializes a new instance of the <see cref="Color"/> struct.
83+ /// </summary>
84+ /// <param name="packed">
85+ /// The packed value.
86+ /// </param>
87+ public Argb ( uint packed = 0 )
88+ {
89+ PackedValue = packed ;
90+ }
91+ /// <summary>
92+ /// Gets or sets the red component.
93+ /// </summary>
94+ public byte R
95+ {
96+ get
97+ {
98+ return ( byte ) ( PackedValue >> RedShift ) ;
99+ }
100+
101+ set
102+ {
103+ PackedValue = PackedValue & RedMask | ( uint ) value << RedShift ;
104+ }
105+ }
106+
107+ /// <summary>
108+ /// Gets or sets the green component.
109+ /// </summary>
110+ public byte G
111+ {
112+ get
113+ {
114+ return ( byte ) ( PackedValue >> GreenShift ) ;
115+ }
116+
117+ set
118+ {
119+ PackedValue = PackedValue & GreenMask | ( uint ) value << GreenShift ;
120+ }
121+ }
122+
123+ /// <summary>
124+ /// Gets or sets the blue component.
125+ /// </summary>
126+ public byte B
127+ {
128+ get
129+ {
130+ return ( byte ) ( PackedValue >> BlueShift ) ;
131+ }
132+
133+ set
134+ {
135+ PackedValue = PackedValue & BlueMask | ( uint ) value << BlueShift ;
136+ }
137+ }
138+
139+ /// <summary>
140+ /// Gets or sets the alpha component.
141+ /// </summary>
142+ public byte A
143+ {
144+ get
145+ {
146+ return ( byte ) ( PackedValue >> AlphaShift ) ;
147+ }
148+
149+ set
150+ {
151+ PackedValue = PackedValue & AlphaMask | ( uint ) value << AlphaShift ;
152+ }
153+ }
154+
155+ /// <inheritdoc/>
156+ public void PackFromVector4 ( Vector4 vector )
157+ {
158+ PackedValue = Pack ( ref vector ) ;
159+ }
160+
161+ /// <inheritdoc/>
162+ public Vector4 ToVector4 ( )
163+ {
164+ return new Vector4 ( R , G , B , A ) / MaxBytes ;
165+ }
166+
167+ /// <inheritdoc/>
168+ public uint PackedValue { get ; set ; }
169+
170+ /// <inheritdoc/>
171+ public void PackFromBytes ( byte x , byte y , byte z , byte w )
172+ {
173+ PackedValue = Pack ( x , y , z , w ) ;
174+ }
175+
176+ /// <summary>
177+ /// Packs the four floats into a <see cref="uint"/>.
178+ /// </summary>
179+ /// <param name="x">The x-component</param>
180+ /// <param name="y">The y-component</param>
181+ /// <param name="z">The z-component</param>
182+ /// <param name="w">The w-component</param>
183+ /// <returns>The <see cref="uint"/></returns>
184+ static uint Pack ( float x , float y , float z , float w )
185+ {
186+ var value = new Vector4 ( x , y , z , w ) ;
187+ return Pack ( ref value ) ;
188+ }
189+ /// <summary>
190+ /// Packs the four floats into a <see cref="uint"/>.
191+ /// </summary>
192+ /// <param name="x">The x-component</param>
193+ /// <param name="y">The y-component</param>
194+ /// <param name="z">The z-component</param>
195+ /// <param name="w">The w-component</param>
196+ /// <returns>The <see cref="uint"/></returns>
197+ static uint Pack ( byte x , byte y , byte z , byte w )
198+ {
199+ return ( uint ) ( x << RedShift | y << GreenShift | z << BlueShift | w << AlphaShift ) ;
200+ }
201+
202+ /// <summary>
203+ /// Packs a <see cref="Vector3"/> into a uint.
204+ /// </summary>
205+ /// <param name="vector">The vector containing the values to pack.</param>
206+ /// <returns>The <see cref="uint"/> containing the packed values.</returns>
207+ static uint Pack ( ref Vector3 vector )
208+ {
209+ var value = new Vector4 ( vector , 1 ) ;
210+ return Pack ( ref value ) ;
211+ }
212+
213+ /// <summary>
214+ /// Packs a <see cref="Vector4"/> into a uint.
215+ /// </summary>
216+ /// <param name="vector">The vector containing the values to pack.</param>
217+ /// <returns>The <see cref="uint"/> containing the packed values.</returns>
218+ static uint Pack ( ref Vector4 vector )
219+ {
220+ vector = Vector4 . Clamp ( vector , Vector4 . Zero , Vector4 . One ) ;
221+ vector *= MaxBytes ;
222+ vector += Half ;
223+ return ( uint ) ( ( ( byte ) vector . X << RedShift )
224+ | ( ( byte ) vector . Y << GreenShift )
225+ | ( ( byte ) vector . Z << BlueShift )
226+ | ( byte ) vector . W << AlphaShift ) ;
227+ }
228+
229+ /// <inheritdoc/>
230+ public void ToBytes ( byte [ ] bytes , int startIndex , ComponentOrder componentOrder )
231+ {
232+ switch ( componentOrder ) {
233+ case ComponentOrder . ZYX :
234+ bytes [ startIndex ] = B ;
235+ bytes [ startIndex + 1 ] = G ;
236+ bytes [ startIndex + 2 ] = R ;
237+ break ;
238+ case ComponentOrder . ZYXW :
239+ bytes [ startIndex ] = B ;
240+ bytes [ startIndex + 1 ] = G ;
241+ bytes [ startIndex + 2 ] = R ;
242+ bytes [ startIndex + 3 ] = A ;
243+ break ;
244+ case ComponentOrder . XYZ :
245+ bytes [ startIndex ] = R ;
246+ bytes [ startIndex + 1 ] = G ;
247+ bytes [ startIndex + 2 ] = B ;
248+ break ;
249+ case ComponentOrder . XYZW :
250+ bytes [ startIndex ] = R ;
251+ bytes [ startIndex + 1 ] = G ;
252+ bytes [ startIndex + 2 ] = B ;
253+ bytes [ startIndex + 3 ] = A ;
254+ break ;
255+ default :
256+ throw new NotSupportedException ( ) ;
257+ }
258+ }
259+
260+ /// <inheritdoc/>
261+ public override bool Equals ( object obj )
262+ {
263+ var a = obj as Argb ;
264+ return ( a != null ) && Equals ( a ) ;
265+ }
266+
267+ /// <inheritdoc/>
268+ public bool Equals ( Argb other )
269+ {
270+ return PackedValue == other . PackedValue ;
271+ }
272+
273+ /// <inheritdoc/>
274+ public override int GetHashCode ( )
275+ {
276+ // ReSharper disable once NonReadonlyMemberInGetHashCode
277+ return PackedValue . GetHashCode ( ) ;
278+ }
279+ }
280+ }
0 commit comments