diff --git a/CMakeLists.txt b/CMakeLists.txt
index bfd765376da7ba8eae364b2be82c3d84237875da..27c22601a3200a7dc46e9e1c4fae7c027c21dd6f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,6 +28,7 @@ if( CMAKE_SYSTEM_NAME STREQUAL "Linux" )
 endif()
 
 set( EXTENSION_360_VIDEO OFF CACHE BOOL "If EXTENSION_360_VIDEO is on, 360Lib will be added" )
+set( EXTENSION_HDRTOOLS OFF CACHE BOOL "If EXTENSION_HDRTOOLS is on, HDRLib will be added" )
 set( SET_ENABLE_TRACING OFF CACHE BOOL "Set ENABLE_TRACING as a compiler flag" )
 set( ENABLE_TRACING OFF CACHE BOOL "If SET_ENABLE_TRACING is on, it will be set to this value" )
 
@@ -136,6 +137,9 @@ if( EXTENSION_360_VIDEO )
   add_subdirectory( "source/Lib/Lib360" )
   add_subdirectory( "source/Lib/AppEncHelper360" )
 endif()
+if ( EXTENSION_HDRTOOLS )
+  add_subdirectory( "source/Lib/HDRLib")
+endif()
 add_subdirectory( "source/Lib/DecoderAnalyserLib" )
 add_subdirectory( "source/Lib/DecoderLib" )
 add_subdirectory( "source/Lib/EncoderLib" )
diff --git a/source/App/EncoderApp/CMakeLists.txt b/source/App/EncoderApp/CMakeLists.txt
index 2299bcf8f1987839181ad36b53cba3e95c844042..dd87e52d1f8244c607c34d42359dd0595e63cd88 100644
--- a/source/App/EncoderApp/CMakeLists.txt
+++ b/source/App/EncoderApp/CMakeLists.txt
@@ -66,6 +66,10 @@ if( EXTENSION_360_VIDEO )
   target_link_libraries( ${EXE_NAME} Lib360 AppEncHelper360 )
 endif()
 
+if( EXTENSION_HDRTOOLS )
+  target_link_libraries( ${EXE_NAME} HDRLib )
+endif()
+
 # lldb custom data formatters
 if( XCODE )
   add_dependencies( ${EXE_NAME} Install${PROJECT_NAME}LldbFiles )
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 9e6bfb2080662d270dc587e2c5dbc4a870578761..5b32d68e688ce80f3e8de6a95a2d9ba230ca2794 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -62,6 +62,9 @@ EncApp::EncApp()
   m_iFrameRcvd = 0;
   m_totalBytes = 0;
   m_essentialBytes = 0;
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  m_metricTime = std::chrono::milliseconds(0);
+#endif
 }
 
 EncApp::~EncApp()
@@ -607,6 +610,25 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setReshapeSignalType                                 ( m_reshapeSignalType );
   m_cEncLib.setReshapeIntraCMD                                   ( m_intraCMD );
   m_cEncLib.setReshapeCW                                         ( m_reshapeCW );
