// The output format is
        // firstPass [X, Y, Z]
        // ProgressivePass1 [encodedX, encodedY, encodedZ]
        // ProgressivePass1 [rawX, rawY, rawZ]
        // ...
        public static void RLGR_SRLEncode(List <Triplet <short[]> > input, ProgressiveQuantizationFactors proQuants, EntropyAlgorithm mode, bool UseReduceExtrapolate, out List <Triplet <byte[]> > output)
        {
            output = new List <Triplet <byte[]> >();
            byte[] x, y, z;

            // fisrt pass
            Triplet <short[]> firstPass = input[0];

            ComputeLL3Deltas(firstPass, UseReduceExtrapolate);
            RFXEncode.RFXEncoderWrapper.RLGREncode(firstPass.X, mode, out x);
            RFXEncode.RFXEncoderWrapper.RLGREncode(firstPass.Y, mode, out y);
            RFXEncode.RFXEncoderWrapper.RLGREncode(firstPass.Z, mode, out z);
            output.Add(new Triplet <byte[]>(x, y, z));

            // fake encodingContext used for SRL encode
            var encodingContext = new RfxProgressiveCodecContext(new [] { RdpegfxTileUtils.GetCodecQuant(ImageQuality_Values.Midium) }, 0, 0, 0, UseReduceExtrapolate);

            encodingContext.DAS = new DwtTile(firstPass.X, firstPass.Y, firstPass.Z);

            var progQuantList = new List <RFX_PROGRESSIVE_CODEC_QUANT>();

            foreach (var quant in proQuants.ProgQuants)
            {
                progQuantList.Add(Utility.ConvertProgQuant(quant));
            }

            // progressive pass
            for (int i = 1; i < input.Count; i++)
            {
                Triplet <short[]> progressivePass = input[i];
                encodingContext.ProgQ         = new DwtTile(progressivePass.X, progressivePass.Y, progressivePass.Z);
                encodingContext.prevProgQuant = progQuantList[i - 1];
                EncodedTile encodedTile = SRLEncode(encodingContext, progQuantList[i]);
                output.Add(new Triplet <byte[]>(encodedTile.YEncodedData, encodedTile.CbEncodedData, encodedTile.CrEncodedData));
                output.Add(new Triplet <byte[]>(encodedTile.YRawData, encodedTile.CbRawData, encodedTile.CrRawData));
                encodingContext.DAS.Add(new DwtTile(progressivePass.X, progressivePass.Y, progressivePass.Z));
                encodingContext.prevProgQuant = progQuantList[i];
            }
        }
        public static void SRLDecode(
            Triplet <byte[]> decodedData,
            Triplet <byte[]> rawData,
            QuantizationFactorsArray quant,
            Triplet <short[]> DAS,
            QuantizationFactorsArray preQuant,
            bool useReduceExtrapolate,
            out Triplet <short[]> output)
        {
            RFX_PROGRESSIVE_CODEC_QUANT progCodecQuant = Utility.ConvertProgQuant(quant);
            RFX_PROGRESSIVE_CODEC_QUANT preCodecQuant  = Utility.ConvertProgQuant(preQuant);
            // construct the fake parameter to invoke RfxProgressiveDecoder.SRLDecode
            var codecContext = new RfxProgressiveCodecContext(new[] { RdpegfxTileUtils.GetCodecQuant(ImageQuality_Values.Midium) }, 0, 0, 0, useReduceExtrapolate);
            var encodeTile   = new EncodedTile
            {
                YEncodedData         = decodedData.X,
                CbEncodedData        = decodedData.Y,
                CrEncodedData        = decodedData.Z,
                YRawData             = rawData.X,
                CbRawData            = rawData.Y,
                CrRawData            = rawData.Z,
                ProgCodecQuant       = progCodecQuant,
                UseReduceExtrapolate = useReduceExtrapolate // Important
            };
            var sentTile = new DwtTile(DAS.X, DAS.Y, DAS.Z);

            sentTile.ProgCodecQuant = preCodecQuant;
            var frame = new SurfaceFrame(0, RdpegfxTileUtils.TileSize, RdpegfxTileUtils.TileSize);

            frame.UpdateTileDwtQ(new TileIndex(0, 0, RdpegfxTileUtils.TileSize, RdpegfxTileUtils.TileSize), sentTile);
            frame.UpdateTriState(new TileIndex(0, 0, RdpegfxTileUtils.TileSize, RdpegfxTileUtils.TileSize), sentTile);
            var tileState = new TileState(frame, new TileIndex(0, 0, RdpegfxTileUtils.TileSize, RdpegfxTileUtils.TileSize));

            SRLDecode(codecContext, encodeTile, tileState);
            output = new Triplet <short[]>(codecContext.YComponent, codecContext.CbComponent, codecContext.CrComponent);
        }