File gdal-ecwjp2-sdk-5.5.patch of Package gdal

From e5cb5406ea9090b2f17cffeeb7ba5fb49e7158f2 Mon Sep 17 00:00:00 2001
From: Chris Tapley <chris.tapley.81@gmail.com>
Date: Tue, 15 Oct 2019 17:19:14 +0800
Subject: [PATCH] ecwjp2 sdk 5.5 changes

- implementation for API breaking changes.
- handle "newabi" rename to "cpp11abi" in configure and configure.ac
- example information in nmake.opt
---
 gdal/configure                   |  34 +++++---
 gdal/configure.ac                |  30 ++++---
 gdal/frmts/ecw/ecwcreatecopy.cpp |  17 ++--
 gdal/frmts/ecw/ecwdataset.cpp    | 133 ++++++++++++++++---------------
 gdal/frmts/ecw/gdal_ecw.h        |  37 +++++----
 gdal/frmts/ecw/jp2userbox.cpp    |  21 +++--
 gdal/nmake.opt                   |  35 ++++++--
 7 files changed, 185 insertions(+), 122 deletions(-)

diff --git a/gdal/configure b/gdal/configure
index 40d038394ed..fd2e3f6c12f 100755
--- a/gdal/configure
+++ b/gdal/configure
@@ -33205,18 +33205,23 @@ $as_echo "found libecwj2 in $with_ecw/lib." >&6; }
 
   # ECW SDK 5.0 style and also for the case where license type is included in path i.e. specific license type is requested.
   elif test -r $with_ecw/lib/$ECW_ARCH/$ECW_CONF/libNCSEcw.a ; then
-    # Test if we must use the newabi version (SDK 5.4)
-    if test -r $with_ecw/lib/newabi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a; then
+    # Test if we must use the newabi/cpp11abi version (SDK 5.4+)
+    if test -r $with_ecw/lib/newabi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a || test -r $with_ecw/lib/cpp11abi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a; then
+        if test -d $with_ecw/lib/newabi; then
+            ECW_ABIDIR=newabi
+        else
+            ECW_ABIDIR=cpp11abi
+        fi
         echo "#include <string>" > testnewabi.cpp
         echo "namespace NCS { class CString { public: static std::wstring Utf8Decode (const std::string &sUtf8); }; }" >> testnewabi.cpp
         echo "int main() { return static_cast<int>(NCS::CString::Utf8Decode(std::string()).size()); }" >> testnewabi.cpp
-        if test -z "`${CXX} ${CXXFLAGS} ${CPPFLAGS} testnewabi.cpp -L$with_ecw/lib/newabi/$ECW_ARCH/$ECW_CONF -lNCSEcw -o testnewabi 2>&1`" ; then
-            ECW_LIBDIR=$with_ecw/lib/newabi/$ECW_ARCH/$ECW_CONF
+        if test -z "`${CXX} ${CXXFLAGS} ${CPPFLAGS} testnewabi.cpp -L$with_ecw/lib/$ECW_ABIDIR/$ECW_ARCH/$ECW_CONF -lNCSEcw -o testnewabi 2>&1`" ; then
+            ECW_LIBDIR=$with_ecw/lib/$ECW_ABIDIR/$ECW_ARCH/$ECW_CONF
             ECW_LIBS="-L$ECW_LIBDIR -lNCSEcw $ECW_FRAMEWORK_COCOA"
             with_ecw=$with_ecw/$ecw_license_type
             ECW_54="yes"
-            { $as_echo "$as_me:${as_lineno-$LINENO}: result: found Intergraph 5.4+ SDK with newabi in ${ECW_LIBDIR}." >&5
-$as_echo "found Intergraph 5.4+ SDK with newabi in ${ECW_LIBDIR}." >&6; }
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: found Intergraph 5.4+ SDK with ${ECW_ABIDIR} in ${ECW_LIBDIR}." >&5
+$as_echo "found Intergraph 5.4+ SDK with ${ECW_ABIDIR} in ${ECW_LIBDIR}." >&6; }
             rm -f testnewabi.*
             rm -f testnewabi
             break
@@ -33234,17 +33239,22 @@ $as_echo "found Intergraph 5.x+ SDK in ${ECW_LIBDIR}." >&6; }
   elif test -d $with_ecw; then
     for ecw_license_type in "Desktop_Read-Write" "Server_Read-Only_EndUser" "Server_Read-Only" "Server_Read-Write" "Desktop_Read-Only"
       do
-        # Test if we must use the newabi version (SDK 5.4)
-        if test -r $with_ecw/$ecw_license_type/lib/newabi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a; then
+        # Test if we must use the newabi/cpp11abi version (SDK 5.4+)
+        if test -r $with_ecw/$ecw_license_type/lib/newabi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a || test -r $with_ecw/$ecw_license_type/lib/cpp11abi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a; then
+            if test -d $with_ecw/lib/newabi; then
+                ECW_ABIDIR=newabi
+            else
+                ECW_ABIDIR=cpp11abi
+            fi
             echo "#include <string>" > testnewabi.cpp
             echo "namespace NCS { class CString { public: static std::wstring Utf8Decode (const std::string &sUtf8); }; }" >> testnewabi.cpp
             echo "int main() { return static_cast<int>(NCS::CString::Utf8Decode(std::string()).size()); }" >> testnewabi.cpp