+  
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  for (int i=0; i<hdrtoolslib::NB_REF_WHITE; i++) {
+    m_cEncLib.setWhitePointDeltaE                                (i, m_whitePointDeltaE[i] );
+  }
+  m_cEncLib.setMaxSampleValue                                    (m_maxSampleValue);
+  m_cEncLib.setSampleRange                                       (m_sampleRange);
+  m_cEncLib.setColorPrimaries                                    (m_colorPrimaries);
+  m_cEncLib.setEnableTFunctionLUT                                (m_enableTFunctionLUT);
+  for (int i=0; i<2; i++) {
+  m_cEncLib.setChromaLocation                                    (i, m_chromaLocation);
+  m_cEncLib.setChromaUPFilter                                    (m_chromaUPFilter);
+  }
+  m_cEncLib.setCropOffsetLeft                                    (m_cropOffsetLeft);
+  m_cEncLib.setCropOffsetTop                                     (m_cropOffsetTop);
+  m_cEncLib.setCropOffsetRight                                   (m_cropOffsetRight);
+  m_cEncLib.setCropOffsetBottom                                  (m_cropOffsetBottom);
+  m_cEncLib.setCalculateHdrMetrics                               (m_calculateHdrMetrics);
+#endif
 }
 
 void EncApp::xCreateLib( std::list<PelUnitBuf*>& recBufList
@@ -743,11 +765,17 @@ void EncApp::encode()
     {
       m_cEncLib.encode( bEos, flush ? 0 : &orgPic, flush ? 0 : &trueOrgPic, snrCSC, recBufList,
                         iNumEncoded, m_isTopFieldFirst );
+#if JVET_O0756_CALCULATE_HDRMETRICS
+      m_metricTime = m_cEncLib.m_metricTime;
+#endif
     }
     else
     {
       m_cEncLib.encode( bEos, flush ? 0 : &orgPic, flush ? 0 : &trueOrgPic, snrCSC, recBufList,
                         iNumEncoded );
+#if JVET_O0756_CALCULATE_HDRMETRICS
+      m_metricTime = m_cEncLib.m_metricTime;
+#endif
     }
 
     // write bistream to file if necessary
diff --git a/source/App/EncoderApp/EncApp.h b/source/App/EncoderApp/EncApp.h
index 146e9dc4a30b209fdf0baf2f33d8aeea21a14177..2d91d85b895347fcd53b7f4a5e4701accbc1c75c 100644
--- a/source/App/EncoderApp/EncApp.h
+++ b/source/App/EncoderApp/EncApp.h
@@ -65,6 +65,10 @@ private:
   uint32_t              m_essentialBytes;
   uint32_t              m_totalBytes;
   fstream           m_bitstream;
+public:
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  std::chrono::duration<long long, ratio<1, 1000000000>> m_metricTime;
+#endif
 
 private:
   // initialization
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index ae65cdc3176e1e1d2c9fb1d8159f17a29b8c74dd..256d62bdce559e3f2ca8a8d831ea1085e7110255 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -833,6 +833,23 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("SummaryPicFilenameBase",                          m_summaryPicFilenameBase,                      string(), "Base filename to use for producing summary picture output files. The actual filenames used will have I.txt, P.txt and B.txt appended. If empty, do not produce a file.")
   ("SummaryVerboseness",                              m_summaryVerboseness,                                0u, "Specifies the level of the verboseness of the text output")
   ("Verbosity,v",                                     m_verbosity,                               (int)VERBOSE, "Specifies the level of the verboseness")
+  
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  ( "WhitePointDeltaE1",                              m_whitePointDeltaE[0],                            100.0, "1st reference white point value")
+  ( "WhitePointDeltaE2",                              m_whitePointDeltaE[1],                           1000.0, "2nd reference white point value")
+  ( "WhitePointDeltaE3",                              m_whitePointDeltaE[2],                           5000.0, "3rd reference white point value")
+  ( "MaxSampleValue",                                 m_maxSampleValue,                               10000.0, "Maximum sample value for floats")
+  ( "InputSampleRange",                               m_sampleRange,                                        0, "Sample Range")
+  ( "InputColorPrimaries",                            m_colorPrimaries,                                     1, "Input Color Primaries")
+  ( "EnableTFunctionLUT",                             m_enableTFunctionLUT,                             false, "Input Color Primaries")
+  ( "ChromaLocation",                                 m_chromaLocation,                                     2, "Location of Chroma Samples")
+  ( "ChromaUpsampleFilter",                           m_chromaUPFilter,                                     1, "420 to 444 conversion filters")
+  ( "CropOffsetLeft",                                 m_cropOffsetLeft,                                     0, "Crop Offset Left position")
+  ( "CropOffsetTop",                                  m_cropOffsetTop,                                      0, "Crop Offset Top position")
+  ( "CropOffsetRight",                                m_cropOffsetRight,                                    0, "Crop Offset Right position")
+  ( "CropOffsetBottom",                               m_cropOffsetBottom,                                   0, "Crop Offset Bottom position")
+  ( "CalculateHdrMetrics",                            m_calculateHdrMetrics,                             true, "Crop Offset Bottom position")
+#endif
 
   //Field coding parameters
   ("FieldCoding",                                     m_isField,                                        false, "Signals if it's a field based coding")
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index ebfc9e723a501e0d4ab3d4a79f75449e885a2f7e..f84cca58e48b90ea7ec15449da348ab7436566da 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -44,6 +44,11 @@
 #if EXTENSION_360_VIDEO
 #include "AppEncHelper360/TExt360AppEncCfg.h"
 #endif
+
+#if JVET_O0756_CALCULATE_HDRMETRICS
+#include "HDRLib/inc/DistortionMetric.H"
+#endif
+
 #include <sstream>
 #include <vector>
 //! \ingroup EncoderApp
@@ -602,6 +607,20 @@ protected:
   friend class TExt360AppEncTop;
 #endif
 
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  double      m_whitePointDeltaE[hdrtoolslib::NB_REF_WHITE];
+  double      m_maxSampleValue;
+  int         m_sampleRange;
+  int         m_colorPrimaries;
+  bool        m_enableTFunctionLUT;
+  int         m_chromaLocation;
+  int         m_chromaUPFilter;
+  int         m_cropOffsetLeft;
+  int         m_cropOffsetTop;
+  int         m_cropOffsetRight;
+  int         m_cropOffsetBottom;
+  bool        m_calculateHdrMetrics;
+#endif
 
   // internal member functions
   bool  xCheckParameter ();                                   ///< check validity of configuration values
diff --git a/source/App/EncoderApp/encmain.cpp b/source/App/EncoderApp/encmain.cpp
index 444c6aff32bce814cc0e227a38a7d60eeff4acc3..b53a822e76b21ff6a6e4425e226d43efd31f5463 100644
--- a/source/App/EncoderApp/encmain.cpp
+++ b/source/App/EncoderApp/encmain.cpp
@@ -168,7 +168,14 @@ int main(int argc, char* argv[])
   clock_t endClock = clock();
   auto endTime = std::chrono::steady_clock::now();
   std::time_t endTime2 = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
-  auto encTime = std::chrono::duration_cast<std::chrono::milliseconds>( endTime- startTime ).count();
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  auto metricTime = pcEncApp->m_metricTime;
+  auto totalTime = std::chrono::duration_cast<std::chrono::milliseconds>( endTime- startTime ).count();
+  auto encTime = std::chrono::duration_cast<std::chrono::milliseconds>( endTime- startTime - metricTime ).count();
+  auto metricTimeuser = std::chrono::duration_cast<std::chrono::milliseconds>( metricTime ).count();
+#else
+  auto encTime = std::chrono::duration_cast<std::chrono::milliseconds>( endTime- startTime).count();
+#endif
   // destroy application encoder class
   pcEncApp->destroy();
 
@@ -176,9 +183,17 @@ int main(int argc, char* argv[])
 
   printf( "\n finished @ %s", std::ctime(&endTime2) );
 
+  #if JVET_O0756_CALCULATE_HDRMETRICS
+  printf(" Encoding Time(Total Time): %12.3f(%12.3f) sec. [user] %12.3f(%12.3f) sec. [elapsed]\n",
+         ((endClock - startClock) * 1.0 / CLOCKS_PER_SEC) - (metricTimeuser/1000.0),
+         (endClock - startClock) * 1.0 / CLOCKS_PER_SEC,
+         totalTime / 1000.0,
+         encTime / 1000.0);
+  #else
   printf(" Total Time: %12.3f sec. [user] %12.3f sec. [elapsed]\n",
          (endClock - startClock) * 1.0 / CLOCKS_PER_SEC,
          encTime / 1000.0);
+  #endif
 
   return 0;
 }
diff --git a/source/Lib/CommonAnalyserLib/CMakeLists.txt b/source/Lib/CommonAnalyserLib/CMakeLists.txt
index 0fd16c8367e1c2756ebb970de74309327d285668..1df56428b5e01a08185274f0d91ca0ea5406a19d 100644
--- a/source/Lib/CommonAnalyserLib/CMakeLists.txt
+++ b/source/Lib/CommonAnalyserLib/CMakeLists.txt
@@ -52,6 +52,10 @@ if( EXTENSION_360_VIDEO )
   target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_360_VIDEO=1 )
 endif()
 
+if( EXTENSION_HDRTOOLS )
+  target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_HDRTOOLS=1 )
+endif()
+
 if( SET_ENABLE_TRACING )
   if( ENABLE_TRACING )
     target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=1 )
diff --git a/source/Lib/CommonLib/CMakeLists.txt b/source/Lib/CommonLib/CMakeLists.txt
index 06cb4088c813a94e400fb9379486eb14fc5050f1..b12307342f0d454321099a2e3c532f01921a3ff1 100644
--- a/source/Lib/CommonLib/CMakeLists.txt
+++ b/source/Lib/CommonLib/CMakeLists.txt
@@ -51,6 +51,10 @@ if( EXTENSION_360_VIDEO )
   target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_360_VIDEO=1 )
 endif()
 
+if( EXTENSION_HDRTOOLS )
+  target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_HDRTOOLS=1 )
+endif()
+
 if( SET_ENABLE_TRACING )
   if( ENABLE_TRACING )
     target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=1 )
diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp
index c7f0b3458ab97d674a17ce33ed9eab6e47f0be1f..89176cc37e6cc2cc1618aab0ca235bbbfffc86cf 100644
--- a/source/Lib/CommonLib/CodingStructure.cpp
+++ b/source/Lib/CommonLib/CodingStructure.cpp
@@ -427,7 +427,7 @@ PredictionUnit& CodingStructure::addPU( const UnitArea &unit, const ChannelType
   {
     prevPU->next = pu;
 #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
-
+    
     CHECK( prevPU->cacheId != pu->cacheId, "Inconsintent cacheId between previous and current PU" );
 #endif
   }
diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index 1610aea3f9afd15e2598225179202d682457e494..c4843da1b04c54ee1149dd905aa3b21d83857e5d 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -44,6 +44,7 @@
 #include <memory.h>
 #include <algorithm>
 
+
 //! \ingroup CommonLib
 //! \{
 
@@ -696,7 +697,7 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio
     xFrac = yFrac = 0;
     JVET_J0090_SET_CACHE_ENABLE( false );
   }
-
+  
   PelBuf &dstBuf  = dstPic.bufs[compID];
   unsigned width  = dstBuf.width;
   unsigned height = dstBuf.height;
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 581cf50dded7d79da45e993258a7f455ca7adfc6..516ec45d586396995547189b67a7a11111a7d7d1 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -277,6 +277,14 @@ typedef std::pair<int, int>  TrCost;
 #define EXTENSION_360_VIDEO                               0   ///< extension for 360/spherical video coding support; this macro should be controlled by makefile, as it would be used to control whether the library is built and linked
 #endif
 
+#ifndef EXTENSION_HDRTOOLS
+#define EXTENSION_HDRTOOLS                                0 //< extension for HDRTools/Metrics support; this macro should be controlled by makefile, as it would be used to control whether the library is built and linked
+#endif
+
+#if EXTENSION_HDRTOOLS
+#define JVET_O0756_CALCULATE_HDRMETRICS                   1
+#endif
+
 #ifndef ENABLE_WPP_PARALLELISM
 #define ENABLE_WPP_PARALLELISM                            0
 #endif
diff --git a/source/Lib/EncoderLib/Analyze.h b/source/Lib/EncoderLib/Analyze.h
index 086c834bf6c9bcd3a4306d526c5e40c2a5c904fe..fce13616231db73a1c3b3ac451ef64255db8862b 100644
--- a/source/Lib/EncoderLib/Analyze.h
+++ b/source/Lib/EncoderLib/Analyze.h
@@ -72,7 +72,11 @@ private:
 #if EXTENSION_360_VIDEO
   TExt360EncAnalyze m_ext360;
 #endif
-
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  double    m_dLogDeltaESum[hdrtoolslib::NB_REF_WHITE];
+  double    m_dPSNRLSum[hdrtoolslib::NB_REF_WHITE];
+#endif
+  
 public:
   virtual ~Analyze()  {}
   Analyze() { clear(); }
@@ -96,13 +100,25 @@ public:
   double  getWPSNR      (const ComponentID compID) const { return m_dPSNRSum[compID] / (double)m_uiNumPic; }
 #endif
   double  getPsnr(ComponentID compID) const { return  m_dPSNRSum[compID];  }
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  double getDeltaE()                  const { return m_dLogDeltaESum[0];  }
+  double getPSNRL()                  const { return m_dPSNRLSum[0];  }
+#endif
   double  getBits()                   const { return  m_dAddBits;   }
   void    setBits(double numBits)     { m_dAddBits = numBits; }
   uint32_t    getNumPic()                 const { return  m_uiNumPic;   }
 #if EXTENSION_360_VIDEO
   TExt360EncAnalyze& getExt360Info() { return m_ext360; }
 #endif
-
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  void addHDRMetricsResult(double dDeltaE[hdrtoolslib::NB_REF_WHITE], double dPSNRL[hdrtoolslib::NB_REF_WHITE]){
+    for (int i=0; i<hdrtoolslib::NB_REF_WHITE; i++) {
+      m_dLogDeltaESum[i] += dDeltaE[i];
+      m_dPSNRLSum[i] += dPSNRL[i];
+    }
+  }
+#endif
+  
   void    setFrmRate  (double dFrameRate) { m_dFrmRate = dFrameRate; } //--CFG_KDY
   void    clear()
   {
@@ -115,6 +131,12 @@ public:
     m_uiNumPic = 0;
 #if EXTENSION_360_VIDEO
     m_ext360.clear();
+#endif
+#if JVET_O0756_CALCULATE_HDRMETRICS
+    for (int i=0; i<hdrtoolslib::NB_REF_WHITE; i++) {
+      m_dLogDeltaESum[i] = 0.0;
+      m_dPSNRLSum[i] = 0.0;
+    }
 #endif
   }
 
@@ -408,7 +430,12 @@ public:
               msg( e_msg_level, "\tTotal Frames |   "   "Bitrate     "  "Y-WPSNR   "  "U-WPSNR   "  "V-WPSNR   "  "YUV-WPSNR" );
             } else
 #endif
-            msg( e_msg_level, "\tTotal Frames |   "   "Bitrate     "  "Y-PSNR    "  "U-PSNR    "  "V-PSNR    "  "YUV-PSNR " );
+            msg( e_msg_level, "\tTotal Frames |   "   "Bitrate     "  "Y-PSNR    "  "U-PSNR    "  "V-PSNR    "  "YUV-PSNR   " );
+#if JVET_O0756_CALCULATE_HDRMETRICS
+          if(!useWPSNR){
+          msg(e_msg_level, "DeltaE   "  "PSNRL   ");
+          }
+#endif
 #if EXTENSION_360_VIDEO
             m_ext360.printHeader(e_msg_level);
 #endif
@@ -442,9 +469,14 @@ public:
 #if ENABLE_QPA
                    useWPSNR ? getWPSNR(COMPONENT_Cr) :
 #endif
-                   getPsnr(COMPONENT_Cr) / (double)getNumPic(),
-                   PSNRyuv );
-
+              getPsnr(COMPONENT_Cr) / (double)getNumPic(),
+              PSNRyuv );
+#if JVET_O0756_CALCULATE_HDRMETRICS
+          if(!useWPSNR){
+          msg( e_msg_level, "  %8.4lf  " "%8.4lf  ", getDeltaE()/(double)getNumPic(), getPSNRL()/(double)getNumPic());
+          }
+#endif
+          
 #if EXTENSION_360_VIDEO
             m_ext360.printPSNRs(getNumPic(), e_msg_level);
 #endif
diff --git a/source/Lib/EncoderLib/CMakeLists.txt b/source/Lib/EncoderLib/CMakeLists.txt
index 89286b308f417c0aa6795129e38fa0612deba306..2a50346f2c45c4a57d7c73788df086a19645d7f0 100644
--- a/source/Lib/EncoderLib/CMakeLists.txt
+++ b/source/Lib/EncoderLib/CMakeLists.txt
@@ -20,6 +20,10 @@ if( EXTENSION_360_VIDEO )
   target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_360_VIDEO=1 )
 endif()
 
