diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp
index cdd826d76c95822b277d94ee9d469bcf4ab68ab9..1a7f7aab297c3d747d237f2c9091f10e2dbc8701 100644
--- a/source/Lib/CommonLib/CodingStructure.cpp
+++ b/source/Lib/CommonLib/CodingStructure.cpp
@@ -207,7 +207,12 @@ const int CodingStructure::signalModeCons( const PartSplit split, Partitioner &p
     minLumaArea = minLumaArea >> 1;
   }
   int minChromaBlock = minLumaArea >> (getChannelTypeScaleX(CHANNEL_TYPE_CHROMA, partitioner.currArea().chromaFormat) + getChannelTypeScaleY(CHANNEL_TYPE_CHROMA, partitioner.currArea().chromaFormat));
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+  bool is2xNChroma = (partitioner.currArea().chromaSize().width == 4 && split == CU_VERT_SPLIT) || (partitioner.currArea().chromaSize().width == 8 && split == CU_TRIV_SPLIT);
+  return minChromaBlock >= 16 && !is2xNChroma ? LDT_MODE_TYPE_INHERIT : ((minLumaArea < 32) || slice->isIntra()) ? LDT_MODE_TYPE_INFER : LDT_MODE_TYPE_SIGNAL;
+#else
   return minChromaBlock >= 16 ? LDT_MODE_TYPE_INHERIT : ((minLumaArea < 32) || slice->isIntra()) ? LDT_MODE_TYPE_INFER : LDT_MODE_TYPE_SIGNAL;
+#endif
 #else
   int width = partitioner.currArea().lwidth();
   int height = partitioner.currArea().lheight();
@@ -219,13 +224,20 @@ const int CodingStructure::signalModeCons( const PartSplit split, Partitioner &p
     else // bt
       return slice->isIntra() ? LDT_MODE_TYPE_INFER : LDT_MODE_TYPE_SIGNAL;
   }
-  else if( width * height == 128 )
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+  else if (((width * height == 128) && (split == CU_TRIH_SPLIT || split == CU_TRIV_SPLIT)) || (width == 8 && split == CU_VERT_SPLIT) || (width == 16 && split == CU_TRIV_SPLIT))
+  {
+    return slice->isIntra() ? LDT_MODE_TYPE_INFER : LDT_MODE_TYPE_SIGNAL;
+  }
+#else
+  else if (width * height == 128)
   {
-    if( split == CU_TRIH_SPLIT || split == CU_TRIV_SPLIT ) // tt
+    if (split == CU_TRIH_SPLIT || split == CU_TRIV_SPLIT) // tt
       return slice->isIntra() ? LDT_MODE_TYPE_INFER : LDT_MODE_TYPE_SIGNAL;
     else // bt
       return LDT_MODE_TYPE_INHERIT;
   }
