diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index 58b58c50d1dbd7faaf7f626666d440d858292116..098535c725f87b510d719d719163803a238e9e8d 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -5707,12 +5707,13 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries
   Specifies the purpose of the \emph{i}-th neural network post-filter.
   \par
   \begin{tabular}{cp{0.35\textwidth}}
-    0 & Unknown or unspecified \\
-    1 & Visual quality improvement \\
-    2 & Chroma upsampling from the 4:2:0 chroma format to the 4:2:2 or 4:4:4 chroma format, or from the 4:2:2 chroma format to the 4:4:4 chroma format \\
-    3 & Increasing the width or height of the cropped decoded output picture without changing the chroma format \\
-    4 & Increasing the width or height of the cropped decoded output picture and upsampling the chroma format \\
-    5 & Frame rate upsampling \\
+    0 & Determined by the application \\
+    (nnpfc\_purpose \& 0x01)  !=  0 & Visual quality improvement \\
+    (nnpfc\_purpose \& 0x02)  !=  0 & Chroma upsampling from the 4:2:0 chroma format to the 4:2:2 or 4:4:4 chroma format, or from the 4:2:2 chroma format to the 4:4:4 chroma format \\
+    (nnpfc\_purpose \& 0x04)  !=  0 & Resolution upsampling (increasing the width or height) \\
+    (nnpfc\_purpose \& 0x08)  !=  0 & Frame rate upsampling \\
+    (nnpfc\_purpose \& 0x10)  !=  0 & Bit depth upsampling \\
+    (nnpfc\_purpose \& 0x20)  !=  0 & Colourization \\
   \end{tabular}
   \\
   \Option{SEINNPostFilterCharacteristicsOutSubCFlag\emph{i}} &
@@ -5725,6 +5726,16 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries
     \end{tabular}
     \\
   \\
+  \Option{SEINNPostFilterCharacteristicsOutColourFormatIdc\emph{i}} &
+  \Default{0} &
+  Specifies the colour format of the NNPF output.
+  \par
+  \begin{tabular}{cp{0.35\textwidth}}
+    1 & The colour format of the NNPF output is the 4:2:0 format \\
+    2 & The colour format of the NNPF output is the 4:2:2 format \\
+    3 & The colour format of the NNPF output is the 4:4:4 format \\
+  \end{tabular}
+  \\
   \Option{SEINNPostFilterCharacteristicsPicWidthInLumaSamples\emph{i}} &
   \Default{0} &
   Specifies the horizontal luma sample counts of the output picture for the \emph{i}-th neural network post-filter.
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 2ac877aa4d76111fa403d31d42cbb8bbf9d9372c..411e580fb9d29f214ae3121f4c9728ae34aa9f72 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -1191,6 +1191,12 @@ void EncApp::xInitLibCfg( int layerIdx )
       {
         m_cEncLib.setNNPostFilterSEICharacteristicsOutSubCFlag(m_nnPostFilterSEICharacteristicsOutSubCFlag[i], i);
       }
