66using System . Linq ;
77using System . Text ;
88using System . Threading . Tasks ;
9+ using System . Windows ;
10+ using System . Windows . Media ;
11+ using System . Windows . Media . Imaging ;
912
1013namespace StreamDeckSharp
1114{
1215 /// <summary>
1316 /// Represents a bitmap that can be used as key images
1417 /// </summary>
15- public class StreamDeckKeyBitmap
18+ public partial class StreamDeckKeyBitmap
1619 {
1720 /// <summary>
1821 /// Solid black bitmap
@@ -23,17 +26,15 @@ public class StreamDeckKeyBitmap
2326 public static StreamDeckKeyBitmap Black { get { return black ; } }
2427 private static readonly StreamDeckKeyBitmap black = new StreamDeckKeyBitmap ( null ) ;
2528
29+ /// <remarks>
30+ /// The raw pixel format is a byte array of length 15552. This number is based on the image
31+ /// dimensions used by StreamDeck 72x72 pixels and 3 channels (RGB) for each pixel. 72 x 72 x 3 = 15552.
32+ ///
33+ /// The channels are in the order BGR and the pixel rows (stride) are in reverse order.
34+ /// If you need some help try <see cref="StreamDeckKeyBitmap"/>
35+ /// </remarks>
2636 internal readonly byte [ ] rawBitmapData ;
2737
28- /// <summary>
29- /// Returns a copy of the internal bitmap.
30- /// </summary>
31- /// <returns></returns>
32- public byte [ ] CloneBitmapData ( )
33- {
34- return ( byte [ ] ) rawBitmapData . Clone ( ) ;
35- }
36-
3738 internal StreamDeckKeyBitmap ( byte [ ] bitmapData )
3839 {
3940 if ( bitmapData != null )
@@ -42,110 +43,5 @@ internal StreamDeckKeyBitmap(byte[] bitmapData)
4243 this . rawBitmapData = bitmapData ;
4344 }
4445 }
45-
46- public static StreamDeckKeyBitmap FromRawBitmap ( byte [ ] bitmapData )
47- {
48- return new StreamDeckKeyBitmap ( bitmapData ) ;
49- }
50-
51- /// <summary>
52- /// Creates a solid color bitmap
53- /// </summary>
54- /// <param name="R">Red channel</param>
55- /// <param name="G">Green channel</param>
56- /// <param name="B">Blue channel</param>
57- /// <returns></returns>
58- public static StreamDeckKeyBitmap FromRGBColor ( byte R , byte G , byte B )
59- {
60- //If everything is 0 (black) take a shortcut ;-)
61- if ( R == 0 && G == 0 && B == 0 ) return Black ;
62-
63- var buffer = new byte [ StreamDeckHID . rawBitmapDataLength ] ;
64- for ( int i = 0 ; i < buffer . Length ; i += 3 )
65- {
66- buffer [ i + 0 ] = B ;
67- buffer [ i + 1 ] = G ;
68- buffer [ i + 2 ] = R ;
69- }
70-
71- return new StreamDeckKeyBitmap ( buffer ) ;
72- }
73-
74- public static StreamDeckKeyBitmap FromStream ( Stream bitmapStream )
75- {
76- using ( Bitmap bitmap = ( Bitmap ) Image . FromStream ( bitmapStream ) )
77- {
78- return FromDrawingBitmap ( bitmap ) ;
79- }
80- }
81-
82- public static StreamDeckKeyBitmap FromFile ( string bitmapFile )
83- {
84- using ( Bitmap bitmap = ( Bitmap ) Image . FromFile ( bitmapFile ) )
85- {
86- return FromDrawingBitmap ( bitmap ) ;
87- }
88- }
89-
90- internal static StreamDeckKeyBitmap FromDrawingBitmap ( Bitmap bitmap )
91- {
92- if ( bitmap . Width != StreamDeckHID . iconSize || bitmap . Height != StreamDeckHID . iconSize ) throw new NotSupportedException ( "Unsupported bitmap dimensions" ) ;
93-
94- BitmapData data = null ;
95- try
96- {
97- data = bitmap . LockBits ( new Rectangle ( 0 , 0 , bitmap . Width , bitmap . Height ) , System . Drawing . Imaging . ImageLockMode . ReadOnly , bitmap . PixelFormat ) ;
98- var managedRGB = new byte [ StreamDeckHID . rawBitmapDataLength ] ;
99-
100- unsafe
101- {
102- byte * bdata = ( byte * ) data . Scan0 ;
103-
104- //TODO: This should be cleaned up
105- //I'm locking for a different approach to parse different PixelFormats without
106- //copying 90% of the code ;-)
107- if ( data . PixelFormat == PixelFormat . Format24bppRgb )
108- {
109- for ( int y = 0 ; y < StreamDeckHID . iconSize ; y ++ )
110- {
111- for ( int x = 0 ; x < StreamDeckHID . iconSize ; x ++ )
112- {
113- var ps = data . Stride * y + x * 3 ;
114- var pt = StreamDeckHID . iconSize * 3 * ( y + 1 ) - ( x + 1 ) * 3 ;
115- managedRGB [ pt + 0 ] = bdata [ ps + 0 ] ;
116- managedRGB [ pt + 1 ] = bdata [ ps + 1 ] ;
117- managedRGB [ pt + 2 ] = bdata [ ps + 2 ] ;
118- }
119- }
120- }
121- else if ( data . PixelFormat == PixelFormat . Format32bppArgb )
122- {
123- for ( int y = 0 ; y < StreamDeckHID . iconSize ; y ++ )
124- {
125- for ( int x = 0 ; x < StreamDeckHID . iconSize ; x ++ )
126- {
127- var ps = data . Stride * y + x * 4 ;
128- var pt = StreamDeckHID . iconSize * 3 * ( y + 1 ) - ( x + 1 ) * 3 ;
129- double alpha = ( double ) bdata [ ps + 3 ] / 255f ;
130- managedRGB [ pt + 0 ] = ( byte ) Math . Round ( bdata [ ps + 0 ] * alpha ) ;
131- managedRGB [ pt + 1 ] = ( byte ) Math . Round ( bdata [ ps + 1 ] * alpha ) ;
132- managedRGB [ pt + 2 ] = ( byte ) Math . Round ( bdata [ ps + 2 ] * alpha ) ;
133- }
134- }
135- }
136- else
137- {
138- throw new NotSupportedException ( "Unsupported pixel format" ) ;
139- }
140- }
141-
142- return new StreamDeckKeyBitmap ( managedRGB ) ;
143- }
144- finally
145- {
146- if ( data != null )
147- bitmap . UnlockBits ( data ) ;
148- }
149- }
15046 }
15147}
0 commit comments