From 442a044498beaced74d0e04c51cbcf4633300bc4 Mon Sep 17 00:00:00 2001
From: Taoran Lu <tlu@dolby.com>
Date: Thu, 24 Jan 2019 16:28:18 -0800
Subject: [PATCH] merge JVET-M0427 into master

---
 cfg/encoder_intra_vtm.cfg                     |    1 +
 source/App/EncoderApp/EncApp.cpp              |    6 +
 source/App/EncoderApp/EncAppCfg.cpp           |   55 +-
 source/App/EncoderApp/EncAppCfg.h             |    7 +-
 source/Lib/CommonLib/Buffer.cpp               |   93 ++
 source/Lib/CommonLib/Buffer.h                 |    5 +
 source/Lib/CommonLib/CodingStructure.cpp      |    8 +
 source/Lib/CommonLib/CodingStructure.h        |    3 +
 source/Lib/CommonLib/CommonDef.h              |   14 +-
 source/Lib/CommonLib/Picture.cpp              |   11 +
 source/Lib/CommonLib/Picture.h                |    8 +
 source/Lib/CommonLib/RdCost.cpp               |  103 ++
 source/Lib/CommonLib/RdCost.h                 |   14 +
 source/Lib/CommonLib/Reshape.cpp              |  232 +++
 source/Lib/CommonLib/Reshape.h                |  100 ++
 source/Lib/CommonLib/Slice.cpp                |   12 +
 source/Lib/CommonLib/Slice.h                  |   48 +-
 source/Lib/CommonLib/TypeDef.h                |   13 +
 source/Lib/CommonLib/Unit.cpp                 |    7 +
 source/Lib/CommonLib/Unit.h                   |    7 +
 source/Lib/DecoderLib/DecCu.cpp               |  139 ++
 source/Lib/DecoderLib/DecCu.h                 |   14 +-
 source/Lib/DecoderLib/DecLib.cpp              |   65 +-
 source/Lib/DecoderLib/DecLib.h                |    6 +
 source/Lib/DecoderLib/VLCReader.cpp           |   45 +-
 source/Lib/DecoderLib/VLCReader.h             |    4 +-
 .../Lib/EncoderLib/EncAdaptiveLoopFilter.cpp  |   31 +
 source/Lib/EncoderLib/EncAdaptiveLoopFilter.h |    6 +
 source/Lib/EncoderLib/EncCfg.h                |   18 +-
 source/Lib/EncoderLib/EncCu.cpp               |   87 ++
 source/Lib/EncoderLib/EncCu.h                 |    4 +-
 source/Lib/EncoderLib/EncGOP.cpp              |  135 ++
 source/Lib/EncoderLib/EncGOP.h                |    6 +
 source/Lib/EncoderLib/EncLib.cpp              |   28 +-
 source/Lib/EncoderLib/EncLib.h                |   10 +
 source/Lib/EncoderLib/EncReshape.cpp          | 1260 +++++++++++++++++
 source/Lib/EncoderLib/EncReshape.h            |  149 ++
 source/Lib/EncoderLib/EncSlice.cpp            |    7 +-
 source/Lib/EncoderLib/InterSearch.cpp         |  146 +-
 source/Lib/EncoderLib/InterSearch.h           |    9 +
 source/Lib/EncoderLib/IntraSearch.cpp         |  131 +-
 source/Lib/EncoderLib/IntraSearch.h           |   13 +-
 source/Lib/EncoderLib/VLCWriter.cpp           |   43 +
 source/Lib/EncoderLib/VLCWriter.h             |    3 +
 44 files changed, 3079 insertions(+), 27 deletions(-)
 create mode 100644 source/Lib/CommonLib/Reshape.cpp
 create mode 100644 source/Lib/CommonLib/Reshape.h
 create mode 100644 source/Lib/EncoderLib/EncReshape.cpp
 create mode 100644 source/Lib/EncoderLib/EncReshape.h

diff --git a/cfg/encoder_intra_vtm.cfg b/cfg/encoder_intra_vtm.cfg
index e3cc0a9ad..3495a5dd1 100644
--- a/cfg/encoder_intra_vtm.cfg
+++ b/cfg/encoder_intra_vtm.cfg
@@ -120,6 +120,7 @@ PBIntraFast                  : 1
 FastMrg                      : 1
 AMaxBT                       : 1
 
+
 ### DO NOT ADD ANYTHING BELOW THIS LINE ###
 ### DO NOT DELETE THE EMPTY LINE BELOW ###
 
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 611f6f82f..b68789432 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -550,6 +550,12 @@ void EncApp::xInitLibCfg()
 
 #endif
   m_cEncLib.setUseALF                                            ( m_alf );
+#if JVET_M0427_INLOOP_RESHAPER
+  m_cEncLib.setReshaper                                          ( m_bLumaReshapeEnable );
+  m_cEncLib.setReshapeSignalType                                 ( m_uiSignalType );
+  m_cEncLib.setReshapeIntraCMD                                   ( m_uiIntraCMD );
+  m_cEncLib.setReshapeCW                                         ( m_reshapeCW );
+#endif  
 }
 
 void EncApp::xCreateLib( std::list<PelUnitBuf*>& recBufList
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index ea91679e6..9be42f93d 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -707,6 +707,13 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #endif
   int warnUnknowParameter = 0;
 
+#if JVET_M0427_INLOOP_RESHAPER
+  const uint32_t defaultBinCW[CW_NUMS - 1]  = { 38, 28 };
+  const uint32_t defaultBinThr[CW_NUMS - 1] = { 2500, 4000 };
+  SMultiValueInput<uint32_t> cfg_BinCW          (0, 64, CW_NUMS - 1, CW_NUMS - 1, defaultBinCW, sizeof(defaultBinCW) / sizeof(uint32_t));
+  SMultiValueInput<uint32_t> cfg_BinThr         (0, std::numeric_limits<uint32_t>::max(), CW_NUMS - 1, CW_NUMS - 1, defaultBinThr, sizeof(defaultBinThr) / sizeof(uint32_t));
+#endif
+
 #if ENABLE_TRACING
   string sTracingRule;
   string sTracingFile;
@@ -882,7 +889,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("WrapAroundOffset",                                m_wrapAroundOffset,                                  0u, "Offset in luma samples used for computing the horizontal wrap-around position")
 
   // ADD_NEW_TOOL : (encoder app) add parsing parameters here
-
+#if JVET_M0427_INLOOP_RESHAPER
+  ("LumaReshapeEnable",                               m_bLumaReshapeEnable,                             false, "Enable Reshaping for Luma Channel")
+  ("ReshapeSignalType",                               m_uiSignalType,                                      0u, "Input signal type: 0: SDR, 1:PQ, 2:HLG")
+  ("IntraCMD",                                        m_uiIntraCMD,                                        0u, "IntraChroma MD: 0: none, 1:fixed to default wPSNR weight")
+#endif
   ("LCTUFast",                                        m_useFastLCTU,                                    false, "Fast methods for large CTU")
   ("FastMrg",                                         m_useFastMrg,                                     false, "Fast methods for inter merge")
   ("PBIntraFast",                                     m_usePbIntraFast,                                 false, "Fast assertion if the intra mode is probable")
@@ -1836,6 +1847,15 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     }
   }
 
+#if JVET_M0427_INLOOP_RESHAPER
+  m_reshapeCW.BinCW.resize(CW_NUMS);
+  m_reshapeCW.RspFps = m_iFrameRate;
+  m_reshapeCW.RspIntraPeriod = m_iIntraPeriod;
+  m_reshapeCW.RspPicSize = m_iSourceWidth*m_iSourceHeight;
+  const int FpsToIpTable[MAX_FRAME_RATE + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 128, 128, 128, 128, 128, 128, 128, 128, 128 };
+  m_reshapeCW.RspFpsToIp = FpsToIpTable[m_iFrameRate];
+  m_reshapeCW.RspBaseQP = m_iQP;
+#endif
 #if ENABLE_TRACING
   g_trace_ctx = tracing_init(sTracingFile, sTracingRule);
   if( bTracingChannelsList && g_trace_ctx )
@@ -2219,6 +2239,30 @@ bool EncAppCfg::xCheckParameter()
 #if SHARP_LUMA_DELTA_QP
   xConfirmPara( m_lumaLevelToDeltaQPMapping.mode && m_uiDeltaQpRD > 0,                      "Luma-level-based Delta QP cannot be used together with slice level multiple-QP optimization\n" );
 #endif
+#if JVET_M0427_INLOOP_RESHAPER
+  if (m_bLumaReshapeEnable && (m_internalBitDepth[CHANNEL_TYPE_LUMA] != 10))
+  {
+    m_bLumaReshapeEnable = false;
+    msg(WARNING, "Reshaping is implemented for 10bit luma internal bitdepth.\n");
+  }
+  if (!m_bLumaReshapeEnable)
+  {
+    m_uiSignalType = RESHAPE_SIGNAL_NULL;
+    m_uiIntraCMD   = 0;
+  }
+  if (m_bLumaReshapeEnable && m_uiSignalType == RESHAPE_SIGNAL_PQ)
+  {
+    m_uiIntraCMD = 1;
+  }
+  else if (m_bLumaReshapeEnable && m_uiSignalType == RESHAPE_SIGNAL_SDR)
+  {
+    m_uiIntraCMD = 0;
+  }
+  else
+  {
+    m_bLumaReshapeEnable = false;
+  }
+#endif
 
   xConfirmPara( m_cbQpOffset < -12,   "Min. Chroma Cb QP Offset is -12" );
   xConfirmPara( m_cbQpOffset >  12,   "Max. Chroma Cb QP Offset is  12" );
@@ -3164,7 +3208,14 @@ void EncAppCfg::xPrintParameter()
     msg( VERBOSE, "WrapAroundOffset:%d ", m_wrapAroundOffset );
   }
   // ADD_NEW_TOOL (add some output indicating the usage of tools)