+#if JVET_AC0154
+      if ((m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) & NNPC_PurposeType::COLOURIZATION) != 0)
+      {
+        m_cEncLib.setNNPostFilterSEICharacteristicsOutColourFormatIdc(ChromaFormat(m_nnPostFilterSEICharacteristicsOutColourFormatIdc[i]), i);
+      }
+#endif
       if (m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) == 3  || m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) == 4)
       {
         m_cEncLib.setNNPostFilterSEICharacteristicsPicWidthInLumaSamples   (m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[i], i);
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 374637333c6138e60151b479fe0b5eb404ef902f..4e0779f507c94b0aef1377172ffe5ff9e9d0a8a9 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1754,6 +1754,12 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     outSubWidthCFlag << "SEINNPostFilterCharacteristicsOutSubCFlag" << i;
     opts.addOptions()(outSubWidthCFlag.str(), m_nnPostFilterSEICharacteristicsOutSubCFlag[i], false, "Specifies output chroma format when upsampling");
 
+#if JVET_AC0154
+    std::ostringstream outColourFormatIdc;
+    outColourFormatIdc << "SEINNPostFilterCharacteristicsOutColourFormatIdc" << i;
+    opts.addOptions()(outColourFormatIdc.str(), m_nnPostFilterSEICharacteristicsOutColourFormatIdc[i], 1u, "Specifies output chroma format for colourization purpose");
+#endif
+
     std::ostringstream picWidthInLumaSamples;
     picWidthInLumaSamples << "SEINNPostFilterCharacteristicsPicWidthInLumaSamples" << i;
     opts.addOptions()(picWidthInLumaSamples.str(), m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[i], 0u, "Specifies the horizontal luma sample counts of the output picture in the Neural Network Post Filter Characteristics SEI message");
@@ -4900,7 +4906,12 @@ bool EncAppCfg::xCheckParameter()
       xConfirmPara(m_nnPostFilterSEICharacteristicsPaddingType[i] > (1 << 4) - 1, "SEINNPostFilterPaddingType must be in the range of 0 to 2^4-1");
       xConfirmPara(m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[i] > 3, "SEINNPostFilterCharacteristicsLog2ParameterBitLengthMinus3 must be in the range of 0 to 3");
       xConfirmPara(m_nnPostFilterSEICharacteristicsNumParametersIdc[i] > 52, "SEINNPostFilterCharacteristicsNumParametersIdc must be in the range of 0 to 52");
+#if JVET_AC0154
+      xConfirmPara(m_nnPostFilterSEICharacteristicsTotalKilobyteSize[i] > (uint32_t) (((uint64_t) 1 << 32) - 2), "SEINNPostFilterCharacteristicsTotalKilobyteSize must be in the range of 0 to 2^32-2");
+      xConfirmPara(m_nnPostFilterSEICharacteristicsNumKmacOperationsIdc[i] > (uint32_t) (((uint64_t) 1 << 32) - 2), "SEICharacteristicsNumKmacOperationsIdc must be in the range of 0 to 2^32-2");
+#else
       xConfirmPara(m_nnPostFilterSEICharacteristicsTotalKilobyteSize[i] > (uint32_t) (((uint64_t) 1 << 32) - 1), "SEINNPostFilterCharacteristicsTotalKilobyteSize must be in the range of 0 to 2^32-1");
+#endif
     }
   }
 
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index af600ac7e724142917c0bea90ecaaa5c963b03c6..d771a4091ffe720285000738d1de58b02b89725b 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -735,6 +735,9 @@ protected:
   bool                  m_nnPostFilterSEICharacteristicsPurposeAndFormattingFlag[MAX_NUM_NN_POST_FILTERS];
   uint32_t              m_nnPostFilterSEICharacteristicsPurpose[MAX_NUM_NN_POST_FILTERS];
   bool                  m_nnPostFilterSEICharacteristicsOutSubCFlag[MAX_NUM_NN_POST_FILTERS];
+#if JVET_AC0154
+  uint32_t              m_nnPostFilterSEICharacteristicsOutColourFormatIdc[MAX_NUM_NN_POST_FILTERS];
+#endif
   uint32_t              m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[MAX_NUM_NN_POST_FILTERS];
   uint32_t              m_nnPostFilterSEICharacteristicsPicHeightInLumaSamples[MAX_NUM_NN_POST_FILTERS];
   uint32_t              m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[MAX_NUM_NN_POST_FILTERS];
diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h
index b25f7c3284313d8686bf4a3c49981873fce16583..18b901c8935fa0405bd521cbc17e0a7438fda847 100644
--- a/source/Lib/CommonLib/SEI.h
+++ b/source/Lib/CommonLib/SEI.h
@@ -1165,6 +1165,9 @@ public:
     , m_outSubCFlag(0)
     , m_outSubWidthC(1)
     , m_outSubHeightC(1)