-            if test -z "`${CXX} ${CXXFLAGS} ${CPPFLAGS} testnewabi.cpp -L$with_ecw/$ecw_license_type/lib/newabi/$ECW_ARCH/$ECW_CONF -lNCSEcw -o testnewabi 2>&1`" ; then
-                ECW_LIBDIR=$with_ecw/$ecw_license_type/lib/newabi/$ECW_ARCH/$ECW_CONF
+            if test -z "`${CXX} ${CXXFLAGS} ${CPPFLAGS} testnewabi.cpp -L$with_ecw/$ecw_license_type/lib/$ECW_ABIDIR/$ECW_ARCH/$ECW_CONF -lNCSEcw -o testnewabi 2>&1`" ; then
+                ECW_LIBDIR=$with_ecw/$ecw_license_type/lib/$ECW_ABIDIR/$ECW_ARCH/$ECW_CONF
                 ECW_LIBS="-L$ECW_LIBDIR -lNCSEcw $ECW_FRAMEWORK_COCOA"
                 with_ecw=$with_ecw/$ecw_license_type
-                { $as_echo "$as_me:${as_lineno-$LINENO}: result: found Intergraph 5.4+ SDK with newabi in ${ECW_LIBDIR}." >&5
-$as_echo "found Intergraph 5.4+ SDK with newabi in ${ECW_LIBDIR}." >&6; }
+                { $as_echo "$as_me:${as_lineno-$LINENO}: result: found Intergraph 5.4+ SDK with ${ECW_ABIDIR} in ${ECW_LIBDIR}." >&5
+$as_echo "found Intergraph 5.4+ SDK with ${ECW_ABIDIR} in ${ECW_LIBDIR}." >&6; }
                 ECW_54="yes"
                 rm -f testnewabi.*
                 rm -f testnewabi
diff --git a/gdal/configure.ac b/gdal/configure.ac
index ce2618cd0fe..c46efad2543 100644
--- a/gdal/configure.ac
+++ b/gdal/configure.ac
@@ -3244,17 +3244,22 @@ else
 
   # ECW SDK 5.0 style and also for the case where license type is included in path i.e. specific license type is requested.
   elif test -r $with_ecw/lib/$ECW_ARCH/$ECW_CONF/libNCSEcw.a ; then
-    # Test if we must use the newabi version (SDK 5.4)
-    if test -r $with_ecw/lib/newabi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a; then
+    # Test if we must use the newabi/cpp11abi version (SDK 5.4+)
+    if test -r $with_ecw/lib/newabi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a || test -r $with_ecw/lib/cpp11abi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a; then
+        if test -d $with_ecw/lib/newabi; then
+            ECW_ABIDIR=newabi
+        else
+            ECW_ABIDIR=cpp11abi
+        fi
         echo "#include <string>" > testnewabi.cpp
         echo "namespace NCS { class CString { public: static std::wstring Utf8Decode (const std::string &sUtf8); }; }" >> testnewabi.cpp
         echo "int main() { return static_cast<int>(NCS::CString::Utf8Decode(std::string()).size()); }" >> testnewabi.cpp
-        if test -z "`${CXX} ${CXXFLAGS} ${CPPFLAGS} testnewabi.cpp -L$with_ecw/lib/newabi/$ECW_ARCH/$ECW_CONF -lNCSEcw -o testnewabi 2>&1`" ; then
-            ECW_LIBDIR=$with_ecw/lib/newabi/$ECW_ARCH/$ECW_CONF
+        if test -z "`${CXX} ${CXXFLAGS} ${CPPFLAGS} testnewabi.cpp -L$with_ecw/lib/$ECW_ABIDIR/$ECW_ARCH/$ECW_CONF -lNCSEcw -o testnewabi 2>&1`" ; then
+            ECW_LIBDIR=$with_ecw/lib/$ECW_ABIDIR/$ECW_ARCH/$ECW_CONF
             ECW_LIBS="-L$ECW_LIBDIR -lNCSEcw $ECW_FRAMEWORK_COCOA"
             with_ecw=$with_ecw/$ecw_license_type
             ECW_54="yes"
-            AC_MSG_RESULT([found Intergraph 5.4+ SDK with newabi in ${ECW_LIBDIR}.])
+            AC_MSG_RESULT([found Intergraph 5.4+ SDK with ${ECW_ABIDIR} in ${ECW_LIBDIR}.])
             rm -f testnewabi.*
             rm -f testnewabi
             break
@@ -3271,16 +3276,21 @@ else
   elif test -d $with_ecw; then
     for ecw_license_type in "Desktop_Read-Write" "Server_Read-Only_EndUser" "Server_Read-Only" "Server_Read-Write" "Desktop_Read-Only"
       do
-        # Test if we must use the newabi version (SDK 5.4)
-        if test -r $with_ecw/$ecw_license_type/lib/newabi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a; then
+        # Test if we must use the newabi/cpp11abi version (SDK 5.4+)
+        if test -r $with_ecw/$ecw_license_type/lib/newabi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a || test -r $with_ecw/$ecw_license_type/lib/cpp11abi/$ECW_ARCH/$ECW_CONF/libNCSEcw.a; then
+            if test -d $with_ecw/lib/newabi; then
+                ECW_ABIDIR=newabi
+            else
+                ECW_ABIDIR=cpp11abi
+            fi
             echo "#include <string>" > testnewabi.cpp
             echo "namespace NCS { class CString { public: static std::wstring Utf8Decode (const std::string &sUtf8); }; }" >> testnewabi.cpp
             echo "int main() { return static_cast<int>(NCS::CString::Utf8Decode(std::string()).size()); }" >> testnewabi.cpp