-
+#if JVET_M0427_INLOOP_RESHAPER
+    msg(VERBOSE, "Reshape:%d ", m_bLumaReshapeEnable);
+    if (m_bLumaReshapeEnable)
+    {
+      msg(VERBOSE, "(Sigal:%s ", m_uiSignalType==0? "SDR" : "HDR-PQ");
+      msg(VERBOSE, ") ");
+    }
+#endif
   msg( VERBOSE, "\nFAST TOOL CFG: " );
   if( m_LargeCTU )
   {
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 9d7b9a62c..3c1c617cf 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -256,7 +256,12 @@ protected:
   unsigned  m_wrapAroundOffset;
 
   // ADD_NEW_TOOL : (encoder app) add tool enabling flags and associated parameters here
-
+#if JVET_M0427_INLOOP_RESHAPER
+  bool      m_bLumaReshapeEnable;
+  uint32_t  m_uiSignalType;
+  uint32_t  m_uiIntraCMD;
+  ReshapeCW m_reshapeCW;
+#endif
   unsigned  m_uiMaxCUWidth;                                   ///< max. CU width in pixel
   unsigned  m_uiMaxCUHeight;                                  ///< max. CU height in pixel
   unsigned  m_uiMaxCUDepth;                                   ///< max. CU depth (as specified by command line)
diff --git a/source/Lib/CommonLib/Buffer.cpp b/source/Lib/CommonLib/Buffer.cpp
index 9fd64da80..1fcae69fd 100644
--- a/source/Lib/CommonLib/Buffer.cpp
+++ b/source/Lib/CommonLib/Buffer.cpp
@@ -343,6 +343,99 @@ void AreaBuf<Pel>::addWeightedAvg(const AreaBuf<const Pel> &other1, const AreaBu
 #undef ADD_AVG_INC
 }
 
+#if JVET_M0427_INLOOP_RESHAPER
+template<>
+void AreaBuf<Pel>::rspSignal(std::vector<Pel>& pLUT)
+{
+  Pel* dst = buf;
+  Pel* src = buf;
+  if (width == 1)
+  {
+    THROW("Blocks of width = 1 not supported");
+  }  
+  else
+  {
+    for (unsigned y = 0; y < height; y++)
+    {
+      for (unsigned x = 0; x < width; x++)
+      {
+        dst[x] = pLUT[src[x]];
+      }
+      dst += stride;
+      src += stride;
+    }
+  }
+}
+
+template<>
+void AreaBuf<Pel>::scaleSignal(const int scale, const bool dir)
+{
+  Pel* dst = buf;
+  Pel* src = buf;
+  int sign, absval;
+
+  if (dir) // forward
+  {
+    if (width == 1)
+    {
+      THROW("Blocks of width = 1 not supported");
+    }
+    else
+    {
+      for (unsigned y = 0; y < height; y++)
+      {
+        for (unsigned x = 0; x < width; x++)
+        {
+          sign = src[x] >= 0 ? 1 : -1;
+          absval = sign * src[x];
+          dst[x] = sign * (((absval << CSCALE_FP_PREC) + (scale >> 1)) / scale);
+          dst[x] = dst[x] > 1023 ? 1023 : dst[x] < -1023 ? -1023 : dst[x];
+        }
+        dst += stride;
+        src += stride;
+      }
+    }
+  }
+  else // inverse
+  {
+    for (unsigned y = 0; y < height; y++)
+    {
+      for (unsigned x = 0; x < width; x++)
+      {
+        sign = src[x] >= 0 ? 1 : -1;
+        absval = sign * src[x];
+        dst[x] = sign * ((absval * scale + (1 << (CSCALE_FP_PREC - 1))) >> CSCALE_FP_PREC);
+      }
+      dst += stride;
+      src += stride;
+    }
+  }
+}
+
+template<>
+Pel AreaBuf <Pel> ::computeAvg() const
+{
+  const Pel* src = buf;
+
+  if (width == 1)
+  {
+    THROW("Blocks of width = 1 not supported");
+  }
+  else
+  {
+    int32_t acc = 0;
+#define AVG_INC   \
+    src +=       stride; 
+#define AVG_OP(ADDR) acc += src[ADDR]
+    SIZE_AWARE_PER_EL_OP(AVG_OP, AVG_INC);
+#undef AVG_INC
+#undef AVG_OP
+    return Pel((acc + (area() >> 1)) / area());
+  }
+}
+
+#endif
+
 template<>
 void AreaBuf<Pel>::addAvg( const AreaBuf<const Pel> &other1, const AreaBuf<const Pel> &other2, const ClpRng& clpRng)
 {
diff --git a/source/Lib/CommonLib/Buffer.h b/source/Lib/CommonLib/Buffer.h
index db9d69e5e..6347c675c 100644
--- a/source/Lib/CommonLib/Buffer.h
+++ b/source/Lib/CommonLib/Buffer.h
@@ -132,6 +132,11 @@ struct AreaBuf : public Size
 
   void toLast               ( const ClpRng& clpRng );
 
+#if JVET_M0427_INLOOP_RESHAPER
+  void rspSignal            ( std::vector<Pel>& pLUT );
+  void scaleSignal          ( const int scale, const bool dir );
+  T    computeAvg           ( ) const;
+#endif
         T& at( const int &x, const int &y )          { return buf[y * stride + x]; }
   const T& at( const int &x, const int &y ) const    { return buf[y * stride + x]; }
 
diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp
index e420621c3..829a7eeac 100644
--- a/source/Lib/CommonLib/CodingStructure.cpp
+++ b/source/Lib/CommonLib/CodingStructure.cpp
@@ -969,6 +969,14 @@ void CodingStructure::copyStructure( const CodingStructure& other, const Channel
 
     // copy data to picture
     picture->getRecoBuf( area ).copyFrom( recoBuf );
+#if JVET_M0427_INLOOP_RESHAPER
+    CPelUnitBuf predBuf = other.getPredBuf(area);
+    if (parent)
+    {
+      getPredBuf(area).copyFrom(predBuf);
+    }
+    picture->getPredBuf(area).copyFrom(predBuf);
+#endif
   }
 }
 
diff --git a/source/Lib/CommonLib/CodingStructure.h b/source/Lib/CommonLib/CodingStructure.h
index 1b57a771f..d7ab5422b 100644
--- a/source/Lib/CommonLib/CodingStructure.h
+++ b/source/Lib/CommonLib/CodingStructure.h
@@ -53,6 +53,9 @@ enum PictureType
 {
   PIC_RECONSTRUCTION = 0,
   PIC_ORIGINAL,
+#if JVET_M0427_INLOOP_RESHAPER
+  PIC_TRUE_ORIGINAL,
+#endif
   PIC_PREDICTION,
   PIC_RESIDUAL,
   PIC_ORG_RESI,
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index dc4295c71..6333d0718 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -404,7 +404,19 @@ static const int CHROMA_REFINEMENT_CANDIDATES = 8; /// 8 candidates BV to choose
 static const int IBC_FAST_METHOD_NOINTRA_IBCCBF0 = 0x01;
 static const int IBC_FAST_METHOD_BUFFERBV = 0X02;
 static const int IBC_FAST_METHOD_ADAPTIVE_SEARCHRANGE = 0X04;
-
+#if JVET_M0427_INLOOP_RESHAPER
+static const int MAX_LUMA_RESHAPING_LUT_SIZE =                 1024;
+static const int CSCALE_FP_PREC =                                11;
+static const int PIC_ANALYZE_CW_BINS =                           32;
+static const int FP_PREC =                                       14;
+static const int log2_MAX_LUMA_RESHAPING_LUT_SIZE =              10;
+static const int log2_PIC_ANALYZE_CW_BINS =                       5;
+static const int PIC_ANALYZE_WIN_SIZE =                           5;
+static const int CW_NUMS =                                        3;
+static const int MAX_FRAME_RATE =                               128;
+static const int PIC_CODE_CW_BINS =                              16;
+static const int log2_PIC_CODE_CW_BINS =                          4;
+#endif
 #if JVET_M0512_MOTION_BUFFER_COMPRESSION
 static constexpr int MV_EXPONENT_BITCOUNT    = 4;
 static constexpr int MV_MANTISSA_BITCOUNT    = 6;
diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp
index d319f1f7e..6157656dc 100644
--- a/source/Lib/CommonLib/Picture.cpp
+++ b/source/Lib/CommonLib/Picture.cpp
@@ -742,6 +742,9 @@ void Picture::create(const ChromaFormat &_chromaFormat, const Size &size, const
   if( !_decoder )
   {
     M_BUFS( 0, PIC_ORIGINAL ).    create( _chromaFormat, a );
+#if JVET_M0427_INLOOP_RESHAPER
+    M_BUFS( 0, PIC_TRUE_ORIGINAL ). create( _chromaFormat, a );
+#endif
   }
 #if !KEEP_PRED_AND_RESI_SIGNALS
 
@@ -846,6 +849,14 @@ const CPelUnitBuf Picture::getOrigBuf(const UnitArea &unit) const { return getBu
        PelUnitBuf Picture::getOrigBuf()                           { return M_BUFS(0,    PIC_ORIGINAL); }
 const CPelUnitBuf Picture::getOrigBuf()                     const { return M_BUFS(0,    PIC_ORIGINAL); }
 
+#if JVET_M0427_INLOOP_RESHAPER
+       PelBuf     Picture::getOrigBuf(const ComponentID compID)       { return getBuf(compID, PIC_ORIGINAL); }
+const CPelBuf     Picture::getOrigBuf(const ComponentID compID) const { return getBuf(compID, PIC_ORIGINAL); }
+       PelUnitBuf Picture::getTrueOrigBuf()                           { return M_BUFS(0, PIC_TRUE_ORIGINAL); }
+const CPelUnitBuf Picture::getTrueOrigBuf()                     const { return M_BUFS(0, PIC_TRUE_ORIGINAL); }
+       PelBuf     Picture::getTrueOrigBuf(const CompArea &blk)        { return getBuf(blk, PIC_TRUE_ORIGINAL); }
+const CPelBuf     Picture::getTrueOrigBuf(const CompArea &blk)  const { return getBuf(blk, PIC_TRUE_ORIGINAL); }
+#endif
        PelBuf     Picture::getPredBuf(const CompArea &blk)        { return getBuf(blk,  PIC_PREDICTION); }
 const CPelBuf     Picture::getPredBuf(const CompArea &blk)  const { return getBuf(blk,  PIC_PREDICTION); }
        PelUnitBuf Picture::getPredBuf(const UnitArea &unit)       { return getBuf(unit, PIC_PREDICTION); }
diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h
index 2e90cc538..3c9c4c650 100644
--- a/source/Lib/CommonLib/Picture.h
+++ b/source/Lib/CommonLib/Picture.h
@@ -192,6 +192,14 @@ struct Picture : public UnitArea
   const CPelUnitBuf getOrigBuf(const UnitArea &unit) const;
          PelUnitBuf getOrigBuf();
   const CPelUnitBuf getOrigBuf() const;
+#if JVET_M0427_INLOOP_RESHAPER
+         PelBuf     getOrigBuf(const ComponentID compID);
+  const CPelBuf     getOrigBuf(const ComponentID compID) const;
+         PelUnitBuf getTrueOrigBuf();
+  const CPelUnitBuf getTrueOrigBuf() const;
+        PelBuf      getTrueOrigBuf(const CompArea &blk);
+  const CPelBuf     getTrueOrigBuf(const CompArea &blk) const;
+#endif
 
          PelBuf     getPredBuf(const CompArea &blk);
   const CPelBuf     getPredBuf(const CompArea &blk) const;
diff --git a/source/Lib/CommonLib/RdCost.cpp b/source/Lib/CommonLib/RdCost.cpp
index 78fbcf0f3..e5976dc0d 100644
--- a/source/Lib/CommonLib/RdCost.cpp
+++ b/source/Lib/CommonLib/RdCost.cpp
@@ -176,6 +176,10 @@ void RdCost::init()
 
   m_motionLambda               = 0;
   m_iCostScale                 = 0;
+#if JVET_M0427_INLOOP_RESHAPER
+  m_iSignalType                = RESHAPE_SIGNAL_NULL;
+  m_chroma_weight              = 1.0;
+#endif
 }
 
 
@@ -2859,6 +2863,11 @@ Distortion RdCost::xGetHADs( const DistParam &rcDtParam )
 
 #if WCG_EXT
 double RdCost::m_lumaLevelToWeightPLUT[LUMA_LEVEL_TO_DQP_LUT_MAXSIZE];
+#if JVET_M0427_INLOOP_RESHAPER
+double     RdCost::m_reshapeLumaLevelToWeightPLUT[LUMA_LEVEL_TO_DQP_LUT_MAXSIZE];
+uint32_t   RdCost::m_iSignalType;
+double     RdCost::m_chroma_weight;
+#endif
 
 void RdCost::saveUnadjustedLambda()
 {
@@ -2868,6 +2877,18 @@ void RdCost::saveUnadjustedLambda()
 
 void RdCost::initLumaLevelToWeightTable()
 {
+#if JVET_M0427_INLOOP_RESHAPER
+  if (m_iSignalType == RESHAPE_SIGNAL_SDR)
+  {
+    double weight = 1.0;
+    for (int i = 0; i < LUMA_LEVEL_TO_DQP_LUT_MAXSIZE; i++)
+    {
+      m_lumaLevelToWeightPLUT[i] = weight;
+    }
+    return;
+  }
+#endif
+
   for (int i = 0; i < LUMA_LEVEL_TO_DQP_LUT_MAXSIZE; i++) {
     double x = i;
     double y;
@@ -2889,7 +2910,69 @@ void RdCost::initLumaLevelToWeightTable()
     
     m_lumaLevelToWeightPLUT[i] = pow(2.0, y / 3.0);      // or power(10, dQp/10)      they are almost equal       
   }
+#if JVET_M0427_INLOOP_RESHAPER
+  memcpy(m_reshapeLumaLevelToWeightPLUT, m_lumaLevelToWeightPLUT, LUMA_LEVEL_TO_DQP_LUT_MAXSIZE * sizeof(double));
+#endif
+}
+
+#if JVET_M0427_INLOOP_RESHAPER
+void RdCost::updateReshapeLumaLevelToWeightTableChromaMD(std::vector<Pel>& ILUT)
+{
+  for (int i = 0; i < LUMA_LEVEL_TO_DQP_LUT_MAXSIZE; i++) // idx in reshaped domain;
+  {
+    m_reshapeLumaLevelToWeightPLUT[i] = m_lumaLevelToWeightPLUT[ILUT[i]];
+  }
+}
+
+void RdCost::restoreReshapeLumaLevelToWeightTable()
+{
+  memcpy(m_reshapeLumaLevelToWeightPLUT, m_lumaLevelToWeightPLUT, LUMA_LEVEL_TO_DQP_LUT_MAXSIZE * sizeof(double));
+}
+
+
+void RdCost::updateReshapeLumaLevelToWeightTable(sliceReshapeInfo &sliceReshape, Pel *wt_table, double cwt)
+{
+  if (m_iSignalType == RESHAPE_SIGNAL_SDR)
+  {
+    if (sliceReshape.getSliceReshapeModelPresentFlag())
+    {
+      double w_bin = 1.0;
+      double weight = 1.0;
+      int hist_lens = MAX_LUMA_RESHAPING_LUT_SIZE / PIC_CODE_CW_BINS;
+
+      for (int i = 0; i < PIC_CODE_CW_BINS; i++)
+      {
+        if ((i < sliceReshape.reshape_model_min_bin_idx) || (i > sliceReshape.reshape_model_max_bin_idx))
+          weight = 1.0;
+        else
+        {
+          if (sliceReshape.reshape_model_bin_CW_delta[i] == 1 || sliceReshape.reshape_model_bin_CW_delta[i] == -1 * MAX_LUMA_RESHAPING_LUT_SIZE / PIC_CODE_CW_BINS)
+            weight = w_bin;
+          else 
+          {
+            weight = (double)wt_table[i] / (double)hist_lens;
+            weight = weight*weight;
+          }
+        }
+        for (int j = 0; j < hist_lens; j++)
+        {
+          int ii = i*hist_lens + j;
+          m_reshapeLumaLevelToWeightPLUT[ii] = weight;
+        }
+      }
+      m_chroma_weight = cwt;
+    }
+    else
+    {
+      THROW("updateReshapeLumaLevelToWeightTable ERROR!!");
+    }
+  }
+  else
+  {
+    THROW("updateReshapeLumaLevelToWeightTable not support other signal types!!");
+  }
 }
+#endif
 
 Distortion RdCost::getWeightedMSE(int compIdx, const Pel org, const Pel cur, const uint32_t uiShift, const Pel orgLuma) 
 {
@@ -2902,8 +2985,28 @@ Distortion RdCost::getWeightedMSE(int compIdx, const Pel org, const Pel cur, con
      CHECK(org!=orgLuma, "");
   }
   // use luma to get weight
+#if JVET_M0427_INLOOP_RESHAPER
+  double weight = 1.0;
+  if (m_iSignalType == RESHAPE_SIGNAL_SDR) 
+  {
+    if (compIdx == COMPONENT_Y)
+      weight = m_reshapeLumaLevelToWeightPLUT[orgLuma];
+    else
+    {
+      weight = m_chroma_weight; 
+    }
+  }
+  else
+      weight = m_reshapeLumaLevelToWeightPLUT[orgLuma];
+#else
   double weight = m_lumaLevelToWeightPLUT[orgLuma];
+#endif
+#if JVET_M0427_INLOOP_RESHAPER // FIXED_PT_WD_CALCULATION
+  int64_t fixedPTweight = (int64_t)(weight * (double)(1 << 16));
+  Intermediate_Int mse = Intermediate_Int((fixedPTweight*(iTemp*iTemp) + (1 << 15)) >> 16);
+#else
   Intermediate_Int mse = Intermediate_Int(weight*(double)iTemp*(double)iTemp+0.5);
+#endif
   distortionVal = Distortion( mse >> uiShift);
   return distortionVal;
 }
diff --git a/source/Lib/CommonLib/RdCost.h b/source/Lib/CommonLib/RdCost.h
index ead8fd5cb..23d2aafa5 100644
--- a/source/Lib/CommonLib/RdCost.h
+++ b/source/Lib/CommonLib/RdCost.h
@@ -108,6 +108,11 @@ private:
   double                  m_dLambda_unadjusted; // TODO: check is necessary
   double                  m_DistScaleUnadjusted;
   static double           m_lumaLevelToWeightPLUT[LUMA_LEVEL_TO_DQP_LUT_MAXSIZE];
+#if JVET_M0427_INLOOP_RESHAPER
+  static double           m_reshapeLumaLevelToWeightPLUT[LUMA_LEVEL_TO_DQP_LUT_MAXSIZE];
+  static uint32_t         m_iSignalType;
+  static double           m_chroma_weight;
+#endif
 #endif
   double                  m_DistScale;
   double                  m_dLambdaMotionSAD[2 /* 0=standard, 1=for transquant bypass when mixed-lossless cost evaluation enabled*/];
@@ -290,6 +295,15 @@ public:
          void    saveUnadjustedLambda       ();
          void    initLumaLevelToWeightTable ();
   inline double  getWPSNRLumaLevelWeight    (int val) { return m_lumaLevelToWeightPLUT[val]; }
+#if JVET_M0427_INLOOP_RESHAPER
+  void           updateReshapeLumaLevelToWeightTableChromaMD (std::vector<Pel>& ILUT);
+  void           restoreReshapeLumaLevelToWeightTable        ();
+  inline double  getWPSNRReshapeLumaLevelWeight              (int val)             { return m_reshapeLumaLevelToWeightPLUT[val]; }
+  uint32_t       getReshapeSignalType                        ()              const { return m_iSignalType; }
+  void           setReshapeSignalType                        (uint32_t type)       { m_iSignalType = type; }
+  void           updateReshapeLumaLevelToWeightTable         (sliceReshapeInfo &sliceReshape, Pel *wt_table, double cwt);
+  inline double* getLumaLevelWeightTable()                   { return m_lumaLevelToWeightPLUT; }
+#endif
 #endif
 
 private:
diff --git a/source/Lib/CommonLib/Reshape.cpp b/source/Lib/CommonLib/Reshape.cpp
new file mode 100644
index 000000000..099b5cb54
--- /dev/null
+++ b/source/Lib/CommonLib/Reshape.cpp
@@ -0,0 +1,232 @@
+/* The copyright in this software is being made available under the BSD
+* License, included below. This software may be subject to other third party
+* and contributor rights, including patent rights, and no such rights are
+* granted under this license.
+*
+* Copyright (c) 2010-2019, ITU/ISO/IEC
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+*  * Redistributions of source code must retain the above copyright notice,
+*    this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above copyright notice,
+*    this list of conditions and the following disclaimer in the documentation
+*    and/or other materials provided with the distribution.
+*  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
+*    be used to endorse or promote products derived from this software without
+*    specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/** \file     Reshape.cpp
+    \brief    common reshaper class
+*/
+#include "Reshape.h"
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#if JVET_M0427_INLOOP_RESHAPER
+ //! \ingroup CommonLib
+ //! \{
+
+ // ====================================================================================================================
+ // Constructor / destructor / create / destroy
+ // ====================================================================================================================
+
+Reshape::Reshape()
+{
+  m_bCTUFlag = false;
+  m_bRecReshaped = false;
+  m_bReshape = true;
+  m_uiCWOrg = MAX_LUMA_RESHAPING_LUT_SIZE / PIC_CODE_CW_BINS;
+}
+
+Reshape::~Reshape()
+{
+}
+
+void  Reshape::create_dec()
+{
+  if (forwardReshapingLUT.empty())
+    forwardReshapingLUT.resize(MAX_LUMA_RESHAPING_LUT_SIZE, 0);
+  if (inverseReshapingLUT.empty())
+    inverseReshapingLUT.resize(MAX_LUMA_RESHAPING_LUT_SIZE, 0);
+  if (m_uiBinCWAll.empty())
+    m_uiBinCWAll.resize(PIC_CODE_CW_BINS, 0);
+  if (m_ReshapePivot.empty())
+    m_ReshapePivot.resize(PIC_CODE_CW_BINS + 1, 0);
+  if (ChromaAdjHelpLUT.empty())
+    ChromaAdjHelpLUT.resize(PIC_CODE_CW_BINS, 2048);
+}
+
+void  Reshape::destroy()
+{
+}
+
+/**
+-Perform inverse of a one dimension LUT
+\param   InputLUT  describing the input LUT
+\retval  OutputLUT describing the inversed LUT of InputLUT
+\param   lut_size  size of LUT in number of samples
+*/
+void Reshape::ReverseLUT(std::vector<Pel>& InputLUT, std::vector<Pel>& OutputLUT, uint16_t lut_size)
+{
+  int i, j;
+  OutputLUT[m_ReshapePivot[m_sliceReshapeInfo.reshape_model_min_bin_idx]] = m_sliceReshapeInfo.reshape_model_min_bin_idx*m_uiCWOrg;
+  for (i = m_sliceReshapeInfo.reshape_model_min_bin_idx; i <= m_sliceReshapeInfo.reshape_model_max_bin_idx; i++)
+  {
+    int16_t X1 = m_ReshapePivot[i];
+    int16_t X2 = m_ReshapePivot[i + 1];
+    OutputLUT[X2] = (i + 1)*m_uiCWOrg;
+    int16_t Y1 = OutputLUT[X1];
+    int16_t Y2 = OutputLUT[X2];
+
+    if (X2 !=X1)
+    {
+      int32_t scale = (int32_t)(Y2 - Y1) * (1 << FP_PREC) / (int32_t)(X2 - X1);
+      for (j = X1 + 1; j < X2; j++)
+      {
+        OutputLUT[j] = (Pel)((scale*(int32_t)(j - X1) + (1 << (FP_PREC - 1))) >> FP_PREC) + Y1;
+      }
+    }
+  }
+
+  for (i = 0; i < m_ReshapePivot[m_sliceReshapeInfo.reshape_model_min_bin_idx]; i++)
+    OutputLUT[i] = OutputLUT[m_ReshapePivot[m_sliceReshapeInfo.reshape_model_min_bin_idx]];
+  for (i = m_ReshapePivot[m_sliceReshapeInfo.reshape_model_max_bin_idx + 1]; i < MAX_LUMA_RESHAPING_LUT_SIZE; i++)
+    OutputLUT[i] = OutputLUT[m_ReshapePivot[m_sliceReshapeInfo.reshape_model_max_bin_idx + 1]];
+
+  bool clipRange = ((m_sliceReshapeInfo.reshape_model_min_bin_idx > 0) && (m_sliceReshapeInfo.reshape_model_max_bin_idx < (PIC_CODE_CW_BINS - 1)));
+  for (i = 0; i < lut_size; i++)
+  {
+    if (clipRange) OutputLUT[i] = Clip3((Pel)64, (Pel)940, OutputLUT[i]);
+    else           OutputLUT[i] = Clip3((Pel)0, (Pel)1023, OutputLUT[i]);
+  }
+}
+
+
+/** compute chroma residuce scale for TU
+* \param average luma pred of TU
+* \return chroma residue scale
+*/
+int  Reshape::calculateChromaAdj(Pel avgLuma)
+{
+  int lumaIdx = Clip3<int>(0, int(LUMA_LEVEL_TO_DQP_LUT_MAXSIZE) - 1, avgLuma);
+  int iAdj = ChromaAdjHelpLUT[getPWLIdxInv(lumaIdx)];
+  return(iAdj);
+}
+
+
+/** find inx of PWL for inverse mapping
+* \param average luma pred of TU
+* \return idx of PWL for inverse mapping
+*/
+int Reshape::getPWLIdxInv(int lumaVal)
+{
+  int idxS = 0;
+  if (lumaVal < m_ReshapePivot[m_sliceReshapeInfo.reshape_model_min_bin_idx + 1])
+    return m_sliceReshapeInfo.reshape_model_min_bin_idx;
+  else if (lumaVal >= m_ReshapePivot[m_sliceReshapeInfo.reshape_model_max_bin_idx])
+    return m_sliceReshapeInfo.reshape_model_max_bin_idx;
+  else
+  {
+    for (idxS = m_sliceReshapeInfo.reshape_model_min_bin_idx; (idxS < m_sliceReshapeInfo.reshape_model_max_bin_idx); idxS++)
+    {
+      if (lumaVal < m_ReshapePivot[idxS + 1])     break;
+    }
+    return idxS;
+  }
+}
+
+/**
+-copy Slice reshaper info structure
+\param   tInfo describing the target Slice reshaper info structure
+\param   sInfo describing the source Slice reshaper info structure
+*/
+void Reshape::copySliceReshaperInfo(sliceReshapeInfo& tInfo, sliceReshapeInfo& sInfo)
+{
+  tInfo.slice_reshaper_model_present_flag = sInfo.slice_reshaper_model_present_flag;
+  if (sInfo.slice_reshaper_model_present_flag)
+  {
+    tInfo.reshape_model_max_bin_idx = sInfo.reshape_model_max_bin_idx;
+    tInfo.reshape_model_min_bin_idx = sInfo.reshape_model_min_bin_idx;
+    memcpy(tInfo.reshape_model_bin_CW_delta, sInfo.reshape_model_bin_CW_delta, sizeof(int)*(PIC_CODE_CW_BINS));
+    tInfo.maxNbitsNeededDeltaCW = sInfo.maxNbitsNeededDeltaCW;
+  }
+  tInfo.slice_reshaper_enable_flag = sInfo.slice_reshaper_enable_flag;
+  if (sInfo.slice_reshaper_enable_flag)
+    tInfo.uiReshapeChromaAdj = sInfo.uiReshapeChromaAdj;
+  else
+    tInfo.uiReshapeChromaAdj = 0;
+}
+
+/** Construct reshaper from syntax
+* \param void
+* \return void
+*/
+void Reshape::constructReshaper()
+{
+  int pwlFwdLUTsize = PIC_CODE_CW_BINS;
+  int pwlFwdBinLen = MAX_LUMA_RESHAPING_LUT_SIZE / PIC_CODE_CW_BINS;
+
+  for (int i = 0; i < m_sliceReshapeInfo.reshape_model_min_bin_idx; i++)
+    m_uiBinCWAll[i] = 0;
+  for (int i = m_sliceReshapeInfo.reshape_model_max_bin_idx + 1; i < PIC_CODE_CW_BINS; i++)
+    m_uiBinCWAll[i] = 0;
+  for (int i = m_sliceReshapeInfo.reshape_model_min_bin_idx; i <= m_sliceReshapeInfo.reshape_model_max_bin_idx; i++)
+    m_uiBinCWAll[i] = (uint16_t)(m_sliceReshapeInfo.reshape_model_bin_CW_delta[i] + (int)m_uiCWOrg);
+
+  for (int i = 0; i < pwlFwdLUTsize; i++)
+  {
+    m_ReshapePivot[i + 1] = m_ReshapePivot[i] + m_uiBinCWAll[i];
+    int16_t Y1 = m_ReshapePivot[i];
+    int16_t Y2 = m_ReshapePivot[i + 1];
+
+    forwardReshapingLUT[i*pwlFwdBinLen] = Clip3((Pel)0, (Pel)1023, (Pel)Y1);
+
+    int log2_pwlFwdBinLen = log2_MAX_LUMA_RESHAPING_LUT_SIZE - log2_PIC_CODE_CW_BINS;
+
+    int32_t scale = ((int32_t)(Y2 - Y1) * (1 << FP_PREC) + (1 << (log2_pwlFwdBinLen - 1))) >> (log2_pwlFwdBinLen);
+    for (int j = 1; j < pwlFwdBinLen; j++)
+    {
+      int tempVal = Y1 + (((int32_t)scale * (int32_t)j + (1 << (FP_PREC - 1))) >> FP_PREC);
+      forwardReshapingLUT[i*pwlFwdBinLen + j] = Clip3((Pel)0, (Pel)1023, (Pel)tempVal);
+    }
+  }
+  ReverseLUT(forwardReshapingLUT, inverseReshapingLUT, MAX_LUMA_RESHAPING_LUT_SIZE);
+  updateChromaDQPLUT();
+}
+
+/** generate chroma residue scaling LUT
+* \param void
+* \return void
+*/
+void Reshape::updateChromaDQPLUT()
+{
+  const int16_t  CW_bin_SC_LUT[2 * PIC_ANALYZE_CW_BINS] = { 16384, 16384, 16384, 16384, 16384, 16384, 16384, 8192, 8192, 8192, 8192, 5461, 5461, 5461, 5461, 4096, 4096, 4096, 4096, 3277, 3277, 3277, 3277, 2731, 2731, 2731, 2731, 2341, 2341, 2341, 2048, 2048, 2048, 1820, 1820, 1820, 1638, 1638, 1638, 1638, 1489, 1489, 1489, 1489, 1365, 1365, 1365, 1365, 1260, 1260, 1260, 1260, 1170, 1170, 1170, 1170, 1092, 1092, 1092, 1092, 1024, 1024, 1024, 1024 }; //p=11
+  for (int i = 0; i < PIC_CODE_CW_BINS; i++)
+  {
+    if ((i < m_sliceReshapeInfo.reshape_model_min_bin_idx) || (i > m_sliceReshapeInfo.reshape_model_max_bin_idx))
+      ChromaAdjHelpLUT[i] = 1 << CSCALE_FP_PREC;
+    else
+      ChromaAdjHelpLUT[i] = CW_bin_SC_LUT[Clip3((uint16_t)1, (uint16_t)64, (uint16_t)(m_uiBinCWAll[i] >> 1)) - 1];
+  }
+}
+#endif
+
+
+//
+//! \}
diff --git a/source/Lib/CommonLib/Reshape.h b/source/Lib/CommonLib/Reshape.h
new file mode 100644
index 000000000..4fec33805
--- /dev/null
+++ b/source/Lib/CommonLib/Reshape.h
@@ -0,0 +1,100 @@
+/* The copyright in this software is being made available under the BSD
+* License, included below. This software may be subject to other third party
+* and contributor rights, including patent rights, and no such rights are
+* granted under this license.
+*
+* Copyright (c) 2010-2019, ITU/ISO/IEC
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+*  * Redistributions of source code must retain the above copyright notice,
+*    this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above copyright notice,
+*    this list of conditions and the following disclaimer in the documentation
+*    and/or other materials provided with the distribution.
+*  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
+*    be used to endorse or promote products derived from this software without
+*    specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+ /** \file     Reshape.h
+     \brief    reshaping header and class (header)
+ */
+
+#ifndef __RESHAPE__
+#define __RESHAPE__
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "CommonDef.h"
+#include "Rom.h"
+#include "CommonLib/Picture.h"
+#if JVET_M0427_INLOOP_RESHAPER
+//! \ingroup CommonLib
+//! \{
+// ====================================================================================================================
+// Class definition
+// ====================================================================================================================
+
+class Reshape
+{
+protected:
+  sliceReshapeInfo        m_sliceReshapeInfo;
+  bool                    m_bCTUFlag;
+  bool                    m_bRecReshaped;
+  std::vector<Pel>        inverseReshapingLUT;
+  std::vector<Pel>        forwardReshapingLUT;
+  std::vector<int>        ChromaAdjHelpLUT;
+  std::vector<uint16_t>   m_uiBinCWAll;
+  uint16_t                m_uiCWOrg;
+  bool                    m_bReshape;
+  std::vector<Pel>        m_ReshapePivot;
+public:
+  Reshape();
+  ~Reshape();
+
+  void create_dec();
+  void destroy();
+
+  void ReverseLUT(std::vector<Pel>& InputLUT, std::vector<Pel>& OutputLUT, uint16_t lut_size);
+  std::vector<Pel>&  getFwdLUT() { return forwardReshapingLUT; }
+  std::vector<Pel>&  getInvLUT() { return inverseReshapingLUT; }
+  std::vector<int>&  getChromaAdjHelpLUT() { return ChromaAdjHelpLUT; }
+
+  bool getCTUFlag()              { return m_bCTUFlag; }
+  void setCTUFlag(bool bCTUFlag) { m_bCTUFlag = bCTUFlag; }
+
+  bool getRecReshaped()          { return m_bRecReshaped; }
+  void setRecReshaped(bool bPicReshaped) { m_bRecReshaped = bPicReshaped; }
+  int  calculateChromaAdj(Pel avgLuma);
+  int  getPWLIdxInv(int lumaVal);
+  sliceReshapeInfo& getSliceReshaperInfo() { return m_sliceReshapeInfo; }
+  void copySliceReshaperInfo(sliceReshapeInfo& tInfo, sliceReshapeInfo& sInfo);
+
+  void constructReshaper();
+  void updateChromaDQPLUT();
+  bool getReshapeFlag() { return m_bReshape; }
+  void setReshapeFlag(bool val) { m_bReshape = val; }
+};// END CLASS DEFINITION Reshape
+
+//! \}
+#endif // 
+#endif // __RESHAPE__
+
+
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index fe1541e00..731eb97e9 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -180,6 +180,15 @@ Slice::Slice()
   }
 
   initMotionLUTs();
+
+#if JVET_M0427_INLOOP_RESHAPER
+  m_sliceReshapeInfo.setUseSliceReshaper(false);
+  m_sliceReshapeInfo.setSliceReshapeModelPresentFlag(false);
+  m_sliceReshapeInfo.setSliceReshapeChromaAdj(0);
+  m_sliceReshapeInfo.reshape_model_min_bin_idx = 0;
+  m_sliceReshapeInfo.reshape_model_max_bin_idx = PIC_CODE_CW_BINS - 1;
+  memset(m_sliceReshapeInfo.reshape_model_bin_CW_delta, 0, PIC_CODE_CW_BINS * sizeof(int));
+#endif
 }
 
 Slice::~Slice()
@@ -1892,6 +1901,9 @@ SPS::SPS()
 , m_spsNextExtension          (*this)
 , m_wrapAroundEnabledFlag     (false)
 , m_wrapAroundOffset          (  0)
+#if JVET_M0427_INLOOP_RESHAPER
+, m_bUseReshape               (false)
+#endif
 {
   for(int ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++)
   {
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index a4e2a2093..d875cac8e 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -291,6 +291,38 @@ struct HrdSubLayerInfo
   uint32_t duBitRateValue    [MAX_CPB_CNT][2];
 };
 
+#if JVET_M0427_INLOOP_RESHAPER
+class sliceReshapeInfo
+{
+public:
+  bool      slice_reshaper_enable_flag;
+  bool      slice_reshaper_model_present_flag;
+  unsigned  uiReshapeChromaAdj;
+  uint32_t  reshape_model_min_bin_idx;
+  uint32_t  reshape_model_max_bin_idx;
+  int       reshape_model_bin_CW_delta[PIC_CODE_CW_BINS];
+  int       maxNbitsNeededDeltaCW;
+  void      setUseSliceReshaper(bool b_useSliceReshaper)                   { slice_reshaper_enable_flag = b_useSliceReshaper;          }
+  bool      getUseSliceReshaper() const                                    { return slice_reshaper_enable_flag;                        }
+  void      setSliceReshapeModelPresentFlag(bool bflag)                    { slice_reshaper_model_present_flag = bflag;                }
+  bool      getSliceReshapeModelPresentFlag() const                        { return   slice_reshaper_model_present_flag;               }
+  void      setSliceReshapeChromaAdj(unsigned uiChromaAdj)                 { uiReshapeChromaAdj = uiChromaAdj;                         }
+  unsigned  getSliceReshapeChromaAdj() const                               { return uiReshapeChromaAdj;                                }
+};
+
+struct ReshapeCW
+{
+  std::vector<uint32_t> BinCW;
+  int RspPicSize;
+  int RspIntraPeriod;
+  int RspFps;
+  int RspBaseQP;
+  int Tid;
+  int SliceQP;
+  int RspFpsToIp;
+};
+#endif
+
 class HRD
 {
 private:
@@ -1033,7 +1065,9 @@ private:
 
   bool              m_wrapAroundEnabledFlag;
   unsigned          m_wrapAroundOffset;
-
+#if JVET_M0427_INLOOP_RESHAPER
+  bool              m_bUseReshape;
+#endif
 public:
 
   SPS();
@@ -1252,6 +1286,10 @@ public:
   bool                    getWrapAroundEnabledFlag() const                                                { return m_wrapAroundEnabledFlag;                                      }
   void                    setWrapAroundOffset(unsigned offset)                                            { m_wrapAroundOffset = offset;                                         }
   unsigned                getWrapAroundOffset() const                                                     { return m_wrapAroundOffset;                                           }
+#if JVET_M0427_INLOOP_RESHAPER
+  void                    setUseReshaper(bool b)                                                          { m_bUseReshape = b;                                                   }
+  bool                    getUseReshaper() const                                                          { return m_bUseReshape;                                                }
+#endif
 };
 
 
@@ -1682,6 +1720,9 @@ private:
   AlfSliceParam              m_alfSliceParam;
   LutMotionCand*             m_MotionCandLut;
 #if JVET_M0170_MRG_SHARELIST
+#if JVET_M0427_INLOOP_RESHAPER
+  sliceReshapeInfo           m_sliceReshapeInfo;
+#endif
 public:
   LutMotionCand*             m_MotionCandLuTsBkup;
 #endif
@@ -1981,7 +2022,10 @@ public:
 
   void                        updateMotionLUTs(LutMotionCand* lutMC, CodingUnit & cu);
   void                        copyMotionLUTs(LutMotionCand* Src, LutMotionCand* Dst);
-
+#if JVET_M0427_INLOOP_RESHAPER
+  const sliceReshapeInfo&     getReshapeInfo() const { return m_sliceReshapeInfo; }
+        sliceReshapeInfo&     getReshapeInfo()       { return m_sliceReshapeInfo; }
+#endif
 protected:
   Picture*              xGetRefPic        (PicList& rcListPic, int poc);
   Picture*              xGetLongTermRefPic(PicList& rcListPic, int poc, bool pocHasMsb);
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 20eb30481..59ef949fd 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -186,7 +186,11 @@ typedef std::pair<int, int>  TrCost;
 #endif
 #endif // ! ENABLE_TRACING
 
+#if JVET_M0427_INLOOP_RESHAPER
+#define WCG_EXT                                           1
+#else
 #define WCG_EXT                                           0 // part of JEM sharp Luma qp
+#endif
 #define WCG_WPSNR                                         WCG_EXT
 
 #if HEVC_TOOLS
@@ -1146,6 +1150,15 @@ enum MsgLevel
   VERBOSE = 5,
   DETAILS = 6
 };
+#if JVET_M0427_INLOOP_RESHAPER
+enum RESHAPE_SIGNAL_TYPE
+{
+  RESHAPE_SIGNAL_SDR = 0,
+  RESHAPE_SIGNAL_PQ  = 1,
+  RESHAPE_SIGNAL_HLG = 2,
+  RESHAPE_SIGNAL_NULL = 100,
+};
+#endif
 
 
 // ---------------------------------------------------------------------------
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index abcb04ae3..536d640ce 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -554,6 +554,9 @@ void TransformUnit::initData()
 #else
   emtIdx             = 0;
 #endif
+#if JVET_M0427_INLOOP_RESHAPER
+  m_iChromaAdj       = 0;
+#endif
 }
 
 void TransformUnit::init(TCoeff **coeffs, Pel **pcmbuf)
@@ -631,3 +634,7 @@ const CCoeffBuf TransformUnit::getCoeffs(const ComponentID id) const { return CC
 
        PelBuf   TransformUnit::getPcmbuf(const ComponentID id)       { return  PelBuf  (m_pcmbuf[id], blocks[id]); }
 const CPelBuf   TransformUnit::getPcmbuf(const ComponentID id) const { return CPelBuf  (m_pcmbuf[id], blocks[id]); }
+#if JVET_M0427_INLOOP_RESHAPER
+int          TransformUnit::getChromaAdj()                     const { return m_iChromaAdj; }
+void         TransformUnit::setChromaAdj(int iChromaAdj)             { m_iChromaAdj = iChromaAdj; }
+#endif
\ No newline at end of file
diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h
index 9d5322234..811a63dd4 100644
--- a/source/Lib/CommonLib/Unit.h
+++ b/source/Lib/CommonLib/Unit.h
@@ -435,6 +435,9 @@ struct TransformUnit : public UnitArea
   CodingUnit      *cu;
   CodingStructure *cs;
   ChannelType      chType;
+ #if JVET_M0427_INLOOP_RESHAPER
+  int              m_iChromaAdj;
+#endif 
 
   uint8_t        depth;
 #if JVET_M0464_UNI_MTS
@@ -467,6 +470,10 @@ struct TransformUnit : public UnitArea
   const CCoeffBuf getCoeffs(const ComponentID id) const;
          PelBuf   getPcmbuf(const ComponentID id);
   const CPelBuf   getPcmbuf(const ComponentID id) const;
+#if JVET_M0427_INLOOP_RESHAPER
+        int       getChromaAdj( )                 const;
+        void      setChromaAdj(int iChromaAdj);
+#endif
 
 #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
   int64_t cacheId;
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 3c2730c00..0cc6269f2 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -62,6 +62,9 @@
 
 DecCu::DecCu()
 {
+#if JVET_M0427_INLOOP_RESHAPER
+  m_tmpStorageLCU = NULL;
+#endif
 }
 
 DecCu::~DecCu()
@@ -74,6 +77,27 @@ void DecCu::init( TrQuant* pcTrQuant, IntraPrediction* pcIntra, InterPrediction*
   m_pcIntraPred     = pcIntra;
   m_pcInterPred     = pcInter;
 }
+#if JVET_M0427_INLOOP_RESHAPER
+void DecCu::initDecCuReshaper  (Reshape* pcReshape, ChromaFormat chromaFormatIDC)
+{
+  m_pcReshape = pcReshape;
+  if (m_tmpStorageLCU == NULL)
+  {
+    m_tmpStorageLCU = new PelStorage;
+    m_tmpStorageLCU->create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
+  }
+
+}
+void DecCu::destoryDecCuReshaprBuf()
+{
+  if (m_tmpStorageLCU)
+  {
+    m_tmpStorageLCU->destroy();
+    delete m_tmpStorageLCU;
+    m_tmpStorageLCU = NULL;
+  }
+}
+#endif
 
 // ====================================================================================================================
 // Public member functions
@@ -185,7 +209,21 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
   {
     m_pcIntraPred->predIntraAng( compID, piPred, pu, bUseFilteredPredictions );
   }
+#if JVET_M0427_INLOOP_RESHAPER
+  const Slice           &slice = *cs.slice;
+  bool bFlag = slice.getReshapeInfo().getUseSliceReshaper() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag() ) || (slice.getSliceType() == P_SLICE && slice.getSPS()->getSpsNext().getCPRMode()));
 