+#if JVET_AC0154
+    , m_outColourFormatIdc(ChromaFormat::CHROMA_420)
+#endif
     , m_picWidthInLumaSamples(0)
     , m_picHeightInLumaSamples(0)
     , m_inpTensorBitDepthMinus8(0)
@@ -1214,6 +1217,9 @@ public:
   bool           m_outSubCFlag;
   uint8_t        m_outSubWidthC;
   uint8_t        m_outSubHeightC;
+  #if JVET_AC0154
+  ChromaFormat   m_outColourFormatIdc;
+  #endif
   uint32_t       m_picWidthInLumaSamples;
   uint32_t       m_picHeightInLumaSamples;
   uint32_t       m_inpTensorBitDepthMinus8;
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index adbd4439429cd0f934f242c205f14f60b8f18cd6..8fa448a6b428ab7f57bad79a8170e03aeed46597 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -58,7 +58,7 @@
 
 #define JVET_AC0139_UNIFIED_MERGE                         1
 #define JVET_AC0096                                       1
-
+#define JVET_AC0154                                       1
 //########### place macros to be be kept below this line ###############
 
 #define GDR_ENABLED   1
@@ -761,6 +761,18 @@ enum NNPC_PaddingType
   FIXED_PADDING = 4
 };
 
+#if JVET_AC0154
+enum NNPC_PurposeType
+{
+  UNKONWN                    = 0,
+  VISUAL_QUALITY_IMPROVEMENT = 1,
+  CHROMA_UPSAMPLING          = 2,
+  RESOLUTION_UPSAMPLING      = 4,
+  FRAME_RATE_UPSAMPLING      = 8,
+  BIT_DEPTH_UPSAMPLING       = 16,
+  COLOURIZATION              = 32
+};
+#else
 enum NNPC_PurposeType
 {
   UNKONWN = 0,
@@ -768,8 +780,9 @@ enum NNPC_PurposeType
   CHROMA_UPSAMPLING = 2,
   INCREASE_PICT_DIMENSION_WITHOUT_CHROMA_UPSAMPLING = 3,
   INCREASE_PICT_DIMENSION_WITH_CHROMA_UPSMAPLING = 4,
-  FRANE_RATE_UPSAMPLING = 5
+  FRAME_RATE_UPSAMPLING = 5
 };
+#endif
 
 enum POST_FILTER_MODE
 {
diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp
index 9148e46ef658e7a22cb0eaa898a35cb479fdeffb..d394a022ef4055105802ba649c7c1db728d7aa4a 100644
--- a/source/Lib/DecoderLib/SEIread.cpp
+++ b/source/Lib/DecoderLib/SEIread.cpp
@@ -2719,13 +2719,37 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC
         sei.m_outSubHeightC = 1;
       }
     }
+#if !JVET_AC0154
     else
     {
       sei.m_outSubWidthC  = subWidthC;
       sei.m_outSubHeightC = subHeightC;
     }
+#endif
     CHECK(((subWidthC == 1) && (subHeightC == 1)) && ((sei.m_purpose == 2) || (sei.m_purpose == 4)),
           "If SubWidthC is equal to 1 and SubHeightC is equal to 1, nnpfc_purpose shall not be equal to 2 or 4");
+
+#if JVET_AC0154
+    if((sei.m_purpose & NNPC_PurposeType::COLOURIZATION) != 0)
+    {
+      CHECK(((chromaFormatIDC != ChromaFormat::CHROMA_400) || (sei.m_purpose & NNPC_PurposeType::CHROMA_UPSAMPLING) != 0),
+          "When ChromaFormatIdc or nnpfc_purpose & 0x02 is not equal to 0, nnpfc_purpose & 0x20 shall be equal to 0");
+
+      sei_read_code(pDecodedMessageOutputStream, 2, val, "nnpfc_out_colour_format_idc");
+      sei.m_outColourFormatIdc = ChromaFormat(val);
+      CHECK(sei.m_outColourFormatIdc == 0, "The value of nnpfc_out_colour_format_idc shall not be equal to 0");
+
+      sei.m_outSubWidthC  = SPS::getWinUnitX(sei.m_outColourFormatIdc);
+      sei.m_outSubHeightC = SPS::getWinUnitY(sei.m_outColourFormatIdc);
+    }
+
+    if (((sei.m_purpose & NNPC_PurposeType::CHROMA_UPSAMPLING) == 0) && ((sei.m_purpose & NNPC_PurposeType::COLOURIZATION) == 0))
+    {
+      sei.m_outSubWidthC  = subWidthC;
+      sei.m_outSubHeightC = subHeightC;
+    }
+#endif
+
     if(sei.m_purpose == 3 || sei.m_purpose == 4)
     {
       sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_pic_width_in_luma_samples");
@@ -2734,16 +2758,30 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC
       sei.m_picHeightInLumaSamples = val;
     }
     