+if( EXTENSION_HDRTOOLS )
+  target_compile_definitions( ${LIB_NAME} PUBLIC EXTENSION_HDRTOOLS=1 )
+endif()
+
 if( SET_ENABLE_TRACING )
   if( ENABLE_TRACING )
     target_compile_definitions( ${LIB_NAME} PUBLIC ENABLE_TRACING=1 )
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 03d0d061258b58838dcdf60b04d67c7932b6bbfa..c4359b09c1c1c6e0c2f2c6e566a5def991b25b05 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -47,6 +47,10 @@
 
 #include "CommonLib/Unit.h"
 
+#if JVET_O0756_CALCULATE_HDRMETRICS
+#include "HDRLib/inc/DistortionMetric.H"
+#endif
+
 struct GOPEntry
 {
   int m_POC;
@@ -652,6 +656,20 @@ protected:
 #endif
 
   bool        m_alf;                                          ///< Adaptive Loop Filter
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  double                       m_whitePointDeltaE[hdrtoolslib::NB_REF_WHITE];
+  double                       m_maxSampleValue;
+  hdrtoolslib::SampleRange     m_sampleRange;
+  hdrtoolslib::ColorPrimaries  m_colorPrimaries;
+  bool                         m_enableTFunctionLUT;
+  hdrtoolslib::ChromaLocation  m_chromaLocation[2];
+  int                          m_chromaUPFilter;
+  int                          m_cropOffsetLeft;
+  int                          m_cropOffsetTop;
+  int                          m_cropOffsetRight;
+  int                          m_cropOffsetBottom;
+  bool                         m_calculateHdrMetrics;
+#endif
 
 public:
   EncCfg()
@@ -1619,8 +1637,36 @@ public:
   void         setEnsureWppBitEqual( bool b)                         { m_ensureWppBitEqual = b; }
   bool         getEnsureWppBitEqual()                          const { return m_ensureWppBitEqual; }
 #endif
-  void        setUseALF( bool b ) { m_alf = b; }
-  bool        getUseALF()                                      const { return m_alf; }
+  void         setUseALF( bool b ) { m_alf = b; }
+  bool         getUseALF()                                      const { return m_alf; }
+  
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  void        setWhitePointDeltaE( uint32_t uiIndex, double dValue ) { m_whitePointDeltaE[ uiIndex ] = dValue; }
+  double      getWhitePointDeltaE( uint32_t uiIndex )          const { return m_whitePointDeltaE[ uiIndex ]; }
+  void        setMaxSampleValue(double dValue)                       { m_maxSampleValue = dValue;}
+  double      getMaxSampleValue()                              const { return m_maxSampleValue;}
+  void        setSampleRange(int iValue)                             { m_sampleRange = static_cast<hdrtoolslib::SampleRange>(iValue);}
+  hdrtoolslib::SampleRange getSampleRange()                    const { return m_sampleRange;}
+  void        setColorPrimaries(int iValue)                          { m_colorPrimaries = static_cast<hdrtoolslib::ColorPrimaries>(iValue);}
+  hdrtoolslib::ColorPrimaries getColorPrimaries()              const { return m_colorPrimaries;}
+  void        setEnableTFunctionLUT(bool bValue)                     { m_enableTFunctionLUT = bValue;}
+  bool        getEnableTFunctionLUT()                          const { return m_enableTFunctionLUT;}
+  void        setChromaLocation(uint32_t uiIndex, int iValue)        { m_chromaLocation[ uiIndex ] = static_cast<hdrtoolslib::ChromaLocation>(iValue);}
+  hdrtoolslib::ChromaLocation getChromaLocation(uint32_t uiIndex) const { return m_chromaLocation[uiIndex];}
+  void        setChromaUPFilter(int iValue)                          { m_chromaUPFilter = iValue;}
+  int         getChromaUPFilter()                              const { return m_chromaUPFilter;}
+  void        setCropOffsetLeft(int iValue)                          { m_cropOffsetLeft = iValue;}
+  int         getCropOffsetLeft()                              const { return m_cropOffsetLeft;}
+  void        setCropOffsetTop(int iValue)                           { m_cropOffsetTop = iValue;}
+  int         getCropOffsetTop()                               const { return m_cropOffsetTop;}
+  void        setCropOffsetRight(int iValue)                         { m_cropOffsetRight = iValue;}
+  int         getCropOffsetRight()                             const { return m_cropOffsetRight;}
+  void        setCropOffsetBottom(int iValue)                        { m_cropOffsetBottom = iValue;}
+  int         getCropOffsetBottom()                            const { return m_cropOffsetBottom;}
+  void        setCalculateHdrMetrics(bool bValue)                    { m_calculateHdrMetrics = bValue;}
+  bool        getCalcluateHdrMetrics()                         const { return m_calculateHdrMetrics;}
+#endif
+
 };
 
 //! \}
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index d710ec005e9c74873396b22f2f4171b61aa0bf0f..edab8c7efafe097a18b3404e0776b5d16ec8f3f1 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -109,6 +109,24 @@ EncGOP::EncGOP()
   m_pcDeblockingTempPicYuv = NULL;
 #endif
 
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  
+  m_ppcFrameOrg = NULL;
+  m_ppcFrameRec = NULL;
+  
+  m_pcConvertFormat = NULL;
+  m_pcConvertIQuantize = NULL;
+  m_pcColorTransform = NULL;
+  m_pcDistortionDeltaE = NULL;
+  m_pcTransferFct = NULL;
+  
+  m_pcColorTransformParams = NULL;
+  m_pcFrameFormat = NULL;
+  
+  m_metricTime = std::chrono::milliseconds(0);
+  
+#endif
+  
   m_bInitAMaxBT         = true;
   m_bgPOC = -1;
   m_picBg = NULL;