+  if (bFlag && slice.getReshapeInfo().getSliceReshapeChromaAdj() && (compID != COMPONENT_Y))
+  {
+    const Area area = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].pos()), recalcSize(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].size()));
+    const CompArea &areaY = CompArea(COMPONENT_Y, tu.chromaFormat, area);
+    PelBuf piPredY;
+    piPredY = cs.picture->getPredBuf(areaY);
+    const Pel avgLuma = piPredY.computeAvg();
+    int adj = m_pcReshape->calculateChromaAdj(avgLuma);
+    tu.setChromaAdj(adj);
+  }
+#endif
   //===== inverse transform =====
   PelBuf piResi = cs.getResiBuf( area );
 
@@ -201,6 +239,13 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
   }
 
   //===== reconstruction =====
+#if JVET_M0427_INLOOP_RESHAPER
+  bFlag = bFlag && (tu.blocks[compID].width*tu.blocks[compID].height > 4);
+  if (bFlag && TU::getCbf(tu, compID) && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj())
+  {  
+    piResi.scaleSignal(tu.getChromaAdj(), 0);
+  }
+#endif
   if( isChroma(compID) && tu.compAlpha[compID] != 0 )
   {
     CrossComponentPrediction::crossComponentPrediction( tu, compID, cs.getResiBuf( tu.Y() ), piResi, piResi, true );
@@ -210,6 +255,21 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
 
   cs.setDecomp( area );
 
+#if JVET_M0427_INLOOP_RESHAPER
+#if REUSE_CU_RESULTS
+  CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+  PelBuf tmpPred;
+#endif
+  if (slice.getReshapeInfo().getUseSliceReshaper() && (m_pcReshape->getCTUFlag() || slice.isIntra() || (slice.getSliceType() == P_SLICE && slice.getSPS()->getSpsNext().getCPRMode())) && compID == COMPONENT_Y)
+  {
+#if REUSE_CU_RESULTS
+    {
+      tmpPred = m_tmpStorageLCU->getBuf(tmpArea);
+      tmpPred.copyFrom(piPred);
+    }
+#endif
+  }
+#endif
 #if KEEP_PRED_AND_RESI_SIGNALS
   pReco.reconstruct( piPred, piResi, tu.cu->cs->slice->clpRng( compID ) );
 #else
@@ -218,10 +278,23 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
 #if !KEEP_PRED_AND_RESI_SIGNALS
   pReco.copyFrom( piPred );
 #endif
+#if JVET_M0427_INLOOP_RESHAPER
+  if (slice.getReshapeInfo().getUseSliceReshaper() && (m_pcReshape->getCTUFlag() || slice.isIntra() || (slice.getSliceType() == P_SLICE && slice.getSPS()->getSpsNext().getCPRMode())) && compID == COMPONENT_Y)
+  {
+#if REUSE_CU_RESULTS
+    {
+      piPred.copyFrom(tmpPred);
+    }
+#endif
+  }
+#endif
 #if REUSE_CU_RESULTS
   if( cs.pcv->isEncoder )
   {
     cs.picture->getRecoBuf( area ).copyFrom( pReco );
+#if JVET_M0427_INLOOP_RESHAPER
+    cs.picture->getPredBuf(area).copyFrom(piPred);
+#endif
   }
 #endif
 }
@@ -394,6 +467,12 @@ void DecCu::xReconInter(CodingUnit &cu)
 
   if (cu.firstPU->mhIntraFlag)
   {
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+    {
+      cu.cs->getPredBuf(*cu.firstPU).Y().rspSignal(m_pcReshape->getFwdLUT());
+    }
+#endif
     m_pcIntraPred->geneWeightedPred(COMPONENT_Y, cu.cs->getPredBuf(*cu.firstPU).Y(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Y, 0));
     m_pcIntraPred->geneWeightedPred(COMPONENT_Cb, cu.cs->getPredBuf(*cu.firstPU).Cb(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Cb, 0));
     m_pcIntraPred->geneWeightedPred(COMPONENT_Cr, cu.cs->getPredBuf(*cu.firstPU).Cr(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Cr, 0));
@@ -410,16 +489,52 @@ void DecCu::xReconInter(CodingUnit &cu)
 
   if (cu.rootCbf)
   {
+#if JVET_M0427_INLOOP_RESHAPER
+#if REUSE_CU_RESULTS
+    const CompArea &area = cu.blocks[COMPONENT_Y];
+    CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+    PelBuf tmpPred;
+#endif
+    if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+    {
+#if REUSE_CU_RESULTS
+      if (cs.pcv->isEncoder)
+      {
+        tmpPred = m_tmpStorageLCU->getBuf(tmpArea);
+        tmpPred.copyFrom(cs.getPredBuf(cu).get(COMPONENT_Y));
+      }
+#endif
+      if (!cu.firstPU->mhIntraFlag && !cu.cpr )
+        cs.getPredBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
+    }
+#endif
 #if KEEP_PRED_AND_RESI_SIGNALS
     cs.getRecoBuf( cu ).reconstruct( cs.getPredBuf( cu ), cs.getResiBuf( cu ), cs.slice->clpRngs() );
 #else
     cs.getResiBuf( cu ).reconstruct( cs.getPredBuf( cu ), cs.getResiBuf( cu ), cs.slice->clpRngs() );
     cs.getRecoBuf( cu ).copyFrom   (                      cs.getResiBuf( cu ) );
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+    {
+#if REUSE_CU_RESULTS
+      if (cs.pcv->isEncoder)
+      {
+        cs.getPredBuf(cu).get(COMPONENT_Y).copyFrom(tmpPred);
+      }
+#endif
+    }
 #endif
   }
   else
   {
     cs.getRecoBuf(cu).copyClip(cs.getPredBuf(cu), cs.slice->clpRngs());
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !cu.cpr)
+    {
+      cs.getRecoBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
+    }
+#endif 
   }
   
   DTRACE    ( g_trace_ctx, D_TMP, "reco " );
@@ -451,6 +566,13 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID )
   }
 
   //===== reconstruction =====
+#if JVET_M0427_INLOOP_RESHAPER
+  const Slice           &slice = *cs.slice;
+  if ( slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && isChroma(compID) && TU::getCbf(currTU, compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() && currTU.blocks[compID].width*currTU.blocks[compID].height > 4 )
+  {
+    resiBuf.scaleSignal(currTU.getChromaAdj(), 0);
+  }
+#endif
   if( isChroma( compID ) && currTU.compAlpha[compID] != 0 )
   {
     CrossComponentPrediction::crossComponentPrediction( currTU, compID, cs.getResiBuf( currTU.Y() ), resiBuf, resiBuf, true );
@@ -472,6 +594,23 @@ void DecCu::xDecodeInterTexture(CodingUnit &cu)
 
     for( auto& currTU : CU::traverseTUs( cu ) )
     {
+#if JVET_M0427_INLOOP_RESHAPER
+      CodingStructure  &cs = *cu.cs;
+      const Slice &slice = *cs.slice;
+      if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && slice.getReshapeInfo().getSliceReshapeChromaAdj() && (compID == COMPONENT_Y))
+      {
+        const CompArea &areaY = currTU.blocks[COMPONENT_Y];
+        PelBuf piPredY = cs.getPredBuf(areaY);
+        CompArea tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+        PelBuf tmpPred = m_tmpStorageLCU->getBuf(tmpArea);
+        tmpPred.copyFrom(piPredY);
+        if (!cu.firstPU->mhIntraFlag && !cu.cpr)
+          tmpPred.rspSignal(m_pcReshape->getFwdLUT());
+        const Pel avgLuma = tmpPred.computeAvg();
+        int adj = m_pcReshape->calculateChromaAdj(avgLuma);
+        currTU.setChromaAdj(adj);
+    }
+#endif
       xDecodeInterTU( currTU, compID );
     }
   }
diff --git a/source/Lib/DecoderLib/DecCu.h b/source/Lib/DecoderLib/DecCu.h
index 67e5dc4fb..40114ce68 100644
--- a/source/Lib/DecoderLib/DecCu.h
+++ b/source/Lib/DecoderLib/DecCu.h
@@ -48,7 +48,9 @@
 #include "CommonLib/InterPrediction.h"
 #include "CommonLib/IntraPrediction.h"
 #include "CommonLib/Unit.h"
-
+#if JVET_M0427_INLOOP_RESHAPER
+#include "CommonLib/Reshape.h"
+#endif
 //! \ingroup DecoderLib
 //! \{
 
@@ -68,6 +70,12 @@ public:
 
   /// destroy internal buffers
   void  decompressCtu     ( CodingStructure& cs, const UnitArea& ctuArea );
+#if JVET_M0427_INLOOP_RESHAPER
+  Reshape*          m_pcReshape;
+  Reshape* getReshape     () { return m_pcReshape; }
+  void initDecCuReshaper  ( Reshape* pcReshape, ChromaFormat chromaFormatIDC) ;
+  void destoryDecCuReshaprBuf();
+#endif
 
 #if JVET_M0170_MRG_SHARELIST
   void setShareStateDec (int shareStateDecIn)  { m_shareStateDec = shareStateDecIn; }
@@ -87,7 +95,9 @@ protected:
   void xDecodeInterTU     ( TransformUnit&   tu, const ComponentID compID );
 
   void xDeriveCUMV        ( CodingUnit&      cu );
-
+#if JVET_M0427_INLOOP_RESHAPER
+  PelStorage        *m_tmpStorageLCU;
+#endif
 private:
   TrQuant*          m_pcTrQuant;
   IntraPrediction*  m_pcIntraPred;
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index 09b493dd5..1bc6e1227 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -353,6 +353,9 @@ DecLib::DecLib()
   , m_cSAO()
 #if JVET_J0090_MEMORY_BANDWITH_MEASURE
   , m_cacheModel()
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+  , m_cReshaper()
 #endif
   , m_pcPic(NULL)
   , m_prevPOC(MAX_INT)
@@ -434,6 +437,10 @@ void DecLib::deletePicBuffer ( )
   m_cacheModel.reportSequence( );
   m_cacheModel.destroy( );
 #endif
+#if JVET_M0427_INLOOP_RESHAPER
+  m_cCuDecoder.destoryDecCuReshaprBuf();
+  m_cReshaper.destroy();
+#endif
 }
 
 Picture* DecLib::xGetNewPicBuffer ( const SPS &sps, const PPS &pps, const uint32_t temporalLayer )
@@ -508,6 +515,14 @@ void DecLib::executeLoopFilters()
 
   CodingStructure& cs = *m_pcPic->cs;
 
+#if JVET_M0427_INLOOP_RESHAPER
+  if (cs.sps->getUseReshaper() && m_cReshaper.getSliceReshaperInfo().getUseSliceReshaper())
+  {
+      CHECK((m_cReshaper.getRecReshaped() == false), "Rec picture is not reshaped!");
+      m_pcPic->getRecoBuf(COMPONENT_Y).rspSignal(m_cReshaper.getInvLUT());
+      m_cReshaper.setRecReshaped(false);
+  }
+#endif
   // deblocking filter
   m_cLoopFilter.loopFilterPic( cs );
 
@@ -738,7 +753,12 @@ void DecLib::xActivateParameterSets()
     m_cLoopFilter.create( sps->getMaxCodingDepth() );
     m_cIntraPred.init( sps->getChromaFormatIdc(), sps->getBitDepth( CHANNEL_TYPE_LUMA ) );
     m_cInterPred.init( &m_cRdCost, sps->getChromaFormatIdc() );
-
+#if JVET_M0427_INLOOP_RESHAPER
+    if (sps->getUseReshaper())
+    {
+      m_cReshaper.create_dec();
+    }
+#endif
 
     bool isField = false;
     bool isTopField = false;
@@ -765,6 +785,12 @@ void DecLib::xActivateParameterSets()
 
     // Recursive structure
     m_cCuDecoder.init( &m_cTrQuant, &m_cIntraPred, &m_cInterPred );
+#if JVET_M0427_INLOOP_RESHAPER
+    if (sps->getUseReshaper())
+    {
+      m_cCuDecoder.initDecCuReshaper(&m_cReshaper, sps->getChromaFormatIdc());
+    }
+#endif
     m_cTrQuant.init( nullptr, sps->getMaxTrSize(), false, false, false, false, false );
 
     // RdCost
@@ -1233,6 +1259,43 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
     CHECK(pcSlice->getRefPic(RefPicList(pcSlice->isInterB() ? 1 - pcSlice->getColFromL0Flag() : 0), pcSlice->getColRefIdx())->getPOC() == pcSlice->getPOC(), "curr ref picture cannot be collocated picture");
   }
 
+#if JVET_M0427_INLOOP_RESHAPER
+  if (pcSlice->getSPS()->getUseReshaper())
+  {
+    m_cReshaper.copySliceReshaperInfo(m_cReshaper.getSliceReshaperInfo(), pcSlice->getReshapeInfo());
+    if (pcSlice->getReshapeInfo().getSliceReshapeModelPresentFlag())
+    {
+      m_cReshaper.constructReshaper();
+    }
+    else
+    {
+      m_cReshaper.setReshapeFlag(false);
+    }
+    if ((pcSlice->getSliceType() == I_SLICE|| (pcSlice->getSliceType() == P_SLICE && pcSlice->getSPS()->getSpsNext().getCPRMode()) ) && m_cReshaper.getSliceReshaperInfo().getUseSliceReshaper())
+    {
+      m_cReshaper.setCTUFlag(false);
+      m_cReshaper.setRecReshaped(true);
+    }
+    else
+    {
+      if (m_cReshaper.getSliceReshaperInfo().getUseSliceReshaper())
+      {
+        m_cReshaper.setCTUFlag(true);
+        m_cReshaper.setRecReshaped(true);
+      }
+      else
+      {
+        m_cReshaper.setCTUFlag(false);
+        m_cReshaper.setRecReshaped(false);
+      }
+    }
+  }
+  else
+  {
+    m_cReshaper.setCTUFlag(false);
+    m_cReshaper.setRecReshaped(false);
+  }
+#endif
 
   //  Decode a picture
   m_cSliceDecoder.decompressSlice( pcSlice, &(nalu.getBitstream()) );
diff --git a/source/Lib/DecoderLib/DecLib.h b/source/Lib/DecoderLib/DecLib.h
index 687ea822a..01e272fc8 100644
--- a/source/Lib/DecoderLib/DecLib.h
+++ b/source/Lib/DecoderLib/DecLib.h
@@ -53,6 +53,9 @@
 #include "CommonLib/AdaptiveLoopFilter.h"
 #include "CommonLib/SEI.h"
 #include "CommonLib/Unit.h"
+#if JVET_M0427_INLOOP_RESHAPER
+#include "CommonLib/Reshape.h"
+#endif
 
 class InputNALUnit;
 
@@ -94,6 +97,9 @@ private:
   LoopFilter              m_cLoopFilter;
   SampleAdaptiveOffset    m_cSAO;
   AdaptiveLoopFilter      m_cALF;
+#if JVET_M0427_INLOOP_RESHAPER
+  Reshape                 m_cReshaper;                        ///< reshaper class
+#endif
   // decoder side RD cost computation
   RdCost                  m_cRdCost;                      ///< RD cost computation class
 #if JVET_J0090_MEMORY_BANDWITH_MEASURE
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 94c056f88..44d883e21 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -853,6 +853,40 @@ void HLSyntaxReader::parseSPSNext( SPSNext& spsNext, const bool usePCM )
   // ADD_NEW_TOOL : (sps extension parser) read tool enabling flags and associated parameters here
 }
 
+#if JVET_M0427_INLOOP_RESHAPER
+void HLSyntaxReader::parseReshaper        (sliceReshapeInfo& info, const SPS* pcSPS, const bool isIntra)
+{
+  unsigned  symbol = 0;
+  READ_FLAG(symbol, "slice_reshape_model_present_flag");                           info.setSliceReshapeModelPresentFlag(symbol == 1);
+  if (info.getSliceReshapeModelPresentFlag())
+  {
+    // parse slice reshaper model
+    memset(info.reshape_model_bin_CW_delta, 0, PIC_CODE_CW_BINS * sizeof(int));
+      READ_UVLC(symbol, "reshaper_model_min_bin_idx");                             info.reshape_model_min_bin_idx = symbol;
+      READ_UVLC(symbol, "max_bin_minus_reshape_model_max_bin_idx");                info.reshape_model_max_bin_idx = PIC_CODE_CW_BINS - 1 - symbol;
+      READ_UVLC(symbol, "reshaper_model_bin_delta_abs_cw_prec_minus1");            info.maxNbitsNeededDeltaCW = symbol+1;
+      assert(info.maxNbitsNeededDeltaCW > 0);
+      for (uint32_t i = info.reshape_model_min_bin_idx; i <= info.reshape_model_max_bin_idx; i++)
+      {
+        READ_CODE(info.maxNbitsNeededDeltaCW, symbol, "reshape_model_abs_CW");                  int absCW = symbol;
+        if (absCW > 0)
+          READ_CODE(1, symbol, "reshape_model_sign_CW");                  int signCW = symbol;
+        info.reshape_model_bin_CW_delta[i] = (1 - 2 * signCW) * absCW;
+      }
+  }
+  READ_FLAG(symbol, "slice_reshaper_enable_flag");                           info.setUseSliceReshaper(symbol == 1);
+
+  if (info.getUseSliceReshaper())
+  {
+    if (!(pcSPS->getUseDualITree() && isIntra))
+    {
+      READ_FLAG(symbol, "slice_reshaper_ChromaAdj");                info.setSliceReshapeChromaAdj(symbol);
+    }
+    else
+      info.setSliceReshapeChromaAdj(0);
+  }
+}
+#endif
 void HLSyntaxReader::parseSPS(SPS* pcSPS)
 {
 #if ENABLE_TRACING
@@ -1171,7 +1205,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
       }
     }
   }
-
+#if JVET_M0427_INLOOP_RESHAPER
+  READ_FLAG(uiCode, "sps_reshaper_enable_flag");                   pcSPS->setUseReshaper(uiCode == 1);
+#endif
   xReadRbspTrailingBits();
 }
 
@@ -1869,6 +1905,13 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
       uiCode = pps->getLoopFilterAcrossSlicesEnabledFlag()?1:0;
     }
     pcSlice->setLFCrossSliceBoundaryFlag( (uiCode==1)?true:false);
+
+#if JVET_M0427_INLOOP_RESHAPER
+    if (sps->getUseReshaper())
+    {
+      parseReshaper(pcSlice->getReshapeInfo(), sps, pcSlice->isIntra());
+    }
+#endif
 #if HEVC_DEPENDENT_SLICES
   }
 #endif