-            if test -z "`${CXX} ${CXXFLAGS} ${CPPFLAGS} testnewabi.cpp -L$with_ecw/$ecw_license_type/lib/newabi/$ECW_ARCH/$ECW_CONF -lNCSEcw -o testnewabi 2>&1`" ; then
-                ECW_LIBDIR=$with_ecw/$ecw_license_type/lib/newabi/$ECW_ARCH/$ECW_CONF
+            if test -z "`${CXX} ${CXXFLAGS} ${CPPFLAGS} testnewabi.cpp -L$with_ecw/$ecw_license_type/lib/$ECW_ABIDIR/$ECW_ARCH/$ECW_CONF -lNCSEcw -o testnewabi 2>&1`" ; then
+                ECW_LIBDIR=$with_ecw/$ecw_license_type/lib/$ECW_ABIDIR/$ECW_ARCH/$ECW_CONF
                 ECW_LIBS="-L$ECW_LIBDIR -lNCSEcw $ECW_FRAMEWORK_COCOA"
                 with_ecw=$with_ecw/$ecw_license_type
-                AC_MSG_RESULT([found Intergraph 5.4+ SDK with newabi in ${ECW_LIBDIR}.])
+                AC_MSG_RESULT([found Intergraph 5.4+ SDK with ${ECW_ABIDIR} in ${ECW_LIBDIR}.])
                 ECW_54="yes"
                 rm -f testnewabi.*
                 rm -f testnewabi
