diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp
index 5f8019a304be09840c4b98ffdc10f31d6d6f0a72..7bd1333159a6690ae84778fda2ff9d2832488fe0 100644
--- a/source/Lib/CommonLib/Rom.cpp
+++ b/source/Lib/CommonLib/Rom.cpp
@@ -452,6 +452,18 @@ void initROM()
 #endif
 
   ::memset(g_isReusedUniMVsFilled, 0, sizeof(g_isReusedUniMVsFilled));
+
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+  for (int qp = 0; qp < 57; qp++)
+  {
+    int qpRem = (qp + 12) % 6;
+    int qpPer = (qp + 12) / 6;
+    int quantiserScale = g_quantScales[0][qpRem];
+    int quantiserRightShift = QUANT_SHIFT + qpPer;
+    double threshQP = ((double)(1 << quantiserRightShift)) / quantiserScale;
+    g_paletteQuant[qp] = (int)(threshQP*0.16 + 0.5);
+  }
+#endif
 }
 
 void destroyROM()
@@ -736,7 +748,11 @@ int16_t *g_triangleWeights[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 2][MAX
 Mv   g_reusedUniMVs[32][32][8][8][2][33];
 bool g_isReusedUniMVsFilled[32][32][8][8];
 
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+uint16_t g_paletteQuant[57];
+#else
 const uint8_t g_paletteQuant[52] = { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 22, 24, 23, 25, 26, 28, 29, 31, 32, 34, 36, 37, 39, 41, 42, 45 };
+#endif
 uint8_t g_paletteRunTopLut [5] = { 0, 1, 1, 2, 2 };
 uint8_t g_paletteRunLeftLut[5] = { 0, 1, 2, 3, 4 };
 
diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h
index 010891cb10e6a2d66619e56e53c7b60f22ca088e..ecdbdd9bc79e9645352fc21264fa241d8685064a 100644
--- a/source/Lib/CommonLib/Rom.h
+++ b/source/Lib/CommonLib/Rom.h
@@ -217,7 +217,11 @@ class  Mv;
 extern Mv   g_reusedUniMVs[32][32][8][8][2][33];
 extern bool g_isReusedUniMVsFilled[32][32][8][8];
 
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+extern uint16_t g_paletteQuant[57];
+#else
 extern const uint8_t g_paletteQuant[52];
+#endif
 extern uint8_t g_paletteRunTopLut[5];
 extern uint8_t g_paletteRunLeftLut[5];
 
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index a52e8adf728f143ba2f908b11bccbeaf9d75f2e2..eb177f29110352577600b4e93965964fc619220f 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -64,6 +64,8 @@
 
 #define JVET_Q0501_PALETTE_WPP_INIT_ABOVECTU              1 // JVET-Q0501: Initialize palette predictor from above CTU row in WPP 
 
+#define JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX        1 // JVET-Q0503/Q0712: Platte encoder improvement/bugfix
+
 #define JVET_Q0819_PH_CHANGES                             1 // JVET-Q0819: Combination of PH related syntax changes
 
 #define JVET_Q0481_PARTITION_CONSTRAINTS_ORDER            1 // JVET-Q0481: Ordering of partition constraints syntax elements in the SPS
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index 5ee8d0ee19ec6d5b677ef1ebf56d425d22c76f58..01aefd05cfdfc5b0cafe6142340bf9e5604b67db 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -1567,13 +1567,83 @@ void IntraSearch::PLTSearch(CodingStructure &cs, Partitioner& partitioner, Compo
   derivePLTLossy(cs, partitioner, compBegin, numComp);
   reorderPLT(cs, partitioner, compBegin, numComp);
 
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+  bool idxExist[MAXPLTSIZE + 1] = { false };
+#endif
   preCalcPLTIndexRD(cs, partitioner, compBegin, numComp); // Pre-calculate distortions for each pixel 
   double rdCost = MAX_DOUBLE;
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+  deriveIndexMap(cs, partitioner, compBegin, numComp, PLT_SCAN_HORTRAV, rdCost, idxExist); // Optimize palette index map (horizontal scan)
+#else
   deriveIndexMap(cs, partitioner, compBegin, numComp, PLT_SCAN_HORTRAV, rdCost); // Optimize palette index map (horizontal scan)
+#endif
   if ((cu.curPLTSize[compBegin] + cu.useEscape[compBegin]) > 1)
   {
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+    deriveIndexMap(cs, partitioner, compBegin, numComp, PLT_SCAN_VERTRAV, rdCost, idxExist); // Optimize palette index map (vertical scan)
+#else
     deriveIndexMap(cs, partitioner, compBegin, numComp, PLT_SCAN_VERTRAV, rdCost); // Optimize palette index map (vertical scan)
+#endif
+  }
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+  // Remove unused palette entries
+  uint8_t newPLTSize = 0;
+  int idxMapping[MAXPLTSIZE + 1];
+  memset(idxMapping, -1, sizeof(int) * (MAXPLTSIZE + 1));
+  for (int i = 0; i < cu.curPLTSize[compBegin]; i++)
+  {
+    if (idxExist[i])
+    {
+      idxMapping[i] = newPLTSize;
+      newPLTSize++;
+    }
+  }
+  idxMapping[cu.curPLTSize[compBegin]] = cu.useEscape[compBegin]? newPLTSize: -1;
+  if (newPLTSize != cu.curPLTSize[compBegin]) // there exist unused palette entries
+  { // update palette table and reuseflag
+    Pel curPLTtmp[MAX_NUM_COMPONENT][MAXPLTSIZE];
+    int reuseFlagIdx = 0, curPLTtmpIdx = 0, reuseEntrySize = 0;
+    memset(cu.reuseflag[compBegin], false, sizeof(bool) * MAXPLTPREDSIZE);
+    for (int curIdx = 0; curIdx < cu.curPLTSize[compBegin]; curIdx++)
+    {
+      if (idxExist[curIdx])
+      {
+        for (int comp = compBegin; comp < (compBegin + numComp); comp++)
+          curPLTtmp[comp][curPLTtmpIdx] = cu.curPLT[comp][curIdx];
+
+        // Update reuse flags
+        if (curIdx < cu.reusePLTSize[compBegin])
+        {
+          bool match = false;
+          for (; reuseFlagIdx < cs.prevPLT.curPLTSize[compBegin]; reuseFlagIdx++)
+          {
+            bool matchTmp = true;
+            for (int comp = compBegin; comp < (compBegin + numComp); comp++)
+            {
+              matchTmp = matchTmp && (curPLTtmp[comp][curPLTtmpIdx] == cs.prevPLT.curPLT[comp][reuseFlagIdx]);
+            }
+            if (matchTmp)
+            {
+              match = true;
+              break;
+            }
+          }
+          if (match)
+          {
+            cu.reuseflag[compBegin][reuseFlagIdx] = true;
+            reuseEntrySize++;
+          }
+        }
+        curPLTtmpIdx++;
+      }
+    }
+    cu.reusePLTSize[compBegin] = reuseEntrySize;
+    // update palette table
+    cu.curPLTSize[compBegin] = newPLTSize;
+    for (int comp = compBegin; comp < (compBegin + numComp); comp++)
+      memcpy( cu.curPLT[comp], curPLTtmp[comp], sizeof(Pel)*cu.curPLTSize[compBegin]);
   }
+#endif
   cu.useRotation[compBegin] = m_bestScanRotationMode;
   int indexMaxSize = cu.useEscape[compBegin] ? (cu.curPLTSize[compBegin] + 1) : cu.curPLTSize[compBegin];
   if (indexMaxSize <= 1)
@@ -1586,6 +1656,9 @@ void IntraSearch::PLTSearch(CodingStructure &cs, Partitioner& partitioner, Compo
   {
     for (uint32_t x = 0; x < width; x++)
     {
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+      curPLTIdx.at(x, y) = idxMapping[curPLTIdx.at(x, y)];
+#endif
       if (curPLTIdx.at(x, y) == cu.curPLTSize[compBegin])
       {
         calcPixelPred(cs, partitioner, y, x, compBegin, numComp);
@@ -1782,7 +1855,11 @@ void IntraSearch::preCalcPLTIndexRD(CodingStructure& cs, Partitioner& partitione
   }
 }
 
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+void IntraSearch::deriveIndexMap(CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp, PLTScanMode pltScanMode, double& dMinCost, bool* idxExist)
+#else
 void IntraSearch::deriveIndexMap(CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp, PLTScanMode pltScanMode, double& dMinCost)
+#endif
 {
   CodingUnit    &cu = *cs.getCU(partitioner.chType);
   TransformUnit &tu = *cs.getTU(partitioner.chType);
@@ -1905,10 +1982,16 @@ void IntraSearch::deriveIndexMap(CodingStructure& cs, Partitioner& partitioner,
   {
     cu.useEscape[compBegin] = m_bestEscape;
     m_bestScanRotationMode = pltScanMode;
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+    memset(idxExist, false, sizeof(bool) * (MAXPLTSIZE + 1));
+#endif
     for (int pos = 0; pos < (width*height); pos++)
     {
       runIndex[pos] = checkIndexTable[pos];
       runType[pos] = checkRunTable[pos];
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+      idxExist[checkIndexTable[pos]] = true;
+#endif
     }
     dMinCost = sumRdCost;
   }
@@ -2072,16 +2155,32 @@ double IntraSearch::rateDistOptPLT(
       rdCost = MAX_DOUBLE;
       return rdCost;
     }
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+    rdCost += m_pcRdCost->getLambda()*(m_truncBinBits[(runIndex > refIndex) ? runIndex - 1 : runIndex][(scanPos == 0) ? (indexMaxValue + 1) : indexMaxValue] << SCALE_BITS);
+#else
     rdCost += m_pcRdCost->getLambda()*m_truncBinBits[(runIndex > refIndex) ? runIndex - 1 : runIndex][(scanPos == 0) ? (indexMaxValue + 1) : indexMaxValue];
+#endif
   }
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+  rdCost += m_indexError[runIndex][m_scanOrder[scanPos].idx] * (1 << SCALE_BITS);
+#else
   rdCost += m_indexError[runIndex][m_scanOrder[scanPos].idx];
+#endif
   if (scanPos > 0)
   {
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+    rdCost += m_pcRdCost->getLambda()*( identityFlag ? (IndexfracBits[(dist < RUN_IDX_THRE) ? dist : RUN_IDX_THRE].intBits[1]) : (IndexfracBits[(dist < RUN_IDX_THRE) ? dist : RUN_IDX_THRE].intBits[0] ) );
+#else
     rdCost += m_pcRdCost->getLambda()*( identityFlag ? (IndexfracBits[(dist < RUN_IDX_THRE) ? dist : RUN_IDX_THRE].intBits[1] >> SCALE_BITS) : (IndexfracBits[(dist < RUN_IDX_THRE) ? dist : RUN_IDX_THRE].intBits[0] >> SCALE_BITS));
+#endif
   }
   if ( !identityFlag && scanPos >= width && prevRunType != PLT_RUN_COPY )
   {
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+    rdCost += m_pcRdCost->getLambda()*TypefracBits.intBits[runType];
+#else
     rdCost += m_pcRdCost->getLambda()*(TypefracBits.intBits[runType] >> SCALE_BITS);
+#endif
   }
   if (!identityFlag || scanPos == 0)
   {
@@ -2251,7 +2350,15 @@ void IntraSearch::derivePLTLossy(CodingStructure& cs, Partitioner& partitioner,
     }
   }
 
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+  TransformUnit &tu = *cs.getTU(partitioner.chType);
+  QpParam cQP(tu, compBegin);
+  int qp = cQP.Qp(true) - 12;
+  qp = (qp < 0) ? 0 : ((qp > 56) ? 56 : qp);
+  int errorLimit = g_paletteQuant[qp];
+#else
   int errorLimit = g_paletteQuant[cu.qp];
+#endif
   uint32_t totalSize = height*width;
   SortingElement *pelList = new SortingElement[totalSize];
   SortingElement  element;
@@ -2340,6 +2447,11 @@ void IntraSearch::derivePLTLossy(CodingStructure& cs, Partitioner& partitioner,
   }
   const int plt_lambda_shift = (compBegin > 0) ? pcmShiftRight_C : pcmShiftRight_L;
   double    bitCost          = m_pcRdCost->getLambda() / (double) (1 << (2 * plt_lambda_shift)) * numColorBits;
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+  bool   reuseflag[MAXPLTPREDSIZE] = { false };
+  int    run;
+  double reuseflagCost;
+#endif
   for (int i = 0; i < MAXPLTSIZE; i++)
   {
     if (pelListSort[i].getCnt())
@@ -2385,6 +2497,22 @@ void IntraSearch::derivePLTLossy(CodingStructure& cs, Partitioner& partitioner,
             }
           }
           cost *= pelListSort[i].getCnt();
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+          run = 0;
+          for (int t2 = t-1; t2 >= 0; t2--)
+          {
+            if (!reuseflag[t2])
+            {
+              run++;
+            }
+            else
+            {
+              break;
+            }
+          }
+          reuseflagCost = m_pcRdCost->getLambda() / (double)(1 << (2 * plt_lambda_shift)) * getEpExGolombNumBins(run ? run + 1 : run, 0);
+          cost += reuseflagCost;
+#endif
           if (cost < bestCost)
           {
             best = t;
@@ -2397,6 +2525,9 @@ void IntraSearch::derivePLTLossy(CodingStructure& cs, Partitioner& partitioner,
           {
             cu.curPLT[comp][paletteSize] = cs.prevPLT.curPLT[comp][best];
           }
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+          reuseflag[best] = true;
+#endif
         }
       }
 
diff --git a/source/Lib/EncoderLib/IntraSearch.h b/source/Lib/EncoderLib/IntraSearch.h
index 72ccaa02148956bceded9d45694cbe2c7c58baf5..9370c143072ad7548d439be5a43bf1270c020143 100644
--- a/source/Lib/EncoderLib/IntraSearch.h
+++ b/source/Lib/EncoderLib/IntraSearch.h
@@ -453,7 +453,11 @@ protected:
   void   calcPixelPred   (      CodingStructure& cs, Partitioner& partitioner, uint32_t    yPos,      uint32_t xPos,             ComponentID compBegin, uint32_t  numComp);
   void     preCalcPLTIndexRD      (CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp);
   void     calcPixelPredRD        (CodingStructure& cs, Partitioner& partitioner, Pel* orgBuf, Pel* pixelValue, Pel* recoValue, ComponentID compBegin, uint32_t numComp);
+#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX
+  void     deriveIndexMap         (CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp, PLTScanMode pltScanMode, double& dCost, bool* idxExist);
+#else
   void     deriveIndexMap         (CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp, PLTScanMode pltScanMode, double& dCost);
+#endif
   bool     deriveSubblockIndexMap(CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, PLTScanMode pltScanMode, int minSubPos, int maxSubPos, const BinFracBits& fracBitsPltRunType, const BinFracBits* fracBitsPltIndexINDEX, const BinFracBits* fracBitsPltIndexCOPY, const double minCost, bool useRotate);
   double   rateDistOptPLT         (bool RunType, uint8_t RunIndex, bool prevRunType, uint8_t prevRunIndex, uint8_t aboveRunIndex, bool& prevCodedRunType, int& prevCodedRunPos, int scanPos, uint32_t width, int dist, int indexMaxValue, const BinFracBits* IndexfracBits, const BinFracBits& TypefracBits);
   void     initTBCTable           (int bitDepth);