-    if (sei.m_purpose == NNPC_PurposeType::FRANE_RATE_UPSAMPLING)
+    if (sei.m_purpose == NNPC_PurposeType::FRAME_RATE_UPSAMPLING)
     {
       sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_number_of_input_pictures_minus2");
       sei.m_numberInputDecodedPicturesMinus2 = val;
       sei.m_numberInterpolatedPictures.resize(sei.m_numberInputDecodedPicturesMinus2 + 1);
+#if JVET_AC0154
+      bool allZeroFlag = false;
+      for (int i = 0; i < sei.m_numberInterpolatedPictures.size(); i++)
+      {
+        sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_interpolated_pictures");
+        sei.m_numberInterpolatedPictures[i] = val;
+        if(sei.m_numberInterpolatedPictures[i] > 0)
+        {
+          allZeroFlag = true;
+        }
+      }
+      CHECK(!allZeroFlag, "At least one value of nnpfc_interpolated_pics[i] shall be greater than 0");
+#else
       for (int i = 0; i < sei.m_numberInterpolatedPictures.size(); i++)
       {
         sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_interpolated_pictures");
         sei.m_numberInterpolatedPictures[i] = val;
       }
+#endif
     }
 
     sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_component_last_flag");
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index f321b4f3e16193fdc3dbce27003d5ea06c4ed8d4..31cfb14c290892d3abd776cfbf29f353916c2583 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -691,6 +691,9 @@ protected:
   bool                    m_nnPostFilterSEICharacteristicsPurposeAndFormattingFlag[MAX_NUM_NN_POST_FILTERS];
   uint32_t                m_nnPostFilterSEICharacteristicsPurpose[MAX_NUM_NN_POST_FILTERS];
   bool                    m_nnPostFilterSEICharacteristicsOutSubCFlag[MAX_NUM_NN_POST_FILTERS];
+#if JVET_AC0154
+  ChromaFormat            m_nnPostFilterSEICharacteristicsOutColourFormatIdc[MAX_NUM_NN_POST_FILTERS];
+#endif
   uint32_t                m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[MAX_NUM_NN_POST_FILTERS];
   uint32_t                m_nnPostFilterSEICharacteristicsPicHeightInLumaSamples[MAX_NUM_NN_POST_FILTERS];
   uint32_t                m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[MAX_NUM_NN_POST_FILTERS];
@@ -1889,6 +1892,10 @@ public:
 
   void        setNNPostFilterSEICharacteristicsOutSubCFlag(bool SubCFlag, int filterIdx) { m_nnPostFilterSEICharacteristicsOutSubCFlag[filterIdx] = SubCFlag; }
   bool        getNNPostFilterSEICharacteristicsOutSubCFlag(int filterIdx) const { return m_nnPostFilterSEICharacteristicsOutSubCFlag[filterIdx]; }