diff --git a/gdal/frmts/ecw/ecwcreatecopy.cpp b/gdal/frmts/ecw/ecwcreatecopy.cpp
index b17592720cb..97f8f45f7ff 100644
--- a/gdal/frmts/ecw/ecwcreatecopy.cpp
+++ b/gdal/frmts/ecw/ecwcreatecopy.cpp
@@ -115,7 +115,7 @@ class GDALECWCompressor final: public CNCSFile {
 
     GDALDataset *m_poSrcDS;
 
-    VSIIOStream m_OStream;
+    std::shared_ptr<VSIIOStream> m_OStream;
     int m_nPercentComplete;
 
     int m_bCancelled;
@@ -143,7 +143,7 @@ class GDALECWCompressor final: public CNCSFile {
 /************************************************************************/
 
 GDALECWCompressor::GDALECWCompressor() :
-    eWorkDT(GDT_Unknown)
+    m_OStream(std::make_shared<VSIIOStream>()), eWorkDT(GDT_Unknown)
 {
     m_poSrcDS = nullptr;
     m_nPercentComplete = -1;
@@ -186,7 +186,7 @@ CPLErr GDALECWCompressor::CloseDown()
 
 {
     Close( true );
-    m_OStream.Close();
+    m_OStream->Close();
 
     return CE_None;
 }
@@ -1008,7 +1008,7 @@ CPLErr GDALECWCompressor::Initialize(
             return CE_Failure;
         }
 
-        m_OStream.Access( fpVSIL, TRUE, (BOOLEAN) bSeekable, pszFilename,
+        m_OStream->Access( fpVSIL, TRUE, (BOOLEAN) bSeekable, pszFilename,
                           0, -1 );
     }
     else
@@ -1114,8 +1114,13 @@ CPLErr GDALECWCompressor::Initialize(
                 oError = GetCNCSError(Open( (char *) pszFilename, false, true ));
             }
         }
-        else
-            oError = CNCSJP2FileView::Open( &(m_OStream) );
+        else {
+#if ECWSDK_VERSION>=55
+            oError = CNCSJP2FileView::Open(m_OStream);
+#else
+            oError = CNCSJP2FileView::Open(m_OStream.get());
+#endif
+        }
     }
 
     if( oError.GetErrorNumber() == NCS_SUCCESS )
diff --git a/gdal/frmts/ecw/ecwdataset.cpp b/gdal/frmts/ecw/ecwdataset.cpp
index 6ef14bd27d9..c2fbd4f3663 100644
--- a/gdal/frmts/ecw/ecwdataset.cpp
+++ b/gdal/frmts/ecw/ecwdataset.cpp
@@ -194,11 +194,11 @@ ECWRasterBand::ECWRasterBand( ECWDataset *poDSIn, int nBandIn, int iOverviewIn,
         CPLDebug("ECW", "Fourth (alpha) band is promoted from 1 bit to 8 bit");
 
     if( (poDSIn->psFileInfo->pBands[nBand-1].nBits % 8) != 0 && !bPromoteTo8Bit )
-        SetMetadataItem("NBITS",
+        GDALPamRasterBand::SetMetadataItem("NBITS",
                         CPLString().Printf("%d",poDSIn->psFileInfo->pBands[nBand-1].nBits),
                         "IMAGE_STRUCTURE" );
 
-    SetDescription(poDSIn->psFileInfo->pBands[nBand-1].szDesc);
+    GDALPamRasterBand::SetDescription(poDSIn->psFileInfo->pBands[nBand-1].szDesc);
 }
 
 /************************************************************************/
@@ -208,7 +208,7 @@ ECWRasterBand::ECWRasterBand( ECWDataset *poDSIn, int nBandIn, int iOverviewIn,
 ECWRasterBand::~ECWRasterBand()
 
 {
-    FlushCache();
+    GDALRasterBand::FlushCache();
 
     while( !apoOverviews.empty() )
     {
@@ -266,7 +266,7 @@ CPLErr ECWRasterBand::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                   GDALDataType eDT,
                                   char **papszOptions )
 {
-    int nResFactor = 1 << (iOverview+1);
+    const int nResFactor = 1 << (iOverview+1);
 
     return poGDS->AdviseRead( nXOff * nResFactor,
                               nYOff * nResFactor,
@@ -312,13 +312,13 @@ CPLErr ECWRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
         NCSBandStats& bandStats = poGDS->pStatistics->BandsStats[nStatsBandIndex];
         if ( bandStats.Histogram != nullptr && bandStats.nHistBucketCount > 0 ){
             *pnBuckets = bandStats.nHistBucketCount;
-            *ppanHistogram = (GUIntBig *)VSIMalloc(bandStats.nHistBucketCount *sizeof(GUIntBig));
+            *ppanHistogram = static_cast<GUIntBig *>(VSIMalloc(bandStats.nHistBucketCount * sizeof(GUIntBig)));
             for (size_t i = 0; i < bandStats.nHistBucketCount; i++){
-                (*ppanHistogram)[i] = (GUIntBig) bandStats.Histogram[i];
+                (*ppanHistogram)[i] = static_cast<GUIntBig>(bandStats.Histogram[i]);
             }
             //JTO: this is not perfect as You can't tell who wrote the histogram !!!
             //It will offset it unnecessarily for files with hists not modified by GDAL.
-            double dfHalfBucket = (bandStats.fMaxHist -  bandStats.fMinHist) / (2 * (*pnBuckets - 1));
+            const double dfHalfBucket = (bandStats.fMaxHist -  bandStats.fMinHist) / (2 * (*pnBuckets - 1));
             if ( pdfMin != nullptr ){
                 *pdfMin = bandStats.fMinHist - dfHalfBucket;
             }
@@ -326,11 +326,7 @@ CPLErr ECWRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
                 *pdfMax = bandStats.fMaxHist + dfHalfBucket;
             }
             bHistogramFromFile = true;
-        }else{
-            bHistogramFromFile = false;
         }
-    }else{
-        bHistogramFromFile = false;
     }
 
     if (!bHistogramFromFile ){
@@ -338,29 +334,21 @@ CPLErr ECWRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
             //compute. Save.
             pamError = GDALPamRasterBand::GetDefaultHistogram(pdfMin, pdfMax, pnBuckets, ppanHistogram, TRUE, f,pProgressData);
             if (pamError == CE_None){
-                CPLErr error2 = SetDefaultHistogram(*pdfMin, *pdfMax, *pnBuckets, *ppanHistogram);
+                const CPLErr error2 = SetDefaultHistogram(*pdfMin, *pdfMax, *pnBuckets, *ppanHistogram);
                 if (error2 != CE_None){
                     //Histogram is there but we failed to save it back to file.
                     CPLError (CE_Warning, CPLE_AppDefined,
                         "SetDefaultHistogram failed in ECWRasterBand::GetDefaultHistogram. Histogram might not be saved in .ecw file." );
                 }
                 return CE_None;
-            }else{
-                //Something went wrong during histogram computation.
-                return pamError;
             }
+            return pamError;
         }
-        else
-        {
-            // No histogram, no forced computation.
-            return CE_Warning;
-        }
-    }
-    else
-    {
-        // Statistics were already there and were used.
-        return CE_None;
+        // No histogram, no forced computation.
+        return CE_Warning;
     }
+    // Statistics were already there and were used.
+    return CE_None;
 }
 
 /************************************************************************/
@@ -426,7 +414,7 @@ CPLErr ECWRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
                 bucketCounts[i] = pStatistics->BandsStats[i].nHistBucketCount;
             }
             bucketCounts[nStatsBandIndex] = nBuckets;
-            if (nBuckets < (int)pStatistics->BandsStats[nStatsBandIndex].nHistBucketCount){
+            if (nBuckets < static_cast<int>(pStatistics->BandsStats[nStatsBandIndex].nHistBucketCount)){
                 pStatistics->BandsStats[nStatsBandIndex].nHistBucketCount = nBuckets;
             }
             error = NCSEcwInitStatistics(&pNewStatistics, nStatsBandCount, bucketCounts);
@@ -454,10 +442,10 @@ CPLErr ECWRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
 
     //at this point we have allocated statistics structure.
     double dfHalfBucket = (dfMax - dfMin) / (2 * nBuckets);
-    pStatistics->BandsStats[nStatsBandIndex].fMinHist = (IEEE4) (dfMin + dfHalfBucket);
-    pStatistics->BandsStats[nStatsBandIndex].fMaxHist = (IEEE4) (dfMax - dfHalfBucket);
+    pStatistics->BandsStats[nStatsBandIndex].fMinHist = static_cast<IEEE4>(dfMin + dfHalfBucket);
+    pStatistics->BandsStats[nStatsBandIndex].fMaxHist = static_cast<IEEE4>(dfMax - dfHalfBucket);
     for (int i=0;i<nBuckets;i++){
-        pStatistics->BandsStats[nStatsBandIndex].Histogram[i] = (UINT64)panHistogram[i];
+        pStatistics->BandsStats[nStatsBandIndex].Histogram[i] = static_cast<UINT64>(panHistogram[i]);
     }
 
     if (hasPAMDefaultHistogram){
@@ -472,7 +460,8 @@ CPLErr ECWRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
 /*                   GetBandIndexAndCountForStatistics()                */
 /************************************************************************/
 
-void ECWRasterBand::GetBandIndexAndCountForStatistics(int &bandIndex, int &bandCount){
+void ECWRasterBand::GetBandIndexAndCountForStatistics(int &bandIndex, int &bandCount) const
+{
     bandIndex = nBand-1;
     bandCount = poGDS->nBands;
     for (int i=0;i<poGDS->nBands;i++){
@@ -500,7 +489,7 @@ double ECWRasterBand::GetMinimum(int* pbSuccess)
             if ( poGDS->pStatistics != nullptr )
             {
                 NCSBandStats& bandStats = poGDS->pStatistics->BandsStats[nStatsBandIndex];
-                if ( bandStats.fMinVal == bandStats.fMinVal )
+                if (!std::isnan(bandStats.fMinVal))
                 {
                     if( pbSuccess )
                         *pbSuccess = TRUE;
@@ -527,7 +516,7 @@ double ECWRasterBand::GetMaximum(int* pbSuccess)
             if ( poGDS->pStatistics != nullptr )
             {
                 NCSBandStats& bandStats = poGDS->pStatistics->BandsStats[nStatsBandIndex];
-                if ( bandStats.fMaxVal == bandStats.fMaxVal )
+                if (!std::isnan(bandStats.fMaxVal))
                 {
                     if( pbSuccess )
                         *pbSuccess = TRUE;
@@ -549,7 +538,7 @@ CPLErr ECWRasterBand::GetStatistics( int bApproxOK, int bForce,
     int bForceCoalesced = bForce;
     // If file version is smaller than 3, there will be no statistics in the file. But if it is version 3 or higher we don't want underlying implementation to compute histogram
     // so we set bForceCoalesced to FALSE.
-    if (poGDS->psFileInfo->nFormatVersion >= 3){
+    if (poGDS->psFileInfo->nFormatVersion >= 3) {
         bForceCoalesced = FALSE;
     }
     // We check if we have PAM histogram. If we have them we return them. This will allow to override statistics stored in the file.
@@ -571,22 +560,22 @@ CPLErr ECWRasterBand::GetStatistics( int bApproxOK, int bForce,
     {
         bStatisticsFromFile = true;
         NCSBandStats& bandStats = poGDS->pStatistics->BandsStats[nStatsBandIndex];
-        if ( pdfMin != nullptr && bandStats.fMinVal == bandStats.fMinVal){
+        if ( pdfMin != nullptr && !std::isnan(bandStats.fMinVal)) {
             *pdfMin = bandStats.fMinVal;
         }else{
             bStatisticsFromFile = false;
         }
-        if ( pdfMax != nullptr && bandStats.fMaxVal == bandStats.fMaxVal){
+        if ( pdfMax != nullptr && !std::isnan(bandStats.fMaxVal)) {
             *pdfMax = bandStats.fMaxVal;
         }else{
             bStatisticsFromFile = false;
         }
-        if ( pdfMean != nullptr && bandStats.fMeanVal == bandStats.fMeanVal){
+        if ( pdfMean != nullptr && !std::isnan(bandStats.fMeanVal)) {
             *pdfMean = bandStats.fMeanVal;
         }else{
             bStatisticsFromFile = false;
         }
-        if ( padfStdDev != nullptr && bandStats.fStandardDev == bandStats.fStandardDev){
+        if ( padfStdDev != nullptr && !std::isnan(bandStats.fStandardDev)) {
             *padfStdDev  = bandStats.fStandardDev;
         }else{
             bStatisticsFromFile = false;
@@ -614,20 +603,18 @@ CPLErr ECWRasterBand::GetStatistics( int bApproxOK, int bForce,
             *padfStdDev = dfStdDev;
         }
         if ( pamError == CE_None){
-            CPLErr err = SetStatistics(dfMin,dfMax,dfMean,dfStdDev);
+            const CPLErr err = SetStatistics(dfMin,dfMax,dfMean,dfStdDev);
             if (err !=CE_None){
                 CPLError (CE_Warning, CPLE_AppDefined,
                     "SetStatistics failed in ECWRasterBand::GetDefaultHistogram. Statistics might not be saved in .ecw file." );
             }
             return CE_None;
-        }else{
-            //whatever happened we return.
-            return pamError;
         }
-    }else{
-        //no statistics and we are not forced to return.
-        return CE_Warning;
+        //whatever happened we return.
+        return pamError;
     }
+    //no statistics and we are not forced to return.
+    return CE_Warning;
 }
 
 /************************************************************************/
@@ -658,10 +645,10 @@ CPLErr ECWRasterBand::SetStatistics( double dfMin, double dfMax,
         }
     }
 
-    poGDS->pStatistics->BandsStats[nStatsBandIndex].fMinVal = (IEEE4) dfMin;
-    poGDS->pStatistics->BandsStats[nStatsBandIndex].fMaxVal = (IEEE4)dfMax;
-    poGDS->pStatistics->BandsStats[nStatsBandIndex].fMeanVal = (IEEE4)dfMean;
-    poGDS->pStatistics->BandsStats[nStatsBandIndex].fStandardDev = (IEEE4)dfStdDev;
+    poGDS->pStatistics->BandsStats[nStatsBandIndex].fMinVal = static_cast<IEEE4>(dfMin);
+    poGDS->pStatistics->BandsStats[nStatsBandIndex].fMaxVal = static_cast<IEEE4>(dfMax);
+    poGDS->pStatistics->BandsStats[nStatsBandIndex].fMeanVal = static_cast<IEEE4>(dfMean);
+    poGDS->pStatistics->BandsStats[nStatsBandIndex].fStandardDev = static_cast<IEEE4>(dfStdDev);
     poGDS->bStatisticsDirty = TRUE;
     //if we have PAM statistics we need to save them as well. Better option would be to remove them from PAM file but I don't know how to do that without messing in PAM internals.
     if ( hasPAMStatistics ){
@@ -692,9 +679,9 @@ CPLErr ECWRasterBand::OldIRasterIO( GDALRWFlag eRWFlag,
                                  GDALRasterIOExtraArg* psExtraArg )
 
 {
-    int          iBand, bDirect;
+    int          iBand;
     GByte        *pabyWorkBuffer = nullptr;
-    int nResFactor = 1 << (iOverview+1);
+    const int nResFactor = 1 << (iOverview+1);
 
     nXOff *= nResFactor;
     nYOff *= nResFactor;
@@ -707,12 +694,12 @@ CPLErr ECWRasterBand::OldIRasterIO( GDALRWFlag eRWFlag,
     int nRet = poGDS->TryWinRasterIO( eRWFlag,
                                nXOff, nYOff,
                                nXSize, nYSize,
-                               (GByte *) pData, nBufXSize, nBufYSize,
+                               static_cast<GByte *>(pData), nBufXSize, nBufYSize,
                                eBufType, 1, &nBand,
                                nPixelSpace, nLineSpace, 0 , psExtraArg);
     if( nRet == TRUE )
         return CE_None;
-    else if( nRet < 0 )
+    if( nRet < 0 )
         return CE_Failure;
 
 /* -------------------------------------------------------------------- */
@@ -732,12 +719,12 @@ CPLErr ECWRasterBand::OldIRasterIO( GDALRWFlag eRWFlag,
 /*      Can we perform direct loads, or must we load into a working     */
 /*      buffer, and transform?                                          */
 /* -------------------------------------------------------------------- */
-    int     nRawPixelSize = GDALGetDataTypeSize(poGDS->eRasterDataType) / 8;
+    const int     nRawPixelSize = GDALGetDataTypeSize(poGDS->eRasterDataType) / 8;
 
-    bDirect = nPixelSpace == 1 && eBufType == GDT_Byte
+    int bDirect = nPixelSpace == 1 && eBufType == GDT_Byte
         && nNewXSize == nBufXSize && nNewYSize == nBufYSize;
     if( !bDirect )
-        pabyWorkBuffer = (GByte *) CPLMalloc(nNewXSize * nRawPixelSize);
+        pabyWorkBuffer = static_cast<GByte *>(CPLMalloc(nNewXSize * nRawPixelSize));
 
 /* -------------------------------------------------------------------- */
 /*      Establish access at the desired resolution.                     */
@@ -747,7 +734,7 @@ CPLErr ECWRasterBand::OldIRasterIO( GDALRWFlag eRWFlag,
     iBand = nBand-1;
     poGDS->nBandIndexToPromoteTo8Bit = ( bPromoteTo8Bit ) ? 0 : -1;
     // TODO: Fix writable strings issue.
-    CNCSError oErr = poGDS->poFileView->SetView( 1, (unsigned int *) (&iBand),
+    CNCSError oErr = poGDS->poFileView->SetView( 1, reinterpret_cast<unsigned int *>(&iBand),
                                                  nXOff, nYOff,
                                                  nXOff + nXSize - 1,
                                                  nYOff + nYSize - 1,
@@ -765,8 +752,8 @@ CPLErr ECWRasterBand::OldIRasterIO( GDALRWFlag eRWFlag,
 /*      Supersampling is not supported by the ECW API, so we will do    */
 /*      it ourselves.                                                   */
 /* -------------------------------------------------------------------- */
-    double  dfSrcYInc = (double)nNewYSize / nBufYSize;
-    double  dfSrcXInc = (double)nNewXSize / nBufXSize;
+    double  dfSrcYInc = static_cast<double>(nNewYSize) / nBufYSize;
+    double  dfSrcXInc = static_cast<double>(nNewXSize) / nBufXSize;
     int         iSrcLine, iDstLine;
     CPLErr eErr = CE_None;
 
@@ -1017,7 +1004,7 @@ ECWDataset::ECWDataset(int bIsJPEG2000In)
 ECWDataset::~ECWDataset()
 
 {
-    FlushCache();
+    GDALPamDataset::FlushCache();
     CleanupWindow();
 
 #if ECWSDK_VERSION>=50
@@ -1070,6 +1057,9 @@ ECWDataset::~ECWDataset()
     // from the GDAL destructor.
     if( poFileView != nullptr && !GDALIsInGlobalDestructor() )
     {
+#if ECWSDK_VERSION >= 55
+        delete poFileView;
+#else
         VSIIOStream *poUnderlyingIOStream = (VSIIOStream *)nullptr;
 
         if( bUsingCustomStream )
@@ -1083,6 +1073,8 @@ ECWDataset::~ECWDataset()
             if( --poUnderlyingIOStream->nFileViewCount == 0 )
                 delete poUnderlyingIOStream;
         }
+#endif
+        poFileView = nullptr;
     }
 
     /* WriteHeader() must be called after closing the file handle to work */
@@ -2549,11 +2541,21 @@ CNCSJP2FileView *ECWDataset::OpenFileView( const char *pszDatasetName,
         {
             CPLDebug( "ECW", "Got mutex." );
         }
-        VSIIOStream *poIOStream = new VSIIOStream();
-        poIOStream->Access( fpVSIL, FALSE, TRUE, pszDatasetName, 0, -1 );
-
+        
         poFileView = new CNCSJP2FileView();
-        oErr = poFileView->Open( poIOStream, bProgressive );
+
+#if ECWSDK_VERSION >= 55
+        NCS::CString streamName(pszDatasetName);
+        auto vsiIoStream = NCS::CView::FindSteamByStreamNameFromOpenDatasets(streamName);
+        if (!vsiIoStream) {
+            vsiIoStream = std::make_shared<VSIIOStream>();
+            std::static_pointer_cast<VSIIOStream>(vsiIoStream)->Access(fpVSIL, FALSE, TRUE, pszDatasetName, 0, -1);
+        }
+        oErr = poFileView->Open(vsiIoStream, bProgressive);
+#else
+        auto vsiIoStream = new VSIIOStream();
+        vsiIoStream->Access(fpVSIL, FALSE, TRUE, pszDatasetName, 0, -1);
+        oErr = poFileView->Open(vsiIoStream, bProgressive);
 
         // The CNCSJP2FileView (poFileView) object may not use the iostream
         // (poIOStream) passed to the CNCSJP2FileView::Open() method if an
@@ -2575,14 +2577,15 @@ CNCSJP2FileView *ECWDataset::OpenFileView( const char *pszDatasetName,
         if ( poUnderlyingIOStream )
             poUnderlyingIOStream->nFileViewCount++;
 
-        if ( poIOStream != poUnderlyingIOStream )
+        if ( vsiIoStream != poUnderlyingIOStream )
         {
-            delete poIOStream;
+            delete vsiIoStream;
         }
         else
         {
             bUsingCustomStream = TRUE;
         }
+#endif
 
         CPLReleaseMutex( hECWDatasetMutex );
 
diff --git a/gdal/frmts/ecw/gdal_ecw.h b/gdal/frmts/ecw/gdal_ecw.h
index 1b479485a33..142a63a21fa 100644
--- a/gdal/frmts/ecw/gdal_ecw.h
+++ b/gdal/frmts/ecw/gdal_ecw.h
@@ -89,7 +89,10 @@ class JP2UserBox final: public CNCSJP2Box {
 
     virtual ~JP2UserBox();
 
-#if ECWSDK_VERSION >= 40
+#if ECWSDK_VERSION >= 55
+    CNCSError Parse(NCS::SDK::CFileBase &JP2File, const NCS::CIOStreamPtr &Stream) override;
+    CNCSError UnParse(NCS::SDK::CFileBase &JP2File, const NCS::CIOStreamPtr &Stream) override;
+#elif ECWSDK_VERSION >= 40
     virtual CNCSError Parse(NCS::SDK::CFileBase &JP2File,
                              NCS::CIOStream &Stream) override;
     virtual CNCSError UnParse(NCS::SDK::CFileBase &JP2File,
@@ -116,9 +119,10 @@ class JP2UserBox final: public CNCSJP2Box {
 /************************************************************************/
 
 class VSIIOStream final: public CNCSJPCIOStream
-
 {
-  private:
+#if ECWSDK_VERSION >= 54
+    NCS_DELETE_ALL_COPY_AND_MOVE(VSIIOStream)
+#endif
     char     *m_Filename;
   public:
 
@@ -131,12 +135,13 @@ class VSIIOStream final: public CNCSJPCIOStream
 
     int      nCOMState;
     int      nCOMLength;
-    GByte    abyCOMType[2];
+    GByte    abyCOMType[2]{};
 
     /* To fix ‘virtual bool NCS::CIOStream::Read(INT64, void*, UINT32)’ was hidden' with SDK 5 */
     using CNCSJPCIOStream::Read;
 
-    VSIIOStream() : m_Filename(nullptr){
+    VSIIOStream() : m_Filename(nullptr)
+    {
         nFileViewCount = 0;
         startOfJPData = 0;
         lengthOfJPData = -1;
@@ -152,13 +157,13 @@ class VSIIOStream final: public CNCSJPCIOStream
         abyCOMType[1] = 0;
     }
     virtual ~VSIIOStream() {
-        Close();
+        VSIIOStream::Close();
         if (m_Filename!=nullptr){
             CPLFree(m_Filename);
         }
     }
 
-    virtual CNCSError Close() override {
+    CNCSError Close() override {
         CNCSError oErr = CNCSJPCIOStream::Close();
         if( fpVSIL != nullptr )
         {
@@ -169,18 +174,17 @@ class VSIIOStream final: public CNCSJPCIOStream
     }
 
 #if ECWSDK_VERSION >= 40
-    virtual VSIIOStream *Clone() override {
+    VSIIOStream *Clone() override {
         CPLDebug( "ECW", "VSIIOStream::Clone()" );
         VSILFILE *fpNewVSIL = VSIFOpenL( m_Filename, "rb" );
         if (fpNewVSIL == nullptr)
         {
             return nullptr;
-        }else
-        {
-            VSIIOStream *pDst = new VSIIOStream();
-            pDst->Access(fpNewVSIL, bWritable, bSeekable, m_Filename, startOfJPData, lengthOfJPData);
-            return pDst;
         }
+        
+        VSIIOStream *pDst = new VSIIOStream();
+        pDst->Access(fpNewVSIL, bWritable, bSeekable, m_Filename, startOfJPData, lengthOfJPData);
+        return pDst;
     }
 #endif /* ECWSDK_VERSION >= 4 */
 
@@ -199,9 +203,10 @@ class VSIIOStream final: public CNCSJPCIOStream
         // if it does not have a path to a real directory, we will
         // substitute something.
         CPLString osFilenameUsed = pszFilename;
+#if ECWSDK_VERSION < 55
         CPLString osPath = CPLGetPath( pszFilename );
         struct stat sStatBuf;
-        if( osPath != "" && stat( osPath, &sStatBuf ) != 0 )
+        if( !osPath.empty() && stat( osPath, &sStatBuf ) != 0 )
         {
             osFilenameUsed = CPLGenerateTempFilename( nullptr );
             // try to preserve the extension.
@@ -212,6 +217,8 @@ class VSIIOStream final: public CNCSJPCIOStream
             }
             CPLDebug( "ECW", "Using filename '%s' for temporary directory determination purposes.", osFilenameUsed.c_str() );
         }
+#endif
+
 #ifdef WIN32
         if( CSLTestBoolean( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
         {
@@ -662,7 +669,7 @@ class ECWRasterBand final: public GDALPamRasterBand
                                int nBufXSize, int nBufYSize,
                                GDALDataType eDT, char **papszOptions ) override;
 #if ECWSDK_VERSION >= 50
-    void GetBandIndexAndCountForStatistics(int &bandIndex, int &bandCount);
+    void GetBandIndexAndCountForStatistics(int &bandIndex, int &bandCount) const;
     virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
                                     int *pnBuckets, GUIntBig ** ppanHistogram,
                                     int bForce,
diff --git a/gdal/frmts/ecw/jp2userbox.cpp b/gdal/frmts/ecw/jp2userbox.cpp
index 2829835a5af..367cc696cfb 100644
--- a/gdal/frmts/ecw/jp2userbox.cpp
+++ b/gdal/frmts/ecw/jp2userbox.cpp
@@ -72,7 +72,7 @@ void JP2UserBox::SetData( int nLengthIn, const unsigned char *pabyDataIn )
         CPLFree( pabyData );
 
     nDataLength = nLengthIn;
-    pabyData = (unsigned char *) CPLMalloc(nDataLength);
+    pabyData = static_cast<unsigned char *>(CPLMalloc(nDataLength));
     memcpy( pabyData, pabyDataIn, nDataLength );
 
     m_bValid = true;
@@ -94,8 +94,10 @@ void JP2UserBox::UpdateXLBox()
 /*                                                                      */
 /*      Parse box, and data contents from file into memory.             */
 /************************************************************************/
-
-#if ECWSDK_VERSION >= 40
+#if ECWSDK_VERSION >= 55
+CNCSError JP2UserBox::Parse(CPL_UNUSED NCS::SDK::CFileBase &JP2File, 
+                            CPL_UNUSED const NCS::CIOStreamPtr &Stream)
+#elif ECWSDK_VERSION >= 40
 CNCSError JP2UserBox::Parse( CPL_UNUSED NCS::SDK::CFileBase &JP2File,
                              CPL_UNUSED NCS::CIOStream &Stream )
 #else
@@ -113,8 +115,10 @@ CNCSError JP2UserBox::Parse( CPL_UNUSED class CNCSJP2File &JP2File,
 /*                                                                      */
 /*      Write box meta information, and data to file.                   */
 /************************************************************************/
-
-#if ECWSDK_VERSION >= 40
+#if ECWSDK_VERSION >= 55
+CNCSError JP2UserBox::UnParse(NCS::SDK::CFileBase &JP2File,
+                              const NCS::CIOStreamPtr &Stream)
+#elif ECWSDK_VERSION >= 40
 CNCSError JP2UserBox::UnParse( NCS::SDK::CFileBase &JP2File,
                                NCS::CIOStream &Stream )
 #else
@@ -136,9 +140,12 @@ CNCSError JP2UserBox::UnParse( class CNCSJP2File &JP2File,
 #else
     Error = CNCSSDKBox::UnParse(JP2File, Stream);
 #endif
-//    NCSJP2_CHECKIO_BEGIN(Error, Stream);
+
+#if ECWSDK_VERSION >= 55
+    Stream->Write(pabyData, nDataLength);
+#else
     Stream.Write(pabyData, nDataLength);
-//    NCSJP2_CHECKIO_END();
+#endif
 
     return Error;
 }
diff --git a/gdal/nmake.opt b/gdal/nmake.opt
index 17f252e44b5..910acb17987 100644
--- a/gdal/nmake.opt
+++ b/gdal/nmake.opt
@@ -342,13 +342,34 @@ JPEG12_SUPPORTED = 1
 # NCSEcw4.lib, and add -DHAVE_COMPRESS to ECWFLAGS.  The ECWDIR setting will
 # also need some adjustment. 
 
-# Uncomment the following and update to enable ECW read support with the 5.0 SDK
-#ECWDIR  =  "c:\Intergraph\ecwsdk5"
-#ECWFLAGS = -DECWSDK_VERSION=50 \
-#       -I$(ECWDIR)\include \
-#       -I$(ECWDIR)\include/NCSECW/api -I$(ECWDIR)\include/NCSECW/jp2 \
-#       -I$(ECWDIR)\include/NCSECW/ecw
-#ECWLIB  =  $(ECWDIR)\lib\vc90\win32\NCSEcw.lib
+# Uncomment the following and update to enable ECW read support with the 5.0+ SDK
+#!IF $(MSVC_VER) < 1910
+#ECW_PLATFORM_TOOLSET_DIR = vc140
+#!ELSE
+#ECW_PLATFORM_TOOLSET_DIR = vc141
+#!ENDIF
+
+#!IF "$(DEBUG)" == "1"
+#ECW_LIB_DEBUG_SUFFIX = d
+#!ENDIF
+
+#!IF "$(WIN64)" == "1"
+#ECW_PLATFORM_DIR = x64
+#!ELSE
+#ECW_PLATFORM_DIR = Win32
+#!ENDIF
+
+#ECWDIR = "C:/Hexagon/ERDAS ECW JPEG 2000 SDK 5.4.0/Desktop Read-Only"
+#ECWDIR = "C:/Hexagon/ERDAS ECW JPEG 2000 SDK 5.5.0/Desktop Read-Only"
+#ECW_MAJOR_MINOR_VERSION = 55
+
+#ECW_INCLUDES = -I$(ECWDIR)/include \
+#       -I$(ECWDIR)/include/NCSEcw/API -I$(ECWDIR)/include/NCSEcw/JP2 \
+#       -I$(ECWDIR)/include/NCSEcw/ECW
+
+#ECW_ENABLE_COMPRESSION = -DHAVE_COMPRESS
+#ECWFLAGS = -DECWSDK_VERSION=$(ECW_MAJOR_MINOR_VERSION) $(ECW_ENABLE_COMPRESSION) $(ECW_INCLUDES)
+#ECWLIB = $(ECWDIR)\lib\$(ECW_PLATFORM_TOOLSET_DIR)\$(ECW_PLATFORM_DIR)\NCSEcw$(ECW_LIB_LINK_SUFFIX).lib
 
 # To build ECW support as a plugin uncomment the following, and make sure
 # to do "nmake /f makefile.vc plugin" in gdal/frmts/ecw and copy the two
openSUSE Build Service is sponsored by