/// <summary>
        /// It decode rawDataCount bytes data into RLEX_RGB_TRIPLET structure array
        /// </summary>
        /// <param name = "rawDataCount"> the number of bytes to be decoeded as raw bitmap </param>
        /// <param name = "bmpPixels"> the structure array that decode result save to </param>
        /// <return> > true if decode success, otherwise return false </return>
        public bool DecodeRawData(uint rawDataCount, ref RLEX_RGB_TRIPLET[] bmpPixels)
        {
            List <RLEX_RGB_TRIPLET> pixelList = new List <RLEX_RGB_TRIPLET>();

            while (rawDataCount > 0)
            {
                RLEX_RGB_TRIPLET pixel = new RLEX_RGB_TRIPLET();
                if (!DecodeByte(ref pixel.B))
                {
                    return(false);
                }
                if (!DecodeByte(ref pixel.G))
                {
                    return(false);
                }
                if (!DecodeByte(ref pixel.R))
                {
                    return(false);
                }
                rawDataCount -= 3;
                pixelList.Add(pixel);
            }
            if (rawDataCount < 0)
            {
                return(false);
            }
            bmpPixels = pixelList.ToArray();
            return(true);
        }
        /// <summary>
        /// convert a color into RLEX_RGB_TRIPLET structure
        /// </summary>
        /// <param name="pixelColor">The color to be converted.</param>
        public static RLEX_RGB_TRIPLET Convert2RGB(Color pixelColor)
        {
            RLEX_RGB_TRIPLET rgbPlette = new RLEX_RGB_TRIPLET();

            rgbPlette.B = pixelColor.B;
            rgbPlette.G = pixelColor.G;
            rgbPlette.R = pixelColor.R;
            return(rgbPlette);
        }
        /// <summary>
        /// Encode a bitmap with
        /// </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 RawEncode(Bitmap subcodecBmp, ref RLEX_RGB_TRIPLET[] bmpPixels)
        {
            if (subcodecBmp == null)
            {
                return(false);
            }

            List <RLEX_RGB_TRIPLET> pixelList = new List <RLEX_RGB_TRIPLET>();

            for (int y = 0; y < subcodecBmp.Height; y++)
            {
                for (int x = 0; x < subcodecBmp.Width; x++)
                {
                    Color            pixelColor = subcodecBmp.GetPixel(x, y);
                    RLEX_RGB_TRIPLET rgbPlette  = Convert2RGB(pixelColor);
                    pixelList.Add(rgbPlette);
                }
            }
            bmpPixels = pixelList.ToArray();
            return(true);
        }
        /// <summary>
        /// Go through the bitmap to find all unique color
        /// </summary>
        /// <param name="subcodeBmp">The bitmap to be encoded in subcodec layer.</param>
        /// <return> a plette dictionary of all unique pixel and it's index in plette  </return>
        public static Dictionary <RLEX_RGB_TRIPLET, byte> GetTripletDict(Bitmap bitmap)
        {
            Dictionary <RLEX_RGB_TRIPLET, byte> pletteIndexDict = new Dictionary <RLEX_RGB_TRIPLET, byte>();
            byte index = 0;

            for (int y = 0; y < bitmap.Height; y++)
            {
                for (int x = 0; x < bitmap.Width; x++)
                {
                    Color            pixelColor = bitmap.GetPixel(x, y);
                    RLEX_RGB_TRIPLET rgb        = Convert2RGB(pixelColor);

                    if (!pletteIndexDict.ContainsKey(rgb))
                    {
                        pletteIndexDict.Add(rgb, index);
                        index++;
                    }
                }
            }
            return(pletteIndexDict);
        }
        /// <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>
        /// Find the index of a color in pletteDict
        /// </summary>
        /// <param name="pixelColor">The color to search.</param>
        /// <param name="pletteDict">The plette dictionary to be searched.</param>
        /// <return> the index of a pixel in plette  </return>
        public static byte ColorToPletIdx(Color pixelColor, Dictionary <RLEX_RGB_TRIPLET, byte> pletteDict)
        {
            RLEX_RGB_TRIPLET rgbPlette = Convert2RGB(pixelColor);

            return(pletteDict[rgbPlette]);
        }