@@ -126,6 +144,32 @@ EncGOP::~EncGOP()
     // reset potential decoder resources
     tryDecodePicture( NULL, 0, std::string("") );
   }
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  
+  delete [] m_ppcFrameOrg;
+  delete [] m_ppcFrameRec;
+  
+  m_ppcFrameOrg = m_ppcFrameRec = NULL;
+  
+  delete m_pcConvertFormat;
+  delete m_pcConvertIQuantize;
+  delete m_pcColorTransform;
+  delete m_pcDistortionDeltaE;
+  delete m_pcTransferFct;
+  
+  m_pcConvertFormat = NULL;
+  m_pcConvertIQuantize = NULL;
+  m_pcColorTransform = NULL;
+  m_pcDistortionDeltaE = NULL;
+  m_pcTransferFct = NULL;
+  
+  delete m_pcColorTransformParams;
+  delete m_pcFrameFormat;
+  
+  m_pcColorTransformParams = NULL;
+  m_pcFrameFormat = NULL;
+  
+#endif
 }
 
 /** Create list to contain pointers to CTU start addresses of slice.
@@ -197,6 +241,68 @@ void EncGOP::init ( EncLib* pcEncLib )
   pcEncLib->getALF()->setAlfWSSD(alfWSSD);
 #endif
   m_pcReshaper = pcEncLib->getReshaper();
+  
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  const bool calculateHdrMetrics = m_pcEncLib->getCalcluateHdrMetrics();
+  if(calculateHdrMetrics){
+  //allocate frame buffers and initialize class members
+  int chainNumber = 5;
+  
+  m_ppcFrameOrg = new hdrtoolslib::Frame* [chainNumber];
+  m_ppcFrameRec = new hdrtoolslib::Frame* [chainNumber];
+  
+  double* whitePointDeltaE = new double[hdrtoolslib::NB_REF_WHITE];
+  for (int i=0; i<hdrtoolslib::NB_REF_WHITE; i++) {
+    whitePointDeltaE[i] = m_pcCfg->getWhitePointDeltaE(i);
+  }
+  double dMaxSampleValue = m_pcCfg->getMaxSampleValue();
+  hdrtoolslib::SampleRange sampleRange = m_pcCfg->getSampleRange();
+  hdrtoolslib::ChromaFormat chFmt = hdrtoolslib::ChromaFormat(m_pcCfg->getChromaFormatIdc());
+  int iBitDepth = m_pcCfg->getBitDepth(CHANNEL_TYPE_LUMA);
+  hdrtoolslib::ColorPrimaries colorPrimaries = m_pcCfg->getColorPrimaries();
+  bool bEnableTFunctionLUT = m_pcCfg->getEnableTFunctionLUT();
+  hdrtoolslib::ChromaLocation* chromaLocation = new hdrtoolslib::ChromaLocation[2];
+  for (int i=0; i<2; i++) {
+    chromaLocation[i] = m_pcCfg->getChromaLocation(i);
+  }
+  int iChromaUpFilter  = m_pcCfg->getChromaUPFilter();
+  int cropOffsetLeft   = m_pcCfg->getCropOffsetLeft();
+  int cropOffsetTop    = m_pcCfg->getCropOffsetTop();
+  int cropOffsetRight  = m_pcCfg->getCropOffsetRight();
+  int cropOffsetBottom = m_pcCfg->getCropOffsetBottom();
+  
+  int iWidth = m_pcCfg->getSourceWidth() - cropOffsetLeft + cropOffsetRight;
+  int iHeight = m_pcCfg->getSourceHeight() - cropOffsetTop  + cropOffsetBottom;
+  
+  m_ppcFrameOrg[0] = new hdrtoolslib::Frame(iWidth, iHeight, false, hdrtoolslib::CM_YCbCr, colorPrimaries, chFmt, sampleRange, iBitDepth, false, hdrtoolslib::TF_PQ, 0);
+  m_ppcFrameRec[0] = new hdrtoolslib::Frame(iWidth, iHeight, false, hdrtoolslib::CM_YCbCr, colorPrimaries, chFmt, sampleRange, iBitDepth, false, hdrtoolslib::TF_PQ, 0);                                                                   // Orginal & Reconstructed 4:2:0
+  
+  m_ppcFrameOrg[1] = new hdrtoolslib::Frame(m_ppcFrameOrg[0]->m_width[hdrtoolslib::Y_COMP], m_ppcFrameOrg[0]->m_height[hdrtoolslib::Y_COMP], false, hdrtoolslib::CM_YCbCr, colorPrimaries, hdrtoolslib::CF_444, sampleRange, iBitDepth, false, hdrtoolslib::TF_PQ, 0);
+  m_ppcFrameRec[1] = new hdrtoolslib::Frame(m_ppcFrameRec[0]->m_width[hdrtoolslib::Y_COMP], m_ppcFrameRec[0]->m_height[hdrtoolslib::Y_COMP], false, hdrtoolslib::CM_YCbCr, colorPrimaries, hdrtoolslib::CF_444, sampleRange, iBitDepth, false, hdrtoolslib::TF_PQ, 0);                                // 420 to 444 conversion
+  
+  m_ppcFrameOrg[2] =  new hdrtoolslib::Frame(m_ppcFrameOrg[0]->m_width[hdrtoolslib::Y_COMP], m_ppcFrameOrg[0]->m_height[hdrtoolslib::Y_COMP], true, hdrtoolslib::CM_YCbCr, colorPrimaries, hdrtoolslib::CF_444, hdrtoolslib::SR_UNKNOWN, 32, false, hdrtoolslib::TF_PQ, 0);
+  m_ppcFrameRec[2] =  new hdrtoolslib::Frame(m_ppcFrameRec[0]->m_width[hdrtoolslib::Y_COMP], m_ppcFrameRec[0]->m_height[hdrtoolslib::Y_COMP], true, hdrtoolslib::CM_YCbCr, colorPrimaries, hdrtoolslib::CF_444, hdrtoolslib::SR_UNKNOWN, 32, false, hdrtoolslib::TF_PQ, 0);                                // 444 to Float conversion
+  
+  m_ppcFrameOrg[3] = new hdrtoolslib::Frame(m_ppcFrameOrg[0]->m_width[hdrtoolslib::Y_COMP], m_ppcFrameOrg[0]->m_height[hdrtoolslib::Y_COMP], true, hdrtoolslib::CM_RGB, hdrtoolslib::CP_2020, hdrtoolslib::CF_444, hdrtoolslib::SR_UNKNOWN, 32, false, hdrtoolslib::TF_PQ, 0);
+  m_ppcFrameRec[3] = new hdrtoolslib::Frame(m_ppcFrameRec[0]->m_width[hdrtoolslib::Y_COMP], m_ppcFrameRec[0]->m_height[hdrtoolslib::Y_COMP], true, hdrtoolslib::CM_RGB, hdrtoolslib::CP_2020, hdrtoolslib::CF_444, hdrtoolslib::SR_UNKNOWN, 32, false, hdrtoolslib::TF_PQ, 0);                                // YCbCr to RGB conversion
+  
+  m_ppcFrameOrg[4] = new hdrtoolslib::Frame(m_ppcFrameOrg[0]->m_width[hdrtoolslib::Y_COMP], m_ppcFrameOrg[0]->m_height[hdrtoolslib::Y_COMP], true, hdrtoolslib::CM_RGB, hdrtoolslib::CP_2020, hdrtoolslib::CF_444, hdrtoolslib::SR_UNKNOWN, 32, false, hdrtoolslib::TF_NULL, 0);
+  m_ppcFrameRec[4] = new hdrtoolslib::Frame(m_ppcFrameRec[0]->m_width[hdrtoolslib::Y_COMP], m_ppcFrameRec[0]->m_height[hdrtoolslib::Y_COMP], true, hdrtoolslib::CM_RGB, hdrtoolslib::CP_2020, hdrtoolslib::CF_444, hdrtoolslib::SR_UNKNOWN, 32, false, hdrtoolslib::TF_NULL, 0);                                // Inverse Transfer Function
+  
+  m_pcFrameFormat = new hdrtoolslib::FrameFormat();
+  m_pcFrameFormat->m_isFloat = true;
+  m_pcFrameFormat->m_chromaFormat = hdrtoolslib::CF_UNKNOWN;
+  m_pcFrameFormat->m_colorSpace = hdrtoolslib::CM_RGB;
+  m_pcFrameFormat->m_colorPrimaries = hdrtoolslib::CP_2020;
+  m_pcFrameFormat->m_sampleRange = hdrtoolslib::SR_UNKNOWN;
+  
+  m_pcConvertFormat = hdrtoolslib::ConvertColorFormat::create(iWidth, iHeight, chFmt, hdrtoolslib::CF_444, iChromaUpFilter, chromaLocation, chromaLocation);
+  m_pcConvertIQuantize = hdrtoolslib::Convert::create(&m_ppcFrameOrg[1]->m_format, &m_ppcFrameOrg[2]->m_format);
+  m_pcColorTransform = hdrtoolslib::ColorTransform::create(m_ppcFrameOrg[2]->m_colorSpace, m_ppcFrameOrg[2]->m_colorPrimaries, m_ppcFrameOrg[3]->m_colorSpace, m_ppcFrameOrg[3]->m_colorPrimaries, true, 1);
+  m_pcDistortionDeltaE = new hdrtoolslib::DistortionMetricDeltaE(m_pcFrameFormat, false, dMaxSampleValue, whitePointDeltaE, 1);
+  m_pcTransferFct = hdrtoolslib::TransferFunction::create(hdrtoolslib::TF_PQ, true, dMaxSampleValue, 0, 0.0, 1.0, bEnableTFunctionLUT);
+  }
+#endif
 }
 
 int EncGOP::xWriteVPS (AccessUnit &accessUnit, const VPS *vps)
@@ -3244,7 +3350,15 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni
     MSEyuvframeWeighted[i] = 0.0;
 #endif
   }
-
+  #if JVET_O0756_CALCULATE_HDRMETRICS
+  double dDeltaE[hdrtoolslib::NB_REF_WHITE];
+  double dPSNRL[hdrtoolslib::NB_REF_WHITE];
+  for (int i=0; i<hdrtoolslib::NB_REF_WHITE; i++) {
+    dDeltaE[i] = 0.0;
+    dPSNRL[i] = 0.0;
+  }
+  #endif
+  
   PelStorage interm;
 
   if (conversion != IPCOLOURSPACE_UNCHANGED)
@@ -3302,7 +3416,18 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni
 #if EXTENSION_360_VIDEO
   m_ext360.calculatePSNRs(pcPic);
 #endif
-
+  
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  const bool calculateHdrMetrics = m_pcEncLib->getCalcluateHdrMetrics();
+  if(calculateHdrMetrics)
+  {
+    auto beforeTime = std::chrono::steady_clock::now();
+    xCalculateHDRMetrics(pcPic, dDeltaE, dPSNRL);
+    auto elapsed = std::chrono::steady_clock::now() - beforeTime;
+    m_metricTime += elapsed;
+  }
+#endif
+  
   /* calculate the size of the access unit, excluding:
    *  - any AnnexB contributions (start_code_prefix, zero_byte, etc.,)
    *  - SEI NAL units
@@ -3339,6 +3464,11 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni
 #if EXTENSION_360_VIDEO
   m_ext360.addResult(m_gcAnalyzeAll);
 #endif
+  #if JVET_O0756_CALCULATE_HDRMETRICS
+  if(calculateHdrMetrics){
+      m_gcAnalyzeAll.addHDRMetricsResult(dDeltaE, dPSNRL);
+  }
+  #endif
   if (pcSlice->isIntra())
   {
     m_gcAnalyzeI.addResult(dPSNR, (double)uibits, MSEyuvframe
@@ -3348,6 +3478,11 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni
 #if EXTENSION_360_VIDEO
     m_ext360.addResult(m_gcAnalyzeI);
 #endif
+    #if JVET_O0756_CALCULATE_HDRMETRICS
+    if(calculateHdrMetrics){
+          m_gcAnalyzeI.addHDRMetricsResult(dDeltaE, dPSNRL);
+    }
+    #endif
   }
   if (pcSlice->isInterP())
   {
@@ -3358,6 +3493,11 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni
 #if EXTENSION_360_VIDEO
     m_ext360.addResult(m_gcAnalyzeP);
 #endif
+    #if JVET_O0756_CALCULATE_HDRMETRICS
+    if(calculateHdrMetrics){
+          m_gcAnalyzeP.addHDRMetricsResult(dDeltaE, dPSNRL);
+    }
+    #endif
   }
   if (pcSlice->isInterB())
   {
@@ -3368,6 +3508,11 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni
 #if EXTENSION_360_VIDEO
     m_ext360.addResult(m_gcAnalyzeB);
 #endif
+    #if JVET_O0756_CALCULATE_HDRMETRICS
+    if(calculateHdrMetrics){
+          m_gcAnalyzeB.addHDRMetricsResult(dDeltaE, dPSNRL);
+    }
+    #endif
   }
 #if WCG_WPSNR
   if (useLumaWPSNR)
@@ -3435,6 +3580,16 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni
       }
     }
 #endif
+    #if JVET_O0756_CALCULATE_HDRMETRICS
+    if(calculateHdrMetrics){
+    for (int i=0; i<1; i++) {
+          msg(NOTICE, " [DeltaE%d %6.4lf dB]", (int)m_pcCfg->getWhitePointDeltaE(i), dDeltaE[i]);
+    }
+    for (int i=0; i<1; i++) {
+          msg(NOTICE, " [PSNRL%d %6.4lf dB]", (int)m_pcCfg->getWhitePointDeltaE(i), dPSNRL[i]);
+    }
+    }
+    #endif
     msg( NOTICE, " [ET %5.0f ]", dEncTime );
 
     // msg( SOME, " [WP %d]", pcSlice->getUseWeightedPrediction());
@@ -3456,6 +3611,102 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni
   }
 }
 
+#if JVET_O0756_CALCULATE_HDRMETRICS
+void EncGOP::xCalculateHDRMetrics( Picture* pcPic, double dDeltaE[hdrtoolslib::NB_REF_WHITE], double dPSNRL[hdrtoolslib::NB_REF_WHITE])
+{
+  copyBuftoFrame(pcPic);
+  
+  ChromaFormat chFmt =  pcPic->chromaFormat;
+  
+  if (chFmt != CHROMA_444) {
+    m_pcConvertFormat->process(m_ppcFrameOrg[1], m_ppcFrameOrg[0]);
+    m_pcConvertFormat->process(m_ppcFrameRec[1], m_ppcFrameRec[0]);
+  }
+  
+  m_pcConvertIQuantize->process(m_ppcFrameOrg[2], m_ppcFrameOrg[1]);
+  m_pcConvertIQuantize->process(m_ppcFrameRec[2], m_ppcFrameRec[1]);
+  
+  m_pcColorTransform->process(m_ppcFrameOrg[3], m_ppcFrameOrg[2]);
+  m_pcColorTransform->process(m_ppcFrameRec[3], m_ppcFrameRec[2]);
+  
+  m_pcTransferFct->forward(m_ppcFrameOrg[4], m_ppcFrameOrg[3]);
+  m_pcTransferFct->forward(m_ppcFrameRec[4], m_ppcFrameRec[3]);
+  
+  // Calculate the Metrics
+  m_pcDistortionDeltaE->computeMetric(m_ppcFrameOrg[4], m_ppcFrameRec[4]);
+  
+  *dDeltaE = m_pcDistortionDeltaE->getDeltaE();
+  *dPSNRL = m_pcDistortionDeltaE->getPsnrL();
+  
+}
+
+void EncGOP::copyBuftoFrame( Picture* pcPic )
+{
+  int cropOffsetLeft   = m_pcCfg->getCropOffsetLeft();
+  int cropOffsetTop    = m_pcCfg->getCropOffsetTop();
+  int cropOffsetRight  = m_pcCfg->getCropOffsetRight();
+  int cropOffsetBottom = m_pcCfg->getCropOffsetBottom();
+  
+  int iHeight = pcPic->getOrigBuf(COMPONENT_Y).height - cropOffsetLeft + cropOffsetRight;
+  int iWidth = pcPic->getOrigBuf(COMPONENT_Y).width - cropOffsetTop + cropOffsetBottom;
+  
+  ChromaFormat chFmt =  pcPic->chromaFormat;
+  
+  Pel* pOrg = pcPic->getOrigBuf(COMPONENT_Y).buf;
+  Pel* pRec = pcPic->getRecoBuf(COMPONENT_Y).buf;
+  
+  uint16_t* yOrg = m_ppcFrameOrg[0]->m_ui16Comp[hdrtoolslib::Y_COMP];
+  uint16_t* yRec = m_ppcFrameRec[0]->m_ui16Comp[hdrtoolslib::Y_COMP];
+  uint16_t* uOrg = m_ppcFrameOrg[0]->m_ui16Comp[hdrtoolslib::Cb_COMP];
+  uint16_t* uRec = m_ppcFrameRec[0]->m_ui16Comp[hdrtoolslib::Cb_COMP];
+  uint16_t* vOrg = m_ppcFrameOrg[0]->m_ui16Comp[hdrtoolslib::Cr_COMP];
+  uint16_t* vRec = m_ppcFrameRec[0]->m_ui16Comp[hdrtoolslib::Cr_COMP];
+  
+  if(chFmt == CHROMA_444){
+    yOrg = m_ppcFrameOrg[1]->m_ui16Comp[hdrtoolslib::Y_COMP];
+    yRec = m_ppcFrameRec[1]->m_ui16Comp[hdrtoolslib::Y_COMP];
+    uOrg = m_ppcFrameOrg[1]->m_ui16Comp[hdrtoolslib::Cb_COMP];
+    uRec = m_ppcFrameRec[1]->m_ui16Comp[hdrtoolslib::Cb_COMP];
+    vOrg = m_ppcFrameOrg[1]->m_ui16Comp[hdrtoolslib::Cr_COMP];
+    vRec = m_ppcFrameRec[1]->m_ui16Comp[hdrtoolslib::Cr_COMP];
+  }
+  
+  for (int i = 0; i < iHeight; i++) {
+    for (int j = 0; j < iWidth; j++) {
+      yOrg[i*iWidth + j] = static_cast<uint16_t>(pOrg[(i + cropOffsetTop) * pcPic->getOrigBuf(COMPONENT_Y).stride + j + cropOffsetLeft]);
+      yRec[i*iWidth + j] = static_cast<uint16_t>(pRec[(i + cropOffsetTop) * pcPic->getRecoBuf(COMPONENT_Y).stride + j + cropOffsetLeft]);
+    }
+  }
+  
+  if (chFmt != CHROMA_444) {
+    iHeight >>= 1;
+    iWidth  >>= 1;
+    cropOffsetLeft >>= 1;
+    cropOffsetTop >>= 1;
+  }
+  
+  pOrg = pcPic->getOrigBuf(COMPONENT_Cb).buf;
+  pRec = pcPic->getRecoBuf(COMPONENT_Cb).buf;
+  
+  for (int i = 0; i < iHeight; i++) {
+    for (int j = 0; j < iWidth; j++) {
+      uOrg[i*iWidth + j] = static_cast<uint16_t>(pOrg[(i + cropOffsetTop) * pcPic->getOrigBuf(COMPONENT_Cb).stride + j + cropOffsetLeft]);
+      uRec[i*iWidth + j] = static_cast<uint16_t>(pRec[(i + cropOffsetTop) * pcPic->getRecoBuf(COMPONENT_Cb).stride + j + cropOffsetLeft]);
+    }
+  }
+  
+  pOrg = pcPic->getOrigBuf(COMPONENT_Cr).buf;
+  pRec = pcPic->getRecoBuf(COMPONENT_Cr).buf;
+  
+  for (int i = 0; i < iHeight; i++) {
+    for (int j = 0; j < iWidth; j++) {
+      vOrg[i*iWidth + j] = static_cast<uint16_t>(pOrg[(i + cropOffsetTop) * pcPic->getOrigBuf(COMPONENT_Cr).stride + j + cropOffsetLeft]);
+      vRec[i*iWidth + j] = static_cast<uint16_t>(pRec[(i + cropOffsetTop) * pcPic->getRecoBuf(COMPONENT_Cr).stride + j + cropOffsetLeft]);
+    }
+  }
+}
+#endif
+
 void EncGOP::xCalculateInterlacedAddPSNR( Picture* pcPicOrgFirstField, Picture* pcPicOrgSecondField,
                                           PelUnitBuf cPicRecFirstField, PelUnitBuf cPicRecSecondField,
                                           const InputColourSpaceConversion conversion, const bool printFrameMSE, double* PSNR_Y
diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h
index 5df421faf9c181651fec189cc039c3efa70cad34..29b4de7a098cf96c1c5058551564dd5680da8176 100644
--- a/source/Lib/EncoderLib/EncGOP.h
+++ b/source/Lib/EncoderLib/EncGOP.h
@@ -61,6 +61,14 @@
 #include "RateCtrl.h"
 #include <vector>
 
+#if JVET_O0756_CALCULATE_HDRMETRICS
+#include "HDRLib/inc/ConvertColorFormat.H"
+#include "HDRLib/inc/Convert.H"
+#include "HDRLib/inc/ColorTransform.H"
+#include "HDRLib/inc/TransferFunction.H"
+#include "HDRLib/inc/DistortionMetricDeltaE.H"
+#endif
+
 //! \ingroup EncoderLib
 //! \{
 
@@ -168,7 +176,25 @@ private:
   bool                    m_bInitAMaxBT;
 
   AUWriterIf*             m_AUWriterIf;
-
+  
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  
+  hdrtoolslib::Frame **m_ppcFrameOrg;
+  hdrtoolslib::Frame **m_ppcFrameRec;
+  
+  hdrtoolslib::ConvertColorFormat* m_pcConvertFormat;
+  hdrtoolslib::Convert* m_pcConvertIQuantize;
+  hdrtoolslib::ColorTransform* m_pcColorTransform;
+  hdrtoolslib::DistortionMetricDeltaE* m_pcDistortionDeltaE;
+  hdrtoolslib::TransferFunction* m_pcTransferFct;
+  
+  hdrtoolslib::ColorTransformParams* m_pcColorTransformParams;
+  hdrtoolslib::FrameFormat* m_pcFrameFormat;
+  
+public:
+  std::chrono::duration<long long, ratio<1, 1000000000>> m_metricTime;
+#endif
+  
 public:
   EncGOP();
   virtual ~EncGOP();
@@ -228,6 +254,11 @@ protected:
   );
   void  xGetBuffer        ( PicList& rcListPic, std::list<PelUnitBuf*>& rcListPicYuvRecOut,
                             int iNumPicRcvd, int iTimeOffset, Picture*& rpcPic, int pocCurr, bool isField );
+    
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  void xCalculateHDRMetrics ( Picture* pcPic, double dDeltaE[hdrtoolslib::NB_REF_WHITE], double dPSNRL[hdrtoolslib::NB_REF_WHITE]);
+  void copyBuftoFrame       ( Picture* pcPic );
+#endif
 
   void  xCalculateAddPSNRs(const bool isField, const bool isFieldTopFieldFirst, const int iGOPid, Picture* pcPic, const AccessUnit&accessUnit, PicList &rcListPic, int64_t dEncTime, const InputColourSpaceConversion snr_conversion, const bool printFrameMSE, double* PSNR_Y
     , bool isEncodeLtRef
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index daca183e0847f7c4fdb8d19e513339d9a697d83f..695806502d77ff34ad626d08abb4f8424ee3b3cc 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -79,6 +79,10 @@ EncLib::EncLib()
 #if ENABLE_SIMD_OPT_BUFFER
   g_pelBufOP.initPelBufOpsX86();
 #endif
+  
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  m_metricTime = std::chrono::milliseconds(0);
+#endif
 
   memset(m_apss, 0, sizeof(m_apss));
 }
@@ -569,6 +573,9 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru
     }
     m_cGOPEncoder.compressGOP(m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut,
       false, false, snrCSC, m_printFrameMSE, true);
+#if JVET_O0756_CALCULATE_HDRMETRICS
+    m_metricTime = m_cGOPEncoder.m_metricTime;
+#endif
     m_cGOPEncoder.setEncodedLTRef(true);
     if (m_RCEnableRateControl)
     {
@@ -634,6 +641,9 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru
                             false, false, snrCSC, m_printFrameMSE
     , false
   );
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  m_metricTime = m_cGOPEncoder.m_metricTime;
+#endif
 
   if ( m_RCEnableRateControl )
   {
@@ -723,7 +733,10 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* pcPicYuvTr
       m_cGOPEncoder.compressGOP(m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, true, isTff, snrCSC, m_printFrameMSE
                               , false
       );
-
+#if JVET_O0756_CALCULATE_HDRMETRICS
+      m_metricTime = m_cGOPEncoder.m_metricTime;
+#endif
+      
       iNumEncoded += m_iNumPicRcvd;
       m_uiNumAllPicCoded += m_iNumPicRcvd;
       m_iNumPicRcvd = 0;
diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h
index 09eaa50d4d436359042ec64f3002938493a4b37f..1b8967c78d13afd0139820be6cf172fd30041d47 100644
--- a/source/Lib/EncoderLib/EncLib.h
+++ b/source/Lib/EncoderLib/EncLib.h
@@ -157,6 +157,9 @@ public:
 #if ENABLE_WPP_PARALLELISM
   std::vector<Ctx>          m_entropyCodingSyncContextStateVec;   ///< context storage for state of contexts at the wavefront/WPP/entropy-coding-sync second CTU of tile-row
 #endif
+#if JVET_O0756_CALCULATE_HDRMETRICS
+  std::chrono::duration<long long, ratio<1, 1000000000>> m_metricTime;
+#endif
 
 protected:
   void  xGetNewPicBuffer  ( std::list<PelUnitBuf*>& rcListPicYuvRecOut, Picture*& rpcPic, int ppsId ); ///< get picture buffer which will be processed. If ppsId<0, then the ppsMap will be queried for the first match.
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index 89f15581bc13e0801824209a5e1f2edb645efe19..bf56323681f6fce3fe19f2d1ba2a07b91f29f241 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -8157,4 +8157,4 @@ bool InterSearch::searchBv(PredictionUnit& pu, int xPos, int yPos, int width, in
 }
 #endif
 
-//! \}
\ No newline at end of file
+//! \}
diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h
index 4fcb540964b20087c5811d6a8700a97ccfb949b3..4cd15fcb2cb25f6de76474d21cedbdb3a6b1d543 100644
--- a/source/Lib/EncoderLib/InterSearch.h
+++ b/source/Lib/EncoderLib/InterSearch.h
@@ -176,8 +176,8 @@ protected:
   bool            m_skipSbtAll;                         // to skip all SBT modes for the current PU
   uint8_t         m_histBestSbt;                        // historical best SBT mode for PU of certain SSE values
   uint8_t         m_histBestMtsIdx;                     // historical best MTS idx  for PU of certain SSE values
-
 public:
+  
   InterSearch();
   virtual ~InterSearch();