diff --git a/source/Lib/CommonLib/Reshape.cpp b/source/Lib/CommonLib/Reshape.cpp
index c8dae7c0ff525ab6c94fa86b1f37bce133fc9b4e..c08d940cdc3b6f8dcc355ed5c322839f717d803f 100644
--- a/source/Lib/CommonLib/Reshape.cpp
+++ b/source/Lib/CommonLib/Reshape.cpp
@@ -73,6 +73,14 @@ void  Reshape::createDec(int bitDepth)
     m_invLUT.resize(m_reshapeLUTSize, 0);
   if (m_binCW.empty())
     m_binCW.resize(PIC_CODE_CW_BINS, 0);
+#if JVET_O0428_LMCS_CLEANUP
+  if (m_inputPivot.empty())
+    m_inputPivot.resize(PIC_CODE_CW_BINS + 1, 0);
+  if (m_fwdScaleCoef.empty())
+    m_fwdScaleCoef.resize(PIC_CODE_CW_BINS, 1 << FP_PREC);
+  if (m_invScaleCoef.empty())
+    m_invScaleCoef.resize(PIC_CODE_CW_BINS, 1 << FP_PREC);
+#endif
   if (m_reshapePivot.empty())
     m_reshapePivot.resize(PIC_CODE_CW_BINS + 1, 0);
   if (m_chromaAdjHelpLUT.empty())
@@ -83,6 +91,7 @@ void  Reshape::destroy()
 {
 }
 