+#if JVET_AC0154
+  void        setNNPostFilterSEICharacteristicsOutColourFormatIdc(ChromaFormat outColourFormatIdc, int filterIdx)     { m_nnPostFilterSEICharacteristicsOutColourFormatIdc[filterIdx] = outColourFormatIdc; }
+  ChromaFormat getNNPostFilterSEICharacteristicsOutColourFormatIdc(int filterIdx) const                               { return m_nnPostFilterSEICharacteristicsOutColourFormatIdc[filterIdx]; }
+#endif 
   void        setNNPostFilterSEICharacteristicsPicWidthInLumaSamples(uint32_t picWidthInLumaSamples, int filterIdx)     { m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[filterIdx] = picWidthInLumaSamples; }
   uint32_t    getNNPostFilterSEICharacteristicsPicWidthInLumaSamples(int filterIdx) const                               { return m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[filterIdx]; }
   void        setNNPostFilterSEICharacteristicsPicHeightInLumaSamples(uint32_t picHeightInLumaSamples, int filterIdx)   { m_nnPostFilterSEICharacteristicsPicHeightInLumaSamples[filterIdx] = picHeightInLumaSamples; }
diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp
index 4e96a2c3c9d79053cd241347bfe81d1d6ba4c9b1..6f92e4ed785a799b38061223e351900609aaf10a 100644
--- a/source/Lib/EncoderLib/SEIEncoder.cpp
+++ b/source/Lib/EncoderLib/SEIEncoder.cpp
@@ -1312,6 +1312,12 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP
     {
       sei->m_outSubCFlag = m_pcCfg->getNNPostFilterSEICharacteristicsOutSubCFlag(filterIdx);
     }
+#if JVET_AC0154
+    if((sei->m_purpose & NNPC_PurposeType::COLOURIZATION) != 0)
+    {
+      sei->m_outColourFormatIdc = m_pcCfg->getNNPostFilterSEICharacteristicsOutColourFormatIdc(filterIdx);
+    }
+#endif
     if(sei->m_purpose == 3 || sei->m_purpose == 4)
     {
       sei->m_picWidthInLumaSamples = m_pcCfg->getNNPostFilterSEICharacteristicsPicWidthInLumaSamples(filterIdx);
@@ -1346,7 +1352,7 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP
       CHECK(!(sei->m_picWidthInLumaSamples >= croppedWidth && sei->m_picWidthInLumaSamples <= croppedWidth * 16 - 1), "m_picWidthInLumaSamples shall be in the range of croppedWidth to croppedWidth * 16 - 1");
       CHECK(!(sei->m_picHeightInLumaSamples >= croppedHeight && sei->m_picHeightInLumaSamples <= croppedHeight * 16 - 1), "m_picHeightInLumaSamples shall be in the range of croppedHeight to croppedHeight * 16 - 1");
     }
-    if (sei->m_purpose == NNPC_PurposeType::FRANE_RATE_UPSAMPLING)
+    if (sei->m_purpose == NNPC_PurposeType::FRAME_RATE_UPSAMPLING)
     {
       sei->m_numberInputDecodedPicturesMinus2 = m_pcCfg->getNNPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2(filterIdx);
       sei->m_numberInterpolatedPictures = m_pcCfg->getNNPostFilterSEICharacteristicsNumberInterpolatedPictures(filterIdx);
diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp
index 159dc6d224421a93050508672bf6f648d4cc8cbf..5be7b918e523fa4620ca2ae873302cdcea417911 100644
--- a/source/Lib/EncoderLib/SEIwrite.cpp
+++ b/source/Lib/EncoderLib/SEIwrite.cpp
@@ -1700,6 +1700,12 @@ void SEIWriter::xWriteSEINeuralNetworkPostFilterCharacteristics(const SEINeuralN
     {
       xWriteFlag(sei.m_outSubCFlag, "nnpfc_out_sub_c_flag");
     }
+#if JVET_AC0154
+    if((sei.m_purpose & NNPC_PurposeType::COLOURIZATION) != 0)
+    {
+      xWriteCode(uint32_t(sei.m_outColourFormatIdc), 2, "nnpfc_out_colour_format_idc");
+    }
+#endif
     if(sei.m_purpose == 3 || sei.m_purpose == 4)
     {
       xWriteUvlc(sei.m_picWidthInLumaSamples, "nnpfc_pic_width_in_luma_samples");