+#endif
   else
   {
     return LDT_MODE_TYPE_INHERIT;
diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp
index 01295fa4e31ca594aec6b52a1800ac349a7e5c75..263b138ca48d1ef1b2ba5f6d42baac4caa95bb93 100644
--- a/source/Lib/CommonLib/IntraPrediction.cpp
+++ b/source/Lib/CommonLib/IntraPrediction.cpp
@@ -265,6 +265,9 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co
   const ChannelType    channelType  = toChannelType( compID );
   const int            iWidth       = piPred.width;
   const int            iHeight      = piPred.height;
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+  CHECK(iWidth == 2, "Width of 2 is not supported");
+#endif
   const uint32_t       uiDirMode    = isLuma( compId ) && pu.cu->bdpcmMode ? BDPCM_IDX : PU::getFinalIntraMode( pu, channelType );
 
   CHECK( floorLog2(iWidth) < 2 && pu.cs->pcv->noChroma2x2, "Size not allowed" );
@@ -740,6 +743,9 @@ bool IntraPrediction::useDPCMForFirstPassIntraEstimation(const PredictionUnit &p
 void IntraPrediction::geneWeightedPred(const ComponentID compId, PelBuf &pred, const PredictionUnit &pu, Pel *srcBuf)
 {
   const int            width = pred.width;
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+  CHECK(width == 2, "Width of 2 is not supported");
+#endif
   const int            height = pred.height;
   const int            srcStride = width;
   const int            dstStride = pred.stride;
@@ -801,15 +807,24 @@ void IntraPrediction::geneIntrainterPred(const CodingUnit &cu)
 
   initIntraPatternChType(cu, pu->Y());
   predIntraAng(COMPONENT_Y, cu.cs->getPredBuf(*pu).Y(), *pu);
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+  if (pu->chromaSize().width > 2)
+  {
+#endif
+    initIntraPatternChType(cu, pu->Cb());
+    predIntraAng(COMPONENT_Cb, cu.cs->getPredBuf(*pu).Cb(), *pu);
 
-  initIntraPatternChType(cu, pu->Cb());
-  predIntraAng(COMPONENT_Cb, cu.cs->getPredBuf(*pu).Cb(), *pu);
-
-  initIntraPatternChType(cu, pu->Cr());
-  predIntraAng(COMPONENT_Cr, cu.cs->getPredBuf(*pu).Cr(), *pu);
-
+    initIntraPatternChType(cu, pu->Cr());
+    predIntraAng(COMPONENT_Cr, cu.cs->getPredBuf(*pu).Cr(), *pu);
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+  }
+#endif
   for (int currCompID = 0; currCompID < 3; currCompID++)
   {
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+    if (pu->chromaSize().width <= 2 && currCompID > 0)
+      continue;
+#endif
     ComponentID currCompID2 = (ComponentID)currCompID;
     PelBuf tmpBuf = currCompID == 0 ? cu.cs->getPredBuf(*pu).Y() : (currCompID == 1 ? cu.cs->getPredBuf(*pu).Cb() : cu.cs->getPredBuf(*pu).Cr());
     switchBuffer(*pu, currCompID2, tmpBuf, getPredictorPtr2(currCompID2, 0));
@@ -824,6 +839,9 @@ inline int  isBelowLeftAvailable  ( const CodingUnit &cu, const ChannelType &chT
 
 void IntraPrediction::initIntraPatternChType(const CodingUnit &cu, const CompArea &area, const bool forceRefFilterFlag)
 {
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+  CHECK(area.width == 2, "Width of 2 is not supported");
+#endif
   const CodingStructure& cs   = *cu.cs;
 
   if (!forceRefFilterFlag)
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index e77565e139e99e6010b485ee6160203043cb6465..579b04df078b99fd9214e84a2ae3e8c90e2b9e85 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_P0641_REMOVE_2xN_CHROMA_INTRA                1 // JVET-P0641: removing 2xN chroma intra blocks
+
 #define JVET_P0206_TMVP_flags                             1 // JVET-P0206: Signalling TMVP usage (remove pps TMVP idc and constraint when RPR is used)
 
 #define JVET_P0599_INTRA_SMOOTHING_INTERP_FILT            1 // JVET-P0599: Cleanup of interpolation filtering for intra prediction
diff --git a/source/Lib/CommonLib/UnitPartitioner.cpp b/source/Lib/CommonLib/UnitPartitioner.cpp
index 362ba8e22d1465a60e781bc1dc8f23ea307048aa..68bf1fda14047ca3eaafba5c5bbc86b51da5f2e5 100644
--- a/source/Lib/CommonLib/UnitPartitioner.cpp
+++ b/source/Lib/CommonLib/UnitPartitioner.cpp
@@ -395,7 +395,9 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca
 
     canBh = implicitSplit == CU_HORZ_SPLIT;
     canBv = implicitSplit == CU_VERT_SPLIT;
-
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+    if (chType == CHANNEL_TYPE_CHROMA && areaC.width == 4) canBv = false;
+#endif
     return;
   }
 
@@ -434,7 +436,11 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca
   if( chType == CHANNEL_TYPE_CHROMA && areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE )     canBh = false;
   if( area.width <= minBtSize )                              canBv = false;
   if( area.width <= MAX_TB_SIZEY && area.height > MAX_TB_SIZEY ) canBv = false;
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+  if (chType == CHANNEL_TYPE_CHROMA && (areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE || areaC.width == 4))     canBv = false;
+#else
   if( chType == CHANNEL_TYPE_CHROMA && areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE )     canBv = false;
+#endif
 #if JVET_P0063_LDT_SPLIT_FIX
   if( modeType == MODE_TYPE_INTER && area.width * area.height == 32 )  canBv = canBh = false;
 #endif
@@ -445,7 +451,11 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca
   if( area.width <= 2 * minTtSize || area.width > maxTtSize || area.height > maxTtSize )
                                                                                        canTv = false;
   if( area.width > MAX_TB_SIZEY || area.height > MAX_TB_SIZEY )  canTv = false;
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+  if (chType == CHANNEL_TYPE_CHROMA && (areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE * 2 || areaC.width == 8))     canTv = false;
+#else
   if( chType == CHANNEL_TYPE_CHROMA && areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE*2 )     canTv = false;
+#endif
 #if JVET_P0063_LDT_SPLIT_FIX
   if( modeType == MODE_TYPE_INTER && area.width * area.height == 64 )  canTv = canTh = false;
 #endif
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 32db51ed89858f27fb5167a470861ac3a050b3e2..13ae6e5be9330fef0fdde60bd9f7236bfc2337d1 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -574,8 +574,15 @@ void DecCu::xReconInter(CodingUnit &cu)
       cu.cs->getPredBuf(*cu.firstPU).Y().rspSignal(m_pcReshape->getFwdLUT());
     }
     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));
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+    if (cu.chromaSize().width > 2)
+    {
+#endif
+      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));
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+    }
+#endif
   }
 
   DTRACE    ( g_trace_ctx, D_TMP, "pred " );
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 5788126d7cb38d387640999f02417e23b7daed78..4a2c2e88a7586e1d2fb16a10785eab9348c0cf90 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -2575,6 +2575,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
           {
             pu.intraDir[0] = PLANAR_IDX;
             pu.intraDir[1] = DM_CHROMA_IDX;
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+            if (pu.chromaSize().width == 2)
+              continue;
+#endif
             uint32_t bufIdx = 0;
             m_pcIntraSearch->initIntraPatternChType(*pu.cu, pu.Cb());
             m_pcIntraSearch->predIntraAng(COMPONENT_Cb, pu.cs->getPredBuf(pu).Cb(), pu);
@@ -2713,12 +2717,26 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             tmpBuf.rspSignal(m_pcReshape->getFwdLUT());
           }
           m_pcIntraSearch->geneWeightedPred(COMPONENT_Y, tmpBuf, pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, bufIdx));
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+          if (pu.chromaSize().width > 2)
+          {
+#endif
           tmpBuf = tempCS->getPredBuf(pu).Cb();
           tmpBuf.copyFrom(acMergeTmpBuffer[uiMergeCand].Cb());
           m_pcIntraSearch->geneWeightedPred(COMPONENT_Cb, tmpBuf, pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Cb, bufIdx));
           tmpBuf = tempCS->getPredBuf(pu).Cr();
           tmpBuf.copyFrom(acMergeTmpBuffer[uiMergeCand].Cr());
           m_pcIntraSearch->geneWeightedPred(COMPONENT_Cr, tmpBuf, pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Cr, bufIdx));
+#if JVET_P0641_REMOVE_2xN_CHROMA_INTRA
+          }
+          else
+          {
+            tmpBuf = tempCS->getPredBuf(pu).Cb();
+            tmpBuf.copyFrom(acMergeTmpBuffer[uiMergeCand].Cb());
+            tmpBuf = tempCS->getPredBuf(pu).Cr();
+            tmpBuf.copyFrom(acMergeTmpBuffer[uiMergeCand].Cr());
+          }
+#endif
         }
         else
         {