diff --git a/source/Lib/DecoderLib/VLCReader.h b/source/Lib/DecoderLib/VLCReader.h
index 56fc8eb43..a80eefc9d 100644
--- a/source/Lib/DecoderLib/VLCReader.h
+++ b/source/Lib/DecoderLib/VLCReader.h
@@ -163,7 +163,9 @@ public:
   void  parseScalingList    ( ScalingList* scalingList );
   void  decodeScalingList   ( ScalingList *scalingList, uint32_t sizeId, uint32_t listId);
 #endif
-
+#if JVET_M0427_INLOOP_RESHAPER
+  void parseReshaper        ( sliceReshapeInfo& sliceReshaperInfo, const SPS* pcSPS, const bool isIntra );
+#endif
   void alf( AlfSliceParam& alfSliceParam );
   void alfFilter( AlfSliceParam& alfSliceParam, const bool isChroma );
 
diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
index f8a713d34..97340a546 100644
--- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
+++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
@@ -40,6 +40,9 @@
 #include "CommonLib/CodingStructure.h"
 
 #define AlfCtx(c) SubCtx( Ctx::ctbAlfFlag, c )
+#if JVET_M0427_INLOOP_RESHAPER
+double EncAdaptiveLoopFilter::m_lumaLevelToWeightPLUT[LUMA_LEVEL_TO_DQP_LUT_MAXSIZE];
+#endif
 
 EncAdaptiveLoopFilter::EncAdaptiveLoopFilter()
   : m_CABACEstimator( nullptr )
@@ -55,6 +58,10 @@ EncAdaptiveLoopFilter::EncAdaptiveLoopFilter()
   m_filterCoeffQuant = nullptr;
   m_filterCoeffSet = nullptr;
   m_diffFilterCoeff = nullptr;
+
+#if JVET_M0427_INLOOP_RESHAPER
+  m_alfWSSD = 0;
+#endif
 }
 
 void EncAdaptiveLoopFilter::create( const int picWidth, const int picHeight, const ChromaFormat chromaFormatIDC, const int maxCUWidth, const int maxCUHeight, const int maxCUDepth, const int inputBitDepth[MAX_NUM_CHANNEL_TYPE], const int internalBitDepth[MAX_NUM_CHANNEL_TYPE] )
@@ -1472,16 +1479,40 @@ void EncAdaptiveLoopFilter::getBlkStats( AlfCovariance* alfCovariace, const AlfF
         classIdx = cl.classIdx;
       }
 
+#if JVET_M0427_INLOOP_RESHAPER
+      double weight = m_lumaLevelToWeightPLUT[org[j]];
+#endif
       int yLocal = org[j] - rec[j];
       calcCovariance( ELocal, rec + j, recStride, shape.pattern.data(), shape.filterLength >> 1, transposeIdx );
       for( int k = 0; k < shape.numCoeff; k++ )
       {
         for( int l = k; l < shape.numCoeff; l++ )
         {
+#if JVET_M0427_INLOOP_RESHAPER
+          if (m_alfWSSD)
+          {
+            alfCovariace[classIdx].E[k][l] += weight * (double)(ELocal[k] * ELocal[l]);
+          }
+          else
+#endif
           alfCovariace[classIdx].E[k][l] += ELocal[k] * ELocal[l];
         }
+#if JVET_M0427_INLOOP_RESHAPER
+        if (m_alfWSSD)
+        {
+          alfCovariace[classIdx].y[k] += weight * (double)(ELocal[k] * yLocal);
+        }
+        else
+#endif
         alfCovariace[classIdx].y[k] += ELocal[k] * yLocal;
       }
+#if JVET_M0427_INLOOP_RESHAPER
+      if (m_alfWSSD)
+      {
+        alfCovariace[classIdx].pixAcc += weight * (double)(yLocal * yLocal);
+      }
+      else
+#endif
       alfCovariace[classIdx].pixAcc += yLocal * yLocal;
     }
     org += orgStride;
diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
index da36a50e5..81a4ee2d0 100644
--- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
+++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
@@ -151,6 +151,12 @@ class EncAdaptiveLoopFilter : public AdaptiveLoopFilter
 public:
   static constexpr int   m_MAX_SCAN_VAL = 11;
   static constexpr int   m_MAX_EXP_GOLOMB = 16;
+#if JVET_M0427_INLOOP_RESHAPER
+  int m_alfWSSD;
+  inline void           setAlfWSSD(int alfWSSD) { m_alfWSSD = alfWSSD; }
+  static double         m_lumaLevelToWeightPLUT[LUMA_LEVEL_TO_DQP_LUT_MAXSIZE];
+  inline  double*       getLumaLevelWeightTable() { return m_lumaLevelToWeightPLUT; }
+#endif
 
 private:
   AlfCovariance***       m_alfCovariance[MAX_NUM_COMPONENT];          // [compIdx][shapeIdx][ctbAddr][classIdx]
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index a34fdac1a..af9445baa 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -256,7 +256,12 @@ protected:
   unsigned  m_wrapAroundOffset;
 
   // ADD_NEW_TOOL : (encoder lib) add tool enabling flags and associated parameters here
-
+#if JVET_M0427_INLOOP_RESHAPER
+  bool      m_bUseReshape;
+  unsigned  m_uiSignalType;
+  unsigned  m_uiIntraCMD;
+  ReshapeCW m_reshapeCW;
+#endif
   bool      m_useFastLCTU;
   bool      m_useFastMrg;
   bool      m_usePbIntraFast;
@@ -790,7 +795,16 @@ public:
 
   // ADD_NEW_TOOL : (encoder lib) add access functions here
 
-
+#if JVET_M0427_INLOOP_RESHAPER
+  void      setReshaper                     ( bool b )                   { m_bUseReshape = b; }
+  bool      getReshaper                     () const                     { return m_bUseReshape; }
+  void      setReshapeSignalType            ( uint32_t uiSignalType )    { m_uiSignalType = uiSignalType; }
+  uint32_t  getReshapeSignalType            () const                     { return m_uiSignalType; }
+  void      setReshapeIntraCMD              (uint32_t uiIntraCMD)        { m_uiIntraCMD = uiIntraCMD; }
+  uint32_t  getReshapeIntraCMD              ()                           { return m_uiIntraCMD; }
+  void      setReshapeCW                    (const ReshapeCW &reshapeCW) { m_reshapeCW = reshapeCW; }
+  const ReshapeCW& getReshapeCW             ()                           { return m_reshapeCW; }
+#endif
   void      setMaxCUWidth                   ( uint32_t  u )      { m_maxCUWidth  = u; }
   uint32_t      getMaxCUWidth                   () const         { return m_maxCUWidth; }
   void      setMaxCUHeight                  ( uint32_t  u )      { m_maxCUHeight = u; }
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 326393399..0c1b6d192 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -232,6 +232,14 @@ void EncCu::destroy()
   delete[] m_pBestMotLUTs; m_pBestMotLUTs = nullptr;
   delete[] m_pTempMotLUTs; m_pTempMotLUTs = nullptr;
 
+#if JVET_M0427_INLOOP_RESHAPER && REUSE_CU_RESULTS
+  if (m_tmpStorageLCU)
+  {
+    m_tmpStorageLCU->destroy();
+    delete m_tmpStorageLCU;  m_tmpStorageLCU = nullptr;
+  }
+#endif
+
 #if REUSE_CU_RESULTS
   m_modeCtrl->destroy();
 
@@ -338,7 +346,15 @@ void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsign
 #if !JVET_M0255_FRACMMVD_SWITCH
   if (m_pcEncCfg->getIBCHashSearch() && ctuRsAddr == 0 && cs.slice->getSPS()->getSpsNext().getIBCMode())
   {
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cs.slice->getSPS()->getUseReshaper() && m_pcReshape->getCTUFlag())
+      cs.picture->getOrigBuf(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
+#endif
     m_ibcHashMap.rebuildPicHashMap(cs.picture->getOrigBuf());
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cs.slice->getSPS()->getUseReshaper() && m_pcReshape->getCTUFlag())
+      cs.picture->getOrigBuf().copyFrom(cs.picture->getTrueOrigBuf());
+#endif
   }
 #endif
   m_modeCtrl->initCTUEncoding( *cs.slice );
@@ -404,7 +420,11 @@ void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsign
   );
 
   // all signals were already copied during compression if the CTU was split - at this point only the structures are copied to the top level CS
+#if JVET_M0427_INLOOP_RESHAPER
+  const bool copyUnsplitCTUSignals = bestCS->cus.size() == 1;
+#else
   const bool copyUnsplitCTUSignals = bestCS->cus.size() == 1 && KEEP_PRED_AND_RESI_SIGNALS;
+#endif
   cs.useSubStructure( *bestCS, partitioner->chType, CS::getArea( *bestCS, area, partitioner->chType ), copyUnsplitCTUSignals, false, false, copyUnsplitCTUSignals );
   cs.slice->copyMotionLUTs(bestMotCandLUTs, cs.slice->getMotionLUTs());
 
@@ -425,7 +445,11 @@ void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsign
       , bestMotCandLUTs
     );
 
+#if JVET_M0427_INLOOP_RESHAPER
+    const bool copyUnsplitCTUSignals = bestCS->cus.size() == 1;
+#else
     const bool copyUnsplitCTUSignals = bestCS->cus.size() == 1 && KEEP_PRED_AND_RESI_SIGNALS;
+#endif
     cs.useSubStructure( *bestCS, partitioner->chType, CS::getArea( *bestCS, area, partitioner->chType ), copyUnsplitCTUSignals, false, false, copyUnsplitCTUSignals );
   }
 
@@ -841,6 +865,9 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par
   {
     bestCS->slice->updateMotionLUTs(bestMotCandLUTs, (*bestCS->cus.back()));
   }
+#if JVET_M0427_INLOOP_RESHAPER
+  bestCS->picture->getPredBuf(currCsArea).copyFrom(bestCS->getPredBuf(currCsArea));
+#endif
   bestCS->picture->getRecoBuf( currCsArea ).copyFrom( bestCS->getRecoBuf( currCsArea ) );
   m_modeCtrl->finishCULevel( partitioner );
 
@@ -1212,6 +1239,10 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
   m_CurrCtx++;
 
   tempCS->getRecoBuf().fill( 0 );
+
+#if JVET_M0427_INLOOP_RESHAPER
+  tempCS->getPredBuf().fill(0);
+#endif
   AffineMVInfo tmpMVInfo;
   bool isAffMVInfoSaved;
   m_pcInterSearch->savePrevAffMVInfo(0, tmpMVInfo, isAffMVInfoSaved);
@@ -1492,6 +1523,9 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
       if( !CS::isDualITree( *tempCS ) )
       {
         cu.cs->picture->getRecoBuf( cu.Y() ).copyFrom( cu.cs->getRecoBuf( COMPONENT_Y ) );
+#if JVET_M0427_INLOOP_RESHAPER
+        cu.cs->picture->getPredBuf(cu.Y()).copyFrom(cu.cs->getPredBuf(COMPONENT_Y));
+#endif
       }
     }
 
@@ -1992,11 +2026,29 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
               m_pcIntraSearch->switchBuffer(pu, COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, intraCnt));
             }
             pu.cs->getPredBuf(pu).copyFrom(acMergeBuffer[mergeCand]);
+#if JVET_M0427_INLOOP_RESHAPER
+            if (pu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+            {
+              pu.cs->getPredBuf(pu).Y().rspSignal(m_pcReshape->getFwdLUT());
+            }
+#endif
             m_pcIntraSearch->geneWeightedPred(COMPONENT_Y, pu.cs->getPredBuf(pu).Y(), pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, intraCnt));
 
             // calculate cost
+#if JVET_M0427_INLOOP_RESHAPER
+            if (pu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+            {
+               pu.cs->getPredBuf(pu).Y().rspSignal(m_pcReshape->getInvLUT());
+            }
+#endif
             distParam.cur = pu.cs->getPredBuf(pu).Y();
             Distortion sadValue = distParam.distFunc(distParam);
+#if JVET_M0427_INLOOP_RESHAPER 
+            if (pu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+            {
+              pu.cs->getPredBuf(pu).Y().rspSignal(m_pcReshape->getFwdLUT());
+            }
+#endif
             m_CABACEstimator->getCtx() = SubCtx(Ctx::MHIntraPredMode, ctxStartIntraMode);
             uint64_t fracModeBits = m_pcIntraSearch->xFracModeBitsIntra(pu, pu.intraDir[0], CHANNEL_TYPE_LUMA);
             double cost = (double)sadValue + (double)(bitsCand + 1) * sqrtLambdaForFirstPass + (double)fracModeBits * sqrtLambdaForFirstPassIntra;
@@ -2228,6 +2280,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           uint32_t bufIdx = (pu.intraDir[0] > 1) ? (pu.intraDir[0] == HOR_IDX ? 2 : 3) : pu.intraDir[0];
           PelBuf tmpBuf = tempCS->getPredBuf(pu).Y();
           tmpBuf.copyFrom(acMergeBuffer[uiMergeCand].Y());
+#if JVET_M0427_INLOOP_RESHAPER
+          if (pu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+          {
+            tmpBuf.rspSignal(m_pcReshape->getFwdLUT());
+          }
+#endif
           m_pcIntraSearch->geneWeightedPred(COMPONENT_Y, tmpBuf, pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, bufIdx));
           tmpBuf = tempCS->getPredBuf(pu).Cb();
           tmpBuf.copyFrom(acMergeBuffer[uiMergeCand].Cb());
@@ -2970,6 +3028,18 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
       Picture* refPic = pu.cu->slice->getPic();
       const CPelBuf refBuf = refPic->getRecoBuf(pu.blocks[COMPONENT_Y]);
       const Pel*        piRefSrch = refBuf.buf;
+#if JVET_M0427_INLOOP_RESHAPER
+      if (tempCS->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+      {
+        const CompArea &area = cu.blocks[COMPONENT_Y];
+        CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+        PelBuf tmpLuma = m_tmpStorageLCU->getBuf(tmpArea);
+        tmpLuma.copyFrom(tempCS->getOrgBuf().Y());
+        tmpLuma.rspSignal(m_pcReshape->getFwdLUT());
+        m_pcRdCost->setDistParam(distParam, tmpLuma, refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
+      }
+      else
+#endif
       m_pcRdCost->setDistParam(distParam, tempCS->getOrgBuf().Y(), refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
       int refStride = refBuf.stride;
       const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(0, 0, tempCS->area.Y().width, tempCS->area.Y().height));
@@ -4005,9 +4075,26 @@ void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&best
       CPelBuf org  = tempCS->getOrgBuf ( compID );
 
 #if WCG_EXT
+#if JVET_M0427_INLOOP_RESHAPER
+      if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (
+        m_pcEncCfg->getReshaper() && (tempCS->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())))
+#else
       if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
+#endif
       {
         const CPelBuf orgLuma = tempCS->getOrgBuf(tempCS->area.blocks[COMPONENT_Y]);
+#if JVET_M0427_INLOOP_RESHAPER
+        if (compID == COMPONENT_Y)
+        {
+          const CompArea &area = cu.blocks[COMPONENT_Y];
+          CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+          PelBuf tmpRecLuma = m_tmpStorageLCU->getBuf(tmpArea);
+          tmpRecLuma.copyFrom(reco);
+          tmpRecLuma.rspSignal(m_pcReshape->getInvLUT());
+          finalDistortion += m_pcRdCost->getDistPart(org, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
+        }
+        else
+#endif
         finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
       }
       else
diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h
index 920e0eca5..4ca7c3944 100644
--- a/source/Lib/EncoderLib/EncCu.h
+++ b/source/Lib/EncoderLib/EncCu.h
@@ -156,7 +156,9 @@ private:
 public:
   /// copy parameters from encoder class
   void  init                ( EncLib* pcEncLib, const SPS& sps PARL_PARAM( const int jId = 0 ) );
-
+#if JVET_M0427_INLOOP_RESHAPER && REUSE_CU_RESULTS
+  void setDecCuReshaperInEncCU(EncReshape* pcReshape, ChromaFormat chromaFormatIDC) { initDecCuReshaper((Reshape*) pcReshape, chromaFormatIDC); }
+#endif
   /// create internal buffers
   void  create              ( EncCfg* encCfg );
 
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index bc863bb6c..93e6d85bb 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -178,7 +178,25 @@ void EncGOP::init ( EncLib* pcEncLib )
   m_AUWriterIf = pcEncLib->getAUWriterIf();
 
 #if WCG_EXT
+#if JVET_M0427_INLOOP_RESHAPER
+  if (m_pcCfg->getReshaper())
+    pcEncLib->getRdCost()->setReshapeSignalType(m_pcCfg->getReshapeSignalType());
+#endif
   pcEncLib->getRdCost()->initLumaLevelToWeightTable();
+#if JVET_M0427_INLOOP_RESHAPER
+  memcpy(pcEncLib->getALF()->getLumaLevelWeightTable(), pcEncLib->getRdCost()->getLumaLevelWeightTable(), LUMA_LEVEL_TO_DQP_LUT_MAXSIZE * sizeof(double));
+  int alfWSSD = 0;
+
+  if (m_pcCfg->getReshaper() && m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ )
+  {
+    alfWSSD = 1;
+  }
+
+  pcEncLib->getALF()->setAlfWSSD(alfWSSD);
+#endif
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+  m_pcReshaper = pcEncLib->getReshaper();
 #endif
 }
 
@@ -2092,6 +2110,96 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
     // now compress (trial encode) the various slice segments (slices, and dependent slices)
     {
       DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "poc", pocCurr ) ) );
+#if JVET_M0427_INLOOP_RESHAPER
+      if (pcSlice->getSPS()->getUseReshaper())
+      {
+        m_pcReshaper->getReshapeCW()->Tid = pcSlice->getTLayer()+(pcSlice->isIntra()?0:1);
+        m_pcReshaper->getReshapeCW()->SliceQP = pcSlice->getSliceQp();
+
+        m_pcReshaper->setSrcReshaped(false);
+        m_pcReshaper->setRecReshaped(true);
+
+        if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ)
+        {
+          m_pcReshaper->preAnalyzerHDR(pcPic, pcSlice->getSliceType(), m_pcCfg->getReshapeCW(), m_pcCfg->getDualITree(), m_pcCfg->getCPRMode());
+        }
+        else if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_SDR)
+        {
+          m_pcReshaper->preAnalyzerSDR(pcPic, pcSlice->getSliceType(), m_pcCfg->getReshapeCW(), m_pcCfg->getDualITree(), m_pcCfg->getCPRMode());
+        }
+        else
+        {
+          THROW("Reshaper for signal other than PQ and SDR currently not defined!");
+        }
+
+        if (pcSlice->getSliceType() == I_SLICE || (pcSlice->getSliceType()==P_SLICE && m_pcCfg->getCPRMode()))
+        {
+          if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ)
+          {
+            m_pcReshaper->initLUTfromdQPModel();
+            m_pcEncLib->getRdCost()->updateReshapeLumaLevelToWeightTableChromaMD(m_pcReshaper->getInvLUT());
+          }
+          else if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_SDR)
+          {
+            if (m_pcReshaper->getReshapeFlag())
+            {
+              m_pcReshaper->constructReshaperSDR();
+              m_pcEncLib->getRdCost()->updateReshapeLumaLevelToWeightTable(m_pcReshaper->getSliceReshaperInfo(), m_pcReshaper->getWeightTable(), m_pcReshaper->getCWeight());
+            }
+          }
+          else
+          {
+           THROW("Reshaper for other signal currently not defined!");
+          }
+
+          m_pcReshaper->setCTUFlag(false);
+          
+          //reshape original signal
+          if (m_pcReshaper->getSliceReshaperInfo().getUseSliceReshaper())
+          {
+            pcPic->getOrigBuf(COMPONENT_Y).rspSignal(m_pcReshaper->getFwdLUT());
+            m_pcReshaper->setSrcReshaped(true);
+            m_pcReshaper->setRecReshaped(true);
+          }
+        }
+        else
+        {
+          if (!m_pcReshaper->getReshapeFlag())
+          {
+            m_pcReshaper->setCTUFlag(false);
+          }
+          else
+            m_pcReshaper->setCTUFlag(true);
+
+          m_pcReshaper->getSliceReshaperInfo().setSliceReshapeModelPresentFlag(false);
+
+          if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ )
+          {
+            m_pcEncLib->getRdCost()->restoreReshapeLumaLevelToWeightTable();
+          }
+          else if (m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_SDR)
+          {
+            int modIP = pcPic->getPOC() - pcPic->getPOC() / m_pcCfg->getReshapeCW().RspFpsToIp * m_pcCfg->getReshapeCW().RspFpsToIp;
+            if (m_pcReshaper->getReshapeFlag() && m_pcCfg->getReshapeCW().RspIntraPeriod == -1 && modIP == 0)           // for LDB, update reshaping curve every second
+            {
+              m_pcReshaper->getSliceReshaperInfo().setSliceReshapeModelPresentFlag(true);
+              m_pcReshaper->constructReshaperSDR();
+              m_pcEncLib->getRdCost()->updateReshapeLumaLevelToWeightTable(m_pcReshaper->getSliceReshaperInfo(), m_pcReshaper->getWeightTable(), m_pcReshaper->getCWeight());
+            }
+          }
+          else
+          {
+            THROW("Reshaper for other signal currently not defined!");
+          }
+        }
+
+        m_pcReshaper->copySliceReshaperInfo(pcSlice->getReshapeInfo(), m_pcReshaper->getSliceReshaperInfo());
+      }
+      else
+      {
+        m_pcReshaper->setCTUFlag(false);
+      }
+#endif
 
       pcSlice->setSliceCurStartCtuTsAddr( 0 );
 #if HEVC_DEPENDENT_SLICES
@@ -2161,6 +2269,17 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
       CodingStructure& cs = *pcPic->cs;
       pcSlice = pcPic->slices[0];
 
