/// <summary>
        /// Create region block based on test type.
        /// </summary>
        /// <param name="bReduceExtrapolate">This is used to indicate if DWT uses the "Reduce Extrapolate" method.</param>
        /// <param name="tileDict">This is used to indicate the dictionary of tile index and encoded data.</param>
        /// <param name="tileDataLength">This is used to indicate the encoded tile data length.</param>
        /// <param name="tileBlockType">This is used to indicate the tile data block type(simple, first, or upgrade).</param>
        public override RFX_Progressive_REGION BuildRegionBlock(bool bReduceExtrapolate, Dictionary<TileIndex, EncodedTile> tileDict, uint tileDataLength, RFXProgCodecBlockType tileBlockType)
        {
            RFX_Progressive_REGION region_block = base.BuildRegionBlock(bReduceExtrapolate, tileDict, tileDataLength, tileBlockType);
            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectLen)
            {
                region_block.blockLen += 1; // Set block length into incorrect value.
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectTileSize)
            {
                region_block.tileSize += 1; // Set tile size in region block is other than 64.
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectRectsNumber)
            {
                region_block.numRects += 1;  // Set numRects larger 1 than TS_RFX_RECT number in region_block.rects field.
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_ZeroRectsNumber)
            {
                // Set Rect number is zero
                region_block.numRects = 0;
                region_block.rects = null;
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectQuantNumber)
            {
                region_block.numQuant += 1; // Set numQuant larger 1 than TS_RFX_CODEC_QUANT number in region_block.quantVals field.
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_ZeroQuantNumber)
            {
                // Set quant data number is zero.
                region_block.numQuant = 0;
                region_block.quantVals = null;
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectProgQuantNumber)
            {
                region_block.numProgQuant += 1; // Set numProgQuant larger 1 than RFX_RPROGRESSIVE_CODEC_QUANT number in quantProgVals field.
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectTileBlockNumber)
            {
                region_block.numTiles += 1;  // Set numTiles larger 1 than tile block number in tiles field.
            }

            return region_block;
        }
        /// <summary>
        /// Create region block.
        /// </summary>
        /// <param name="bReduceExtrapolate">This is used to indicate if DWT uses the "Reduce Extrapolate" method.</param>
        /// <param name="tileDict">This is used to indicate the dictionary of tile index and encoded data.</param>
        /// <param name="tileDataLength">This is used to indicate the encoded tile data length.</param>
        /// <param name="tileBlockType">This is used to indicate the tile data block type(simple, first, or upgrade).</param>
        public virtual RFX_Progressive_REGION BuildRegionBlock(bool bReduceExtrapolate, Dictionary<TileIndex, EncodedTile> TileDict, uint tileDataLength, RFXProgCodecBlockType tileBlockType)
        {
            // Create region block data.
            byte tfFlag = Convert.ToByte(bReduceExtrapolate);
            List<TS_RFX_RECT> tileRectList = new List<TS_RFX_RECT>();
            foreach (KeyValuePair<TileIndex, EncodedTile> tilePair in TileDict)
            {

                TS_RFX_RECT tileRect = new TS_RFX_RECT();
                tileRect.x = (ushort)(tilePair.Key.X * RFX_Progressive_CONST.CONTEXT_TILESIZE);
                tileRect.y = (ushort)(tilePair.Key.Y * RFX_Progressive_CONST.CONTEXT_TILESIZE);
                tileRect.width = tilePair.Key.WidthInSurface;
                tileRect.height = tilePair.Key.HeightInSurface;

                tileRectList.Add(tileRect);
            }
            TS_RFX_RECT[] tileRects = tileRectList.ToArray();
            EncodedTile[] tileDataArr = TileDict.Values.ToArray();

            bool bProg = (tileBlockType == RFXProgCodecBlockType.WBT_TILE_SIMPLE) ? false : true;

            RFX_Progressive_REGION region_block = new RFX_Progressive_REGION(bProg, tfFlag, tileDataLength, tileRects, tileDataArr);
            return region_block;
        }
        /// <summary>
        /// Build tile data blocks(tile simple or tile first or tile upgrade).
        /// </summary>
        /// <param name="quantIdx">This is used to indicate index in TS_RFX_CODEC_QUANT array of region block</param>
        /// <param name="tileIdx">This is used to indicate the tile index.</param>
        /// <param name="tileData">This is used to indicate the encoded tile data.</param>
        /// <param name="tileBlockType">This is used to indicate the tile data block type(simple, first, or upgrade).</param>
        public RFX_Progressive_DataBlock BuildTileDataBlock(byte quantIdx, TileIndex tileIdx, EncodedTile tileData, RFXProgCodecBlockType tileBlockType)
        {
            RFX_Progressive_DataBlock tile_block;

            if (tileBlockType == RFXProgCodecBlockType.WBT_TILE_PROGRESSIVE_FIRST)
            {
                tile_block = new RFX_Progressive_TILE_FIRST(quantIdx, tileIdx, tileData);
            }
            else if (tileBlockType == RFXProgCodecBlockType.WBT_TILE_PROGRESSIVE_UPGRADE)
            {
                tile_block = new RFX_PROGRESSIVE_TILE_UPGRADE(quantIdx, tileIdx, tileData);
            }
            else
            {
                tile_block = new RFX_Progressive_TILE_SIMPLE(quantIdx, tileIdx, tileData);
            }

            return tile_block;
        }
        /// <summary>
        /// Decode this PDU from the PduMarshaler.
        /// </summary>
        /// <param name="marshaler">This is used to decode the fields of this PDU.</param>
        public override bool Decode(PduMarshaler marshaler)
        {
            try
            {
                this.blockType = (RFXProgCodecBlockType) marshaler.ReadUInt16();
                this.blockLen = marshaler.ReadUInt32();

                this.decodedLen = 6;
                return true;
            }
            catch
            {
                marshaler.Reset();
                throw new PDUDecodeException(this.GetType(), marshaler.ReadToEnd());
            }
        }
        /// <summary>
        /// Return a binary array for a tile data which is encoded by Rfx Progressive Codec.
        /// </summary>
        /// <param name="bSync">This is used to indicate if sync block needed.</param>
        /// <param name="bContext">This is used to indicate if context block needed.</param>
        /// <param name="bSubDiff">This is used to indicate if subband_diffing flag is enabled in context block.</param>
        /// <param name="bReduceExtrapolate">This is used to indicate if DWT uses the "Reduce Extrapolate" method.</param>
        /// <param name="tileDict">This is used to indicate the dictionary of tile index and encoded data.</param>
        /// <param name="tileDataType">This is used to indicate the tile data type(simple, first, or upgrade).</param>
        public byte[] PackRfxProgCodecDataBlock(bool bSync, bool bContext, bool bSubDiff, bool bReduceExtrapolate,
            Dictionary<TileIndex, EncodedTile> tileDict, RFXProgCodecBlockType tileDataType)
        {
            // Clear existing blocks before create a new RFX_progressive_datablock frame.
            blkList.Clear();
            ushort regionCount = 1;   // Set region count as 1 by default.

            // Create frame begin block and previous sync/context block if needed.
            CreateBeginBlocks(bSync, bContext, bSubDiff, regionCount);

            // Create region and tile data blocks.
            CreateRegionTileBlocks(bReduceExtrapolate, tileDict, tileDataType);

            // Create and add frame_end block.
            CreateFrameEndBlock();

            return ToBytes();
        }
        /// <summary>
        /// Create region blocks and tile data blocks(tile simple or tile first or tile upgrade).
        /// </summary>
        /// <param name="bReduceExtrapolate">This is used to indicate if DWT uses the "Reduce Extrapolate" method.</param>
        /// <param name="tileDict">This is used to indicate the dictionary of tile index and encoded data.</param>
        /// <param name="tileBlockType">This is used to indicate the tile data block type(simple, first, or upgrade).</param>
        public virtual void CreateRegionTileBlocks(bool bReduceExtrapolate, Dictionary<TileIndex, EncodedTile> tileDict, RFXProgCodecBlockType tileBlockType)
        {
            List<RFX_Progressive_DataBlock> tile_block_list = new List<RFX_Progressive_DataBlock>();
            uint tileDataLength = 0;

            foreach (KeyValuePair<TileIndex, EncodedTile> tilePair in tileDict)
            {
                // Set quantIdx is always 0 since all tiles share same quant table.
                RFX_Progressive_DataBlock tile_block = BuildTileDataBlock(0, tilePair.Key, tilePair.Value, tileBlockType);
                tile_block_list.Add(tile_block);
                tileDataLength += tile_block.blockLen;
            }

            RFX_Progressive_REGION region_block = BuildRegionBlock(bReduceExtrapolate, tileDict, tileDataLength, tileBlockType);

            blkList.Add(region_block);
            // Add tile_data blocks after region block
            blkList.AddRange(tile_block_list);
        }
        /// <summary>
        /// Create region blocks and tile data blocks(tile simple or tile first or tile upgrade) based on test type.
        /// </summary>
        /// <param name="bReduceExtrapolate">This is used to indicate if DWT uses the "Reduce Extrapolate" method.</param>
        /// <param name="tileDict">This is used to indicate the dictionary of tile index and encoded data.</param>
        /// <param name="tileBlockType">This is used to indicate the tile data block type(simple, first, or upgrade).</param>
        public override void CreateRegionTileBlocks(bool bReduceExtrapolate, Dictionary <TileIndex, EncodedTile> tileDict, RFXProgCodecBlockType tileBlockType)
        {
            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_AfterFrameEndBlock)
            {
                base.CreateFrameEndBlock();
            }

            List <RFX_Progressive_DataBlock> tile_block_list = new List <RFX_Progressive_DataBlock>();
            uint tileDataLength = 0;
            RFX_Progressive_DataBlock tile_block = new RFX_Progressive_DataBlock();

            foreach (KeyValuePair <TileIndex, EncodedTile> tilePair in tileDict)
            {
                // Set quantIdx is always 0 since all tiles share same quant table.
                tile_block = BuildTileDataBlock(0, tilePair.Key, tilePair.Value, tileBlockType);
                tile_block_list.Add(tile_block);
                tileDataLength += tile_block.blockLen;
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_InvalidTileBlockType)
            {
                // Change type of last block
                tile_block.blockType = (RFXProgCodecBlockType)0xffff; // Set invalid block type to 0xffff.
            }

            RFX_Progressive_REGION region_block = BuildRegionBlock(bReduceExtrapolate, tileDict, tileDataLength, tileBlockType);

            blkList.Add(region_block);

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_BeforeFrameBeginBlock)
            {
                CreateFrameBeginBlock(1);   // Set region count as 1 since encoded image data exists.
            }

            // Add tile_data blocks after region block.
            blkList.AddRange(tile_block_list);
        }
        /// <summary>
        /// Create region block based on test type.
        /// </summary>
        /// <param name="bReduceExtrapolate">This is used to indicate if DWT uses the "Reduce Extrapolate" method.</param>
        /// <param name="tileDict">This is used to indicate the dictionary of tile index and encoded data.</param>
        /// <param name="tileDataLength">This is used to indicate the encoded tile data length.</param>
        /// <param name="tileBlockType">This is used to indicate the tile data block type(simple, first, or upgrade).</param>
        public override RFX_Progressive_REGION BuildRegionBlock(bool bReduceExtrapolate, Dictionary <TileIndex, EncodedTile> tileDict, uint tileDataLength, RFXProgCodecBlockType tileBlockType)
        {
            RFX_Progressive_REGION region_block = base.BuildRegionBlock(bReduceExtrapolate, tileDict, tileDataLength, tileBlockType);

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectLen)
            {
                region_block.blockLen += 1; // Set block length into incorrect value.
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectTileSize)
            {
                region_block.tileSize += 1; // Set tile size in region block is other than 64.
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectRectsNumber)
            {
                region_block.numRects += 1;  // Set numRects larger 1 than TS_RFX_RECT number in region_block.rects field.
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_ZeroRectsNumber)
            {
                // Set Rect number is zero
                region_block.numRects = 0;
                region_block.rects    = null;
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectQuantNumber)
            {
                region_block.numQuant += 1; // Set numQuant larger 1 than TS_RFX_CODEC_QUANT number in region_block.quantVals field.
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_ZeroQuantNumber)
            {
                // Set quant data number is zero.
                region_block.numQuant  = 0;
                region_block.quantVals = null;
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectProgQuantNumber)
            {
                region_block.numProgQuant += 1; // Set numProgQuant larger 1 than RFX_RPROGRESSIVE_CODEC_QUANT number in quantProgVals field.
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_IncorrectTileBlockNumber)
            {
                region_block.numTiles += 1;  // Set numTiles larger 1 than tile block number in tiles field.
            }

            return(region_block);
        }
        /// <summary>
        /// Create region blocks and tile data blocks(tile simple or tile first or tile upgrade) based on test type.
        /// </summary>
        /// <param name="bReduceExtrapolate">This is used to indicate if DWT uses the "Reduce Extrapolate" method.</param>
        /// <param name="tileDict">This is used to indicate the dictionary of tile index and encoded data.</param>
        /// <param name="tileBlockType">This is used to indicate the tile data block type(simple, first, or upgrade).</param>
        public override void CreateRegionTileBlocks(bool bReduceExtrapolate, Dictionary<TileIndex, EncodedTile> tileDict, RFXProgCodecBlockType tileBlockType)
        {
            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_AfterFrameEndBlock)
            {
                base.CreateFrameEndBlock();
            }

            List<RFX_Progressive_DataBlock> tile_block_list = new List<RFX_Progressive_DataBlock>();
            uint tileDataLength = 0;
            RFX_Progressive_DataBlock tile_block = new RFX_Progressive_DataBlock();

            foreach (KeyValuePair<TileIndex, EncodedTile> tilePair in tileDict)
            {
                // Set quantIdx is always 0 since all tiles share same quant table.
                tile_block = BuildTileDataBlock(0, tilePair.Key, tilePair.Value, tileBlockType);
                tile_block_list.Add(tile_block);
                tileDataLength += tile_block.blockLen;
            }

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_InvalidTileBlockType)
            {
                // Change type of last block
                tile_block.blockType = (RFXProgCodecBlockType)0xffff; // Set invalid block type to 0xffff.
            }

            RFX_Progressive_REGION region_block = BuildRegionBlock(bReduceExtrapolate, tileDict, tileDataLength, tileBlockType);

            blkList.Add(region_block);

            if (bmTestType == RdpegfxNegativeTypes.RfxProgCodec_RegionBlock_BeforeFrameBeginBlock)
            {
                CreateFrameBeginBlock(1);   // Set region count as 1 since encoded image data exists.
            }

            // Add tile_data blocks after region block.
            blkList.AddRange(tile_block_list);
        }