+#if !JVET_O0428_LMCS_CLEANUP
 /**
 -Perform inverse of a one dimension LUT
 \param   InputLUT  describing the input LUT
@@ -121,6 +130,7 @@ void Reshape::reverseLUT(std::vector<Pel>& inputLUT, std::vector<Pel>& outputLUT
     outputLUT[i] = Clip3((Pel)0, (Pel)((1<<m_lumaBD)-1), outputLUT[i]);
   }
 }
+#endif
 
 
 /** compute chroma residuce scale for TU
@@ -229,6 +239,13 @@ int  Reshape::calculateChromaAdjVpduNei(TransformUnit &tu, const CompArea &areaY
 int Reshape::getPWLIdxInv(int lumaVal)
 {
   int idxS = 0;
+#if JVET_O0428_LMCS_CLEANUP
+  for (idxS = m_sliceReshapeInfo.reshaperModelMinBinIdx; (idxS <= m_sliceReshapeInfo.reshaperModelMaxBinIdx); idxS++)
+  {
+    if (lumaVal < m_reshapePivot[idxS + 1])     break;
+  }
+  return idxS;
+#else
   if (lumaVal < m_reshapePivot[m_sliceReshapeInfo.reshaperModelMinBinIdx + 1])
     return m_sliceReshapeInfo.reshaperModelMinBinIdx;
   else if (lumaVal >= m_reshapePivot[m_sliceReshapeInfo.reshaperModelMaxBinIdx])
@@ -241,6 +258,7 @@ int Reshape::getPWLIdxInv(int lumaVal)
     }
     return idxS;
   }
+#endif
 }
 
 /**
@@ -281,6 +299,34 @@ void Reshape::constructReshaper()
   for (int i = m_sliceReshapeInfo.reshaperModelMinBinIdx; i <= m_sliceReshapeInfo.reshaperModelMaxBinIdx; i++)
     m_binCW[i] = (uint16_t)(m_sliceReshapeInfo.reshaperModelBinCWDelta[i] + (int)m_initCW);
 
+#if JVET_O0428_LMCS_CLEANUP
+  for (int i = 0; i < pwlFwdLUTsize; i++)
+  {
+    m_reshapePivot[i + 1] = m_reshapePivot[i] + m_binCW[i];
+    m_inputPivot[i + 1] = m_inputPivot[i] + m_initCW;
+    m_fwdScaleCoef[i] = ((int32_t)m_binCW[i] * (1 << FP_PREC) + (1 << (floorLog2(pwlFwdBinLen) - 1))) >> floorLog2(pwlFwdBinLen);
+    if (m_binCW[i] == 0)
+    {
+      m_invScaleCoef[i] = 0;
+      m_chromaAdjHelpLUT[i] = 1 << CSCALE_FP_PREC;
+    }
+    else
+    {
+      m_invScaleCoef[i] = (int32_t)(m_initCW * (1 << FP_PREC) / m_binCW[i]);
+      m_chromaAdjHelpLUT[i] = m_invScaleCoef[i];
+    }
+  }
+  for (int lumaSample = 0; lumaSample < m_reshapeLUTSize; lumaSample++)
+  {
+    int idxY = lumaSample / m_initCW;
+    int tempVal = m_reshapePivot[idxY] + ((m_fwdScaleCoef[idxY] * (lumaSample - m_inputPivot[idxY]) + (1 << (FP_PREC - 1))) >> FP_PREC);
+    m_fwdLUT[lumaSample] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)(tempVal));
+
+    int idxYInv = getPWLIdxInv(lumaSample);
+    int invSample = m_inputPivot[idxYInv] + ((m_invScaleCoef[idxYInv] * (lumaSample - m_reshapePivot[idxYInv]) + (1 << (FP_PREC - 1))) >> FP_PREC);
+    m_invLUT[lumaSample] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)(invSample));
+  }
+#else
   for (int i = 0; i < pwlFwdLUTsize; i++)
   {
     m_reshapePivot[i + 1] = m_reshapePivot[i] + m_binCW[i];
@@ -300,8 +346,10 @@ void Reshape::constructReshaper()
   }
   reverseLUT(m_fwdLUT, m_invLUT, m_reshapeLUTSize);
   updateChromaScaleLUT();
+#endif
 }
 
+#if !JVET_O0428_LMCS_CLEANUP
 /** generate chroma residue scaling LUT
 * \param void
 * \return void
@@ -316,6 +364,7 @@ void Reshape::updateChromaScaleLUT()
       m_chromaAdjHelpLUT[i] = m_initCW * (1 << CSCALE_FP_PREC) / m_binCW[i];
   }
 }
+#endif
 
 
 //
diff --git a/source/Lib/CommonLib/Reshape.h b/source/Lib/CommonLib/Reshape.h
index 5d23e08ee0b1176897f2c1316b64ac8c87c94336..853e6f7b88520b46cbf8fcac86bac319c49f13b5 100644
--- a/source/Lib/CommonLib/Reshape.h
+++ b/source/Lib/CommonLib/Reshape.h
@@ -64,6 +64,11 @@ protected:
   uint16_t                m_initCW;
   bool                    m_reshape;
   std::vector<Pel>        m_reshapePivot;
+#if JVET_O0428_LMCS_CLEANUP
+  std::vector<Pel>        m_inputPivot;
+  std::vector<int32_t>    m_fwdScaleCoef;
+  std::vector<int32_t>    m_invScaleCoef;
+#endif
   int                     m_lumaBD;
   int                     m_reshapeLUTSize;
 #if JVET_O1109_UNFIY_CRS
@@ -82,7 +87,9 @@ public:
   void createDec(int bitDepth);
   void destroy();
 
+#if !JVET_O0428_LMCS_CLEANUP
   void reverseLUT(std::vector<Pel>& inputLUT, std::vector<Pel>& outputLUT, uint16_t lutSize);
+#endif
   std::vector<Pel>&  getFwdLUT() { return m_fwdLUT; }
   std::vector<Pel>&  getInvLUT() { return m_invLUT; }
   std::vector<int>&  getChromaAdjHelpLUT() { return m_chromaAdjHelpLUT; }
@@ -98,7 +105,9 @@ public:
   void copySliceReshaperInfo(SliceReshapeInfo& tInfo, SliceReshapeInfo& sInfo);
 
   void constructReshaper();
+#if !JVET_O0428_LMCS_CLEANUP
   void updateChromaScaleLUT();
+#endif
   bool getReshapeFlag() { return m_reshape; }
   void setReshapeFlag(bool b) { m_reshape = b; }
 #if JVET_O1109_UNFIY_CRS
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index c6bbc3252879884bbe2b13f632c361011ac5f424..55112c7137b0a12eac79ba31deea4f9fc87c7bfe 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -62,6 +62,8 @@
 
 #define JVET_O0429_CRS_LAMBDA_FIX                         1 // JVET-O0429: fix encoder lambda rounding used in CRS
 
+#define JVET_O0428_LMCS_CLEANUP                           1 // JVET-O0428: LMCS cleanups
+
 #define JVET_O0164_REMOVE_AMVP_SPATIAL_SCALING            1 // JVET-O0164/JVET-O0587: remove spatial AMVP candidate scaling
 
 #define JVET_O0162_IBC_MVP_FLAG                           1 // JVET-O0162/O0331/O0480/O0574: IBC mvp flag conditioned on MaxNumMergeCand>1
diff --git a/source/Lib/EncoderLib/EncReshape.cpp b/source/Lib/EncoderLib/EncReshape.cpp
index b590850165dbabdab17d6e6d54fb6307f75d69d8..5abfc38ae4473d3251eedd4fb10abff155bf48e4 100644
--- a/source/Lib/EncoderLib/EncReshape.cpp
+++ b/source/Lib/EncoderLib/EncReshape.cpp
@@ -78,6 +78,14 @@ void  EncReshape::createEnc(int picWidth, int picHeight, uint32_t maxCUWidth, ui
     m_binImportance.resize(PIC_ANALYZE_CW_BINS);
   if (m_reshapePivot.empty())
     m_reshapePivot.resize(PIC_CODE_CW_BINS + 1, 0);
+#if JVET_O0428_LMCS_CLEANUP
+  if (m_inputPivot.empty())
+    m_inputPivot.resize(PIC_CODE_CW_BINS + 1, 0);
+  if (m_fwdScaleCoef.empty())
+    m_fwdScaleCoef.resize(PIC_CODE_CW_BINS, 1 << FP_PREC);
+  if (m_invScaleCoef.empty())
+    m_invScaleCoef.resize(PIC_CODE_CW_BINS, 1 << FP_PREC);
+#endif
   if (m_chromaAdjHelpLUT.empty())
     m_chromaAdjHelpLUT.resize(PIC_CODE_CW_BINS, 1<<CSCALE_FP_PREC);
 
@@ -1039,6 +1047,12 @@ void EncReshape::initLUTfromdQPModel()
   {
     m_binCW[i] = m_reshapePivot[i + 1] - m_reshapePivot[i];
   }
+#if JVET_O0428_LMCS_CLEANUP
+  for (int i = 0; i <= PIC_CODE_CW_BINS; i++)
+  {
+    m_inputPivot[i] = m_initCW * i;
+  }
+#endif
 
   int maxAbsDeltaCW = 0, absDeltaCW = 0, deltaCW = 0;
   for (int i = m_sliceReshapeInfo.reshaperModelMinBinIdx; i <= m_sliceReshapeInfo.reshaperModelMaxBinIdx; i++)
@@ -1050,6 +1064,32 @@ void EncReshape::initLUTfromdQPModel()
   }
   m_sliceReshapeInfo.maxNbitsNeededDeltaCW = std::max(1, 1 + floorLog2(maxAbsDeltaCW));
 
+#if JVET_O0428_LMCS_CLEANUP
+  for (int i = 0; i < pwlFwdLUTsize; i++)
+  {
+    m_fwdScaleCoef[i] = ((int32_t)m_binCW[i] * (1 << FP_PREC) + (1 << (floorLog2(pwlFwdBinLen) - 1))) >> floorLog2(pwlFwdBinLen);
+    if (m_binCW[i] == 0)
+    {
+      m_invScaleCoef[i] = 0;
+      m_chromaAdjHelpLUT[i] = 1 << CSCALE_FP_PREC;
+    }
+    else
+    {
+      m_invScaleCoef[i] = (int32_t)(m_initCW * (1 << FP_PREC) / m_binCW[i]);
+      m_chromaAdjHelpLUT[i] = m_invScaleCoef[i];
+    }
+  }
+  for (int lumaSample = 0; lumaSample < m_reshapeLUTSize; lumaSample++)
+  {
+    int idxY = lumaSample / m_initCW;
+    int tempVal = m_reshapePivot[idxY] + ((m_fwdScaleCoef[idxY] * (lumaSample - m_inputPivot[idxY]) + (1 << (FP_PREC - 1))) >> FP_PREC);
+    m_fwdLUT[lumaSample] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)(tempVal));
+
+    int idxYInv = getPWLIdxInv(lumaSample);
+    int invSample = m_inputPivot[idxYInv] + ((m_invScaleCoef[idxYInv] * (lumaSample - m_reshapePivot[idxYInv]) + (1 << (FP_PREC - 1))) >> FP_PREC);
+    m_invLUT[lumaSample] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)(invSample));
+  }
+#else
   for (int i = 0; i < pwlFwdLUTsize; i++)
   {
     int16_t Y1 = m_reshapePivot[i];
@@ -1065,6 +1105,7 @@ void EncReshape::initLUTfromdQPModel()
   }
   reverseLUT(m_fwdLUT, m_invLUT, m_reshapeLUTSize);
   updateChromaScaleLUT();
+#endif
 }
 
 void EncReshape::constructReshaperSDR()
@@ -1075,8 +1116,12 @@ void EncReshape::constructReshaperSDR()
   int histBins = PIC_ANALYZE_CW_BINS;
   int histLenth = totCW/histBins;
   int log2HistLenth = floorLog2(histLenth);
+#if !JVET_O0428_LMCS_CLEANUP
   int16_t *tempFwdLUT = new int16_t[m_reshapeLUTSize + 1]();
   int i, j;
+#else
+  int i;
+#endif
   int cwScaleBins1, cwScaleBins2;
   int maxAllowedCW = totCW-1;
 
@@ -1205,6 +1250,12 @@ void EncReshape::constructReshaperSDR()
       m_binCW[i] = bdShift > 0 ? m_binCW[i] * (1 << bdShift) : m_binCW[i] / (1 << (-bdShift));
     }
   }
+#if JVET_O0428_LMCS_CLEANUP
+  for (int i = 0; i <= PIC_CODE_CW_BINS; i++)
+  {
+    m_inputPivot[i] = m_initCW * i;
+  }
+#endif
 
   for (int i = 0; i < PIC_CODE_CW_BINS; i++)
   {
@@ -1245,6 +1296,39 @@ void EncReshape::constructReshaperSDR()
   int sumBins = 0;
   for (i = 0; i < PIC_CODE_CW_BINS; i++)   { sumBins += m_binCW[i];  }
   CHECK(sumBins >= m_reshapeLUTSize, "SDR CW assignment is wrong!!");
+#if JVET_O0428_LMCS_CLEANUP
+  for (int i = 0; i < PIC_CODE_CW_BINS; i++)
+  {
+    m_reshapePivot[i + 1] = m_reshapePivot[i] + m_binCW[i];
+    m_fwdScaleCoef[i] = ((int32_t)m_binCW[i] * (1 << FP_PREC) + (1 << (log2HistLenth - 1))) >> log2HistLenth;
+    if (m_binCW[i] == 0)
+    {
+      m_invScaleCoef[i] = 0;
+      m_chromaAdjHelpLUT[i] = 1 << CSCALE_FP_PREC;
+    }
+    else
+    {
+      m_invScaleCoef[i] = (int32_t)(m_initCW * (1 << FP_PREC) / m_binCW[i]);
+      m_chromaAdjHelpLUT[i] = m_invScaleCoef[i];
+    }
+  }
+  for (int lumaSample = 0; lumaSample < m_reshapeLUTSize; lumaSample++)
+  {
+    int idxY = lumaSample / m_initCW;
+    int tempVal = m_reshapePivot[idxY] + ((m_fwdScaleCoef[idxY] * (lumaSample - m_inputPivot[idxY]) + (1 << (FP_PREC - 1))) >> FP_PREC);
+    m_fwdLUT[lumaSample] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)(tempVal));
+
+    int idxYInv = getPWLIdxInv(lumaSample);
+    int invSample = m_inputPivot[idxYInv] + ((m_invScaleCoef[idxYInv] * (lumaSample - m_reshapePivot[idxYInv]) + (1 << (FP_PREC - 1))) >> FP_PREC);
+    m_invLUT[lumaSample] = Clip3((Pel)0, (Pel)((1 << m_lumaBD) - 1), (Pel)(invSample));
+  }
+  for (i = 0; i < PIC_CODE_CW_BINS; i++)
+  {
+    int start = i*histLenth;
+    int end = (i + 1)*histLenth - 1;
+    m_cwLumaWeight[i] = m_fwdLUT[end] - m_fwdLUT[start];
+  }
+#else
   memset(tempFwdLUT, 0, (m_reshapeLUTSize + 1) * sizeof(int16_t));
   tempFwdLUT[0] = 0;
 
@@ -1274,6 +1358,7 @@ void EncReshape::constructReshaperSDR()
 
   reverseLUT(m_fwdLUT, m_invLUT, m_reshapeLUTSize);
   updateChromaScaleLUT();
+#endif
 }
 
 #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
@@ -1308,6 +1393,11 @@ void EncReshape::copyState(const EncReshape &other)
   m_initCW           = other.m_initCW;
   m_reshape          = other.m_reshape;
   m_reshapePivot     = other.m_reshapePivot;
+#if JVET_O0428_LMCS_CLEANUP
+  m_inputPivot       = other.m_inputPivot;
+  m_fwdScaleCoef     = other.m_fwdScaleCoef;
+  m_invScaleCoef     = other.m_invScaleCoef;
+#endif
   m_lumaBD           = other.m_lumaBD;
   m_reshapeLUTSize   = other.m_reshapeLUTSize;
 }