+#if JVET_M0427_INLOOP_RESHAPER 
+      if (pcSlice->getSPS()->getUseReshaper() && m_pcReshaper->getSliceReshaperInfo().getUseSliceReshaper())
+      {
+          CHECK((m_pcReshaper->getRecReshaped() == false), "Rec picture is not reshaped!");
+          pcPic->getRecoBuf(COMPONENT_Y).rspSignal(m_pcReshaper->getInvLUT());
+          m_pcReshaper->setRecReshaped(false);
+
+          pcPic->getOrigBuf().copyFrom(pcPic->getTrueOrigBuf());
+      }
+#endif
+
       // SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas
       if( pcSlice->getSPS()->getSAOEnabledFlag() && m_pcCfg->getSaoCtuBoundary() )
       {
@@ -2527,7 +2646,11 @@ void EncGOP::printOutSummary(uint32_t uiNumAllPicCoded, bool isField, const bool
   const bool    useWPSNR = m_pcEncLib->getUseWPSNR();
 #endif
 #if WCG_WPSNR
+#if JVET_M0427_INLOOP_RESHAPER
+  const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcCfg->getReshaper() && m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ);
+#else
   const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled();
+#endif
 #endif
 
   if( m_pcCfg->getDecodeBitstream(0).empty() && m_pcCfg->getDecodeBitstream(1).empty() && !m_pcCfg->useFastForwardToPOC() )
@@ -2868,7 +2991,11 @@ uint64_t EncGOP::xFindDistortionPlane(const CPelBuf& pic0, const CPelBuf& pic1,
 double EncGOP::xFindDistortionPlaneWPSNR(const CPelBuf& pic0, const CPelBuf& pic1, const uint32_t rshift, const CPelBuf& picLuma0,
   ComponentID compID, const ChromaFormat chfmt    )
 {
+#if JVET_M0427_INLOOP_RESHAPER
+  const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcCfg->getReshaper() && m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ);
+#else
   const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled();
+#endif
   if (!useLumaWPSNR)
   {
     return 0;
@@ -3001,13 +3128,21 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni
   const CPelUnitBuf& pic = cPicD;
   CHECK(!(conversion == IPCOLOURSPACE_UNCHANGED), "Unspecified error");
 //  const CPelUnitBuf& org = (conversion != IPCOLOURSPACE_UNCHANGED) ? pcPic->getPicYuvTrueOrg()->getBuf() : pcPic->getPicYuvOrg()->getBuf();
+#if JVET_M0427_INLOOP_RESHAPER
+  const CPelUnitBuf& org = sps.getUseReshaper() ? pcPic->getTrueOrigBuf() : pcPic->getOrigBuf();
+#else
   const CPelUnitBuf& org = pcPic->getOrigBuf();
+#endif
 #if ENABLE_QPA
   const bool    useWPSNR = m_pcEncLib->getUseWPSNR();
 #endif
   double  dPSNR[MAX_NUM_COMPONENT];
 #if WCG_WPSNR
+#if JVET_M0427_INLOOP_RESHAPER
+  const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcCfg->getReshaper() && m_pcCfg->getReshapeSignalType() == RESHAPE_SIGNAL_PQ);
+#else
   const bool    useLumaWPSNR = m_pcEncLib->getLumaLevelToDeltaQPMapping().isEnabled();
+#endif
   double  dPSNRWeighted[MAX_NUM_COMPONENT];
   double  MSEyuvframeWeighted[MAX_NUM_COMPONENT];
 #endif
diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h
index ca2121451..e2c11c170 100644
--- a/source/Lib/EncoderLib/EncGOP.h
+++ b/source/Lib/EncoderLib/EncGOP.h
@@ -47,6 +47,9 @@
 #include "CommonLib/NAL.h"
 #include "EncSampleAdaptiveOffset.h"
 #include "EncAdaptiveLoopFilter.h"
+#if JVET_M0427_INLOOP_RESHAPER
+#include "EncReshape.h"
+#endif
 #include "EncSlice.h"
 #include "VLCWriter.h"
 #include "CABACWriter.h"
@@ -139,6 +142,9 @@ private:
   //--Adaptive Loop filter
   EncSampleAdaptiveOffset*  m_pcSAO;
   EncAdaptiveLoopFilter*    m_pcALF;
+#if JVET_M0427_INLOOP_RESHAPER
+  EncReshape*               m_pcReshaper;
+#endif
   RateCtrl*                 m_pcRateCtrl;
   // indicate sequence first
   bool                    m_bSeqFirst;
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 4d8506f02..b8ff0a60e 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -136,6 +136,12 @@ void EncLib::create ()
     m_cEncALF.create( getSourceWidth(), getSourceHeight(), m_chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, m_bitDepth, m_inputBitDepth );
   }
 
+#if JVET_M0427_INLOOP_RESHAPER
+  if (m_bUseReshape)
+  {
+    m_cReshaper.create_enc( getSourceWidth(), getSourceHeight(), m_maxCUWidth, m_maxCUHeight );
+  }
+#endif
   if ( m_RCEnableRateControl )
   {
     m_cRateCtrl.init(m_framesToBeEncoded, m_RCTargetBitrate, (int)((double)m_iFrameRate / m_temporalSubsampleRatio + 0.5), m_iGOPSize, m_iSourceWidth, m_iSourceHeight,
@@ -165,6 +171,9 @@ void EncLib::destroy ()
   m_cEncSAO.            destroy();
   m_cLoopFilter.        destroy();
   m_cRateCtrl.          destroy();
+#if JVET_M0427_INLOOP_RESHAPER
+  m_cReshaper.          destroy();
+#endif
 #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
   for( int jId = 0; jId < m_numCuEncStacks; jId++ )
   {
@@ -318,13 +327,21 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
                        &m_cTrQuant,
                        &m_cRdCost,
                        cabacEstimator,
-                       getCtxCache(), m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth );
+                       getCtxCache(), m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth 
+#if JVET_M0427_INLOOP_RESHAPER
+                     , &m_cReshaper
+#endif
+  );
   m_cInterSearch.init( this,
                        &m_cTrQuant,
                        m_iSearchRange,
                        m_bipredSearchRange,
                        m_motionEstimationSearchMethod,
-                       m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, &m_cRdCost, cabacEstimator, getCtxCache() );
+    m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, &m_cRdCost, cabacEstimator, getCtxCache()
+#if JVET_M0427_INLOOP_RESHAPER
+                     , &m_cReshaper
+#endif
+  );
 
   // link temporary buffets from intra search with inter search to avoid unneccessary memory overhead
   m_cInterSearch.setTempBuffers( m_cIntraSearch.getSplitCSBuf(), m_cIntraSearch.getFullCSBuf(), m_cIntraSearch.getSaveCSBuf() );
@@ -551,6 +568,9 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru
       const SPS *pSPS=m_spsMap.getPS(pPPS->getSPSId());
 
       pcPicCurr->M_BUFS( 0, PIC_ORIGINAL ).swap( *pcPicYuvOrg );
+#if JVET_M0427_INLOOP_RESHAPER
+      pcPicCurr->M_BUFS( 0, PIC_TRUE_ORIGINAL).swap(*cPicYuvTrueOrg);
+#endif
 
       pcPicCurr->finalInit( *pSPS, *pPPS );
     }
@@ -902,7 +922,9 @@ void EncLib::xInitSPS(SPS &sps)
   sps.setWrapAroundEnabledFlag                      ( m_wrapAround );
   sps.setWrapAroundOffset                   ( m_wrapAroundOffset );
   // ADD_NEW_TOOL : (encoder lib) set tool enabling flags and associated parameters here
-
+#if JVET_M0427_INLOOP_RESHAPER
+  sps.setUseReshaper(m_bUseReshape);
+#endif
   int minCUSize =  sps.getMaxCUWidth() >> sps.getLog2DiffMaxMinCodingBlockSize();
   int log2MinCUSize = 0;
   while(minCUSize > 1)
diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h
index 07109efcd..f966d8277 100644
--- a/source/Lib/EncoderLib/EncLib.h
+++ b/source/Lib/EncoderLib/EncLib.h
@@ -53,6 +53,9 @@
 #include "InterSearch.h"
 #include "IntraSearch.h"
 #include "EncSampleAdaptiveOffset.h"
+#if JVET_M0427_INLOOP_RESHAPER
+#include "EncReshape.h"
+#endif
 #include "EncAdaptiveLoopFilter.h"
 #include "RateCtrl.h"
 
@@ -98,6 +101,10 @@ private:
   CABACEncoder              m_CABACEncoder;
 #endif
 
+#if JVET_M0427_INLOOP_RESHAPER
+  EncReshape                m_cReshaper;                        ///< reshaper class
+#endif
+
   // processing unit
   EncGOP                    m_cGOPEncoder;                        ///< GOP encoder
   EncSlice                  m_cSliceEncoder;                      ///< slice encoder
@@ -219,6 +226,9 @@ public:
   int                    getNumCuEncStacks()              const { return m_numCuEncStacks; }
 #endif
 
+#if JVET_M0427_INLOOP_RESHAPER
+  EncReshape*            getReshaper()                          { return  &m_cReshaper; }
+#endif
   // -------------------------------------------------------------------------------------------------------------------
   // encoder function
   // -------------------------------------------------------------------------------------------------------------------
