The TS_BITMAP_DATA structure wraps the bitmap data bytestream for a screen area rectangle containing a clipping taken from the server-side screen frame buffer.
file:///C:/ts_dev/TestSuites/MS-RDPBCGR/TestSuite/Src/TD/latest_XMLS_16may/RDPBCGR/ _rfc_ms-rdpbcgr2_1_8_1_1_3_1_2_1.xml
        public static TS_BITMAP_DATA CreateBitmapData(ushort left, ushort top, ushort width, ushort height)
        {
            Random r = new Random();
            TS_BITMAP_DATA bitmap = new TS_BITMAP_DATA();
            bitmap.destLeft = left;
            bitmap.destTop = top;
            bitmap.destRight = (ushort)(left + width - 1);
            bitmap.destBottom = (ushort)(top + height - 1);

            bitmap.width = width;
            bitmap.height = height;

            bitmap.bitsPerPixel = 16;
            bitmap.Flags = TS_BITMAP_DATA_Flags_Values.NO_BITMAP_COMPRESSION_HDR;

            bitmap.bitmapLength = (ushort)((width * 2 + 3) / 4 * 4 * height);
            bitmap.bitmapDataStream = new byte[bitmap.bitmapLength];

            for (int i = 0; i < bitmap.bitmapLength; i++)
                bitmap.bitmapDataStream[i] = (byte)r.Next(0, 64);

            return bitmap;
        }
        /// <summary>
        /// Parse TS_BITMAP_DATA
        /// (parser index is updated according to parsed length)
        /// </summary>
        /// <param name="data">data to be parsed</param>
        /// <param name="currentIndex">current parser index</param>
        /// <returns>TS_BITMAP_DATA</returns>
        private TS_BITMAP_DATA ParseTsBitmapData(byte[] data, ref int currentIndex)
        {
            TS_BITMAP_DATA bitmapData = new TS_BITMAP_DATA();

            // TS_BITMAP_DATA: destLeft
            bitmapData.destLeft = ParseUInt16(data, ref currentIndex, false);

            // TS_BITMAP_DATA: destTop
            bitmapData.destTop = ParseUInt16(data, ref currentIndex, false);

            // TS_BITMAP_DATA: destRight
            bitmapData.destRight = ParseUInt16(data, ref currentIndex, false);

            // TS_BITMAP_DATA: destBottom
            bitmapData.destBottom = ParseUInt16(data, ref currentIndex, false);

            // TS_BITMAP_DATA: width
            bitmapData.width = ParseUInt16(data, ref currentIndex, false);

            // TS_BITMAP_DATA: height
            bitmapData.height = ParseUInt16(data, ref currentIndex, false);

            // TS_BITMAP_DATA: bitsPerPixel
            bitmapData.bitsPerPixel = ParseUInt16(data, ref currentIndex, false);

            // TS_BITMAP_DATA: Flags
            bitmapData.Flags = (TS_BITMAP_DATA_Flags_Values)ParseUInt16(data, ref currentIndex, false);

            // TS_BITMAP_DATA: bitmapLength
            bitmapData.bitmapLength = ParseUInt16(data, ref currentIndex, false);

            // 32bpp is not supported
            if (bitmapData.bitsPerPixel == ConstValue.BITS_PER_PIXEL_32)
            {
                throw new NotSupportedException("32bpp compressed bitmaps are not supported!");
            }

            // If header is absent
            if (IsFlagExist((UInt16)bitmapData.Flags, (UInt16)TS_BITMAP_DATA_Flags_Values.NO_BITMAP_COMPRESSION_HDR))
            {
                // TS_BITMAP_DATA: bitmapDataStream
                bitmapData.bitmapDataStream = GetBytes(data, ref currentIndex, bitmapData.bitmapLength);
            }
            else
            {
                // reserve current parser index
                int reservedIndex = currentIndex;

                // TS_BITMAP_DATA: bitmapComprHdr
                bitmapData.bitmapComprHdr = ParseTsCdHeader(data, ref currentIndex);

                // TS_BITMAP_DATA: bitmapDataStream
                int remainLength = bitmapData.bitmapLength - (currentIndex - reservedIndex);
                bitmapData.bitmapDataStream = GetBytes(data, ref currentIndex, remainLength);
            }

            // Decompress if bitmapData were compressed
            if (IsFlagExist((UInt16)bitmapData.Flags, (UInt16)TS_BITMAP_DATA_Flags_Values.BITMAP_COMPRESSION))
            {
                RleDecompressor.Decompress(
                    bitmapData.bitmapDataStream,
                    (ColorDepth)bitmapData.bitsPerPixel,
                    bitmapData.width,
                    bitmapData.height);
            }
            return bitmapData;
        }
        public static TS_FP_UPDATE_BITMAP CreateFPUpdateBitmap(TS_BITMAP_DATA data)
        {
            TS_FP_UPDATE_BITMAP bitmap = new TS_FP_UPDATE_BITMAP();

            bitmap.updateHeader = (byte)(((int)updateCode_Values.FASTPATH_UPDATETYPE_BITMAP & 0x0f)
                | (((int)fragmentation_Value.FASTPATH_FRAGMENT_SINGLE) << 4)
                | ((int)compressedType_Values.None << 6));
            bitmap.compressionFlags = compressedType_Values.None;
            bitmap.bitmapUpdateData.updateType = (ushort)updateType_Values.UPDATETYPE_BITMAP;
            bitmap.bitmapUpdateData.numberRectangles = 1;
            bitmap.bitmapUpdateData.rectangles = new TS_BITMAP_DATA[1];
            bitmap.bitmapUpdateData.rectangles[0] = data;

            bitmap.size = (ushort)(22 + bitmap.bitmapUpdateData.rectangles[0].bitmapLength);
            if (bitmap.bitmapUpdateData.rectangles[0].Flags != TS_BITMAP_DATA_Flags_Values.NO_BITMAP_COMPRESSION_HDR)
            {
                bitmap.size += (ushort)Marshal.SizeOf(bitmap.bitmapUpdateData.rectangles[0].bitmapComprHdr);
            }

            return bitmap;
        }