/// <summary>
        /// It decode subcodec layer byte stream into CLEARCODEC_SUBCODECS_DATA structure.
        /// </summary>
        /// <param name="subcodecData">The structure that decode result save to.</param>
        /// <returns>true if decode success, otherwise return false.</returns>
        public bool Decode(ref CLEARCODEC_SUBCODEC_DATA subcodecData)
        {
            if (decodeData == null) return false;

            List<CLEARCODEC_SUBCODEC> subcodecList = new List<CLEARCODEC_SUBCODEC>();
            while (offset < decodeData.Count())
            {
                CLEARCODEC_SUBCODEC subcodec = new CLEARCODEC_SUBCODEC();
                if (!DecodeSubcodec(ref subcodec)) return false;
                subcodecList.Add(subcodec);
            }
            subcodecData.subcodecArr = subcodecList.ToArray();
            return true;
        }
        /// <summary>
        /// Convert CLEARCODEC_SUBCODEC structure into byte stream.
        /// </summary>
        /// <param name="scStruct">The encoded CLEARCODEC_SUBCODEC structure.</param>
        public byte[] ToBytes(CLEARCODEC_SUBCODEC_DATA subcodecsData)
        {
            List <byte> bufList = new List <byte>();

            if (subcodecsData.subcodecArr == null)
            {
                return(null);
            }
            for (int i = 0; i < subcodecsData.subcodecArr.Count(); i++)
            {
                bufList.AddRange(ToBytes(subcodecsData.subcodecArr[i]));
            }

            return(bufList.ToArray());
        }
        /// <summary>
        /// It decode subcodec layer byte stream into CLEARCODEC_SUBCODECS_DATA structure.
        /// </summary>
        /// <param name="subcodecData">The structure that decode result save to.</param>
        /// <returns>true if decode success, otherwise return false.</returns>
        public bool Decode(ref CLEARCODEC_SUBCODEC_DATA subcodecData)
        {
            if (decodeData == null)
            {
                return(false);
            }

            List <CLEARCODEC_SUBCODEC> subcodecList = new List <CLEARCODEC_SUBCODEC>();

            while (offset < decodeData.Count())
            {
                CLEARCODEC_SUBCODEC subcodec = new CLEARCODEC_SUBCODEC();
                if (!DecodeSubcodec(ref subcodec))
                {
                    return(false);
                }
                subcodecList.Add(subcodec);
            }
            subcodecData.subcodecArr = subcodecList.ToArray();
            return(true);
        }
        /// <summary>
        /// Encode multiple bitmap areas via subcodec into byte stream
        /// </summary>
        /// <param name="bandDict">The structure saves multiple subcodec layer bitmap, subcodecID and position.</param>
        public static CLEARCODEC_SUBCODEC_DATA Encode(Dictionary <ClearCodec_RECT16, BMP_INFO> subcodecDict)
        {
            List <CLEARCODEC_SUBCODEC> subcodecList = new List <CLEARCODEC_SUBCODEC>();

            foreach (KeyValuePair <ClearCodec_RECT16, BMP_INFO> scArea in subcodecDict)
            {
                CLEARCODEC_SUBCODEC scData = new CLEARCODEC_SUBCODEC();
                if (!EncodeSubcodec((Bitmap)(scArea.Value.bmp), scArea.Key, scArea.Value.scID, ref scData))
                {
                    // skip a subcodec layer bitmap if it failed to be encoded.
                    continue;
                }

                subcodecList.Add(scData);
            }

            CLEARCODEC_SUBCODEC_DATA subcodecs = new CLEARCODEC_SUBCODEC_DATA();

            subcodecs.subcodecArr = subcodecList.ToArray();

            return(subcodecs);
        }
        /// <summary>
        /// Encode multiple bitmap areas via subcodec into byte stream
        /// </summary>
        /// <param name="bandDict">The structure saves multiple subcodec layer bitmap, subcodecID and position.</param>
        public static CLEARCODEC_SUBCODEC_DATA Encode(Dictionary<ClearCodec_RECT16, BMP_INFO> subcodecDict)
        {
            List<CLEARCODEC_SUBCODEC> subcodecList = new List<CLEARCODEC_SUBCODEC>();

            foreach (KeyValuePair<ClearCodec_RECT16, BMP_INFO> scArea in subcodecDict)
            {
                CLEARCODEC_SUBCODEC scData = new CLEARCODEC_SUBCODEC();
                if (!EncodeSubcodec((Bitmap)(scArea.Value.bmp), scArea.Key, scArea.Value.scID, ref scData))
                {
                    // skip a subcodec layer bitmap if it failed to be encoded.
                    continue;
                }

                subcodecList.Add(scData);
            }

            CLEARCODEC_SUBCODEC_DATA subcodecs = new CLEARCODEC_SUBCODEC_DATA();
            subcodecs.subcodecArr = subcodecList.ToArray();

            return subcodecs;
        }
        /// <summary>
        /// Convert CLEARCODEC_SUBCODEC structure into byte stream.
        /// </summary>
        /// <param name="scStruct">The encoded CLEARCODEC_SUBCODEC structure.</param>
        public byte[] ToBytes(CLEARCODEC_SUBCODEC_DATA subcodecsData)
        {
            List<byte> bufList = new List<byte>();

            if (subcodecsData.subcodecArr == null) return null;
            for (int i = 0; i < subcodecsData.subcodecArr.Count(); i++)
            {
                bufList.AddRange(ToBytes(subcodecsData.subcodecArr[i]));
            }

            return bufList.ToArray();
        }
        /// <summary>
        /// Encode the residual, band, and subcodec layer images into a bytestream.
        /// </summary>
        public byte[] EncodeCompositePayload()
        {
            List <byte> buf = new List <byte>();

            if (resBmp != null)
            {
                CLEARCODEC_RESIDUAL_DATA resData = ClearCodecResidualEncoder.Encode(resBmp);
                compPayload.residualData = ToBytes(resData);
                if (compPayload.residualData == null)
                {
                    return(null);
                }
                compPayload.residualByteCount = (uint)compPayload.residualData.Count();
            }
            else
            {
                compPayload.residualByteCount = 0;
                compPayload.residualData      = null;
            }

            if (bandDict.Count() != 0)  // Band image are loaded before.
            {
                ClearCodecBandEncoder bandencoder = ClearCodecBandEncoder.GetInstance();
                if ((this.flags & ClearCodec_BitmapStream.CLEARCODEC_FLAG_CACHE_RESET) != 0)
                {
                    bandencoder.ResetVBarStorage();
                }
                CLEARCODEC_BAND_DATA bandsData = bandencoder.Encode(bandDict);
                compPayload.bandData = ToBytes(bandsData);
                if (compPayload.bandData == null)
                {
                    return(null);
                }
                compPayload.bandByteCount = (uint)compPayload.bandData.Count();
            }
            else
            {
                compPayload.bandByteCount = 0;
                compPayload.bandData      = null;
            }

            if (subcodecDict.Count() != 0)  // Subcodec image are loaded before.
            {
                CLEARCODEC_SUBCODEC_DATA subcodecs = ClearCodecSubCodecEncoder.Encode(subcodecDict);
                compPayload.subcodecData = ToBytes(subcodecs);
                if (compPayload.subcodecData == null)
                {
                    return(null);
                }
                compPayload.subcodecByteCount = (uint)compPayload.subcodecData.Count();
            }
            else
            {
                compPayload.subcodecByteCount = 0;
                compPayload.subcodecData      = null;
            }

            buf.AddRange(TypeMarshal.ToBytes <uint>(compPayload.residualByteCount));
            buf.AddRange(TypeMarshal.ToBytes <uint>(compPayload.bandByteCount));
            buf.AddRange(TypeMarshal.ToBytes <uint>(compPayload.subcodecByteCount));

            if (compPayload.residualByteCount > 0)
            {
                buf.AddRange(compPayload.residualData);
            }

            if (compPayload.bandByteCount > 0)
            {
                buf.AddRange(compPayload.bandData);
            }

            if (compPayload.subcodecByteCount > 0)
            {
                buf.AddRange(compPayload.subcodecData);
            }

            return(buf.ToArray());
        }