diff --git a/source/Lib/EncoderLib/EncReshape.cpp b/source/Lib/EncoderLib/EncReshape.cpp
new file mode 100644
index 000000000..709060962
--- /dev/null
+++ b/source/Lib/EncoderLib/EncReshape.cpp
@@ -0,0 +1,1260 @@
+/* The copyright in this software is being made available under the BSD
+* License, included below. This software may be subject to other third party
+* and contributor rights, including patent rights, and no such rights are
+* granted under this license.
+*
+* Copyright (c) 2010-2019, ITU/ISO/IEC
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+*  * Redistributions of source code must retain the above copyright notice,
+*    this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above copyright notice,
+*    this list of conditions and the following disclaimer in the documentation
+*    and/or other materials provided with the distribution.
+*  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
+*    be used to endorse or promote products derived from this software without
+*    specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/** \file     EncReshape.cpp
+\brief    encoder reshaper class
+*/
+#include "EncReshape.h"
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#if JVET_M0427_INLOOP_RESHAPER
+//! \ingroup EncLib
+//! \{
+
+// ====================================================================================================================
+// Constructor / destructor / create / destroy
+// ====================================================================================================================
+
+EncReshape::EncReshape()
+{
+  m_bCTUFlag     = false;
+  m_bSrcReshaped = false;
+  m_bRecReshaped = false;
+  m_bReshape     = true;
+  m_bExceedSTD   = false;
+  m_uiCWOrgAnalyze = MAX_LUMA_RESHAPING_LUT_SIZE / PIC_ANALYZE_CW_BINS;
+  m_uiCWOrg = MAX_LUMA_RESHAPING_LUT_SIZE / PIC_CODE_CW_BINS;
+  m_tcase        = 0;
+  m_rateAdpMode  = 0;
+  m_chromaAdj    = 0;
+}
+
+EncReshape::~EncReshape()
+{
+}
+
+void  EncReshape::create_enc(int picWidth, int picHeight, uint32_t maxCUWidth, uint32_t maxCUHeight)
+{
+  if (forwardReshapingLUT.empty())
+    forwardReshapingLUT.resize(MAX_LUMA_RESHAPING_LUT_SIZE, 0);
+  if (inverseReshapingLUT.empty())
+    inverseReshapingLUT.resize(MAX_LUMA_RESHAPING_LUT_SIZE,0);
+  if (m_uiBinCWAll.empty())
+    m_uiBinCWAll.resize(PIC_ANALYZE_CW_BINS);
+  if (m_uiBinImportance.empty())
+    m_uiBinImportance.resize(PIC_ANALYZE_CW_BINS);
+  if (m_ReshapePivot.empty())
+    m_ReshapePivot.resize(PIC_CODE_CW_BINS + 1, 0);
+  if (ChromaAdjHelpLUT.empty())
+    ChromaAdjHelpLUT.resize(PIC_CODE_CW_BINS, 2048);
+
+  m_sliceReshapeInfo.setUseSliceReshaper(true);
+  m_sliceReshapeInfo.setSliceReshapeChromaAdj(true);
+  m_sliceReshapeInfo.setSliceReshapeModelPresentFlag(true);
+  m_sliceReshapeInfo.reshape_model_min_bin_idx = 0;
+  m_sliceReshapeInfo.reshape_model_max_bin_idx = PIC_CODE_CW_BINS - 1;
+  memset(m_sliceReshapeInfo.reshape_model_bin_CW_delta, 0, (PIC_CODE_CW_BINS) * sizeof(int));
+
+  m_picWidth = picWidth;
+  m_picHeight = picHeight;
+  m_maxCUWidth = maxCUWidth;
+  m_maxCUHeight = maxCUHeight;
+  m_widthInCtus = (m_picWidth + m_maxCUWidth - 1) / m_maxCUWidth;
+  m_heightInCtus = (m_picHeight + m_maxCUHeight - 1) / m_maxCUHeight;
+  m_numCtuInFrame = m_widthInCtus * m_heightInCtus;
+}
+
+void  EncReshape::destroy()
+{
+}
+
+/**
+-Perform HDR set up
+\param   pcPic describe pointer of current coding picture
+\param   sliceType describe the slice type
+*/
+void EncReshape::preAnalyzerHDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT, bool isCPR)
+{
+  m_sliceReshapeInfo.slice_reshaper_enable_flag = true;
+  if (reshapeCW.RspIntraPeriod == 1)
+  {
+    if (pcPic->getPOC() == 0)          { m_sliceReshapeInfo.slice_reshaper_model_present_flag = true;  }
+    else                               { m_sliceReshapeInfo.slice_reshaper_model_present_flag = false; }
+  }
+  else
+  {
+    if (sliceType == I_SLICE || (sliceType==P_SLICE && isCPR) )             { m_sliceReshapeInfo.slice_reshaper_model_present_flag = true;  }
+    else                                                                    { m_sliceReshapeInfo.slice_reshaper_model_present_flag = false; }
+  }
+  if ((sliceType == I_SLICE || (sliceType == P_SLICE && isCPR)) && isDualT) { m_sliceReshapeInfo.uiReshapeChromaAdj = 0;                    }
+  else                                                                      { m_sliceReshapeInfo.uiReshapeChromaAdj = 1;                    }
+}
+
+/**
+-Perform picture analysis for SDR
+\param   pcPic describe pointer of current coding picture
+\param   sliceType describe the slice type
+\param   reshapeCW describe some input info
+*/
+void EncReshape::preAnalyzerSDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT, bool isCPR)
+{
+  m_sliceReshapeInfo.slice_reshaper_model_present_flag = true;
+  m_sliceReshapeInfo.slice_reshaper_enable_flag = true;
+
+  int modIP = pcPic->getPOC() - pcPic->getPOC() / reshapeCW.RspFpsToIp * reshapeCW.RspFpsToIp;
+
+  if (sliceType == I_SLICE || (reshapeCW.RspIntraPeriod == -1 && modIP == 0) || (sliceType== P_SLICE && isCPR))
+  {
+    if (m_sliceReshapeInfo.slice_reshaper_model_present_flag == true)
+    {
+      uint32_t uiStdMin = 16 * 4;
+      uint32_t uiStdMax = 235 * 4;
+      int  bin_len = MAX_LUMA_RESHAPING_LUT_SIZE / PIC_ANALYZE_CW_BINS;
+      uint32_t min_start_bin_idx, max_end_bin_idx;
+
+      m_reshapeCW = reshapeCW;
+
+      for (int b = 0; b < PIC_ANALYZE_CW_BINS; b++)
+      {
+        m_uiBinImportance[b] = 0;
+        m_uiBinCWAll[b] = bin_len;
+      }
+
+      min_start_bin_idx = int(floor((double(uiStdMin) / double(bin_len))));
+      max_end_bin_idx = int(floor((double(uiStdMax) / double(bin_len))));
+
+      m_sliceReshapeInfo.reshape_model_min_bin_idx = min_start_bin_idx;
+      m_sliceReshapeInfo.reshape_model_max_bin_idx = max_end_bin_idx;
+
+      PelBuf picY = pcPic->getOrigBuf(COMPONENT_Y);
+      const int iWidth = picY.width;
+      const int iHeight = picY.height;
+      const int iStride = picY.stride;
+
+      double dBlockBinVarSum[PIC_ANALYZE_CW_BINS] = { 0.0 };
+      uint32_t   dBlockBinCnt[PIC_ANALYZE_CW_BINS] = { 0 };
+
+      const uint32_t uiWinSize = PIC_ANALYZE_WIN_SIZE;
+      const uint32_t uiWinLens = (uiWinSize - 1) >> 1;
+
+      int64_t tempSq = 0;
+      int64_t leftSum = 0, leftSumSq = 0;
+      int64_t *leftColSum = new int64_t[iWidth];
+      int64_t *leftColSumSq = new int64_t[iWidth];
+      memset(leftColSum, 0, iWidth * sizeof(int64_t));
+      memset(leftColSumSq, 0, iWidth * sizeof(int64_t));
+      int64_t topSum = 0, topSumSq = 0;
+      int64_t *topRowSum = new int64_t[iHeight];
+      int64_t *topRowSumSq = new int64_t[iHeight];
+      memset(topRowSum, 0, iHeight * sizeof(int64_t));
+      memset(topRowSumSq, 0, iHeight * sizeof(int64_t));
+      int64_t *topColSum = new int64_t[iWidth];
+      int64_t *topColSumSq = new int64_t[iWidth];
+      memset(topColSum, 0, iWidth * sizeof(int64_t));
+      memset(topColSumSq, 0, iWidth * sizeof(int64_t));
+
+      for (uint32_t y = 0; y < iHeight; y++)
+      {
+        for (uint32_t x = 0; x < iWidth; x++)
+        {
+          const Pel pPxlY = picY.buf[x];
+          int64_t uiSum = 0;
+          int64_t uiSumSq = 0;
+          uint32_t uiNumPixInPart = 0;
+
+          uint32_t y1 = std::max((int)(y - uiWinLens), 0);
+          uint32_t y2 = std::min((int)(y + uiWinLens), (iHeight - 1));
+          uint32_t x1 = std::max((int)(x - uiWinLens), 0);
+          uint32_t x2 = std::min((int)(x + uiWinLens), (iWidth - 1));
+
+
+          uint32_t bx = 0, by = 0;
+          const Pel *pWinY = &picY.buf[0];
+          uiNumPixInPart = (x2 - x1 + 1) * (y2 - y1 + 1);
+
+          if (x == 0 && y == 0)           // for the 1st Pixel, calc all points
+          {
+            for (by = y1; by <= y2; by++)
+            {
+              for (bx = x1; bx <= x2; bx++)
+              {
+                tempSq = pWinY[bx] * pWinY[bx];
+                leftSum += pWinY[bx];
+                leftSumSq += tempSq;
+                leftColSum[bx] += pWinY[bx];
+                leftColSumSq[bx] += tempSq;
+                topColSum[bx] += pWinY[bx];
+                topColSumSq[bx] += tempSq;
+                topRowSum[by] += pWinY[bx];
+                topRowSumSq[by] += tempSq;
+              }
+              pWinY += iStride;
+            }
+            topSum = leftSum;
+            topSumSq = leftSumSq;
+            uiSum = leftSum;
+            uiSumSq = leftSumSq;
+          }
+          else if (x == 0 && y > 0)       // for the 1st column, calc the bottom stripe
+          {
+            if (y < iHeight - uiWinLens)
+            {
+              pWinY += uiWinLens*iStride;
+              topRowSum[y + uiWinLens] = 0;
+              topRowSumSq[y + uiWinLens] = 0;
+              for (bx = x1; bx <= x2; bx++)
+              {
+                topRowSum[y + uiWinLens] += pWinY[bx];
+                topRowSumSq[y + uiWinLens] += pWinY[bx] * pWinY[bx];
+              }
+              topSum += topRowSum[y + uiWinLens];
+              topSumSq += topRowSumSq[y + uiWinLens];
+            }
+            if (y > uiWinLens)
+            {
+              topSum -= topRowSum[y - 1 - uiWinLens];
+              topSumSq -= topRowSumSq[y - 1 - uiWinLens];
+            }
+
+            memset(leftColSum, 0, iWidth * sizeof(int64_t));
+            memset(leftColSumSq, 0, iWidth * sizeof(int64_t));
+            pWinY = &picY.buf[0];
+            pWinY -= (y <= uiWinLens ? y : uiWinLens)*iStride;
+            for (by = y1; by <= y2; by++)
+            {
+              for (bx = x1; bx <= x2; bx++)
+              {
+                leftColSum[bx] += pWinY[bx];
+                leftColSumSq[bx] += pWinY[bx] * pWinY[bx];
+              }
+              pWinY += iStride;
+            }
+
+            leftSum = topSum;
+            leftSumSq = topSumSq;
+            uiSum = topSum;
+            uiSumSq = topSumSq;
+          }
+
+          else if (x > 0)
+          {
+            if (x < iWidth - uiWinLens)
+            {
+              pWinY -= (y <= uiWinLens ? y : uiWinLens)*iStride;
+              if (y == 0)                 // for the 1st row, calc the right stripe
+              {
+                leftColSum[x + uiWinLens] = 0;
+                leftColSumSq[x + uiWinLens] = 0;
+                for (by = y1; by <= y2; by++)
+                {
+                  leftColSum[x + uiWinLens] += pWinY[x + uiWinLens];
+                  leftColSumSq[x + uiWinLens] += pWinY[x + uiWinLens] * pWinY[x + uiWinLens];
+                  pWinY += iStride;
+                }
+              }
+              else                        // for the main area, calc the B-R point 
+              {
+                leftColSum[x + uiWinLens] = topColSum[x + uiWinLens];
+                leftColSumSq[x + uiWinLens] = topColSumSq[x + uiWinLens];
+                if (y < iHeight - uiWinLens)
+                {
+                  pWinY = &picY.buf[0];
+                  pWinY += uiWinLens * iStride;
+                  leftColSum[x + uiWinLens] += pWinY[x + uiWinLens];
+                  leftColSumSq[x + uiWinLens] += pWinY[x + uiWinLens] * pWinY[x + uiWinLens];
+                }
+                if (y > uiWinLens)
+                {
+                  pWinY = &picY.buf[0];
+                  pWinY -= (uiWinLens + 1) * iStride;
+                  leftColSum[x + uiWinLens] -= pWinY[x + uiWinLens];
+                  leftColSumSq[x + uiWinLens] -= pWinY[x + uiWinLens] * pWinY[x + uiWinLens];
+                }
+              }
+              topColSum[x + uiWinLens] = leftColSum[x + uiWinLens];
+              topColSumSq[x + uiWinLens] = leftColSumSq[x + uiWinLens];
+              leftSum += leftColSum[x + uiWinLens];
+              leftSumSq += leftColSumSq[x + uiWinLens];
+            }
+            if (x > uiWinLens)
+            {
+              leftSum -= leftColSum[x - 1 - uiWinLens];
+              leftSumSq -= leftColSumSq[x - 1 - uiWinLens];
+            }
+            uiSum = leftSum;
+            uiSumSq = leftSumSq;
+          }
+
+          double dAverage = double(uiSum) / uiNumPixInPart;
+          double dVariance = double(uiSumSq) / uiNumPixInPart - dAverage * dAverage;
+          double dVarLog10 = log10(dVariance + 1.0);
+
+          uint32_t uiBinNum = (uint32_t)floor((double)pPxlY / (double)PIC_ANALYZE_CW_BINS);
+          dBlockBinVarSum[uiBinNum] += dVarLog10;
+          dBlockBinCnt[uiBinNum]++;
+        }
+        picY.buf += iStride;
+      }
+
+      delete[] topColSum;
+      delete[] topColSumSq;
+      delete[] topRowSum;
+      delete[] topRowSumSq;
+      delete[] leftColSum;
+      delete[] leftColSumSq;
+
+      for (int b = 0; b < PIC_ANALYZE_CW_BINS; b++)
+      {
+        if (dBlockBinCnt[b] > 0)
+          dBlockBinVarSum[b] = dBlockBinVarSum[b] / dBlockBinCnt[b];
+      }
+
+      m_bReshape = true;
+      m_bExceedSTD = false;
+      m_bUseAdpCW = false;
+      m_chromaWeight = 1.0;
+      m_sliceReshapeInfo.uiReshapeChromaAdj = 1;
+      bool   bIntraAdp = false;
+      bool   bInterAdp = true;
+      double dReshapeTH1 = 0.0;
+      double dReshapeTH2 = 5.0;
+      deriveReshapeParametersSDRfromStats(dBlockBinCnt, dBlockBinVarSum, &dReshapeTH1, &dReshapeTH2, &bIntraAdp, &bInterAdp);
+
+      if (m_rateAdpMode == 2 && reshapeCW.RspBaseQP <= 22)
+      {
+        bIntraAdp = false;
+        bInterAdp = false;
+      }
+
+      m_sliceReshapeInfo.slice_reshaper_enable_flag = bIntraAdp;
+
+      if (!bIntraAdp && !bInterAdp)
+      {
+        m_sliceReshapeInfo.slice_reshaper_model_present_flag = false;
+        m_bReshape = false;
+        return;
+      }
+
+      if (m_bExceedSTD)
+      {
+        min_start_bin_idx = 2;
+        max_end_bin_idx = 29;
+        for (int b = 0; b < PIC_ANALYZE_CW_BINS; b++)
+        {
+          if (dBlockBinCnt[b] > 0 && b < min_start_bin_idx)
+            min_start_bin_idx = b;
+          if (dBlockBinCnt[b] > 0 && b > max_end_bin_idx)
+            max_end_bin_idx = b;
+        }
+        m_sliceReshapeInfo.reshape_model_min_bin_idx = min_start_bin_idx;
+        m_sliceReshapeInfo.reshape_model_max_bin_idx = max_end_bin_idx;
+      }
+
+      if (reshapeCW.RspBaseQP <= 22 && m_rateAdpMode == 1)
+      {
+        for (int i = 0; i < PIC_ANALYZE_CW_BINS; i++)
+        {
+          if (i >= min_start_bin_idx && i <= max_end_bin_idx)
+            m_uiBinCWAll[i] = m_uiCWOrgAnalyze + 1;
+          else
+            m_uiBinCWAll[i] = 0;
+        }
+      }
+      else if (m_bUseAdpCW)
+      {
+        double Alpha = 1.0, Beta = 0.0;
+        deriveReshapeParameters(dBlockBinVarSum, min_start_bin_idx, max_end_bin_idx, m_reshapeCW, Alpha, Beta);
+        for (int i = 0; i < PIC_ANALYZE_CW_BINS; i++)
+        {
+          if (i >= min_start_bin_idx && i <= max_end_bin_idx)
+            m_uiBinCWAll[i] = (uint32_t)round(Alpha*dBlockBinVarSum[i] + Beta);
+          else
+            m_uiBinCWAll[i] = 0;
+        }
+      }
+      else
+      {
+        for (int b = min_start_bin_idx; b <= max_end_bin_idx; b++)
+        {
+          if (dBlockBinVarSum[b] < dReshapeTH1)
+            m_uiBinImportance[b] = 2;
+          else if (dBlockBinVarSum[b] > dReshapeTH2)
+            m_uiBinImportance[b] = 3;
+          else
+            m_uiBinImportance[b] = 1;
+        }
+
+        for (int i = 0; i < PIC_ANALYZE_CW_BINS; i++)
+        {
+          if (m_uiBinImportance[i] == 0)
+            m_uiBinCWAll[i] = 0;
+          else if (m_uiBinImportance[i] == 1)
+            m_uiBinCWAll[i] = m_uiCWOrgAnalyze + 1;
+          else if (m_uiBinImportance[i] == 2)
+            m_uiBinCWAll[i] = m_reshapeCW.BinCW[0];
+          else if (m_uiBinImportance[i] == 3)
+            m_uiBinCWAll[i] = m_reshapeCW.BinCW[1];
+          else
+            THROW("SDR Reshape Bin Importance not supported");
+        }
+      }
+      if (m_reshapeCW.RspPicSize <= 1497600 && reshapeCW.RspIntraPeriod == -1 && modIP == 0 && sliceType != I_SLICE)
+      {
+        m_sliceReshapeInfo.slice_reshaper_enable_flag = false;
+      }
+
+    }
+    m_chromaAdj = m_sliceReshapeInfo.uiReshapeChromaAdj;
+    if ((sliceType == I_SLICE || (sliceType == P_SLICE && isCPR)) && isDualT)
+    {
+        m_sliceReshapeInfo.uiReshapeChromaAdj = 0;
+    }
+  }
+  else // Inter slices
+  {
+    m_sliceReshapeInfo.slice_reshaper_model_present_flag = false;
+    m_sliceReshapeInfo.uiReshapeChromaAdj = m_chromaAdj;
+
+    if (!m_bReshape)
+    {
+      m_sliceReshapeInfo.slice_reshaper_enable_flag = false;
+    }
+    else
+    {
+      const int cTid = m_reshapeCW.Tid;
+      bool enableRsp = m_tcase == 5 ? false : (m_tcase < 5 ? (cTid < m_tcase + 1 ? false : true) : (cTid <= 10 - m_tcase ? true : false));
+      m_sliceReshapeInfo.slice_reshaper_enable_flag = enableRsp;
+    }
+  }
+}
+
+// Bubble Sort to  descending order with index
+void EncReshape::bubbleSortDsd(double* array, int * idx, int n)
+{
+  int i, j;
+  bool swapped;
+  for (i = 0; i < n - 1; i++)
+  {
+    swapped = false;
+    for (j = 0; j < n - i - 1; j++)
+    {
+      if (array[j] < array[j + 1])
+      {
+        swap(&array[j], &array[j + 1]);
+        swap(&idx[j], &idx[j + 1]);
+        swapped = true;
+      }
+    }
+    if (swapped == false)
+      break;
+  }
+}
+
+void EncReshape::deriveReshapeParametersSDRfromStats(uint32_t * dBlockBinCnt, double *dBlockBinVarSum, double* dReshapeTH1, double* dReshapeTH2, bool *bIntraAdp, bool *bInterAdp)
+{
+  int    BinIdxSortDsd[PIC_ANALYZE_CW_BINS] = { 0 };
+  double BinVarSortDsd[PIC_ANALYZE_CW_BINS] = { 0.0 };
+  double BinHist[PIC_ANALYZE_CW_BINS] = { 0.0 };
+  double BinVarSortDsdCDF[PIC_ANALYZE_CW_BINS] = { 0.0 };
+
+  double maxBinVar = 0.0, meanBinVar = 0.0, minBinVar = 5.0;
+  int    nonZeroBinCt = 0;
+  for (int b = 0; b < PIC_ANALYZE_CW_BINS; b++)
+  {
+    BinHist[b] = (double)dBlockBinCnt[b] / (double)(m_reshapeCW.RspPicSize);
+    if (BinHist[b] > 0.001)
+    {
+      nonZeroBinCt++;
+      meanBinVar += dBlockBinVarSum[b];
+      if (dBlockBinVarSum[b] > maxBinVar)        {        maxBinVar = dBlockBinVarSum[b];      }
+      if (dBlockBinVarSum[b] < minBinVar)        {        minBinVar = dBlockBinVarSum[b];      }
+    }
+    BinVarSortDsd[b] = dBlockBinVarSum[b];
+    BinIdxSortDsd[b] = b;
+  }
+  if ((BinHist[0] + BinHist[1] + BinHist[PIC_ANALYZE_CW_BINS - 2] + BinHist[PIC_ANALYZE_CW_BINS - 1]) > 0.01)   {    m_bExceedSTD = true;  }
+  if ((BinHist[PIC_ANALYZE_CW_BINS - 2] + BinHist[PIC_ANALYZE_CW_BINS - 1]) > 0.01)   {    *bInterAdp = false;    return;   }
+  else                                                                                {    *bInterAdp = true;               }
+
+  meanBinVar = meanBinVar / (double)nonZeroBinCt;
+  bubbleSortDsd(BinVarSortDsd, BinIdxSortDsd, PIC_ANALYZE_CW_BINS);
+  BinVarSortDsdCDF[0] = BinHist[BinIdxSortDsd[0]];
+  for (int b = 1; b < PIC_ANALYZE_CW_BINS; b++)
+  {
+    BinVarSortDsdCDF[b] = BinVarSortDsdCDF[b - 1] + BinHist[BinIdxSortDsd[b]];
+  }
+
+  int firstBinVarLessThanVal1 = 0; // Val1 = 3.5
+  int firstBinVarLessThanVal2 = 0; // Val2 = 3.0
+  int firstBinVarLessThanVal3 = 0; // Val3 = 2.5
+  int firstBinVarLessThanVal4 = 0; // Val4 = 2.0
+  for (int b = 0; b < PIC_ANALYZE_CW_BINS - 1; b++)
+  {
+    if (BinVarSortDsd[b] > 3.5)     {      firstBinVarLessThanVal1 = b + 1;    }
+    if (BinVarSortDsd[b] > 3.0)     {      firstBinVarLessThanVal2 = b + 1;    }
+    if (BinVarSortDsd[b] > 2.5)     {      firstBinVarLessThanVal3 = b + 1;    }
+    if (BinVarSortDsd[b] > 2.0)     {      firstBinVarLessThanVal4 = b + 1;    }
+  }
+
+  m_reshapeCW.BinCW[0] = 38;
+  m_reshapeCW.BinCW[1] = 28;
+
+  if (m_reshapeCW.RspIntraPeriod == -1)
+  {
+    *bIntraAdp = true;
+    if (m_reshapeCW.RspPicSize > 1497600)
+    {
+      m_reshapeCW.BinCW[0] = 36;
+      *dReshapeTH1 = 2.4;
+      *dReshapeTH2 = 4.5;
+      m_rateAdpMode = 2;
+
+      if (meanBinVar >= 2.52)
+      {
+        if (BinVarSortDsdCDF[firstBinVarLessThanVal2] > 0.5)
+        {
+          *dReshapeTH1 = 2.5;
+          *dReshapeTH2 = 3.0;
+        }
+        else if (BinVarSortDsdCDF[firstBinVarLessThanVal2] < 0.1 && BinVarSortDsdCDF[firstBinVarLessThanVal1] > 0.02)
+        {
+          *dReshapeTH1 = 2.2;
+        }
+        else if (BinVarSortDsdCDF[firstBinVarLessThanVal2] > 0.25)
+        {
+          m_reshapeCW.BinCW[1] = 30;
+          *dReshapeTH1 = 2.0;
+          m_rateAdpMode = 0;
+        }
+        else
+        {
+          m_reshapeCW.BinCW[1] = 30;
+          m_rateAdpMode = 1;
+        }
+      }
+    }
+    else if (m_reshapeCW.RspPicSize > 660480)
+    {
+      m_reshapeCW.BinCW[0] = 34;
+      *dReshapeTH1 = 3.4;
+      *dReshapeTH2 = 4.0;
+      m_rateAdpMode = 2;
+
+      if (BinVarSortDsdCDF[firstBinVarLessThanVal4] > 0.6)
+      {
+        if (maxBinVar < 3.5)
+        {
+          m_bUseAdpCW = true;
+          m_reshapeCW.BinCW[0] = 38;
+        }
+        else
+        {
+          m_reshapeCW.BinCW[0] = 40;
+          *dReshapeTH1 = 2.2;
+          *dReshapeTH2 = 4.5;
+          m_rateAdpMode = 0;
+        }
+      }
+      else
+      {
+        if (maxBinVar > 3.3)
+        {
+          m_reshapeCW.BinCW[1] = 30;
+        }
+        else
+        {
+          m_reshapeCW.BinCW[1] = 28;
+        }
+      }
+    }
+    else if (m_reshapeCW.RspPicSize > 249600)
+    {
+      m_reshapeCW.BinCW[0] = 36;
+      *dReshapeTH1 = 2.5;
+      *dReshapeTH2 = 4.5;
+
+      if (m_bExceedSTD)
+      {
+        m_reshapeCW.BinCW[0] = 36;
+        m_reshapeCW.BinCW[1] = 30;
+      }
+      if (minBinVar > 2.6)
+      {
+        *dReshapeTH1 = 3.0;
+      }
+      else {
+        double diff1 = BinVarSortDsdCDF[firstBinVarLessThanVal4] - BinVarSortDsdCDF[firstBinVarLessThanVal3];
+        double diff2 = BinVarSortDsdCDF[firstBinVarLessThanVal2] - BinVarSortDsdCDF[firstBinVarLessThanVal1];
+        if (diff1 > 0.4 || BinVarSortDsdCDF[firstBinVarLessThanVal1] > 0.1)
+        {
+          m_bUseAdpCW = true;
+          m_rateAdpMode = 1;
+        }
+        else if (diff2 <= 0.1 && BinVarSortDsdCDF[firstBinVarLessThanVal4] > 0.99 && BinVarSortDsdCDF[firstBinVarLessThanVal3] > 0.642 && BinVarSortDsdCDF[firstBinVarLessThanVal2] > 0.03)
+        {
+          m_bUseAdpCW = true;
+          m_rateAdpMode = 1;
+        }
+        else
+        {
+          m_rateAdpMode = 2;
+        }
+      }
+    }
+    else
+    {
+      m_reshapeCW.BinCW[0] = 36;
+      *dReshapeTH1 = 2.6;
+      *dReshapeTH2 = 4.5;
+
+      if (BinVarSortDsdCDF[firstBinVarLessThanVal2] > 0.5 && maxBinVar < 4.7)
+      {
+        *dReshapeTH1 = 3.2;
+        m_rateAdpMode = 1;
+      }
+    }
+  }
+  else if (m_reshapeCW.RspIntraPeriod == 1)
+  {
+    *bIntraAdp = true;
+    if (m_reshapeCW.RspPicSize > 5184000)
+    {
+      *dReshapeTH1 = 2.0;
+      *dReshapeTH2 = 3.0;
+      m_rateAdpMode = 2;
+
+      if (maxBinVar > 2.4)
+      {
+        if (BinVarSortDsdCDF[firstBinVarLessThanVal4] > 0.88) 
+        {
+          if (maxBinVar < 2.695)
+          {
+            *dReshapeTH2 = 2.2;
+          }
+          else 
+          {
+            if (BinVarSortDsdCDF[firstBinVarLessThanVal3] < 0.45)
+            {
+              *dReshapeTH1 = 2.5;
+              *dReshapeTH2 = 4.0;
+              m_reshapeCW.BinCW[0] = 36;
+              m_sliceReshapeInfo.uiReshapeChromaAdj = 0;
+              m_rateAdpMode = 0;
+            }
+            else
+            {
+              m_bUseAdpCW = true;
+              m_reshapeCW.BinCW[0] = 36;
+              m_reshapeCW.BinCW[1] = 30;
+            }
+          }
+        }
+        else 
+        {
+          if (maxBinVar > 2.8)
+          {
+            *dReshapeTH1 = 2.2;
+            *dReshapeTH2 = 4.0;
+            m_reshapeCW.BinCW[0] = 36;
+            m_sliceReshapeInfo.uiReshapeChromaAdj = 0;
+          }
+          else
+          {
+            m_bUseAdpCW = true;
+            m_reshapeCW.BinCW[0] = 38;
+            m_reshapeCW.BinCW[1] = 28;
+          }
+        }
+      }
+      else
+      {
+        if (maxBinVar > 2.24)
+        {
+          m_bUseAdpCW = true;
+          m_reshapeCW.BinCW[0] = 34;
+          m_reshapeCW.BinCW[1] = 30;
+        }
+      }
+    }
+    else if (m_reshapeCW.RspPicSize > 1497600)
+    {
+      *dReshapeTH1 = 2.0;
+      *dReshapeTH2 = 4.5;
+      m_rateAdpMode = 2;
+
+      if (BinVarSortDsdCDF[firstBinVarLessThanVal2] > 0.25)
+      {
+        int firstVarCDFLargerThanVal = 1;
+        for (int b = 0; b < PIC_ANALYZE_CW_BINS; b++)
+        {
+          if (BinVarSortDsdCDF[b] > 0.7)
+          {
+            firstVarCDFLargerThanVal = b;
+            break;
+          }
+        }
+        if (meanBinVar < 2.52 || BinVarSortDsdCDF[firstBinVarLessThanVal2] > 0.5)
+        {
+          *dReshapeTH1 = 2.2;
+          *dReshapeTH2 = (BinVarSortDsd[firstVarCDFLargerThanVal] + BinVarSortDsd[firstVarCDFLargerThanVal - 1]) / 2.0;
+        }
+        else
+        {
+          m_reshapeCW.BinCW[1] = 30;
+          *dReshapeTH2 = 2.8;
+        }
+      }
+      else if (BinVarSortDsdCDF[firstBinVarLessThanVal2] < 0.1 && BinVarSortDsdCDF[firstBinVarLessThanVal1] > 0.02)
+      {
+        m_reshapeCW.BinCW[0] = 36;
+        *dReshapeTH1 = 3.5;
+        m_rateAdpMode = 1;
+      }
+    }
+    else if (m_reshapeCW.RspPicSize > 660480)
+    {
+      *dReshapeTH1 = 2.5;
+      *dReshapeTH2 = 4.5;
+      m_rateAdpMode = 1;
+
+      if (BinVarSortDsdCDF[firstBinVarLessThanVal4] > 0.6)
+      {
+        if (maxBinVar < 3.5)
+        {
+          *dReshapeTH1 = 2.0;
+        }
+      }
+      else
+      {
+        if (maxBinVar > 3.3)
+        {
+          m_reshapeCW.BinCW[0] = 35;
+        }
+        else
+        {
+          *dReshapeTH1 = 2.8;
+          m_reshapeCW.BinCW[0] = 35;
+        }
+      }
+    }
+    else if (m_reshapeCW.RspPicSize > 249600)
+    {
+      m_rateAdpMode = 1;
+      m_reshapeCW.BinCW[0] = 36;
+      *dReshapeTH1 = 2.5;
+      *dReshapeTH2 = 4.5;
+    }
+    else
+    {
+      if (BinVarSortDsdCDF[firstBinVarLessThanVal2] < 0.33 && m_reshapeCW.RspFps>40)
+      {
+        *bIntraAdp = false;
+        *bInterAdp = false;
+      }
+      else
+      {
+        m_rateAdpMode = 1;
+        m_reshapeCW.BinCW[0] = 36;
+        *dReshapeTH1 = 3.0;
+        *dReshapeTH2 = 4.0;
+      }
+    }
+  }
+  else
+  {
+    if (m_reshapeCW.RspPicSize > 5184000)
+    {
+      m_reshapeCW.BinCW[0] = 40;
+      *dReshapeTH2 = 4.0;
+      m_rateAdpMode = 2;
+
+      if (maxBinVar < 2.4)
+      {
+        *dReshapeTH1 = 3.0;
+        if (m_reshapeCW.RspBaseQP <= 22)
+          m_tcase = 3;
+      }
+      else if (maxBinVar > 3.0)
+      {
+        if (minBinVar > 1)
+        {
+          m_reshapeCW.BinCW[0] = 36;
+          *dReshapeTH1 = 2.8;
+          *dReshapeTH2 = 3.5;
+          m_sliceReshapeInfo.uiReshapeChromaAdj = 0;
+          m_chromaWeight = 1.05;
+          m_rateAdpMode = 0;
+        }
+        else
+        {
+          m_reshapeCW.BinCW[0] = 36;
+          *dReshapeTH1 = 2.2;
+          *dReshapeTH2 = 3.5;
+          m_sliceReshapeInfo.uiReshapeChromaAdj = 0;
+          m_chromaWeight = 0.95;
+          if (m_reshapeCW.RspBaseQP <= 27 && m_reshapeCW.RspBaseQP >=25)
+            m_tcase = 3;
+        }
+      }
+      else
+      {
+        *dReshapeTH1 = 1.5;
+      }
+    }
+    else if (m_reshapeCW.RspPicSize > 1497600)
+    {
+      *dReshapeTH1 = 2.5;
+      *dReshapeTH2 = 4.5;
+      m_rateAdpMode = 1; 
+
+      if (meanBinVar < 2.52)
+      {
+        *bIntraAdp = true;
+        m_rateAdpMode = 0;
+        m_tcase = 9;
+      }
+      else
+      {
+        if (BinVarSortDsdCDF[firstBinVarLessThanVal2] > 0.5)
+        {
+          *dReshapeTH2 = 3.0;
+          *bIntraAdp = true;
+        }
+        else if (BinVarSortDsdCDF[firstBinVarLessThanVal2] < 0.1 && BinVarSortDsdCDF[firstBinVarLessThanVal1] > 0.02)
+        {
+          *dReshapeTH1 = 3.0;
+          *bIntraAdp = true;
+          m_rateAdpMode = 0;
+          m_tcase = 9;
+        }
+        else if (BinVarSortDsdCDF[firstBinVarLessThanVal2] > 0.25)
+        {
+          *dReshapeTH1 = 2.4;
+          m_reshapeCW.BinCW[0] = 36;
+        }
+        else
+        {
+          *dReshapeTH1 = 2.4;
+          m_reshapeCW.BinCW[0] = 36;
+        }
+      }
+    }
+    else if (m_reshapeCW.RspPicSize > 660480)
+    {
+      *bIntraAdp = true;
+      m_rateAdpMode = 1;  
+
+      if (BinVarSortDsdCDF[firstBinVarLessThanVal4] > 0.6)
+      {
+        if (maxBinVar < 3.5)
+        {
+          *dReshapeTH1 = 2.1;
+          *dReshapeTH2 = 3.5;
+        }
+        else
+        {
+          *dReshapeTH1 = 2.4;
+          *dReshapeTH2 = 4.5;
+          m_reshapeCW.BinCW[0] = 40;
+          m_rateAdpMode = 0;  
+        }
+      }
+      else
+      {
+        if (maxBinVar > 3.3)
+        {
+          *dReshapeTH1 = 3.5;
+          *dReshapeTH2 = 3.8;
+        }
+        else
+        {
+          *dReshapeTH1 = 3.0;
+          *dReshapeTH2 = 4.0;
+          m_reshapeCW.BinCW[1] = 30;
+        }
+      }
+    }
+    else if (m_reshapeCW.RspPicSize > 249600)
+    {
+      m_reshapeCW.BinCW[1] = 30;
+      *dReshapeTH1 = 2.5;
+      *dReshapeTH2 = 4.5;
+      *bIntraAdp = true;
+      m_rateAdpMode = 1;
+
+      if (minBinVar > 2.6)
+      {
+        *dReshapeTH1 = 3.2;
+        m_rateAdpMode = 0;
+        m_tcase = 9;
+      }
+      else {
+        double diff1 = BinVarSortDsdCDF[firstBinVarLessThanVal4] - BinVarSortDsdCDF[firstBinVarLessThanVal3];
+        double diff2 = BinVarSortDsdCDF[firstBinVarLessThanVal2] - BinVarSortDsdCDF[firstBinVarLessThanVal1];
+        if (diff1 > 0.4 || BinVarSortDsdCDF[firstBinVarLessThanVal1] > 0.1)
+        {
+          *dReshapeTH1 = 2.9;
+          *bIntraAdp = false;
+        }
+        else
+        {
+          if (diff2 > 0.1)
+          {
+            *dReshapeTH1 = 2.5;
+          }
+          else
+          {
+            *dReshapeTH1 = 2.9;
+            if (BinVarSortDsdCDF[firstBinVarLessThanVal4] > 0.99 && BinVarSortDsdCDF[firstBinVarLessThanVal3] > 0.642 && BinVarSortDsdCDF[firstBinVarLessThanVal2] > 0.03)
+            {
+              m_rateAdpMode = 0;
+              m_tcase = 9;
+            }
+          }
+        }
+      }
+    }
+    else
+    {
+      m_reshapeCW.BinCW[0] = 36;
+      m_reshapeCW.BinCW[1] = 30;
+      *dReshapeTH1 = 2.6;
+      *dReshapeTH2 = 4.5;
+      *bIntraAdp = true;
+      m_rateAdpMode = 1;
+      if (BinVarSortDsdCDF[firstBinVarLessThanVal2] > 0.5 && maxBinVar < 4.7)
+      {
+        *dReshapeTH1 = 3.4;
+      }
+    }
+  }
+}
+
+void EncReshape::deriveReshapeParameters(double *array, int start, int end, ReshapeCW respCW, double &alpha, double &beta)
+{
+  double minVar = 10.0, maxVar = 0.0;
+  for (int b = start; b <= end; b++)
+  {
+    if (array[b] < minVar)       minVar = array[b];
+    if (array[b] > maxVar)       maxVar = array[b];
+  }
+  double maxCW = (double)respCW.BinCW[0];
+  double minCW = (double)respCW.BinCW[1];
+  alpha = (minCW - maxCW) / (maxVar - minVar);
+  beta = (maxCW*maxVar - minCW*minVar) / (maxVar - minVar);
+}
+
+/**
+-Init reshaping LUT  from dQP model
+*/
+void EncReshape::initLUTfromdQPModel()
+{
+  initModelParam();
+  int pwlFwdLUTsize = PIC_CODE_CW_BINS;
+  int pwlFwdBinLen = MAX_LUMA_RESHAPING_LUT_SIZE / PIC_CODE_CW_BINS;
+  int p1 = m_DftModel.ScaleFracPrec; //=16, precision of 0.015
+  int p2 = m_DftModel.OffsetFracPrec; //=1, precision of 7.5
+  int total_shift = p1 + p2;
+  int scaleFP = (1 - 2 * m_DftModel.ScaleSign)  * m_DftModel.ScaleAbs;
+  int offsetFP = (1 - 2 * m_DftModel.OffsetSign) * m_DftModel.OffsetAbs;
+  int maxQP = (1 - 2 * m_DftModel.MaxQPSign)  * m_DftModel.MaxQPAbs;
+  int minQP = (1 - 2 * m_DftModel.MinQPSign)  * m_DftModel.MinQPAbs;
+  int maxFP = maxQP * (1 << total_shift);
+  int minFP = minQP * (1 << total_shift);
+  int temp, signval, absval;
+  int dQPDIV6_FP;
+  int32_t * SlopeLUT = new int32_t[MAX_LUMA_RESHAPING_LUT_SIZE]();
+  int32_t * fLUT_HP = new int32_t[MAX_LUMA_RESHAPING_LUT_SIZE]();
+
+  for (int i = 0; i < LUMA_LEVEL_TO_DQP_LUT_MAXSIZE; i++)
+  {
+    temp = int64_t((scaleFP*i) * (1 << p2)) + int64_t(offsetFP * (1 << p1));
+    temp = temp > maxFP ? maxFP : temp < minFP ? minFP : temp;
+    signval = temp >= 0 ? 1 : -1;
+    absval = signval * temp;
+    dQPDIV6_FP = signval * (((absval + 3) / 6 + (1 << (total_shift - 17))) >> (total_shift - 16));
+    SlopeLUT[i] = calcEXP2(dQPDIV6_FP);
+  }
+
+  if (m_DftModel.FullRangeInputFlag == 0)  
+  {
+    for (int i = 0; i < 64; i++)                               {      SlopeLUT[i] = 0;    }
+    for (int i = 940; i < MAX_LUMA_RESHAPING_LUT_SIZE; i++)    {      SlopeLUT[i] = 0;    }
+  }
+
+  for (int i = 0; i < MAX_LUMA_RESHAPING_LUT_SIZE - 1; i++)
+    fLUT_HP[i + 1] = fLUT_HP[i] + SlopeLUT[i];
+  if (SlopeLUT != nullptr)   {    delete[] SlopeLUT;    SlopeLUT = nullptr;  }
+
+  int max_Y = (fLUT_HP[MAX_LUMA_RESHAPING_LUT_SIZE - 1] + (1 << 7)) >> 8;
+  int Roffset = max_Y >> 1;
+  for (int i = 0; i < MAX_LUMA_RESHAPING_LUT_SIZE; i++)
+  {
+    forwardReshapingLUT[i] = (short)(((fLUT_HP[i] >> 8) * (MAX_LUMA_RESHAPING_LUT_SIZE - 1) + Roffset) / max_Y);
+  }
+
+  if (fLUT_HP != nullptr)   {    delete[] fLUT_HP;    fLUT_HP = nullptr;  }
+  m_sliceReshapeInfo.reshape_model_min_bin_idx = 1;
+  m_sliceReshapeInfo.reshape_model_max_bin_idx = 14;
+
+  for (int i = 0; i < pwlFwdLUTsize; i++)
+  {
+    int16_t X1 = i * pwlFwdBinLen;
+    m_ReshapePivot[i] = forwardReshapingLUT[X1];
+  }
+  m_ReshapePivot[pwlFwdLUTsize] = 1023;
+
+  for (int i = 0; i < pwlFwdLUTsize; i++)
+  {
+    m_uiBinCWAll[i] = m_ReshapePivot[i + 1] - m_ReshapePivot[i];
+  }
+
+  int maxAbsDeltaCW = 0, AbsDeltaCW = 0, DeltaCW = 0;
+  for (int i = m_sliceReshapeInfo.reshape_model_min_bin_idx; i <= m_sliceReshapeInfo.reshape_model_max_bin_idx; i++)
+  {
+    DeltaCW = (int)m_uiBinCWAll[i] - (int)m_uiCWOrg;
+    m_sliceReshapeInfo.reshape_model_bin_CW_delta[i] = DeltaCW;
+    AbsDeltaCW = (DeltaCW < 0) ? (-DeltaCW) : DeltaCW;
+    if (AbsDeltaCW > maxAbsDeltaCW)     {      maxAbsDeltaCW = AbsDeltaCW;    }
+  }
+  m_sliceReshapeInfo.maxNbitsNeededDeltaCW = g_aucLog2[maxAbsDeltaCW << 1];
+
+  for (int i = 0; i < pwlFwdLUTsize; i++)
+  {
+    int16_t Y1 = m_ReshapePivot[i];
+    int16_t Y2 = m_ReshapePivot[i + 1];
+    forwardReshapingLUT[i*pwlFwdBinLen] = Clip3((Pel)0, (Pel)1023, (Pel)Y1);
+    int log2_pwlFwdBinLen = log2_MAX_LUMA_RESHAPING_LUT_SIZE - log2_PIC_CODE_CW_BINS;
+    int32_t scale = ((int32_t)(Y2 - Y1) * (1 << FP_PREC) + (1 << (log2_pwlFwdBinLen - 1))) >> (log2_pwlFwdBinLen);
+    for (int j = 1; j < pwlFwdBinLen; j++)
+    {
+      int tempVal = Y1 + (((int32_t)scale * (int32_t)j + (1 << (FP_PREC - 1))) >> FP_PREC);
+      forwardReshapingLUT[i*pwlFwdBinLen + j] = Clip3((Pel)0, (Pel)1023, (Pel)tempVal);
+    }
+  }
+  ReverseLUT(forwardReshapingLUT, inverseReshapingLUT, MAX_LUMA_RESHAPING_LUT_SIZE);
+  updateChromaDQPLUT();
+}
+
+
+/**
+-Perform fixe point exp2 calculation
+\param   val  input value
+\retval  output value = exp2(val)
+*/
+int EncReshape::calcEXP2(int val)
+{
+  int32_t i, f, r, s;
+  r = 0x00000e20;
+
+  i = ((int32_t)(val)+0x8000) & ~0xffff;
+  f = (int32_t)(val)-i;
+  s = ((15 << 16) - i) >> 16;
+
+  r = (r * f + 0x3e1cc333) >> 17;
+  r = (r * f + 0x58bd46a6) >> 16;
+  r = r * f + 0x7ffde4a3;
+  return (uint32_t)r >> s;
+}
+
+void EncReshape::constructReshaperSDR()
+{
+  int used_codewords;
+  int tot_cw = MAX_LUMA_RESHAPING_LUT_SIZE;
+  int hist_bins = PIC_ANALYZE_CW_BINS;
+  int log2_hist_lens = log2_MAX_LUMA_RESHAPING_LUT_SIZE - log2_PIC_ANALYZE_CW_BINS;
+  int hist_lens = m_uiCWOrgAnalyze;
+  int16_t *Y_LUT_all = new int16_t[MAX_LUMA_RESHAPING_LUT_SIZE + 1]();
+  int i, j;
+  int cw_scale_bins1, cw_scale_bins2;
+  int max_allow_cw = tot_cw;
+
+  cw_scale_bins1 = m_reshapeCW.BinCW[0];
+  cw_scale_bins2 = m_reshapeCW.BinCW[1];
+
+  used_codewords = 0;
+  for (i = 0; i < hist_bins; i++)
+    used_codewords += m_uiBinCWAll[i];
+
+  if (used_codewords > max_allow_cw)
+  {
+    int cnt0 = 0, cnt1 = 0, cnt2 = 0;
+    for (i = 0; i < hist_bins; i++)
+    {
+      if (m_uiBinCWAll[i] == hist_lens + 1)               cnt0++;
+      else if (m_uiBinCWAll[i] == cw_scale_bins1)         cnt1++;
+      else if (m_uiBinCWAll[i] == cw_scale_bins2)         cnt2++;
+    }
+
+    int delta_cw = used_codewords - max_allow_cw;
+    int cw_reduce1 = (cw_scale_bins1 - hist_lens - 1) * cnt1;
+    int cw_reduce2 = (hist_lens + 1 - cw_scale_bins2) * cnt0;
+
+    if (delta_cw <= cw_reduce1)
+    {
+      int idx = 0;
+      while (delta_cw > 0)
+      {
+        if (m_uiBinCWAll[idx] > (hist_lens + 1))
+        {
+          m_uiBinCWAll[idx]--;
+          delta_cw--;
+        }
+        idx++;
+        if (idx == hist_bins)
+          idx = 0;
+      }
+    }
+    else if (delta_cw > cw_reduce1 && delta_cw <= (cw_reduce1 + cw_reduce2))
+    {
+      delta_cw -= cw_reduce1;
+      int idx = 0;
+      while (delta_cw > 0)
+      {
+        if (m_uiBinCWAll[idx] > cw_scale_bins2 && m_uiBinCWAll[idx] < cw_scale_bins1)
+        {
+          m_uiBinCWAll[idx]--;
+          delta_cw--;
+        }
+        idx++;
+        if (idx == hist_bins)
+          idx = 0;
+      }
+      for (i = 0; i < hist_bins; i++)
+      {
+        if (m_uiBinCWAll[i] == cw_scale_bins1)
+          m_uiBinCWAll[i] = hist_lens + 1;
+      }
+    }
+    else if (delta_cw > (cw_reduce1 + cw_reduce2))
+    {
+      delta_cw -= (cw_reduce1 + cw_reduce2);
+      int idx = 0;
+      while (delta_cw > 0)
+      {
+        if (m_uiBinCWAll[idx] > 0 && m_uiBinCWAll[idx] < (hist_lens + 1))
+        {
+          m_uiBinCWAll[idx]--;
+          delta_cw--;
+        }
+        idx++;
+        if (idx == hist_bins)
+          idx = 0;
+      }
+      for (i = 0; i < hist_bins; i++)
+      {
+        if (m_uiBinCWAll[i] == m_uiCWOrgAnalyze + 1)
+          m_uiBinCWAll[i] = cw_scale_bins2;
+        if (m_uiBinCWAll[i] == cw_scale_bins1)
+          m_uiBinCWAll[i] = m_uiCWOrgAnalyze + 1;
+      }
+    }
+  }
+
+  for (int i = 0; i < PIC_CODE_CW_BINS; i++)
+  {
+    m_uiBinCWAll[i] = m_uiBinCWAll[2 * i] + m_uiBinCWAll[2 * i + 1];
+  }
+  m_sliceReshapeInfo.reshape_model_min_bin_idx = 0;
+  m_sliceReshapeInfo.reshape_model_max_bin_idx = PIC_CODE_CW_BINS - 1;
+  for (int i = 0; i < PIC_CODE_CW_BINS; i++)
+  {
+    if (m_uiBinCWAll[i] > 0)
+    {
+      m_sliceReshapeInfo.reshape_model_min_bin_idx = i;
+      break;
+    }
+  }
+  for (int i = PIC_CODE_CW_BINS - 1; i >= 0; i--)
+  {
+    if (m_uiBinCWAll[i] > 0)
+    {
+      m_sliceReshapeInfo.reshape_model_max_bin_idx = i;
+      break;
+    }
+  }
+
+  int maxAbsDeltaCW = 0, AbsDeltaCW = 0, DeltaCW = 0;
+  for (int i = m_sliceReshapeInfo.reshape_model_min_bin_idx; i <= m_sliceReshapeInfo.reshape_model_max_bin_idx; i++)
+  {
+    DeltaCW = (int)m_uiBinCWAll[i] - (int)m_uiCWOrg;
+    m_sliceReshapeInfo.reshape_model_bin_CW_delta[i] = DeltaCW;
+    AbsDeltaCW = (DeltaCW < 0) ? (-DeltaCW) : DeltaCW;
+    if (AbsDeltaCW > maxAbsDeltaCW)      {      maxAbsDeltaCW = AbsDeltaCW;    }
+  }
+  m_sliceReshapeInfo.maxNbitsNeededDeltaCW = g_aucLog2[maxAbsDeltaCW << 1];
+
+  hist_bins = PIC_CODE_CW_BINS;
+  log2_hist_lens = log2_MAX_LUMA_RESHAPING_LUT_SIZE - log2_PIC_CODE_CW_BINS;
+  hist_lens = m_uiCWOrg;
+
+  int sum_bins = 0;
+  for (i = 0; i < hist_bins; i++)   {    sum_bins += m_uiBinCWAll[i];  }
+
+  CHECK(sum_bins > max_allow_cw, "SDR CW assignment is wrong!!");
+
+  memset(Y_LUT_all, 0, (MAX_LUMA_RESHAPING_LUT_SIZE + 1) * sizeof(int16_t));
+  Y_LUT_all[0] = 0;
+
+  for (i = 0; i < hist_bins; i++)
+  {
+    Y_LUT_all[(i + 1)*hist_lens] = Y_LUT_all[i*hist_lens] + m_uiBinCWAll[i];
+    int16_t Y1 = Y_LUT_all[i*hist_lens];
+    int16_t Y2 = Y_LUT_all[(i + 1)*hist_lens];
+    m_ReshapePivot[i + 1] = Y2;
+    int32_t scale = ((int32_t)(Y2 - Y1) * (1 << FP_PREC) + (1 << (log2_hist_lens - 1))) >> (log2_hist_lens);
+    forwardReshapingLUT[i*hist_lens] = Clip3((Pel)0, (Pel)1023, (Pel)Y1);
+    for (j = 1; j < hist_lens; j++)
+    {
+      Y_LUT_all[i*hist_lens + j] = Y1 + (((int32_t)scale * (int32_t)j + (1 << (FP_PREC - 1))) >> FP_PREC);
+      forwardReshapingLUT[i*hist_lens + j] = Clip3((Pel)0, (Pel)1023, (Pel)Y_LUT_all[i*hist_lens + j]);
+    }
+  }
+
+  for (i = 0; i < PIC_CODE_CW_BINS; i++)
+  {
+    int i_start = i*hist_lens;
+    int i_end = (i + 1)*hist_lens - 1;
+    m_cwLumaWeight[i] = forwardReshapingLUT[i_end] - forwardReshapingLUT[i_start];
+  }
+
+  if (Y_LUT_all != nullptr)   {     delete[] Y_LUT_all;    Y_LUT_all = nullptr;  }
+
+  ReverseLUT(forwardReshapingLUT, inverseReshapingLUT, MAX_LUMA_RESHAPING_LUT_SIZE);  
+  updateChromaDQPLUT();
+}
+
+#endif
+//
+//! \}
diff --git a/source/Lib/EncoderLib/EncReshape.h b/source/Lib/EncoderLib/EncReshape.h
new file mode 100644
index 000000000..ea186506e
--- /dev/null
+++ b/source/Lib/EncoderLib/EncReshape.h
@@ -0,0 +1,149 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2010-2019, ITU/ISO/IEC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
+ *    be used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /** \file     EncReshape.h
+     \brief    encoder reshaping header and class (header)
+ */
+
+#ifndef __ENCRESHAPE__
+#define __ENCRESHAPE__
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+#include "CommonLib/Reshape.h"
+#if JVET_M0427_INLOOP_RESHAPER
+
+//! \ingroup EncoderLib
+//! \{
+
+// ====================================================================================================================
+// Class definition
+// ====================================================================================================================
+
+struct ModelInfo
+{
+  unsigned FullRangeInputFlag;
+  unsigned ScaleIntPrec;
+  unsigned ScaleInt;
+  unsigned ScaleFracPrec;
+  unsigned ScaleFrac;
+  unsigned ScaleSign;
+  unsigned OffsetIntPrec;
+  unsigned OffsetInt;
+  unsigned OffsetFracPrec;
+  unsigned OffsetFrac;
+  unsigned OffsetSign;
+  unsigned MinMaxQPAbsPrec;
+  unsigned MaxQPAbs;
+  unsigned MaxQPSign;
+  unsigned MinQPAbs;
+  unsigned MinQPSign;
+  unsigned ScaleAbs;
+  unsigned OffsetAbs;
+};
+
+class EncReshape : public Reshape
+{
+private:
+  bool                    m_bSrcReshaped;
+  int                     m_picWidth;
+  int                     m_picHeight;
+  uint32_t                m_maxCUWidth;
+  uint32_t                m_maxCUHeight;
+  uint32_t                m_widthInCtus;
+  uint32_t                m_heightInCtus;
+  uint32_t                m_numCtuInFrame;
+  bool                    m_bExceedSTD;
+  std::vector<uint32_t>   m_uiBinImportance;
+  int                     m_tcase;
+  int                     m_rateAdpMode;
+  bool                    m_bUseAdpCW;
+  uint16_t                m_uiCWOrgAnalyze;
+  ModelInfo               m_DftModel;
+  ReshapeCW               m_reshapeCW;
+  Pel                     m_cwLumaWeight[PIC_CODE_CW_BINS];
+  double                  m_chromaWeight;  
+  int                     m_chromaAdj;
+public:
+
+  EncReshape();
+  ~EncReshape();
+
+  void create_enc( int picWidth, int picHeight, uint32_t maxCUWidth, uint32_t maxCUHeight);
+  void destroy();
+
+  bool getSrcReshaped() { return m_bSrcReshaped; }
+  void setSrcReshaped(bool bPicReshaped) { m_bSrcReshaped = bPicReshaped; }
+
+  void preAnalyzerSDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT, bool isCPR);
+  void preAnalyzerHDR(Picture *pcPic, const SliceType sliceType, const ReshapeCW& reshapeCW, bool isDualT, bool isCPR);
+  void bubbleSortDsd(double *array, int * idx, int n);
+  void swap(int *xp, int *yp) { int temp = *xp;  *xp = *yp;  *yp = temp; }
+  void swap(double *xp, double *yp) { double temp = *xp;  *xp = *yp;  *yp = temp; }
+  void deriveReshapeParametersSDRfromStats(uint32_t *, double*, double* dReshapeTH1, double* dReshapeTH2, bool *bIntraAdp, bool *bInterAdp);
+  void deriveReshapeParameters(double *array, int start, int end, ReshapeCW respCW, double &alpha, double &beta);
+  void initLUTfromdQPModel();
+  int  calcEXP2(int val);
+  void constructReshaperSDR();
+  ReshapeCW *        getReshapeCW() { return &m_reshapeCW; }
+  Pel * getWeightTable() { return m_cwLumaWeight; }
+  double getCWeight() { return m_chromaWeight; }
+
+  void initModelParam(double dScale = 0.015, double dOffset = -7.5, int QPMax = 6, int QPMin = -3)
+  {
+    /// dQP model:  dQP = clip3(QPMin, QPMax, dScale*Y+dOffset);
+    m_DftModel.FullRangeInputFlag = 0; 
+    m_DftModel.ScaleIntPrec = 0;
+    m_DftModel.ScaleFracPrec = 16;
+    m_DftModel.OffsetIntPrec = 3;
+    m_DftModel.OffsetFracPrec = 1;
+    m_DftModel.MinMaxQPAbsPrec = 3;
+    m_DftModel.ScaleSign = dScale < 0 ? 1 : 0;
+    m_DftModel.ScaleAbs = unsigned((dScale < 0 ? -dScale : dScale) * (1 << m_DftModel.ScaleFracPrec));
+    m_DftModel.ScaleInt = m_DftModel.ScaleAbs >> m_DftModel.ScaleFracPrec;
+    m_DftModel.ScaleFrac = m_DftModel.ScaleAbs - (m_DftModel.ScaleInt << m_DftModel.ScaleFracPrec);
+    m_DftModel.OffsetSign = dOffset < 0 ? 1 : 0;
+    m_DftModel.OffsetAbs = unsigned((dOffset < 0 ? -dOffset : dOffset) * (1 << m_DftModel.OffsetFracPrec));
+    m_DftModel.OffsetInt = m_DftModel.OffsetAbs >> m_DftModel.OffsetFracPrec;
+    m_DftModel.OffsetFrac = m_DftModel.OffsetAbs - (m_DftModel.OffsetInt << m_DftModel.OffsetFracPrec);
+    m_DftModel.MaxQPSign = QPMax < 0 ? 1 : 0;
+    m_DftModel.MaxQPAbs = m_DftModel.MaxQPSign ? -QPMax : QPMax;
+    m_DftModel.MinQPSign = QPMin < 0 ? 1 : 0;
+    m_DftModel.MinQPAbs = m_DftModel.MinQPSign ? -QPMin : QPMin;
+  }
+};// END CLASS DEFINITION EncReshape
+
+//! \}
+#endif
+#endif
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 35f64d386..b847fd37f 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -1612,7 +1612,12 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
       resetGbiCodingOrder(false, cs);
       m_pcInterSearch->initWeightIdxBits();
     }
