/// <summary>
        /// Convert CLEARCODEC_SUBCODEC_RLEX structure into byte stream.
        /// </summary>
        /// <param name="rlex">The encoded CLEARCODEC_SUBCODEC_RLEX structure.</param>
        public byte[] ToBytes(CLEARCODEC_SUBCODEC_RLEX rlex)
        {
            List <byte> bufList = new List <byte>();

            if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Band_Subcodec_IncorrectPaletteCount)
            {
                bufList.AddRange(TypeMarshal.ToBytes <byte>(rlex.paletteCount));
            }
            else
            {
                bufList.AddRange(TypeMarshal.ToBytes <byte>((byte)(rlex.paletteCount + 1)));
            }
            for (int i = 0; i < rlex.paletteEntries.Count(); i++)
            {
                bufList.AddRange(TypeMarshal.ToBytes <byte>(rlex.paletteEntries[i].B));
                bufList.AddRange(TypeMarshal.ToBytes <byte>(rlex.paletteEntries[i].G));
                bufList.AddRange(TypeMarshal.ToBytes <byte>(rlex.paletteEntries[i].R));
            }

            // Blow encode rlex segment.

            // Calculate bit number for stopIndex.
            byte bitNum = 0;
            byte count  = (byte)(rlex.paletteCount - 1);

            while (count > 0)
            {
                bitNum++;
                count >>= 1;
            }

            for (int i = 0; i < rlex.segments.Count(); i++)
            {
                byte stopIdx_suiteDepth = (byte)(rlex.segments[i].stopIndex | (rlex.segments[i].suiteDepth << bitNum));
                bufList.AddRange(TypeMarshal.ToBytes <byte>(stopIdx_suiteDepth));
                if (rlex.segments[i].runLengthFactor < 0xff)
                {
                    bufList.AddRange(TypeMarshal.ToBytes <byte>((byte)rlex.segments[i].runLengthFactor));
                }
                else if (rlex.segments[i].runLengthFactor < 0xffff)
                {
                    bufList.AddRange(TypeMarshal.ToBytes <byte>((byte)0xff));
                    bufList.AddRange(TypeMarshal.ToBytes <ushort>((ushort)rlex.segments[i].runLengthFactor));
                }
                else
                {
                    bufList.AddRange(TypeMarshal.ToBytes <byte>((byte)0xff));
                    bufList.AddRange(TypeMarshal.ToBytes <ushort>((ushort)0xffff));
                    bufList.AddRange(TypeMarshal.ToBytes <uint>((uint)rlex.segments[i].runLengthFactor));
                }
            }

            return(bufList.ToArray());
        }
        /// <summary>
        /// It decode rlexByteCount bytes data into CLEARCODEC_SUBCODEC_RLEX structure
        /// </summary>
        /// <param name = "rlexByteCount"> the number of bytes to be decoded into CLEARCODEC_SUBCODEC_RLEX structure </param>
        /// <param name = "rlex"> the structure that decode result save to </param>
        /// <return> true if decode success, otherwise return false </return>
        public bool DecodeRlexData(uint rlexByteCount, ref CLEARCODEC_SUBCODEC_RLEX rlex)
        {
            if (!DecodeByte(ref rlex.paletteCount)) return false;
            rlexByteCount--;

            // calculate bitNum of stopIndex in rlex segment
            byte bitNum = 0;
            byte count = rlex.paletteCount;
            // calculate bit number for stopIndex
            while (count > 0)
            {
                bitNum++;
                count >>= 1;
            }

            // decode pletteEntries
            List<RLEX_RGB_TRIPLET> pletList = new List<RLEX_RGB_TRIPLET>();
            for (int i = 0; i < rlex.paletteCount; i++)
            {
                RLEX_RGB_TRIPLET plet = new RLEX_RGB_TRIPLET();
                if (!DecodeByte(ref plet.B)) return false;
                if (!DecodeByte(ref plet.G)) return false;
                if (!DecodeByte(ref plet.R)) return false;
                rlexByteCount -= 3;
                pletList.Add(plet);
            }
            rlex.paletteEntries = pletList.ToArray();

            // decode rlex segments
            List<CLEARCODEC_SUBCODEC_RLEX_SEGMENT> segList = new List<CLEARCODEC_SUBCODEC_RLEX_SEGMENT>();
            while (rlexByteCount > 0)
            {
                CLEARCODEC_SUBCODEC_RLEX_SEGMENT rlex_seg = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT();
                byte decodedBytes = DecodeRlexSeg(bitNum, ref rlex_seg);
                if (decodedBytes == 0) return false;
                rlexByteCount -= decodedBytes;
                segList.Add(rlex_seg);
            }

            if (rlexByteCount < 0) return false;
            rlex.segments = segList.ToArray();
            return true;
        }
        /// <summary>
        /// Encode a bitmap with RLEX method
        /// </summary>
        /// <param name="subcodeBmp">The bitmap to be encoded in subcodec layer.</param>
        /// <return> > 0 if encode success, otherwise return 0 </return>
        public static bool RlexEncode(Bitmap subcodecBmp, ref CLEARCODEC_SUBCODEC_RLEX rlex)
        {
            if (subcodecBmp == null) return false;

            Dictionary<RLEX_RGB_TRIPLET, byte> pletteDict = GetTripletDict(subcodecBmp);

            // if the bitmap color number is bigger than 255, RLEX subcodec encoding can't be applied.
            if (pletteDict.Count() > 0xff)
                return false;

            rlex.paletteCount = (byte)pletteDict.Count();
            rlex.paletteEntries = new RLEX_RGB_TRIPLET[rlex.paletteCount];
            int index=0;
            foreach (KeyValuePair<RLEX_RGB_TRIPLET, byte> triPlette in pletteDict)
            {
                rlex.paletteEntries[index] = triPlette.Key;
                index++;
            }

            List<CLEARCODEC_SUBCODEC_RLEX_SEGMENT> rlexSegList = new List<CLEARCODEC_SUBCODEC_RLEX_SEGMENT>();
            CLEARCODEC_SUBCODEC_RLEX_SEGMENT rlex_seg = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT();

            rlex_seg.suiteDepth = 0; // we always set suite depth is 0 due to only 1 color in a suite
            rlex_seg.stopIndex = ColorToPletIdx(subcodecBmp.GetPixel(0, 0), pletteDict);
            rlex_seg.runLengthFactor = 0;   // the first pixel in blow loop is at (0, 0), rlfactor is init as 0 here.

            for (int y = 0; y < subcodecBmp.Height; y++)
            {
                for (int x = 0; x < subcodecBmp.Width; x++)
                {
                    if (x == 0 && y == 0) continue; // skip the pixel (0, 0)
                    Color pixelColor = subcodecBmp.GetPixel(x, y);
                    byte pletIdx = ColorToPletIdx(pixelColor, pletteDict);

                    if (rlex_seg.stopIndex == pletIdx)  // same color as previous one
                    {
                        rlex_seg.runLengthFactor++;
                    }
                    else
                    {
                        // add old structure into list
                        rlexSegList.Add(rlex_seg);
                        // create a new structure for the pixel
                        rlex_seg = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT();
                        rlex_seg.suiteDepth = 0;
                        rlex_seg.stopIndex = pletIdx;
                        rlex_seg.runLengthFactor = 0;
                    }
                }

            }
            // add the final structure into list
            rlexSegList.Add(rlex_seg);

            rlex.segments = rlexSegList.ToArray();

            return true;
        }
        /// <summary>
        /// Convert CLEARCODEC_SUBCODEC_RLEX structure into byte stream.
        /// </summary>
        /// <param name="rlex">The encoded CLEARCODEC_SUBCODEC_RLEX structure.</param>
        public byte[] ToBytes(CLEARCODEC_SUBCODEC_RLEX rlex)
        {
            List<byte> bufList = new List<byte>();

            if (ccTestType != RdpegfxNegativeTypes.ClearCodec_Band_Subcodec_IncorrectPaletteCount)
            {
                bufList.AddRange(TypeMarshal.ToBytes<byte>(rlex.paletteCount));
            }
            else
            {
                bufList.AddRange(TypeMarshal.ToBytes<byte>((byte)(rlex.paletteCount + 1)));
            }
            for (int i = 0; i < rlex.paletteEntries.Count(); i++)
            {
                bufList.AddRange(TypeMarshal.ToBytes<byte>(rlex.paletteEntries[i].B));
                bufList.AddRange(TypeMarshal.ToBytes<byte>(rlex.paletteEntries[i].G));
                bufList.AddRange(TypeMarshal.ToBytes<byte>(rlex.paletteEntries[i].R));
            }

            // Blow encode rlex segment.

            // Calculate bit number for stopIndex.
            byte bitNum = 0;
            byte count = (byte)(rlex.paletteCount - 1);

            while (count > 0)
            {
                bitNum++;
                count >>= 1;
            }

            for (int i = 0; i < rlex.segments.Count(); i++)
            {
                byte stopIdx_suiteDepth = (byte)(rlex.segments[i].stopIndex | (rlex.segments[i].suiteDepth << bitNum));
                bufList.AddRange(TypeMarshal.ToBytes<byte>(stopIdx_suiteDepth));
                if (rlex.segments[i].runLengthFactor < 0xff)
                {
                    bufList.AddRange(TypeMarshal.ToBytes<byte>((byte)rlex.segments[i].runLengthFactor));
                }
                else if (rlex.segments[i].runLengthFactor < 0xffff)
                {
                    bufList.AddRange(TypeMarshal.ToBytes<byte>((byte)0xff));
                    bufList.AddRange(TypeMarshal.ToBytes<ushort>((ushort)rlex.segments[i].runLengthFactor));
                }
                else
                {
                    bufList.AddRange(TypeMarshal.ToBytes<byte>((byte)0xff));
                    bufList.AddRange(TypeMarshal.ToBytes<ushort>((ushort)0xffff));
                    bufList.AddRange(TypeMarshal.ToBytes<uint>((uint)rlex.segments[i].runLengthFactor));
                }
            }

            return bufList.ToArray();
        }
        /// <summary>
        /// It decode rlexByteCount bytes data into CLEARCODEC_SUBCODEC_RLEX structure
        /// </summary>
        /// <param name = "rlexByteCount"> the number of bytes to be decoded into CLEARCODEC_SUBCODEC_RLEX structure </param>
        /// <param name = "rlex"> the structure that decode result save to </param>
        /// <return> true if decode success, otherwise return false </return>
        public bool DecodeRlexData(uint rlexByteCount, ref CLEARCODEC_SUBCODEC_RLEX rlex)
        {
            if (!DecodeByte(ref rlex.paletteCount))
            {
                return(false);
            }
            rlexByteCount--;

            // calculate bitNum of stopIndex in rlex segment
            byte bitNum = 0;
            byte count  = rlex.paletteCount;

            // calculate bit number for stopIndex
            while (count > 0)
            {
                bitNum++;
                count >>= 1;
            }

            // decode pletteEntries
            List <RLEX_RGB_TRIPLET> pletList = new List <RLEX_RGB_TRIPLET>();

            for (int i = 0; i < rlex.paletteCount; i++)
            {
                RLEX_RGB_TRIPLET plet = new RLEX_RGB_TRIPLET();
                if (!DecodeByte(ref plet.B))
                {
                    return(false);
                }
                if (!DecodeByte(ref plet.G))
                {
                    return(false);
                }
                if (!DecodeByte(ref plet.R))
                {
                    return(false);
                }
                rlexByteCount -= 3;
                pletList.Add(plet);
            }
            rlex.paletteEntries = pletList.ToArray();

            // decode rlex segments
            List <CLEARCODEC_SUBCODEC_RLEX_SEGMENT> segList = new List <CLEARCODEC_SUBCODEC_RLEX_SEGMENT>();

            while (rlexByteCount > 0)
            {
                CLEARCODEC_SUBCODEC_RLEX_SEGMENT rlex_seg = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT();
                byte decodedBytes = DecodeRlexSeg(bitNum, ref rlex_seg);
                if (decodedBytes == 0)
                {
                    return(false);
                }
                rlexByteCount -= decodedBytes;
                segList.Add(rlex_seg);
            }

            if (rlexByteCount < 0)
            {
                return(false);
            }
            rlex.segments = segList.ToArray();
            return(true);
        }
        /// <summary>
        /// Encode a bitmap with RLEX method
        /// </summary>
        /// <param name="subcodeBmp">The bitmap to be encoded in subcodec layer.</param>
        /// <return> > 0 if encode success, otherwise return 0 </return>
        public static bool RlexEncode(Bitmap subcodecBmp, ref CLEARCODEC_SUBCODEC_RLEX rlex)
        {
            if (subcodecBmp == null)
            {
                return(false);
            }

            Dictionary <RLEX_RGB_TRIPLET, byte> pletteDict = GetTripletDict(subcodecBmp);

            // if the bitmap color number is bigger than 255, RLEX subcodec encoding can't be applied.
            if (pletteDict.Count() > 0xff)
            {
                return(false);
            }

            rlex.paletteCount   = (byte)pletteDict.Count();
            rlex.paletteEntries = new RLEX_RGB_TRIPLET[rlex.paletteCount];
            int index = 0;

            foreach (KeyValuePair <RLEX_RGB_TRIPLET, byte> triPlette in pletteDict)
            {
                rlex.paletteEntries[index] = triPlette.Key;
                index++;
            }

            List <CLEARCODEC_SUBCODEC_RLEX_SEGMENT> rlexSegList = new List <CLEARCODEC_SUBCODEC_RLEX_SEGMENT>();
            CLEARCODEC_SUBCODEC_RLEX_SEGMENT        rlex_seg    = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT();

            rlex_seg.suiteDepth      = 0; // we always set suite depth is 0 due to only 1 color in a suite
            rlex_seg.stopIndex       = ColorToPletIdx(subcodecBmp.GetPixel(0, 0), pletteDict);
            rlex_seg.runLengthFactor = 0; // the first pixel in blow loop is at (0, 0), rlfactor is init as 0 here.

            for (int y = 0; y < subcodecBmp.Height; y++)
            {
                for (int x = 0; x < subcodecBmp.Width; x++)
                {
                    if (x == 0 && y == 0)
                    {
                        continue;                   // skip the pixel (0, 0)
                    }
                    Color pixelColor = subcodecBmp.GetPixel(x, y);
                    byte  pletIdx    = ColorToPletIdx(pixelColor, pletteDict);

                    if (rlex_seg.stopIndex == pletIdx)  // same color as previous one
                    {
                        rlex_seg.runLengthFactor++;
                    }
                    else
                    {
                        // add old structure into list
                        rlexSegList.Add(rlex_seg);
                        // create a new structure for the pixel
                        rlex_seg                 = new CLEARCODEC_SUBCODEC_RLEX_SEGMENT();
                        rlex_seg.suiteDepth      = 0;
                        rlex_seg.stopIndex       = pletIdx;
                        rlex_seg.runLengthFactor = 0;
                    }
                }
            }
            // add the final structure into list
            rlexSegList.Add(rlex_seg);

            rlex.segments = rlexSegList.ToArray();

            return(true);
        }