-
+#if JVET_M0427_INLOOP_RESHAPER && REUSE_CU_RESULTS
+    if (pcSlice->getSPS()->getUseReshaper())
+    {
+      m_pcCuEncoder->setDecCuReshaperInEncCU(m_pcLib->getReshaper(), pcSlice->getSPS()->getChromaFormatIdc());
+    }
+#endif
 #if ENABLE_WPP_PARALLELISM
     pEncLib->getCuEncoder( dataId )->compressCtu( cs, ctuArea, ctuRsAddr, prevQP, currQP );
 #else
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index 1b5559dff..0da2c547d 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -89,6 +89,9 @@ InterSearch::InterSearch()
   , m_pFullCS                     (nullptr)
   , m_pcEncCfg                    (nullptr)
   , m_pcTrQuant                   (nullptr)
+#if JVET_M0427_INLOOP_RESHAPER
+  , m_pcReshape                   (nullptr)
+#endif
   , m_iSearchRange                (0)
   , m_bipredSearchRange           (0)
   , m_motionEstimationSearchMethod(MESEARCH_FULL)
@@ -193,6 +196,9 @@ void InterSearch::init( EncCfg*        pcEncCfg,
                         RdCost*        pcRdCost,
                         CABACWriter*   CABACEstimator,
                         CtxCache*      ctxCache
+#if JVET_M0427_INLOOP_RESHAPER
+                      , EncReshape*    pcReshape
+#endif
 )
 {
   CHECK(m_isInitialized, "Already initialized");
@@ -205,6 +211,9 @@ void InterSearch::init( EncCfg*        pcEncCfg,
   m_motionEstimationSearchMethod = motionEstimationSearchMethod;
   m_CABACEstimator               = CABACEstimator;
   m_CtxCache                     = ctxCache;
+#if JVET_M0427_INLOOP_RESHAPER
+  m_pcReshape                    = pcReshape;
+#endif
 
   for( uint32_t iDir = 0; iDir < MAX_NUM_REF_LIST_ADAPT_SR; iDir++ )
   {
@@ -1268,6 +1277,18 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf,
     CPelBuf  tmpPattern = pBuf->Y();
     CPelBuf* pcPatternKey = &tmpPattern;
 
+#if JVET_M0427_INLOOP_RESHAPER
+    if ((pu.cs->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag()))
+    {
+      const CompArea &area = pu.blocks[COMPONENT_Y];
+      CompArea    tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+      PelBuf tmpOrgLuma = m_tmpStorageLCU.getBuf(tmpArea);
+      tmpOrgLuma.copyFrom(tmpPattern);
+      tmpOrgLuma.rspSignal(m_pcReshape->getFwdLUT());
+      pcPatternKey = (CPelBuf*)&tmpOrgLuma;
+    }
+#endif
+
     m_lumaClpRng = pu.cs->slice->clpRng(COMPONENT_Y);
     Picture* refPic = pu.cu->slice->getPic();
 
@@ -5445,6 +5466,23 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
     tu.emtIdx         = 0;
 #endif
 
+#if JVET_M0427_INLOOP_RESHAPER
+    const Slice           &slice = *cs.slice;
+    if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && slice.getReshapeInfo().getSliceReshapeChromaAdj())
+    {
+      const CompArea      &areaY = tu.blocks[COMPONENT_Y];
+      PelBuf              piPredY = cs.getPredBuf(areaY);
+      CompArea      tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+      PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
+      tmpPred.copyFrom(piPredY);
+      if (!cu.firstPU->mhIntraFlag && !cu.cpr)
+        tmpPred.rspSignal(m_pcReshape->getFwdLUT());
+      const Pel           avgLuma = tmpPred.computeAvg();
+      int                    adj  = m_pcReshape->calculateChromaAdj(avgLuma);
+      tu.setChromaAdj(adj);
+    }
+#endif
+
     double minCost            [MAX_NUM_TBLOCKS];
 #if !JVET_M0464_UNI_MTS
     bool   checkTransformSkip [MAX_NUM_TBLOCKS];
@@ -5570,7 +5608,15 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
 #if RDOQ_CHROMA_LAMBDA
           m_pcTrQuant->selectLambda(compID);
 #endif
-
+#if JVET_M0427_INLOOP_RESHAPER
+          if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj())
+          {
+            int cScale = tu.getChromaAdj();
+            double dCScale = round((double)(1 << CSCALE_FP_PREC) / (double)cScale);
+            double tmpWeight = dCScale*dCScale;
+            m_pcTrQuant->setLambda(m_pcTrQuant->getLambda() / tmpWeight);
+          }
+#endif 
           TCoeff     currAbsSum = 0;
           uint64_t   currCompFracBits = 0;
           Distortion currCompDist = 0;
@@ -5584,7 +5630,14 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
             PelBuf resiBuf = csFull->getResiBuf( compArea );
             crossComponentPrediction( tu, compID, lumaResi, resiBuf, resiBuf, false );
           }
-
+#if JVET_M0427_INLOOP_RESHAPER
+          if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() && tu.blocks[compID].width*tu.blocks[compID].height > 4 )
+          {
+            PelBuf resiBuf = csFull->getResiBuf(compArea);
+            int cScale = tu.getChromaAdj();
+            resiBuf.scaleSignal(cScale, 1);
+          }
+#endif
 #if JVET_M0464_UNI_MTS
           if( nNumTransformCands > 1 )
           {
@@ -5666,6 +5719,13 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
             CPelBuf orgResiBuf = csFull->getOrgResiBuf(compArea);
 
             m_pcTrQuant->invTransformNxN(tu, compID, resiBuf, cQP);
+#if JVET_M0427_INLOOP_RESHAPER
+            if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() && tu.blocks[compID].width*tu.blocks[compID].height > 4 )
+            {
+              int cScale = tu.getChromaAdj();
+              resiBuf.scaleSignal(cScale, 0);
+            }
+#endif
 
             if (bUseCrossCPrediction)
             {
@@ -5941,6 +6001,12 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
     cs.getResiBuf().fill(0);
     {
       cs.getRecoBuf().copyFrom(cs.getPredBuf() );
+#if JVET_M0427_INLOOP_RESHAPER
+      if (m_pcEncCfg->getReshaper() && (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag()) && !cu.firstPU->mhIntraFlag && !cu.cpr)
+      {
+        cs.getRecoBuf().Y().rspSignal(m_pcReshape->getFwdLUT());
+      }
+#endif
     }
 
 
@@ -5958,9 +6024,26 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
       CPelBuf reco = cs.getRecoBuf (compID);
       CPelBuf org  = cs.getOrgBuf  (compID);
 #if WCG_EXT
+#if JVET_M0427_INLOOP_RESHAPER
+      if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (
+        m_pcEncCfg->getReshaper() && (cs.slice->getReshapeInfo().getUseSliceReshaper()&& m_pcReshape->getCTUFlag())))
+#else
       if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
+#endif
       {
         const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
+#if JVET_M0427_INLOOP_RESHAPER
+        if (compID == COMPONENT_Y)
+        {
+          const CompArea &areaY = cu.Y();
+          CompArea      tmpArea1(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+          PelBuf tmpRecLuma = m_tmpStorageLCU.getBuf(tmpArea1);
+          tmpRecLuma.copyFrom(reco);
+          tmpRecLuma.rspSignal(m_pcReshape->getInvLUT());
+          distortion += m_pcRdCost->getDistPart(org, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
+        }
+        else
+#endif
         distortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
       }
       else
@@ -5999,6 +6082,21 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
   if (luma)
   {
     cs.getResiBuf().bufs[0].copyFrom(cs.getOrgBuf().bufs[0]);
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+    {
+      const CompArea &areaY = cu.Y();
+      CompArea      tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+      PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
+      tmpPred.copyFrom(cs.getPredBuf(COMPONENT_Y));
+
+      if (!cu.firstPU->mhIntraFlag && !cu.cpr)
+        tmpPred.rspSignal(m_pcReshape->getFwdLUT());
+      cs.getResiBuf(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT());
+      cs.getResiBuf(COMPONENT_Y).subtract(tmpPred);
+    }
+    else
+#endif
     cs.getResiBuf().bufs[0].subtract(cs.getPredBuf().bufs[0]);
   }
   if (chroma)
@@ -6087,7 +6185,30 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
 
   if (luma)
   {
-    cs.getRecoBuf().bufs[0].reconstruct(cs.getPredBuf().bufs[0], cs.getResiBuf().bufs[0], cs.slice->clpRngs().comp[0]);
+#if JVET_M0427_INLOOP_RESHAPER
+    if (cu.rootCbf && cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+    {
+      const CompArea &areaY = cu.Y();
+      CompArea      tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+      PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
+      tmpPred.copyFrom(cs.getPredBuf(COMPONENT_Y));
+
+      if (!cu.firstPU->mhIntraFlag && !cu.cpr)
+        tmpPred.rspSignal(m_pcReshape->getFwdLUT());
+
+      cs.getRecoBuf(COMPONENT_Y).reconstruct(tmpPred, cs.getResiBuf(COMPONENT_Y), cs.slice->clpRng(COMPONENT_Y));
+    }
+    else
+    {
+#endif
+      cs.getRecoBuf().bufs[0].reconstruct(cs.getPredBuf().bufs[0], cs.getResiBuf().bufs[0], cs.slice->clpRngs().comp[0]);
+#if JVET_M0427_INLOOP_RESHAPER
+      if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !cu.cpr)
+      {
+        cs.getRecoBuf().bufs[0].rspSignal(m_pcReshape->getFwdLUT());
+      }
+    }
+#endif
   }
   if (chroma)
   {
@@ -6109,10 +6230,27 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
     CPelBuf org  = cs.getOrgBuf  (compID);
 
 #if WCG_EXT
+#if JVET_M0427_INLOOP_RESHAPER 
+    if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || ( 
+      m_pcEncCfg->getReshaper() && (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() ) ) )
+#else
     if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
+#endif
     {
       const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
-      finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
+#if JVET_M0427_INLOOP_RESHAPER
+      if (compID == COMPONENT_Y)
+      {
+        const CompArea &areaY = cu.Y();
+        CompArea      tmpArea1(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size());
+        PelBuf tmpRecLuma = m_tmpStorageLCU.getBuf(tmpArea1);
+        tmpRecLuma.copyFrom(reco);
+        tmpRecLuma.rspSignal(m_pcReshape->getInvLUT());
+        finalDistortion += m_pcRdCost->getDistPart(org, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
+      }
+      else
+#endif
+        finalDistortion += m_pcRdCost->getDistPart(org, reco, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
     }
     else
 #endif
diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h
index 27030ab31..24f096b79 100644
--- a/source/Lib/EncoderLib/InterSearch.h
+++ b/source/Lib/EncoderLib/InterSearch.h
@@ -54,6 +54,9 @@
 #include "CommonLib/IbcHashMap.h"
 #include <unordered_map>
 #include <vector>
+#if JVET_M0427_INLOOP_RESHAPER
+#include "EncReshape.h"
+#endif
 //! \ingroup EncoderLib
 //! \{
 
@@ -126,6 +129,9 @@ protected:
 
   // interface to classes
   TrQuant*        m_pcTrQuant;
+#if JVET_M0427_INLOOP_RESHAPER
+  EncReshape*     m_pcReshape;
+#endif
 
   // ME parameters
   int             m_iSearchRange;
@@ -164,6 +170,9 @@ public:
                                       RdCost*        pcRdCost,
                                       CABACWriter*   CABACEstimator,
                                       CtxCache*      ctxCache
+#if JVET_M0427_INLOOP_RESHAPER
+                                     , EncReshape*   m_pcReshape
+#endif
                                     );
 
   void destroy                      ();
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index ac23b0a31..b0b870af7 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -60,6 +60,9 @@ IntraSearch::IntraSearch()
   , m_pcEncCfg      (nullptr)
   , m_pcTrQuant     (nullptr)
   , m_pcRdCost      (nullptr)
+#if JVET_M0427_INLOOP_RESHAPER
+  , m_pcReshape     (nullptr)
+#endif
   , m_CABACEstimator(nullptr)
   , m_CtxCache      (nullptr)
   , m_isInitialized (false)
@@ -149,6 +152,9 @@ void IntraSearch::destroy()
     m_pSharedPredTransformSkip[ch] = nullptr;
   }
 
+#if JVET_M0427_INLOOP_RESHAPER
+  m_tmpStorageLCU.destroy();
+#endif
   m_isInitialized = false;
 }
 
@@ -168,6 +174,9 @@ void IntraSearch::init( EncCfg*        pcEncCfg,
                         const uint32_t     maxCUWidth,
                         const uint32_t     maxCUHeight,
                         const uint32_t     maxTotalCUDepth
+#if JVET_M0427_INLOOP_RESHAPER
+                       , EncReshape*   pcReshape
+#endif
 )
 {
   CHECK(m_isInitialized, "Already initialized");
@@ -176,10 +185,16 @@ void IntraSearch::init( EncCfg*        pcEncCfg,
   m_pcRdCost                     = pcRdCost;
   m_CABACEstimator               = CABACEstimator;
   m_CtxCache                     = ctxCache;
+#if JVET_M0427_INLOOP_RESHAPER
+  m_pcReshape                    = pcReshape;
+#endif
 
   const ChromaFormat cform = pcEncCfg->getChromaFormatIdc();
 
   IntraPrediction::init( cform, pcEncCfg->getBitDepth( CHANNEL_TYPE_LUMA ) );
+#if JVET_M0427_INLOOP_RESHAPER
+  m_tmpStorageLCU.create(UnitArea(cform, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
+#endif
 
   for( uint32_t ch = 0; ch < MAX_NUM_TBLOCKS; ch++ )
   {
@@ -363,6 +378,17 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
 
         const bool bUseHadamard = cu.transQuantBypass == 0;
 
+#if JVET_M0427_INLOOP_RESHAPER
+        if (cu.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
+        {
+          CompArea      tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+          PelBuf tmpOrg = m_tmpStorageLCU.getBuf(tmpArea);
+          tmpOrg.copyFrom(piOrg);
+          tmpOrg.rspSignal(m_pcReshape->getFwdLUT());
+          m_pcRdCost->setDistParam(distParam, tmpOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
+        }
+        else
+#endif
         m_pcRdCost->setDistParam(distParam, piOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
 
         distParam.applyWeight = false;
@@ -688,8 +714,11 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
       csTemp->releaseIntermediateData();
     } // Mode loop
 
+#if JVET_M0427_INLOOP_RESHAPER
+    cs.useSubStructure(*csBest, partitioner.chType, pu.singleChan(CHANNEL_TYPE_LUMA), true, true, keepResi, keepResi);
+#else
     cs.useSubStructure( *csBest, partitioner.chType, pu.singleChan( CHANNEL_TYPE_LUMA ), KEEP_PRED_AND_RESI_SIGNALS, true, keepResi, keepResi );
-
+#endif
     csBest->releaseIntermediateData();
     //=== update PU data ====
     pu.intraDir[0] = uiBestPUMode;
@@ -907,6 +936,10 @@ void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
 #if KEEP_PRED_AND_RESI_SIGNALS
             saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   ( area ) );
             saveCS.getResiBuf     ( area ).copyFrom( cs.getResiBuf   ( area ) );
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+            saveCS.getPredBuf     ( area ).copyFrom( cs.getPredBuf   (area ) );
+            cs.picture->getPredBuf( area ).copyFrom( cs.getPredBuf   (area ) );
 #endif
             cs.picture->getRecoBuf( area ).copyFrom( cs.getRecoBuf( area ) );
 
@@ -931,6 +964,11 @@ void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner)
         cs.getPredBuf         ( area ).copyFrom( saveCS.getPredBuf( area ) );
         cs.getResiBuf         ( area ).copyFrom( saveCS.getResiBuf( area ) );
 #endif
+#if JVET_M0427_INLOOP_RESHAPER
+        cs.getPredBuf         ( area ).copyFrom( saveCS.getPredBuf( area ) );
+        cs.picture->getPredBuf( area ).copyFrom( cs.getPredBuf    ( area ) );
+#endif
+
         cs.picture->getRecoBuf( area ).copyFrom( cs.    getRecoBuf( area ) );
 
         for( uint32_t j = 0; j < saveCS.tus.size(); j++ )
@@ -967,6 +1005,9 @@ void IntraSearch::IPCMSearch(CodingStructure &cs, Partitioner& partitioner)
   cs.cost     = 0;
 
   cs.setDecomp(cs.area);
+#if JVET_M0427_INLOOP_RESHAPER
+  cs.picture->getPredBuf(cs.area).copyFrom(cs.getPredBuf());
+#endif 
 }
 
 void IntraSearch::xEncPCM(CodingStructure &cs, Partitioner& partitioner, const ComponentID &compID)
@@ -1274,8 +1315,33 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
   DTRACE( g_trace_ctx, D_PRED, "@(%4d,%4d) [%2dx%2d] IMode=%d\n", tu.lx(), tu.ly(), tu.lwidth(), tu.lheight(), uiChFinalMode );
   //DTRACE_PEL_BUF( D_PRED, piPred, tu, tu.cu->predMode, COMPONENT_Y );
 
+#if JVET_M0427_INLOOP_RESHAPER
+  const Slice           &slice = *cs.slice;
+  bool bFlag = slice.getReshapeInfo().getUseSliceReshaper() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag()) || (slice.getSliceType() == P_SLICE && slice.getSPS()->getSpsNext().getCPRMode()));
+  if (bFlag && slice.getReshapeInfo().getSliceReshapeChromaAdj() && isChroma(compID))
+  {
+    const Area area = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].pos()), recalcSize(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].size()));
+    const CompArea &areaY = CompArea(COMPONENT_Y, tu.chromaFormat, area );
+    PelBuf piPredY;
+    piPredY = cs.picture->getPredBuf(areaY);
+    const Pel avgLuma = piPredY.computeAvg();
+    int adj = m_pcReshape->calculateChromaAdj(avgLuma);
+    tu.setChromaAdj(adj);
+  }
+#endif
   //===== get residual signal =====
   piResi.copyFrom( piOrg  );
+#if JVET_M0427_INLOOP_RESHAPER
+  if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && compID==COMPONENT_Y)
+  {
+    CompArea      tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+    PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
+    tmpPred.copyFrom(piPred);
+    piResi.rspSignal(m_pcReshape->getFwdLUT());
+    piResi.subtract(tmpPred);
+  }
+  else
+#endif
   piResi.subtract( piPred );
 
   if (pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isLuma(compID))
@@ -1303,6 +1369,19 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
   m_pcTrQuant->selectLambda(compID);
 #endif
 
+#if JVET_M0427_INLOOP_RESHAPER
+  bFlag = bFlag && (tu.blocks[compID].width*tu.blocks[compID].height > 4);  // chroma blk size greater than 2x2
+  if (bFlag && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() )
+  {
+    int cScale = tu.getChromaAdj();
+    double dCScale = round((double)(1 << CSCALE_FP_PREC) / (double)cScale);
+    double tmpWeight = dCScale*dCScale;
+    m_pcTrQuant->setLambda(m_pcTrQuant->getLambda() / tmpWeight);
+
+    piResi.scaleSignal(tu.getChromaAdj(), 1);
+  }
+#endif 
+
 #if JVET_M0464_UNI_MTS
   if( trModes )
   {
@@ -1329,19 +1408,51 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
   }
 
   //===== reconstruction =====
+#if JVET_M0427_INLOOP_RESHAPER
+  if (bFlag && uiAbsSum > 0 && isChroma(compID) && slice.getReshapeInfo().getSliceReshapeChromaAdj() )
+  {
+    piResi.scaleSignal(tu.getChromaAdj(), 0);
+  }
+#endif
   if (bUseCrossCPrediction)
   {
     CrossComponentPrediction::crossComponentPrediction(tu, compID, cs.getResiBuf(tu.Y()), piResi, piResi, true);
   }
 
+#if JVET_M0427_INLOOP_RESHAPER
+  if (slice.getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && compID == COMPONENT_Y)
+  {
+    CompArea      tmpArea(COMPONENT_Y, area.chromaFormat, Position(0,0), area.size());
+    PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
+    tmpPred.copyFrom(piPred);
+    piReco.reconstruct(tmpPred, piResi, cs.slice->clpRng(compID));
+  }
+  else 
+#endif
   piReco.reconstruct(piPred, piResi, cs.slice->clpRng( compID ));
 
   //===== update distortion =====
 #if WCG_EXT
+#if JVET_M0427_INLOOP_RESHAPER
+  if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcEncCfg->getReshaper()
+    && slice.getReshapeInfo().getUseSliceReshaper() && (m_pcReshape->getCTUFlag() || (isChroma(compID) && m_pcEncCfg->getReshapeIntraCMD()))))
+#else
   if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
+#endif
   {
     const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
-    ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE_WTD, &orgLuma );
+#if JVET_M0427_INLOOP_RESHAPER
+    if (compID == COMPONENT_Y)
+    {
+      CompArea      tmpArea1(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
+      PelBuf tmpRecLuma = m_tmpStorageLCU.getBuf(tmpArea1);
+      tmpRecLuma.copyFrom(piReco);
+      tmpRecLuma.rspSignal(m_pcReshape->getInvLUT());
+      ruiDist += m_pcRdCost->getDistPart(piOrg, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
+    }
+    else
+#endif
+      ruiDist += m_pcRdCost->getDistPart(piOrg, piReco, bitDepth, compID, DF_SSE_WTD, &orgLuma);
   }
   else
 #endif
@@ -1602,7 +1713,7 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
 
         if( bestModeId[COMPONENT_Y] != lastCheckId )
         {
-#if KEEP_PRED_AND_RESI_SIGNALS
+#if KEEP_PRED_AND_RESI_SIGNALS || JVET_M0427_INLOOP_RESHAPER
           saveCS.getPredBuf( tu.Y() ).copyFrom( csFull->getPredBuf( tu.Y() ) );
 #endif
           saveCS.getRecoBuf( tu.Y() ).copyFrom( csFull->getRecoBuf( tu.Y() ) );
@@ -1622,7 +1733,7 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
 
     if( bestModeId[COMPONENT_Y] != lastCheckId )
     {
-#if KEEP_PRED_AND_RESI_SIGNALS
+#if KEEP_PRED_AND_RESI_SIGNALS || JVET_M0427_INLOOP_RESHAPER
       csFull->getPredBuf( tu.Y() ).copyFrom( saveCS.getPredBuf( tu.Y() ) );
 #endif
       csFull->getRecoBuf( tu.Y() ).copyFrom( saveCS.getRecoBuf( tu.Y() ) );
@@ -1707,6 +1818,9 @@ void IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
     {
       // otherwise this would've happened in useSubStructure
       cs.picture->getRecoBuf( currArea.Y() ).copyFrom( cs.getRecoBuf( currArea.Y() ) );
+#if JVET_M0427_INLOOP_RESHAPER
+      cs.picture->getPredBuf( currArea.Y() ).copyFrom( cs.getPredBuf( currArea.Y() ) );
+#endif
     }
 
     cs.cost = m_pcRdCost->calcRdCost( cs.fracBits, cs.dist );
@@ -1874,6 +1988,9 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partition
 #if KEEP_PRED_AND_RESI_SIGNALS
               saveCS.getPredBuf   (area).copyFrom(cs.getPredBuf   (area));
               saveCS.getOrgResiBuf(area).copyFrom(cs.getOrgResiBuf(area));
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+              saveCS.getPredBuf   (area).copyFrom(cs.getPredBuf   (area));
 #endif
               if( keepResi )
               {
@@ -1894,6 +2011,9 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partition
 #if KEEP_PRED_AND_RESI_SIGNALS
         cs.getPredBuf   (area).copyFrom(saveCS.getPredBuf   (area));
         cs.getOrgResiBuf(area).copyFrom(saveCS.getOrgResiBuf(area));
+#endif
+#if JVET_M0427_INLOOP_RESHAPER
+        cs.getPredBuf   (area).copyFrom(saveCS.getPredBuf   (area));
 #endif
         if( keepResi )
         {
@@ -1906,6 +2026,9 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT(CodingStructure &cs, Partition
         m_CABACEstimator->getCtx() = ctxBest;
       }
 
+#if JVET_M0427_INLOOP_RESHAPER
+      cs.picture->getPredBuf(area).copyFrom(cs.getPredBuf(area));
+#endif
       cs.picture->getRecoBuf(area).copyFrom(cs.getRecoBuf(area));
 
       cbfs.cbf(compID) = TU::getCbf(currTU, compID);
diff --git a/source/Lib/EncoderLib/IntraSearch.h b/source/Lib/EncoderLib/IntraSearch.h
index 3c1ce2b81..e6d1cc736 100644
--- a/source/Lib/EncoderLib/IntraSearch.h
+++ b/source/Lib/EncoderLib/IntraSearch.h
@@ -48,6 +48,9 @@
 #include "CommonLib/TrQuant.h"
 #include "CommonLib/Unit.h"
 #include "CommonLib/RdCost.h"
+#if JVET_M0427_INLOOP_RESHAPER
+#include "EncReshape.h"
+#endif
 
 //! \ingroup EncoderLib
 //! \{
@@ -81,7 +84,9 @@ private:
   uint32_t   m_savedRdModeList  [4][NUM_LUMA_MODE], m_savedNumRdModes[4];
   int        m_savedExtendRefList[4][NUM_LUMA_MODE];
 #endif
-
+#if JVET_M0427_INLOOP_RESHAPER
+  PelStorage      m_tmpStorageLCU;
+#endif
 protected:
   // interface to option
   EncCfg*         m_pcEncCfg;
@@ -89,6 +94,9 @@ protected:
   // interface to classes
   TrQuant*        m_pcTrQuant;
   RdCost*         m_pcRdCost;
+#if JVET_M0427_INLOOP_RESHAPER
+  EncReshape*     m_pcReshape;
+#endif
 
   // RD computation
   CABACWriter*    m_CABACEstimator;
@@ -109,6 +117,9 @@ public:
                                     const uint32_t     maxCUWidth,
                                     const uint32_t     maxCUHeight,
                                     const uint32_t     maxTotalCUDepth
+#if JVET_M0427_INLOOP_RESHAPER
+                                  , EncReshape*   m_pcReshape
+#endif
                                   );
 
   void destroy                    ();
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index 82300aae2..32a2d0735 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -593,6 +593,39 @@ void HLSWriter::codeSPSNext( const SPSNext& spsNext, const bool usePCM )
   // ADD_NEW_TOOL : (sps extension writer) write tool enabling flags and associated parameters here
 }
 
+#if JVET_M0427_INLOOP_RESHAPER
+void HLSWriter::codeReshaper(const sliceReshapeInfo& pSliceReshaperInfo, const SPS* pcSPS, const bool isIntra)
+{
+  WRITE_FLAG(pSliceReshaperInfo.getSliceReshapeModelPresentFlag() ? 1 : 0, "slice_reshaper_model_present_flag");
+  if (pSliceReshaperInfo.getSliceReshapeModelPresentFlag())
+  {
+    // code slice reshaper model
+    WRITE_UVLC(pSliceReshaperInfo.reshape_model_min_bin_idx, "reshaper_model_min_bin_idx");
+    WRITE_UVLC(PIC_CODE_CW_BINS - 1 - pSliceReshaperInfo.reshape_model_max_bin_idx, "reshaper_model_max_bin_idx");
+    assert(pSliceReshaperInfo.maxNbitsNeededDeltaCW > 0);
+    WRITE_UVLC(pSliceReshaperInfo.maxNbitsNeededDeltaCW-1, "reshaper_model_bin_delta_abs_cw_prec_minus1");
+
+     for (int i = pSliceReshaperInfo.reshape_model_min_bin_idx; i <= pSliceReshaperInfo.reshape_model_max_bin_idx; i++)
+     {
+       int CW_delta = pSliceReshaperInfo.reshape_model_bin_CW_delta[i];
+       int signCW = (CW_delta < 0) ? 1 : 0;
+       int absCW = (CW_delta < 0) ? (-CW_delta) : CW_delta;
+       WRITE_CODE(absCW, pSliceReshaperInfo.maxNbitsNeededDeltaCW, "reshape_model_abs_CW");
+       if (absCW > 0)
+         WRITE_FLAG(signCW, "reshape_model_sign_CW");
+     }
+  }
+
+  WRITE_FLAG(pSliceReshaperInfo.getUseSliceReshaper() ? 1 : 0, "slice_reshaper_enable_flag");
+
+  if (!pSliceReshaperInfo.getUseSliceReshaper())
+    return;
+
+  if (!(pcSPS->getUseDualITree() && isIntra))
+    WRITE_FLAG(pSliceReshaperInfo.getSliceReshapeChromaAdj(), "slice_reshaper_chromaAdj");
+};
+#endif // #if JVET_M0427_INLOOP_RESHAPER
+
 void HLSWriter::codeSPS( const SPS* pcSPS )
 {
 
@@ -838,6 +871,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
       }
     }
   }
+#if JVET_M0427_INLOOP_RESHAPER
+  WRITE_FLAG(pcSPS->getUseReshaper() ? 1 : 0, "sps_reshaper_enable_flag");
+#endif
   xWriteRbspTrailingBits();
 }
 
@@ -1341,6 +1377,13 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
     {
       WRITE_FLAG(pcSlice->getLFCrossSliceBoundaryFlag()?1:0, "slice_loop_filter_across_slices_enabled_flag");
     }
+
+#if JVET_M0427_INLOOP_RESHAPER
+    if (pcSlice->getSPS()->getUseReshaper())
+    {
+      codeReshaper(pcSlice->getReshapeInfo(), pcSlice->getSPS(), pcSlice->isIntra());
+    }
+#endif
 #if HEVC_DEPENDENT_SLICES
   }
 #endif
diff --git a/source/Lib/EncoderLib/VLCWriter.h b/source/Lib/EncoderLib/VLCWriter.h
index 2e3dd35f9..1b9cb53f4 100644
--- a/source/Lib/EncoderLib/VLCWriter.h
+++ b/source/Lib/EncoderLib/VLCWriter.h
@@ -145,6 +145,9 @@ private:
   void alfGolombEncode( const int coeff, const int k );
   void truncatedUnaryEqProb( int symbol, int maxSymbol );
 
+#if JVET_M0427_INLOOP_RESHAPER
+  void  codeReshaper            ( const sliceReshapeInfo& pSliceReshaperInfo, const SPS* pcSPS, const bool isIntra);
+#endif
 };
 
 //! \}
-- 
GitLab