LCOV - code coverage report
Current view: directory - frmts/ecw - ecwcreatecopy.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 489 395 80.8 %
Date: 2013-03-30 Functions: 40 27 67.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: ecwcreatecopy.cpp 25804 2013-03-25 18:50:26Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL ECW Driver
       5                 :  * Purpose:  ECW CreateCopy method implementation.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2001, 2004, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "gdal_ecw.h"
      31                 : #include "ogr_spatialref.h"
      32                 : 
      33                 : CPL_CVSID("$Id: ecwcreatecopy.cpp 25804 2013-03-25 18:50:26Z rouault $");
      34                 : 
      35                 : #if defined(FRMT_ecw) && defined(HAVE_COMPRESS)
      36                 : 
      37                 : class GDALECWCompressor : public CNCSFile {
      38                 : 
      39                 : public:
      40                 :     GDALECWCompressor();
      41                 :     virtual ~GDALECWCompressor();
      42                 :     virtual CNCSError WriteReadLine(UINT32 nNextLine, void **ppInputArray);
      43                 : #if ECWSDK_VERSION>=50
      44                 :     virtual void WriteStatus(IEEE4 fPercentComplete, const NCS::CString &sStatusText, const CompressionCounters &Counters);
      45                 : #else 
      46                 :   virtual void WriteStatus(UINT32 nCurrentLine);
      47                 :   
      48                 : #endif
      49                 : 
      50                 :     virtual bool WriteCancel();
      51                 : 
      52                 :     CPLErr  Initialize( const char *pszFilename, char **papszOptions, 
      53                 :                         int nXSize, int nYSize, int nBands, const char * const * papszBandDescriptions, int bRGBColorSpace,
      54                 :                         GDALDataType eType, 
      55                 :                         const char *pszWKT, double *padfGeoTransform,
      56                 :                         int nGCPCount, const GDAL_GCP *pasGCPList,
      57                 :                         int bIsJPEG2000 );
      58                 :     CPLErr  CloseDown();
      59                 : 
      60                 :     CPLErr  PrepareCoverageBox( const char *pszWKT, double *padfGeoTransform );
      61                 :     CPLErr  WriteJP2Box( GDALJP2Box * );
      62                 :     CPLErr  WriteLineBIL(UINT16 nBands, void **ppOutputLine, UINT32 *pLineSteps = NULL);
      63               0 :     virtual NCSEcwCellType WriteReadLineGetCellType() {
      64               0 :         return sFileInfo.eCellType;
      65                 :     }
      66                 : #ifdef ECW_FW
      67                 :     CNCSJP2File::CNCSJPXAssocBox  m_oGMLAssoc;
      68                 : #endif
      69                 : 
      70                 :     // Data
      71                 : 
      72                 :     GDALDataset *m_poSrcDS;
      73                 : 
      74                 :     VSIIOStream m_OStream;
      75                 :     int m_nPercentComplete;
      76                 : 
      77                 :     int m_bCancelled;
      78                 : 
      79                 :     GDALProgressFunc  pfnProgress;
      80                 :     void             *pProgressData;
      81                 : 
      82                 :     
      83                 :     GDALDataType eWorkDT;
      84                 : 
      85                 :     JP2UserBox** papoJP2UserBox;
      86                 :     int          nJP2UserBox;
      87                 :     
      88                 : private : 
      89                 :     NCSFileViewFileInfoEx sFileInfo;
      90                 : };
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                         GDALECWCompressor()                          */
      94                 : /************************************************************************/
      95                 : 
      96              50 : GDALECWCompressor::GDALECWCompressor()
      97                 : 
      98                 : {
      99              50 :     m_poSrcDS = NULL;
     100              50 :     m_nPercentComplete = -1;
     101              50 :     m_bCancelled = FALSE;
     102              50 :     pfnProgress = GDALDummyProgress;
     103              50 :     pProgressData = NULL;
     104              50 :     papoJP2UserBox = NULL;
     105              50 :     nJP2UserBox = 0;
     106              50 :     NCSInitFileInfoEx(&sFileInfo);
     107              50 : }
     108                 : 
     109                 : /************************************************************************/
     110                 : /*                         ~GDALECWCompressor()                         */
     111                 : /************************************************************************/
     112                 : 
     113              50 : GDALECWCompressor::~GDALECWCompressor()
     114                 : 
     115                 : {
     116                 :     int i;
     117              85 :     for(i=0;i<nJP2UserBox;i++)
     118              35 :         delete papoJP2UserBox[i];
     119              50 :     CPLFree(papoJP2UserBox);
     120              50 : }
     121                 : 
     122                 : /************************************************************************/
     123                 : /*                             CloseDown()                              */
     124                 : /************************************************************************/
     125                 : 
     126              20 : CPLErr GDALECWCompressor::CloseDown()
     127                 : 
     128                 : {
     129              60 :     for( int i = 0; i < sFileInfo.nBands; i++ )
     130                 :     {
     131              40 :         CPLFree( sFileInfo.pBands[i].szDesc );
     132                 :     }
     133              20 :     CPLFree( sFileInfo.pBands );
     134                 : 
     135              20 :     Close( true );
     136              20 :     m_OStream.Close();
     137                 : 
     138              20 :     return CE_None;
     139                 : }
     140                 : 
     141                 : /************************************************************************/
     142                 : /*                           WriteReadLine()                            */
     143                 : /************************************************************************/
     144                 : 
     145            1714 : CNCSError GDALECWCompressor::WriteReadLine( UINT32 nNextLine, 
     146                 :                                             void **ppInputArray )
     147                 : 
     148                 : {
     149                 :     int    iBand, *panBandMap;
     150                 :     CPLErr eErr;
     151                 :     GByte *pabyLineBuf;
     152            1714 :     int nWordSize = GDALGetDataTypeSize( eWorkDT ) / 8;
     153                 : 
     154            1714 :     panBandMap = (int *) CPLMalloc(sizeof(int) * sFileInfo.nBands);
     155            4598 :     for( iBand = 0; iBand < sFileInfo.nBands; iBand++ )
     156            2884 :         panBandMap[iBand] = iBand+1;
     157                 : 
     158                 :     pabyLineBuf = (GByte *) CPLMalloc( sFileInfo.nSizeX * sFileInfo.nBands
     159            1714 :                                        * nWordSize );
     160                 : 
     161                 :     eErr = m_poSrcDS->RasterIO( GF_Read, 0, nNextLine, sFileInfo.nSizeX, 1, 
     162                 :                                 pabyLineBuf, sFileInfo.nSizeX, 1, 
     163                 :                                 eWorkDT, 
     164                 :                                 sFileInfo.nBands, panBandMap,
     165            1714 :                                 nWordSize, 0, nWordSize * sFileInfo.nSizeX );
     166                 : 
     167            4598 :     for( iBand = 0; iBand < (int) sFileInfo.nBands; iBand++ )
     168                 :     {
     169                 :         memcpy( ppInputArray[iBand],
     170                 :                 pabyLineBuf + nWordSize * sFileInfo.nSizeX * iBand, 
     171            2884 :                 nWordSize * sFileInfo.nSizeX );
     172                 :     }
     173                 : 
     174            1714 :     CPLFree( pabyLineBuf );
     175            1714 :     CPLFree( panBandMap );
     176                 : 
     177            1714 :     if( eErr == CE_None )
     178            1714 :         return NCS_SUCCESS;
     179                 :     else
     180               0 :         return NCS_FILEIO_ERROR;
     181                 : }
     182                 : 
     183                 : /************************************************************************/
     184                 : /*                            WriteStatus()                             */
     185                 : /************************************************************************/
     186                 : #if ECWSDK_VERSION>=50
     187                 : void GDALECWCompressor::WriteStatus(IEEE4 fPercentComplete, const NCS::CString &sStatusText, const CompressionCounters &Counters) 
     188                 : {
     189                 :   char szBuff[2048];
     190                 :   sStatusText.utf8_str(szBuff, 2047);
     191                 :   szBuff[2047] = '\0';
     192                 : 
     193                 :   m_bCancelled = !pfnProgress( 
     194                 :                       fPercentComplete/100.0, 
     195                 :                       szBuff, 
     196                 :                       pProgressData );
     197                 : }
     198                 : #else
     199                 : 
     200            1714 : void GDALECWCompressor::WriteStatus( UINT32 nCurrentLine )
     201                 : 
     202                 : {
     203                 :     m_bCancelled = 
     204                 :         !pfnProgress( nCurrentLine / (float) sFileInfo.nSizeY, 
     205            1714 :                       NULL, pProgressData );
     206            1714 : }
     207                 : #endif 
     208                 : /************************************************************************/
     209                 : /*                            WriteCancel()                             */
     210                 : /************************************************************************/
     211                 : 
     212            1714 : bool GDALECWCompressor::WriteCancel()
     213                 : 
     214                 : {
     215            1714 :     return (bool) m_bCancelled;
     216                 : }
     217                 : 
     218                 : /************************************************************************/
     219                 : /*                         PrepareCoverageBox()                         */
     220                 : /************************************************************************/
     221                 : 
     222               0 : CPLErr  GDALECWCompressor::PrepareCoverageBox( const char *pszWKT, 
     223                 :                                                double *padfGeoTransform )
     224                 : 
     225                 : {
     226                 : #ifndef ECW_FW
     227               0 :     return CE_Failure;
     228                 : #else
     229                 : /* -------------------------------------------------------------------- */
     230                 : /*      Try do determine a PCS or GCS code we can use.                  */
     231                 : /* -------------------------------------------------------------------- */
     232                 :     OGRSpatialReference oSRS;
     233                 :     char *pszWKTCopy = (char *) pszWKT;
     234                 :     int nEPSGCode = 0;
     235                 :     char szSRSName[100];
     236                 : 
     237                 :     if( oSRS.importFromWkt( &pszWKTCopy ) != OGRERR_NONE )
     238                 :         return CE_Failure;
     239                 : 
     240                 :     if( oSRS.IsProjected() )
     241                 :     {
     242                 :         const char *pszAuthName = oSRS.GetAuthorityName( "PROJCS" );
     243                 : 
     244                 :         if( pszAuthName != NULL && EQUAL(pszAuthName,"epsg") )
     245                 :         {
     246                 :             nEPSGCode = atoi(oSRS.GetAuthorityCode( "PROJCS" ));
     247                 :         }
     248                 :     }
     249                 :     else if( oSRS.IsGeographic() )
     250                 :     {
     251                 :         const char *pszAuthName = oSRS.GetAuthorityName( "GEOGCS" );
     252                 : 
     253                 :         if( pszAuthName != NULL && EQUAL(pszAuthName,"epsg") )
     254                 :         {
     255                 :             nEPSGCode = atoi(oSRS.GetAuthorityCode( "GEOGCS" ));
     256                 :         }
     257                 :     }
     258                 : 
     259                 :     if( nEPSGCode != 0 )
     260                 :         sprintf( szSRSName, "urn:ogc:def:crs:EPSG::%d", nEPSGCode );
     261                 :     else
     262                 :         strcpy( szSRSName, 
     263                 :                 "gmljp2://xml/CRSDictionary.gml#ogrcrs1" );
     264                 : 
     265                 : /* -------------------------------------------------------------------- */
     266                 : /*      For now we hardcode for a minimal instance format.              */
     267                 : /* -------------------------------------------------------------------- */
     268                 :     char szDoc[4000];
     269                 : 
     270                 :     sprintf( szDoc, 
     271                 : "<gml:FeatureCollection\n"
     272                 : "   xmlns:gml=\"http://www.opengis.net/gml\"\n"
     273                 : "   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
     274                 : "   xsi:schemaLocation=\"http://www.opengis.net/gml http://www.math.ubc.ca/~burggraf/gml/gml4jp2.xsd\">\n"
     275                 : "  <gml:boundedBy>\n"
     276                 : "    <gml:Null>withheld</gml:Null>\n"
     277                 : "  </gml:boundedBy>\n"
     278                 : "  <gml:featureMember>\n"
     279                 : "    <gml:FeatureCollection>\n"
     280                 : "      <gml:featureMember>\n"
     281                 : "        <gml:RectifiedGridCoverage dimension=\"2\" gml:id=\"RGC0001\">\n"
     282                 : "          <gml:rectifiedGridDomain>\n"
     283                 : "            <gml:RectifiedGrid dimension=\"2\">\n"
     284                 : "              <gml:limits>\n"
     285                 : "                <gml:GridEnvelope>\n"
     286                 : "                  <gml:low>0 0</gml:low>\n"
     287                 : "                  <gml:high>%d %d</gml:high>\n"
     288                 : "                </gml:GridEnvelope>\n"
     289                 : "              </gml:limits>\n"
     290                 : "              <gml:axisName>x</gml:axisName>\n"
     291                 : "              <gml:axisName>y</gml:axisName>\n"
     292                 : "              <gml:origin>\n"
     293                 : "                <gml:Point gml:id=\"P0001\" srsName=\"%s\">\n"
     294                 : "                  <gml:pos>%.15g %.15g</gml:pos>\n"
     295                 : "                </gml:Point>\n"
     296                 : "              </gml:origin>\n"
     297                 : "              <gml:offsetVector srsName=\"%s\">%.15g %.15g</gml:offsetVector>\n"
     298                 : "              <gml:offsetVector srsName=\"%s\">%.15g %.15g</gml:offsetVector>\n"
     299                 : "            </gml:RectifiedGrid>\n"
     300                 : "          </gml:rectifiedGridDomain>\n"
     301                 : "          <gml:rangeSet>\n"
     302                 : "            <gml:File>\n"
     303                 : "              <gml:fileName>urn:ogc:tc:gmljp2:codestream:0</gml:fileName>\n"
     304                 : "              <gml:fileStructure>Record Interleaved</gml:fileStructure>\n"
     305                 : "            </gml:File>\n"
     306                 : "          </gml:rangeSet>\n"
     307                 : "        </gml:RectifiedGridCoverage>\n"
     308                 : "      </gml:featureMember>\n"
     309                 : "    </gml:FeatureCollection>\n"
     310                 : "  </gml:featureMember>\n"
     311                 : "</gml:FeatureCollection>\n",
     312                 :              sFileInfo.nSizeX-1, sFileInfo.nSizeY-1, 
     313                 :              szSRSName,
     314                 :              padfGeoTransform[0] + padfGeoTransform[1] * 0.5
     315                 :                                  + padfGeoTransform[4] * 0.5, 
     316                 :              padfGeoTransform[3] + padfGeoTransform[2] * 0.5
     317                 :                                  + padfGeoTransform[5] * 0.5,
     318                 :              szSRSName, 
     319                 :              padfGeoTransform[1], padfGeoTransform[2],
     320                 :              szSRSName,
     321                 :              padfGeoTransform[4], padfGeoTransform[5] );
     322                 : 
     323                 : /* -------------------------------------------------------------------- */
     324                 : /*      If we need a user defined CRSDictionary entry, prepare it       */
     325                 : /*      here.                                                           */
     326                 : /* -------------------------------------------------------------------- */
     327                 :     char *pszDictBox = NULL;
     328                 : 
     329                 :     if( nEPSGCode == 0 )
     330                 :     {
     331                 :         char *pszGMLDef = NULL;
     332                 : 
     333                 :         if( oSRS.exportToXML( &pszGMLDef, NULL ) == OGRERR_NONE )
     334                 :         {
     335                 :             pszDictBox = (char *) CPLMalloc(strlen(pszGMLDef) + 4000);
     336                 :             
     337                 :             sprintf( pszDictBox, 
     338                 : "<gml:Dictionary gml:id=\"CRSU1\" \n"
     339                 : "        xmlns:gml=\"http://www.opengis.net/gml\"\n"
     340                 : "        xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
     341                 : "        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
     342                 : "  <gml:dictionaryEntry>\n"
     343                 : "%s\n"
     344                 : "  </gml:dictionaryEntry>\n"
     345                 : "</gml:Dictionary>\n",
     346                 :                      pszGMLDef );
     347                 :         }
     348                 :         CPLFree( pszGMLDef );
     349                 :     }
     350                 : 
     351                 : /* -------------------------------------------------------------------- */
     352                 : /*      Setup the various required boxes.                               */
     353                 : /* -------------------------------------------------------------------- */
     354                 :     JP2UserBox *poGMLData;
     355                 :     CNCSJP2File::CNCSJPXAssocBox *poAssoc;
     356                 :     CNCSJP2File::CNCSJPXLabelBox *poLabel;
     357                 : 
     358                 :     poLabel = new CNCSJP2File::CNCSJPXLabelBox();
     359                 :     poLabel->SetLabel( "gml.data" );
     360                 :     poLabel->m_bValid = true;
     361                 :     m_oGMLAssoc.m_OtherBoxes.push_back( poLabel );
     362                 :     m_oGMLAssoc.m_OwnedBoxes.push_back( poLabel );
     363                 :     
     364                 :     poAssoc = new CNCSJP2File::CNCSJPXAssocBox();
     365                 :     m_oGMLAssoc.m_OtherBoxes.push_back( poAssoc );
     366                 :     m_oGMLAssoc.m_OwnedBoxes.push_back( poAssoc );
     367                 :     poAssoc->m_bValid = true;
     368                 : 
     369                 :     poLabel = new CNCSJP2File::CNCSJPXLabelBox();
     370                 :     poLabel->SetLabel( "gml.root-instance" );
     371                 :     poLabel->m_bValid = true;
     372                 :     poAssoc->m_OtherBoxes.push_back( poLabel );
     373                 :     poAssoc->m_OwnedBoxes.push_back( poLabel );
     374                 : 
     375                 :     poGMLData = new JP2UserBox();
     376                 :     poGMLData->m_nTBox = 'xml '; /* Is it correct on a big-endian host ? Does ECW work on big-endian hosts ;-) */
     377                 :     poGMLData->SetData( strlen( szDoc ), (unsigned char *) szDoc );
     378                 :     poAssoc->m_OtherBoxes.push_back( poGMLData );
     379                 :     poAssoc->m_OwnedBoxes.push_back( poGMLData );
     380                 : 
     381                 :     if( pszDictBox != NULL )
     382                 :     {
     383                 :         poAssoc = new CNCSJP2File::CNCSJPXAssocBox();
     384                 :         m_oGMLAssoc.m_OtherBoxes.push_back( poAssoc );
     385                 :         m_oGMLAssoc.m_OwnedBoxes.push_back( poAssoc );
     386                 :         poAssoc->m_bValid = true;
     387                 :         
     388                 :         poLabel = new CNCSJP2File::CNCSJPXLabelBox();
     389                 :         poLabel->SetLabel( "CRSDictionary.gml" );
     390                 :         poLabel->m_bValid = true;
     391                 :         poAssoc->m_OtherBoxes.push_back( poLabel );
     392                 :         poAssoc->m_OwnedBoxes.push_back( poLabel );
     393                 : 
     394                 :         poGMLData = new JP2UserBox();
     395                 :         poGMLData->m_nTBox = 'xml '; /* Is it correct on a big-endian host ? Does ECW work on big-endian hosts ;-) */
     396                 :         poGMLData->SetData( strlen(pszDictBox), 
     397                 :                             (unsigned char *) pszDictBox );
     398                 :         poAssoc->m_OtherBoxes.push_back( poGMLData );
     399                 :         poAssoc->m_OwnedBoxes.push_back( poGMLData );
     400                 : 
     401                 :         CPLFree( pszDictBox );
     402                 :     }
     403                 : 
     404                 :     m_oGMLAssoc.m_bValid = true;
     405                 :     AddBox( &m_oGMLAssoc );
     406                 : 
     407                 :     return CE_None;
     408                 : #endif /* def ECW_FW */
     409                 : }
     410                 : 
     411                 : /************************************************************************/
     412                 : /*                            WriteJP2Box()                             */
     413                 : /************************************************************************/
     414                 : 
     415              36 : CPLErr GDALECWCompressor::WriteJP2Box( GDALJP2Box * poBox )
     416                 : 
     417                 : {
     418                 :     JP2UserBox  *poECWBox;
     419                 : 
     420              36 :     if( poBox == NULL )
     421               1 :         return CE_None;
     422                 : 
     423              35 :     poECWBox = new JP2UserBox();
     424              35 :     memcpy( &(poECWBox->m_nTBox), poBox->GetType(), 4 );
     425              35 :     CPL_MSBPTR32( &(poECWBox->m_nTBox) );
     426                 : 
     427                 :     poECWBox->SetData( (int) poBox->GetDataLength(), 
     428              35 :                        poBox->GetWritableData() );
     429                 : 
     430              35 :     AddBox( poECWBox );
     431                 : 
     432              70 :     delete poBox;
     433                 : 
     434                 :     papoJP2UserBox =(JP2UserBox**) CPLRealloc(papoJP2UserBox,
     435              35 :                                     (nJP2UserBox + 1) * sizeof(JP2UserBox*));
     436              35 :     papoJP2UserBox[nJP2UserBox] = poECWBox;
     437              35 :     nJP2UserBox ++;
     438                 : 
     439              35 :     return CE_None;
     440                 : }
     441                 : 
     442                 : /************************************************************************/
     443                 : /*                            WriteLineBIL()                            */
     444                 : /************************************************************************/
     445                 : 
     446             200 : CPLErr  GDALECWCompressor::WriteLineBIL(UINT16 nBands, void **ppOutputLine, UINT32 *pLineSteps){
     447                 : 
     448             200 :     CNCSError oError = CNCSFile::WriteLineBIL(sFileInfo.eCellType,nBands, ppOutputLine, pLineSteps);
     449                 : 
     450             200 :     if( oError.GetErrorNumber() != NCS_SUCCESS )
     451                 :     {
     452               0 :         ECWReportError(oError, "Scanline write write failed.\n");
     453               0 :         return CE_Failure;
     454                 :     }
     455             200 :     return CE_None;
     456                 : }
     457                 : /************************************************************************/
     458                 : /*                             Initialize()                             */
     459                 : /*                                                                      */
     460                 : /*      Initialize compressor output.                                   */
     461                 : /************************************************************************/
     462                 : 
     463              24 : CPLErr GDALECWCompressor::Initialize( 
     464                 :     const char *pszFilename, char **papszOptions, 
     465                 :     int nXSize, int nYSize, int nBands, const char * const * papszBandDescriptions, int bRGBColorSpace,
     466                 :     GDALDataType eType, 
     467                 :     const char *pszWKT, double *padfGeoTransform,
     468                 :     int nGCPCount, const GDAL_GCP *pasGCPList,
     469                 :     int bIsJPEG2000 )
     470                 : 
     471                 : {
     472                 :      const char *pszOption;
     473                 : /* -------------------------------------------------------------------- */
     474                 : /*      For 4.x and beyond you need a license key to compress data.     */
     475                 : /*      Check for it as a configuration option or a creation option.    */
     476                 : /* -------------------------------------------------------------------- */
     477                 : #if ECWSDK_VERSION >= 40 
     478                 :     const char* pszECWKey = CSLFetchNameValue( papszOptions, "ECW_ENCODE_KEY");
     479                 :     if( pszECWKey == NULL )
     480                 :         pszECWKey = CPLGetConfigOption( "ECW_ENCODE_KEY", NULL );
     481                 :     
     482                 :     const char* pszECWCompany = 
     483                 :         CSLFetchNameValue( papszOptions, "ECW_ENCODE_COMPANY");
     484                 :     if( pszECWCompany == NULL )
     485                 :         pszECWCompany = CPLGetConfigOption( "ECW_ENCODE_COMPANY", NULL );
     486                 :     
     487                 :     if( pszECWKey && pszECWCompany)
     488                 :     {
     489                 :         CPLDebug( "ECW", "SetOEMKey(%s,%s)", pszECWCompany, pszECWKey );
     490                 :         CNCSFile::SetOEMKey( (char *) pszECWCompany, (char *)pszECWKey );
     491                 :     }
     492                 :     else if( pszECWKey || pszECWCompany )
     493                 :     {
     494                 :         CPLError( CE_Failure, CPLE_AppDefined,
     495                 :                   "Only one of ECW_ENCODE_KEY and ECW_ENCODE_COMPANY were provided.\nBoth are required." );
     496                 :         return CE_Failure;
     497                 :     }else{
     498                 :         CPLError( CE_Failure, CPLE_AppDefined,
     499                 :                   "None of ECW_ENCODE_KEY and ECW_ENCODE_COMPANY were provided.\nBoth are required." );
     500                 :         return CE_Failure;
     501                 :     }
     502                 : 
     503                 : #endif /* ECWSDK_VERSION >= 40 */
     504                 : 
     505                 : /* -------------------------------------------------------------------- */
     506                 : /*      Do some rudimentary checking in input.                          */
     507                 : /* -------------------------------------------------------------------- */
     508              24 :     if( nBands == 0 )
     509                 :     {
     510                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     511               0 :                   "ECW driver requires at least one band." );
     512               0 :         return CE_Failure;
     513                 :     }
     514                 : 
     515                 : /* -------------------------------------------------------------------- */
     516                 : /*      Parse out some known options.                                   */
     517                 : /* -------------------------------------------------------------------- */
     518                 :     float      fTargetCompression;
     519                 : 
     520                 :     // Default compression based on image type per request from Paul Beaty.
     521              24 :     if( nBands > 1 ) 
     522              10 :         fTargetCompression = 95.0;
     523                 :     else
     524              14 :         fTargetCompression = 90.0;
     525                 : 
     526              24 :     if( CSLFetchNameValue(papszOptions, "TARGET") != NULL )
     527                 :     {
     528                 :         fTargetCompression = (float) 
     529               6 :             atof(CSLFetchNameValue(papszOptions, "TARGET"));
     530                 : 
     531                 :         /* The max allowed value should be 100 - 100 / 65535 = 99.9984740978 */
     532                 :         /* so that nCompressionRate fits on a uint16 (see below) */
     533                 :         /* No need to be so pedantic, so we will limit to 99.99 % */
     534                 :         /* (compression rate = 10 000) */
     535               6 :         if( fTargetCompression < 0.0 || fTargetCompression > 99.99 )
     536                 :         {
     537                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     538                 :                       "TARGET compression of %.3f invalid, should be a\n"
     539                 :                       "value between 0 and 99.99 percent.\n",
     540               0 :                       (double) fTargetCompression );
     541               0 :             return CE_Failure;
     542                 :         }
     543                 :     }
     544                 :         
     545                 : /* -------------------------------------------------------------------- */
     546                 : /*      Create and initialize compressor.                               */
     547                 : /* -------------------------------------------------------------------- */
     548              24 :     NCSFileViewFileInfoEx    *psClient = &(sFileInfo);
     549                 : #if ECWSDK_VERSION >= 50
     550                 :     bool bECWV3 = false;
     551                 :     pszOption = CSLFetchNameValue(papszOptions, "ECW_FORMAT_VERSION");
     552                 :     if( pszOption != NULL )
     553                 :     {
     554                 :         bECWV3 = (3 == atoi(pszOption));
     555                 :     }
     556                 :     psClient->nFormatVersion = (bECWV3)?3:2; 
     557                 : #endif
     558              24 :     psClient->nBands = (UINT16) nBands;
     559              24 :     psClient->nSizeX = nXSize;
     560              24 :     psClient->nSizeY = nYSize;
     561              24 :     psClient->nCompressionRate = (UINT16) MAX(1,100/(100-fTargetCompression));
     562              24 :     psClient->eCellSizeUnits = ECW_CELL_UNITS_METERS;
     563                 : 
     564              24 :     if( nBands == 1 )
     565              14 :         psClient->eColorSpace = NCSCS_GREYSCALE;
     566              15 :     else if( nBands == 3 && bRGBColorSpace)
     567               5 :         psClient->eColorSpace = NCSCS_sRGB;
     568                 : #if ECWSDK_VERSION >= 40
     569                 :     else if( nBands  == 4 && bRGBColorSpace )
     570                 :         psClient->eColorSpace = NCSCS_sRGB;
     571                 : #endif
     572                 :     else
     573               5 :         psClient->eColorSpace = NCSCS_MULTIBAND;
     574                 : 
     575                 : /* -------------------------------------------------------------------- */
     576                 : /*      Figure out the data type.                                       */
     577                 : /* -------------------------------------------------------------------- */
     578              24 :     int bSigned = FALSE;
     579              24 :     int nBits = 8;
     580              24 :     eWorkDT = eType;
     581                 : 
     582              24 :     switch( eWorkDT  )
     583                 :     {
     584                 :         case GDT_Byte:
     585                 : #if ECWSDK_VERSION >=50
     586                 :             psClient->nCellBitDepth = 8;
     587                 : #endif
     588              18 :             psClient->eCellType = NCSCT_UINT8;
     589              18 :             nBits = 8;
     590              18 :             bSigned = FALSE;
     591              18 :             break;
     592                 :             
     593                 :         case GDT_UInt16:
     594                 : #if ECWSDK_VERSION >=50
     595                 :             psClient->nCellBitDepth = 16;
     596                 : #endif
     597               1 :             psClient->eCellType = NCSCT_UINT16;
     598               1 :             nBits = 16;
     599               1 :             bSigned = FALSE;
     600               1 :             break;
     601                 :             
     602                 :         case GDT_UInt32:
     603                 : #if ECWSDK_VERSION >=50
     604                 :             psClient->nCellBitDepth = 32;
     605                 : #endif
     606               1 :             psClient->eCellType = NCSCT_UINT32;
     607               1 :             nBits = 32;
     608               1 :             bSigned = FALSE;
     609               1 :             break;
     610                 :             
     611                 :         case GDT_Int16:
     612                 : #if ECWSDK_VERSION >=50
     613                 :             psClient->nCellBitDepth = 16;
     614                 : #endif
     615               2 :             psClient->eCellType = NCSCT_INT16;
     616               2 :             nBits = 16;
     617               2 :             bSigned = TRUE;
     618               2 :             break;
     619                 :             
     620                 :         case GDT_Int32:
     621                 : #if ECWSDK_VERSION >=50
     622                 :             psClient->nCellBitDepth = 32;
     623                 : #endif
     624               1 :             psClient->eCellType = NCSCT_INT32;
     625               1 :             nBits = 32;
     626               1 :             bSigned = TRUE;
     627               1 :             break;
     628                 :             
     629                 :         case GDT_Float32:
     630               1 :             psClient->eCellType = NCSCT_IEEE4;
     631               1 :             nBits = 32;
     632               1 :             bSigned = TRUE;
     633               1 :             break;
     634                 :             
     635                 :         case GDT_Float64:
     636               0 :             psClient->eCellType = NCSCT_IEEE8;
     637               0 :             nBits = 64;
     638               0 :             bSigned = TRUE;
     639               0 :             break;
     640                 : 
     641                 :         default:
     642                 :             // We treat complex types as float.  
     643               0 :             psClient->eCellType = NCSCT_IEEE4;
     644               0 :             nBits = 32;
     645               0 :             bSigned = TRUE;
     646               0 :             eWorkDT = GDT_Float32;
     647                 :             break;
     648                 :     }
     649                 : 
     650                 : /* -------------------------------------------------------------------- */
     651                 : /*      Create band information structures.                             */
     652                 : /* -------------------------------------------------------------------- */
     653                 :     int iBand;
     654                 : 
     655                 :     psClient->pBands = (NCSFileBandInfo *) 
     656              24 :         CPLMalloc( sizeof(NCSFileBandInfo) * nBands );
     657              68 :     for( iBand = 0; iBand < nBands; iBand++ )
     658                 :     {
     659              44 :         psClient->pBands[iBand].nBits = (UINT8) nBits;
     660              44 :         psClient->pBands[iBand].bSigned = (BOOLEAN)bSigned;
     661              44 :         psClient->pBands[iBand].szDesc = CPLStrdup(papszBandDescriptions[iBand]);
     662                 :     }
     663                 : 
     664                 : /* -------------------------------------------------------------------- */
     665                 : /*      Allow CNCSFile::SetParameter() requests.                        */
     666                 : /* -------------------------------------------------------------------- */
     667                 : 
     668              24 :     if( bIsJPEG2000 )
     669                 :     {
     670              21 :         pszOption = CSLFetchNameValue(papszOptions, "PROFILE");
     671              21 :         if( pszOption != NULL && EQUAL(pszOption,"BASELINE_0") ) 
     672                 :             SetParameter( 
     673               0 :                 CNCSJP2FileView::JP2_COMPRESS_PROFILE_BASELINE_0 );
     674              21 :         else if( pszOption != NULL && EQUAL(pszOption,"BASELINE_1") ) 
     675                 :             SetParameter( 
     676               0 :                 CNCSJP2FileView::JP2_COMPRESS_PROFILE_BASELINE_1 );
     677              21 :         else if( pszOption != NULL && EQUAL(pszOption,"BASELINE_2") )
     678                 :             SetParameter( 
     679               0 :                 CNCSJP2FileView::JP2_COMPRESS_PROFILE_BASELINE_2 );
     680              27 :         else if( pszOption != NULL && EQUAL(pszOption,"NPJE") ) 
     681                 :             SetParameter( 
     682               6 :                 CNCSJP2FileView::JP2_COMPRESS_PROFILE_NITF_BIIF_NPJE );
     683              15 :         else if( pszOption != NULL && EQUAL(pszOption,"EPJE") ) 
     684                 :             SetParameter( 
     685               0 :                 CNCSJP2FileView::JP2_COMPRESS_PROFILE_NITF_BIIF_EPJE );
     686                 :         
     687              21 :         pszOption = CSLFetchNameValue(papszOptions, "CODESTREAM_ONLY" );
     688              21 :         if( pszOption != NULL ) 
     689                 :             SetParameter(
     690                 :                 CNCSJP2FileView::JP2_COMPRESS_CODESTREAM_ONLY, 
     691               3 :                 (bool) CSLTestBoolean( pszOption ) );
     692                 :         
     693              21 :         pszOption = CSLFetchNameValue(papszOptions, "LEVELS");
     694              21 :         if( pszOption != NULL )
     695                 :             SetParameter( CNCSJP2FileView::JP2_COMPRESS_LEVELS, 
     696               0 :                                       (UINT32) atoi(pszOption) );
     697                 :         
     698              21 :         pszOption = CSLFetchNameValue(papszOptions, "LAYERS");
     699              21 :         if( pszOption != NULL )
     700                 :             SetParameter( CNCSJP2FileView::JP2_COMPRESS_LAYERS, 
     701               3 :                                       (UINT32) atoi(pszOption) );
     702                 : 
     703              21 :         pszOption = CSLFetchNameValue(papszOptions, "PRECINCT_WIDTH");
     704              21 :         if( pszOption != NULL )
     705                 :             SetParameter( CNCSJP2FileView::JP2_COMPRESS_PRECINCT_WIDTH,
     706               0 :                                       (UINT32) atoi(pszOption) );
     707                 : 
     708              21 :         pszOption = CSLFetchNameValue(papszOptions, "PRECINCT_HEIGHT");
     709              21 :         if( pszOption != NULL )
     710                 :             SetParameter(CNCSJP2FileView::JP2_COMPRESS_PRECINCT_HEIGHT, 
     711               0 :                                      (UINT32) atoi(pszOption) );
     712                 : 
     713              21 :         pszOption = CSLFetchNameValue(papszOptions, "TILE_WIDTH");
     714              21 :         if( pszOption != NULL )
     715                 :             SetParameter( CNCSJP2FileView::JP2_COMPRESS_TILE_WIDTH, 
     716               0 :                                       (UINT32) atoi(pszOption) );
     717                 : 
     718              21 :         pszOption = CSLFetchNameValue(papszOptions, "TILE_HEIGHT");
     719              21 :         if( pszOption != NULL )
     720                 :             SetParameter( CNCSJP2FileView::JP2_COMPRESS_TILE_HEIGHT, 
     721               0 :                                       (UINT32) atoi(pszOption) );
     722                 : 
     723              21 :         pszOption = CSLFetchNameValue(papszOptions, "INCLUDE_SOP");
     724              21 :         if( pszOption != NULL )
     725                 :             SetParameter( CNCSJP2FileView::JP2_COMPRESS_INCLUDE_SOP, 
     726               0 :                                       (bool) CSLTestBoolean( pszOption ) );
     727                 :     
     728              21 :         pszOption = CSLFetchNameValue(papszOptions, "INCLUDE_EPH");
     729              21 :         if( pszOption != NULL )
     730                 :             SetParameter( CNCSJP2FileView::JP2_COMPRESS_INCLUDE_EPH, 
     731               0 :                                       (bool) CSLTestBoolean( pszOption ) );
     732                 :     
     733              21 :         pszOption = CSLFetchNameValue(papszOptions, "PROGRESSION");
     734              21 :         if( pszOption != NULL && EQUAL(pszOption,"LRCP") )
     735                 :             SetParameter( 
     736               0 :                 CNCSJP2FileView::JP2_COMPRESS_PROGRESSION_LRCP );
     737                 :                                   
     738              21 :         else if( pszOption != NULL && EQUAL(pszOption,"RLCP") )
     739                 :             SetParameter( 
     740               0 :                 CNCSJP2FileView::JP2_COMPRESS_PROGRESSION_RLCP );
     741                 : 
     742              21 :         else if( pszOption != NULL && EQUAL(pszOption,"RPCL") )
     743                 :             SetParameter( 
     744               0 :                 CNCSJP2FileView::JP2_COMPRESS_PROGRESSION_RPCL );
     745                 : 
     746              21 :         pszOption = CSLFetchNameValue(papszOptions, "GEODATA_USAGE");
     747              21 :         if( pszOption == NULL )
     748                 :             // Default to supressing ECW SDK geodata, just use our own stuff.
     749              21 :             SetGeodataUsage( JP2_GEODATA_USE_NONE );
     750               0 :         else if( EQUAL(pszOption,"NONE") )
     751               0 :             SetGeodataUsage( JP2_GEODATA_USE_NONE );
     752               0 :         else if( EQUAL(pszOption,"PCS_ONLY") )
     753               0 :             SetGeodataUsage( JP2_GEODATA_USE_PCS_ONLY );
     754               0 :         else if( EQUAL(pszOption,"GML_ONLY") )
     755               0 :             SetGeodataUsage( JP2_GEODATA_USE_GML_ONLY );
     756               0 :         else if( EQUAL(pszOption,"PCS_GML") )
     757               0 :             SetGeodataUsage( JP2_GEODATA_USE_PCS_GML );
     758               0 :         else if( EQUAL(pszOption,"GML_PCS") )
     759               0 :             SetGeodataUsage( JP2_GEODATA_USE_GML_PCS );
     760               0 :         else if( EQUAL(pszOption,"ALL") )
     761               0 :             SetGeodataUsage( JP2_GEODATA_USE_GML_PCS_WLD );
     762                 : 
     763              21 :         pszOption = CSLFetchNameValue(papszOptions, "DECOMPRESS_LAYERS");
     764              21 :         if( pszOption != NULL )
     765                 :             SetParameter( 
     766                 :                 CNCSJP2FileView::JP2_DECOMPRESS_LAYERS, 
     767               0 :                 (UINT32) atoi(pszOption) );
     768                 : 
     769                 :         pszOption = CSLFetchNameValue(papszOptions, 
     770              21 :                                       "DECOMPRESS_RECONSTRUCTION_PARAMETER");
     771              21 :         if( pszOption != NULL )
     772                 :             SetParameter( 
     773                 :                 CNCSJP2FileView::JPC_DECOMPRESS_RECONSTRUCTION_PARAMETER, 
     774               0 :                 (IEEE4) atof(pszOption) );
     775                 :     }
     776                 :                                   
     777                 : /* -------------------------------------------------------------------- */
     778                 : /*      Georeferencing.                                                 */
     779                 : /* -------------------------------------------------------------------- */
     780                 : 
     781              24 :     psClient->fOriginX = 0.0;
     782              24 :     psClient->fOriginY = psClient->nSizeY;
     783              24 :     psClient->fCellIncrementX = 1.0;
     784              24 :     psClient->fCellIncrementY = -1.0;
     785              24 :     psClient->fCWRotationDegrees = 0.0;
     786                 :     
     787              24 :     if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0.0 )
     788                 :         CPLError( CE_Warning, CPLE_NotSupported, 
     789                 :                   "Rotational coefficients ignored, georeferencing of\n"
     790               0 :                   "output ECW file will be incorrect.\n" );
     791                 :     else
     792                 :     {
     793              24 :         psClient->fOriginX = padfGeoTransform[0];
     794              24 :         psClient->fOriginY = padfGeoTransform[3];
     795              24 :         psClient->fCellIncrementX = padfGeoTransform[1];
     796              24 :         psClient->fCellIncrementY = padfGeoTransform[5];
     797                 :     }
     798                 : 
     799                 : /* -------------------------------------------------------------------- */
     800                 : /*      Projection.                                                     */
     801                 : /* -------------------------------------------------------------------- */
     802                 :     char szProjection[128];
     803                 :     char szDatum[128];
     804                 :     char szUnits[128];
     805                 : 
     806              24 :     strcpy( szProjection, "RAW" );
     807              24 :     strcpy( szDatum, "RAW" );
     808                 :     
     809              24 :     if( CSLFetchNameValue(papszOptions, "PROJ") != NULL )
     810                 :     {
     811                 :         strncpy( szProjection, 
     812               0 :                 CSLFetchNameValue(papszOptions, "PROJ"), sizeof(szProjection) );
     813               0 :         szProjection[sizeof(szProjection)-1] = 0;
     814                 :     }
     815                 : 
     816              24 :     if( CSLFetchNameValue(papszOptions, "DATUM") != NULL )
     817                 :     {
     818               0 :         strncpy( szDatum, CSLFetchNameValue(papszOptions, "DATUM"), sizeof(szDatum) );
     819               0 :         szDatum[sizeof(szDatum)-1] = 0;
     820               0 :         if( EQUAL(szProjection,"RAW") )
     821               0 :             strcpy( szProjection, "GEODETIC" );
     822                 :     }
     823                 : 
     824              24 :     const char* pszUnits = CSLFetchNameValue(papszOptions, "UNITS");
     825              24 :     if( pszUnits != NULL )
     826                 :     {
     827               0 :         psClient->eCellSizeUnits = ECWTranslateToCellSizeUnits(pszUnits);
     828                 :     }
     829                 : 
     830              24 :     if( EQUAL(szProjection,"RAW") && pszWKT != NULL )
     831                 :     {
     832              23 :         ECWTranslateFromWKT( pszWKT, szProjection, sizeof(szProjection), szDatum, sizeof(szDatum), szUnits );
     833              23 :         psClient->eCellSizeUnits = ECWTranslateToCellSizeUnits(szUnits);
     834                 :     }
     835                 : 
     836              24 :     psClient->szDatum = szDatum;
     837              24 :     psClient->szProjection = szProjection;
     838                 : 
     839                 :     CPLDebug( "ECW", "Writing with PROJ=%s, DATUM=%s, UNITS=%s", 
     840              24 :               szProjection, szDatum, ECWTranslateFromCellSizeUnits(psClient->eCellSizeUnits) );
     841                 : 
     842                 : /* -------------------------------------------------------------------- */
     843                 : /*      Setup GML and GeoTIFF information.                              */
     844                 : /* -------------------------------------------------------------------- */
     845              24 :     GDALJP2Metadata oJP2MD;
     846                 : 
     847              24 :     oJP2MD.SetProjection( pszWKT );
     848              24 :     oJP2MD.SetGeoTransform( padfGeoTransform );
     849              24 :     oJP2MD.SetGCPs( nGCPCount, pasGCPList );
     850              24 :     if (bIsJPEG2000) {
     851                 : 
     852              21 :         if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) )
     853              18 :             WriteJP2Box( oJP2MD.CreateGMLJP2(nXSize,nYSize) );
     854              21 :         if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) )
     855              18 :             WriteJP2Box( oJP2MD.CreateJP2GeoTIFF() );
     856                 : 
     857                 :     }
     858                 : /* -------------------------------------------------------------------- */
     859                 : /*      We handle all jpeg2000 files via the VSIIOStream, but ECW       */
     860                 : /*      files cannot be done this way for some reason.                  */
     861                 : /* -------------------------------------------------------------------- */
     862              24 :     VSILFILE *fpVSIL = NULL;
     863                 : 
     864              24 :     if( bIsJPEG2000 )
     865                 :     {
     866              21 :         fpVSIL = VSIFOpenL( pszFilename, "wb+" );
     867              21 :         if( fpVSIL == NULL )
     868                 :         {
     869                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     870               2 :                       "Failed to open %s.", pszFilename );
     871               2 :             return CE_Failure;
     872                 :         }
     873                 : 
     874              19 :         m_OStream.Access( fpVSIL, TRUE, pszFilename, 0, -1 );
     875                 :     }    
     876                 : 
     877                 : /* -------------------------------------------------------------------- */
     878                 : /*      Check if we can enable large files.  This option should only    */
     879                 : /*      be set when the application is adhering to one of the           */
     880                 : /*      ERMapper options for licensing larger than 500MB input          */
     881                 : /*      files.  See Bug 767.  This option no longer exists with         */
     882                 : /*      version 4+.                                                     */
     883                 : /* -------------------------------------------------------------------- */
     884                 : #if ECWSDK_VERSION < 40
     885              22 :     const char *pszLargeOK = CSLFetchNameValue(papszOptions, "LARGE_OK");
     886              22 :     if( pszLargeOK == NULL )
     887              22 :         pszLargeOK = "NO";
     888                 : 
     889              22 :     pszLargeOK = CPLGetConfigOption( "ECW_LARGE_OK", pszLargeOK );
     890                 : 
     891              22 :     if( CSLTestBoolean(pszLargeOK) )
     892                 :     {
     893               0 :         CNCSFile::SetKeySize();
     894               0 :         CPLDebug( "ECW", "Large file generation enabled." );
     895                 :     }
     896                 : #endif /* ECWSDK_VERSION < 40 */
     897                 : 
     898                 : /* -------------------------------------------------------------------- */
     899                 : /*      Set the file info.                                              */
     900                 : /* -------------------------------------------------------------------- */
     901              22 :     CNCSError oError;
     902                 : 
     903              22 :     oError = SetFileInfo( sFileInfo );
     904                 : 
     905              22 :     if( oError.GetErrorNumber() == NCS_SUCCESS )
     906                 :     {
     907              22 :         if( fpVSIL == NULL )
     908               3 :             oError = Open( (char *) pszFilename, false, true );
     909                 :         else
     910              19 :             oError = CNCSJP2FileView::Open( &(m_OStream) );
     911                 :     }
     912                 : 
     913              22 :     if( oError.GetErrorNumber() == NCS_SUCCESS )
     914              20 :         return CE_None;
     915               2 :     else if( oError.GetErrorNumber() == NCS_INPUT_SIZE_EXCEEDED )
     916                 :     {
     917                 :         CPLError( CE_Failure, CPLE_AppDefined,
     918               0 :                   "ECW SDK compress limit exceeded." );
     919               0 :         return CE_Failure;
     920                 :     }
     921                 :     else
     922                 :     {
     923               2 :         ECWReportError(oError);
     924                 : 
     925               2 :         return CE_Failure;
     926               0 :     }
     927                 : }
     928                 : 
     929                 : /************************************************************************/
     930                 : /*                      ECWIsInputRGBColorSpace()                       */
     931                 : /************************************************************************/
     932                 : 
     933              24 : static int ECWIsInputRGBColorSpace(GDALDataset* poSrcDS)
     934                 : {
     935              24 :     int  nBands = poSrcDS->GetRasterCount();
     936                 : 
     937                 : /* -------------------------------------------------------------------- */
     938                 : /*      Is the input RGB or RGBA?                                       */
     939                 : /* -------------------------------------------------------------------- */
     940              24 :     int bRGBColorSpace = FALSE;
     941              24 :     int bRGB = FALSE;
     942              24 :     if ( nBands>=3 ) {
     943               7 :         bRGB = (poSrcDS->GetRasterBand(1)->GetColorInterpretation() 
     944              14 :                  == GCI_RedBand);
     945               7 :         bRGB &= (poSrcDS->GetRasterBand(2)->GetColorInterpretation() 
     946              14 :                  == GCI_GreenBand);
     947               7 :         bRGB &= (poSrcDS->GetRasterBand(3)->GetColorInterpretation() 
     948              14 :                  == GCI_BlueBand);
     949                 :     }
     950              24 :     if( nBands == 3 )
     951                 :     {
     952               5 :         bRGBColorSpace = bRGB;
     953                 :     }
     954              19 :     else if( nBands == 4 && bRGB )
     955                 :     {
     956               1 :         bRGBColorSpace = (poSrcDS->GetRasterBand(4)->GetColorInterpretation() 
     957               2 :                  == GCI_AlphaBand);
     958                 :     }
     959                 : 
     960              24 :     return bRGBColorSpace;
     961                 : }
     962                 : 
     963                 : /************************************************************************/
     964                 : /*                           ECWCreateCopy()                            */
     965                 : /************************************************************************/
     966                 : 
     967                 : static GDALDataset *
     968              22 : ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
     969                 :                int bStrict, char ** papszOptions, 
     970                 :                GDALProgressFunc pfnProgress, void * pProgressData,
     971                 :                int bIsJPEG2000 )
     972                 : 
     973                 : {
     974              22 :     ECWInitialize();
     975                 : 
     976                 : /* -------------------------------------------------------------------- */
     977                 : /*      Get various values from the source dataset.                     */
     978                 : /* -------------------------------------------------------------------- */
     979              22 :     int  nBands = poSrcDS->GetRasterCount();
     980              22 :     int  nXSize = poSrcDS->GetRasterXSize();
     981              22 :     int  nYSize = poSrcDS->GetRasterYSize();
     982                 : 
     983              22 :     if (nBands == 0)
     984                 :     {
     985                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     986               0 :                   "ECW driver does not support source dataset with zero band.\n");
     987               0 :         return NULL;
     988                 :     }
     989                 : 
     990              22 :     GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     991                 : 
     992              22 :     const char *pszWKT = poSrcDS->GetProjectionRef();
     993              22 :     double adfGeoTransform[6] = { 0, 1, 0, 0, 0, 1 };;
     994                 : 
     995              22 :     poSrcDS->GetGeoTransform( adfGeoTransform );
     996                 : 
     997              22 :     if( poSrcDS->GetGCPCount() > 0 )
     998               1 :         pszWKT = poSrcDS->GetGCPProjection();
     999                 : 
    1000                 : /* -------------------------------------------------------------------- */
    1001                 : /*      Confirm the datatype is 8bit.  It appears no other datatype     */
    1002                 : /*      is supported in ECW format.                                     */
    1003                 : /* -------------------------------------------------------------------- */
    1004              22 :     bool bECWV3 = false;
    1005                 : 
    1006                 :     #if ECWSDK_VERSION >= 50
    1007                 :     if (bIsJPEG2000 == FALSE){
    1008                 :         const char* pszOption = CSLFetchNameValue(papszOptions, "ECW_FORMAT_VERSION");
    1009                 :         if( pszOption != NULL )
    1010                 :         {
    1011                 :             bECWV3 = (3 == atoi(pszOption));
    1012                 :         }
    1013                 :     }
    1014                 :     #endif
    1015              22 :     if(! (eType == GDT_Byte  || (bECWV3 && eType==GDT_UInt16 ) || bIsJPEG2000 ) )
    1016                 :     {
    1017               0 :         if( bStrict )
    1018                 :         {
    1019                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1020                 :                       "Attempt to create ECW file with pixel data type %s failed.\n"
    1021                 :                       "Only Byte data type supported for ECW version 2 files. ECW version 3 files supports UInt16 and Int16 as well.",
    1022               0 :                       GDALGetDataTypeName( eType ) );
    1023                 :         }
    1024                 :         else
    1025                 :         {
    1026                 :             CPLError( CE_Warning, CPLE_AppDefined,
    1027                 :                       "ECW does not support data type, ignoring request for %s.",
    1028               0 :                       GDALGetDataTypeName( eType ) );
    1029               0 :             eType = GDT_Byte;
    1030                 :         }
    1031                 :     }
    1032                 : 
    1033                 : /* -------------------------------------------------------------------- */
    1034                 : /*      Is the input RGB or RGBA?                                       */
    1035                 : /* -------------------------------------------------------------------- */
    1036              22 :     int bRGBColorSpace = ECWIsInputRGBColorSpace(poSrcDS);
    1037                 : 
    1038                 : /* -------------------------------------------------------------------- */
    1039                 : /*      Setup the compressor.                                           */
    1040                 : /* -------------------------------------------------------------------- */
    1041              22 :     GDALECWCompressor         oCompressor;
    1042              22 :     CNCSError oErr;
    1043                 : 
    1044              22 :     oCompressor.pfnProgress = pfnProgress;
    1045              22 :     oCompressor.pProgressData = pProgressData;
    1046              22 :     oCompressor.m_poSrcDS = poSrcDS;
    1047                 : 
    1048              22 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
    1049               0 :         return NULL;
    1050                 : 
    1051              22 :     char** papszBandDescriptions = (char**) CPLMalloc(nBands * sizeof(char*));
    1052                 :     int i;
    1053              62 :     for (i=0;i<nBands;i++){
    1054                 :         /* Make a copy since ECWGetColorInterpretationName() can return a string generated */
    1055                 :         /* by CPLSPrintf(), which has just a few rotating entries. */
    1056              40 :         papszBandDescriptions[i] = CPLStrdup(ECWGetColorInterpretationName(poSrcDS->GetRasterBand(i+1)->GetColorInterpretation(), i));
    1057                 :     }
    1058              44 :     if( oCompressor.Initialize( pszFilename, papszOptions, 
    1059                 :                                 nXSize, nYSize, nBands, papszBandDescriptions, bRGBColorSpace,
    1060                 :                                 eType, pszWKT, adfGeoTransform, 
    1061              22 :                                 poSrcDS->GetGCPCount(), 
    1062              22 :                                 poSrcDS->GetGCPs(),
    1063                 :                                 bIsJPEG2000 )
    1064                 :         != CE_None )
    1065                 :     {
    1066               8 :         for (i=0;i<nBands;i++)
    1067               4 :             CPLFree(papszBandDescriptions[i]);
    1068               4 :         CPLFree(papszBandDescriptions);
    1069               4 :         return NULL;
    1070                 :     }
    1071                 : 
    1072                 : /* -------------------------------------------------------------------- */
    1073                 : /*      Start the compression.                                          */
    1074                 : /* -------------------------------------------------------------------- */
    1075              18 :     oErr = oCompressor.Write();
    1076                 : 
    1077              18 :     if( oErr.GetErrorNumber() != NCS_SUCCESS )
    1078                 :     {
    1079               0 :         ECWReportError(oErr);
    1080               0 :         return NULL;
    1081                 :     }
    1082                 : 
    1083                 : /* -------------------------------------------------------------------- */
    1084                 : /*      Cleanup, and return read-only handle.                           */
    1085                 : /* -------------------------------------------------------------------- */
    1086              18 :     oCompressor.CloseDown();
    1087              54 :     for (i=0;i<nBands;i++)
    1088              36 :         CPLFree(papszBandDescriptions[i]);
    1089              18 :     CPLFree(papszBandDescriptions);
    1090              18 :     pfnProgress( 1.001, NULL, pProgressData );
    1091                 : 
    1092                 : /* -------------------------------------------------------------------- */
    1093                 : /*      Re-open dataset, and copy any auxilary pam information.         */
    1094                 : /* -------------------------------------------------------------------- */
    1095              18 :     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
    1096                 :     GDALPamDataset *poDS;
    1097                 :     
    1098              18 :     if (bIsJPEG2000)
    1099              17 :         poDS = (GDALPamDataset*) ECWDatasetOpenJPEG2000(&oOpenInfo);
    1100                 :     else
    1101               1 :         poDS = (GDALPamDataset*) ECWDataset::OpenECW(&oOpenInfo);
    1102                 : 
    1103              18 :     if( poDS )
    1104              18 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    1105                 : 
    1106              18 :     return poDS;
    1107                 : }
    1108                 : 
    1109                 : /************************************************************************/
    1110                 : /*                          ECWCreateCopyECW()                          */
    1111                 : /************************************************************************/
    1112                 : 
    1113                 : GDALDataset *
    1114              19 : ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS, 
    1115                 :                   int bStrict, char ** papszOptions, 
    1116                 :                   GDALProgressFunc pfnProgress, void * pProgressData )
    1117                 : 
    1118                 : {
    1119              19 :     int nBands = poSrcDS->GetRasterCount();
    1120              19 :     if (nBands == 0)
    1121                 :     {
    1122                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1123               1 :                   "ECW driver does not support source dataset with zero band.\n");
    1124               1 :         return NULL;
    1125                 :     }
    1126                 : 
    1127              18 :     if( !EQUAL(CPLGetExtension(pszFilename),"ecw") )
    1128                 :     {
    1129                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1130                 :                   "ECW driver does not support creating ECW files\n"
    1131               0 :                   "with an extension other than .ecw" );
    1132               0 :         return NULL;
    1133                 :     }
    1134              18 :     bool bECWV3 = false;
    1135                 : 
    1136                 : #if ECWSDK_VERSION >= 50
    1137                 : 
    1138                 :     const char* pszOption = CSLFetchNameValue(papszOptions, "ECW_FORMAT_VERSION");
    1139                 :     if( pszOption != NULL )
    1140                 :     {
    1141                 :         bECWV3 = (3 == atoi(pszOption));
    1142                 :     }
    1143                 : 
    1144                 : #endif
    1145                 : 
    1146              18 :     if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte 
    1147                 :         && !(bECWV3 && (poSrcDS->GetRasterBand(1)->GetRasterDataType() == GDT_UInt16))  
    1148                 :         && bStrict )
    1149                 :     {
    1150                 :          
    1151              10 :         if (poSrcDS->GetRasterBand(1)->GetRasterDataType() == GDT_UInt16 || poSrcDS->GetRasterBand(1)->GetRasterDataType() == GDT_Int16){
    1152                 :             CPLError( CE_Failure, CPLE_NotSupported, 
    1153                 :                   "ECW driver doesn't support data type %s. "
    1154                 :                   "Enable ECW version 3 write by using ECWV3=ON option.\n", 
    1155                 :                   GDALGetDataTypeName( 
    1156               2 :                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
    1157                 :         }else{
    1158                 :             CPLError( CE_Failure, CPLE_NotSupported, 
    1159                 :                   "ECW driver doesn't support data type %s. "
    1160                 :                   "Only eight or sixteen bit bands supported. \n", 
    1161                 :                   GDALGetDataTypeName( 
    1162               8 :                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
    1163                 :         }
    1164                 : 
    1165              10 :         return NULL;
    1166                 :     }
    1167                 : 
    1168               8 :     if( poSrcDS->GetRasterXSize() < 128 || poSrcDS->GetRasterYSize() < 128 )
    1169                 :     {
    1170                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1171                 :                   "ECW driver requires image to be at least 128x128,\n"
    1172                 :                   "the source image is %dx%d.\n", 
    1173                 :                   poSrcDS->GetRasterXSize(),
    1174               5 :                   poSrcDS->GetRasterYSize() );
    1175                 :                   
    1176               5 :         return NULL;
    1177                 :     }
    1178                 : 
    1179               3 :     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
    1180                 :     {
    1181                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
    1182                 :                   "ECW driver ignores color table. "
    1183                 :                   "The source raster band will be considered as grey level.\n"
    1184               0 :                   "Consider using color table expansion (-expand option in gdal_translate)\n");
    1185               0 :         if (bStrict)
    1186               0 :             return NULL;
    1187                 :     }
    1188                 : 
    1189                 :     return ECWCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions, 
    1190               3 :                           pfnProgress, pProgressData, FALSE );
    1191                 : }
    1192                 : 
    1193                 : /************************************************************************/
    1194                 : /*                       ECWCreateCopyJPEG2000()                        */
    1195                 : /************************************************************************/
    1196                 : 
    1197                 : GDALDataset *
    1198              24 : ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS, 
    1199                 :                        int bStrict, char ** papszOptions, 
    1200                 :                        GDALProgressFunc pfnProgress, void * pProgressData )
    1201                 : 
    1202                 : {
    1203              24 :     int nBands = poSrcDS->GetRasterCount();
    1204              24 :     if (nBands == 0)
    1205                 :     {
    1206                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1207               1 :                   "JP2ECW driver does not support source dataset with zero band.\n");
    1208               1 :         return NULL;
    1209                 :     }
    1210                 : 
    1211              23 :     if( EQUAL(CPLGetExtension(pszFilename),"ecw") )
    1212                 :     {
    1213                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1214                 :                   "JP2ECW driver does not support creating JPEG2000 files\n"
    1215               0 :                   "with a .ecw extension.  Please use anything else." );
    1216               0 :         return NULL;
    1217                 :     }
    1218                 : 
    1219              23 :     if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte 
    1220                 :         && poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte 
    1221                 :         && poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Int16
    1222                 :         && poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_UInt16
    1223                 :         && poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Int32
    1224                 :         && poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_UInt32
    1225                 :         && poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Float32
    1226                 :         && poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Float64
    1227                 :         && bStrict )
    1228                 :     {
    1229                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1230                 :                   "JP2ECW driver doesn't support data type %s. ",
    1231                 :                   GDALGetDataTypeName( 
    1232               4 :                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
    1233                 : 
    1234               4 :         return NULL;
    1235                 :     }
    1236                 : 
    1237              19 :     if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
    1238                 :     {
    1239                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, 
    1240                 :                   "JP2ECW driver ignores color table. "
    1241                 :                   "The source raster band will be considered as grey level.\n"
    1242               0 :                   "Consider using color table expansion (-expand option in gdal_translate)\n");
    1243               0 :         if (bStrict)
    1244               0 :             return NULL;
    1245                 :     }
    1246                 : 
    1247                 :     return ECWCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions, 
    1248              19 :                           pfnProgress, pProgressData, TRUE );
    1249                 : }
    1250                 : 
    1251                 : /************************************************************************/
    1252                 : /************************************************************************
    1253                 :  
    1254                 :                ECW/JPEG200 Create() Support
    1255                 :                ----------------------------
    1256                 : 
    1257                 :   The remainder of the file is code to implement the Create() method. 
    1258                 :   New dataset and raster band classes are defined specifically for the
    1259                 :   purpose of being write-only.  In particular, you cannot read back data
    1260                 :   from these datasets, and writing must occur in a pretty specific order.
    1261                 :   
    1262                 :   That is, you need to write all metadata (projection, georef, etc) first
    1263                 :   and then write the image data.  All bands data for the first scanline
    1264                 :   should be written followed by all bands for the second scanline and so on.
    1265                 : 
    1266                 :   Creation supports the same virtual subfile names as CreateCopy() supports. 
    1267                 : 
    1268                 :  ************************************************************************/
    1269                 : /************************************************************************/
    1270                 : 
    1271                 : /************************************************************************/
    1272                 : /* ==================================================================== */
    1273                 : /*        ECWWriteDataset       */
    1274                 : /* ==================================================================== */
    1275                 : /************************************************************************/
    1276                 : 
    1277                 : class ECWWriteRasterBand;
    1278                 : 
    1279                 : class CPL_DLL ECWWriteDataset : public GDALDataset
    1280                 : {
    1281                 :     friend class ECWWriteRasterBand;
    1282                 : 
    1283                 :     char      *pszFilename;
    1284                 : 
    1285                 :     int       bIsJPEG2000;
    1286                 :     GDALDataType eDataType;
    1287                 :     char    **papszOptions;
    1288                 :   
    1289                 :     char     *pszProjection;
    1290                 :     double    adfGeoTransform[6];
    1291                 : 
    1292                 :     GDALECWCompressor oCompressor;
    1293                 :     int       bCrystalized;
    1294                 :     
    1295                 :     int       nLoadedLine;
    1296                 :     GByte     *pabyBILBuffer;
    1297                 :     
    1298                 :     CPLErr    Crystalize();
    1299                 :     CPLErr    FlushLine();
    1300                 : 
    1301                 :   public:
    1302                 :             ECWWriteDataset( const char *, int, int, int, 
    1303                 :                                  GDALDataType, char **papszOptions,
    1304                 :                                  int );
    1305                 :             ~ECWWriteDataset();
    1306                 : 
    1307                 :     virtual void   FlushCache( void );
    1308                 : 
    1309                 :     virtual CPLErr GetGeoTransform( double * );
    1310                 :     virtual const char* GetProjectionRef();
    1311                 :     virtual CPLErr SetGeoTransform( double * );
    1312                 :     virtual CPLErr SetProjection( const char *pszWKT );
    1313                 : };
    1314                 : 
    1315                 : /************************************************************************/
    1316                 : /* ==================================================================== */
    1317                 : /*                         ECWWriteRasterBand                           */
    1318                 : /* ==================================================================== */
    1319                 : /************************************************************************/
    1320                 :  
    1321                 : class ECWWriteRasterBand : public GDALRasterBand
    1322              59 : {
    1323                 :     friend class ECWWriteDataset;
    1324                 :     
    1325                 :     // NOTE: poDS may be altered for NITF/JPEG2000 files!
    1326                 :     ECWWriteDataset     *poGDS;
    1327                 : 
    1328                 :     GDALColorInterp     eInterp;
    1329                 : 
    1330                 :   public:
    1331                 : 
    1332                 :                    ECWWriteRasterBand( ECWWriteDataset *, int );
    1333                 : 
    1334               6 :     virtual CPLErr SetColorInterpretation( GDALColorInterp eInterpIn ) 
    1335               6 :         { eInterp = eInterpIn; return CE_None; }
    1336               6 :     virtual GDALColorInterp GetColorInterpretation() 
    1337               6 :         { return eInterp; }
    1338                 : 
    1339                 :     virtual CPLErr IReadBlock( int, int, void * );
    1340                 :     virtual CPLErr IWriteBlock( int, int, void * );
    1341                 : };
    1342                 : 
    1343                 : /************************************************************************/
    1344                 : /*                          ECWWriteDataset()                           */
    1345                 : /************************************************************************/
    1346                 : 
    1347              28 : ECWWriteDataset::ECWWriteDataset( const char *pszFilename, 
    1348                 :                                   int nXSize, int nYSize, int nBandCount, 
    1349                 :                                   GDALDataType eType,
    1350              28 :                                   char **papszOptions, int bIsJPEG2000 )
    1351                 : 
    1352                 : {
    1353              28 :     bCrystalized = FALSE;
    1354              28 :     pabyBILBuffer = NULL;
    1355              28 :     nLoadedLine = -1;
    1356                 : 
    1357              28 :     eAccess = GA_Update;
    1358                 : 
    1359              28 :     this->bIsJPEG2000 = bIsJPEG2000;
    1360              28 :     this->eDataType = eType;
    1361              28 :     this->papszOptions = CSLDuplicate( papszOptions );
    1362              28 :     this->pszFilename = CPLStrdup( pszFilename );
    1363                 : 
    1364              28 :     nRasterXSize = nXSize;
    1365              28 :     nRasterYSize = nYSize;
    1366              28 :     pszProjection = NULL;
    1367                 : 
    1368              28 :     adfGeoTransform[0] = 0.0;
    1369              28 :     adfGeoTransform[1] = 1.0;
    1370              28 :     adfGeoTransform[2] = 0.0;
    1371              28 :     adfGeoTransform[3] = 0.0;
    1372              28 :     adfGeoTransform[4] = 0.0;
    1373              28 :     adfGeoTransform[5] = 1.0;
    1374                 : 
    1375                 :     // create band objects.
    1376              87 :     for( int iBand = 1; iBand <= nBandCount; iBand++ )
    1377                 :     {
    1378              59 :         SetBand( iBand, new ECWWriteRasterBand( this, iBand ) );
    1379                 :     }
    1380              28 : }
    1381                 : 
    1382                 : /************************************************************************/
    1383                 : /*                          ~ECWWriteDataset()                          */
    1384                 : /************************************************************************/
    1385                 : 
    1386              28 : ECWWriteDataset::~ECWWriteDataset()
    1387                 : 
    1388                 : {
    1389              28 :     FlushCache();
    1390                 : 
    1391              28 :     if( bCrystalized )
    1392                 :     {
    1393               2 :         if( nLoadedLine == nRasterYSize - 1 )
    1394               2 :             FlushLine();
    1395               2 :         oCompressor.CloseDown();
    1396                 :     }
    1397                 : 
    1398              28 :     CPLFree( pabyBILBuffer );
    1399              28 :     CPLFree( pszProjection );
    1400              28 :     CSLDestroy( papszOptions );
    1401              28 :     CPLFree( pszFilename );
    1402              28 : }
    1403                 : 
    1404                 : /************************************************************************/
    1405                 : /*                             FlushCache()                             */
    1406                 : /************************************************************************/
    1407                 : 
    1408              29 : void ECWWriteDataset::FlushCache()
    1409                 : 
    1410                 : {
    1411              29 :     BlockBasedFlushCache();
    1412              29 : }
    1413                 : 
    1414                 : /************************************************************************/
    1415                 : /*                         GetProjectionRef()                           */
    1416                 : /************************************************************************/
    1417                 : 
    1418               0 : const char*  ECWWriteDataset::GetProjectionRef()
    1419                 : {
    1420               0 :     return pszProjection;
    1421                 : }
    1422                 : 
    1423                 : /************************************************************************/
    1424                 : /*                          GetGeoTransform()                           */
    1425                 : /************************************************************************/
    1426                 : 
    1427              26 : CPLErr ECWWriteDataset::GetGeoTransform( double *padfGeoTransform )
    1428                 : 
    1429                 : {
    1430              26 :     memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
    1431              26 :     return CE_None;
    1432                 : }
    1433                 : 
    1434                 : /************************************************************************/
    1435                 : /*                          SetGeoTransform()                           */
    1436                 : /************************************************************************/
    1437                 : 
    1438              27 : CPLErr ECWWriteDataset::SetGeoTransform( double *padfGeoTransform )
    1439                 : 
    1440                 : {
    1441              27 :     memcpy( adfGeoTransform, padfGeoTransform, sizeof(double) * 6 );
    1442              27 :     return CE_None;
    1443                 : }
    1444                 : 
    1445                 : /************************************************************************/
    1446                 : /*                           SetProjection()                            */
    1447                 : /************************************************************************/
    1448                 : 
    1449              27 : CPLErr ECWWriteDataset::SetProjection( const char *pszWKT )
    1450                 : 
    1451                 : {
    1452              27 :     CPLFree( pszProjection );
    1453              27 :     pszProjection = CPLStrdup( pszWKT );
    1454                 : 
    1455              27 :     return CE_None;
    1456                 : }
    1457                 : 
    1458                 : 
    1459                 : /************************************************************************/
    1460                 : /*                             Crystalize()                             */
    1461                 : /************************************************************************/
    1462                 : 
    1463               2 : CPLErr ECWWriteDataset::Crystalize()
    1464                 : 
    1465                 : {
    1466               2 :     int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
    1467                 : 
    1468                 :     CPLErr eErr;
    1469               2 :     CNCSError oError;
    1470                 : 
    1471               2 :     if( bCrystalized )
    1472               0 :         return CE_None;
    1473                 :     
    1474               2 :     const char **paszBandDescriptions = (const char **) CPLMalloc(nBands * sizeof(char *));
    1475               6 :     for (int i = 0; i < GetRasterCount(); i++ ){
    1476               4 :         paszBandDescriptions[i] = GetRasterBand(i+1)->GetDescription();
    1477                 :     }
    1478                 : 
    1479               2 :     int bRGBColorSpace = ECWIsInputRGBColorSpace(this);
    1480                 : 
    1481                 :     eErr = oCompressor.Initialize( pszFilename, papszOptions, 
    1482                 :                                    nRasterXSize, nRasterYSize, nBands,paszBandDescriptions, bRGBColorSpace,
    1483                 :                                    eDataType, 
    1484                 :                                    pszProjection, adfGeoTransform, 
    1485                 :                                    0, NULL,
    1486               2 :                                    bIsJPEG2000 );
    1487                 : 
    1488               2 :     if( eErr == CE_None )
    1489               2 :         bCrystalized = TRUE;
    1490                 : 
    1491               2 :     nLoadedLine = -1;
    1492               2 :     pabyBILBuffer = (GByte *) CPLMalloc( nWordSize * nBands * nRasterXSize );
    1493                 :     
    1494               2 :     CPLFree(paszBandDescriptions);
    1495                 :     
    1496               2 :     return eErr;
    1497                 : }
    1498                 : 
    1499                 : /************************************************************************/
    1500                 : /*                             FlushLine()                              */
    1501                 : /************************************************************************/
    1502                 : 
    1503             202 : CPLErr ECWWriteDataset::FlushLine()
    1504                 : 
    1505                 : {
    1506             202 :     int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
    1507                 :     CPLErr eErr;
    1508                 : 
    1509                 : /* -------------------------------------------------------------------- */
    1510                 : /*      Crystalize if not already done.                                 */
    1511                 : /* -------------------------------------------------------------------- */
    1512             202 :     if( !bCrystalized )
    1513                 :     {
    1514               2 :         eErr = Crystalize();
    1515                 : 
    1516               2 :         if( eErr != CE_None )
    1517               0 :             return eErr;
    1518                 :     }
    1519                 : 
    1520                 : /* -------------------------------------------------------------------- */
    1521                 : /*      Write out the currently loaded line.                            */
    1522                 : /* -------------------------------------------------------------------- */
    1523             202 :     if( nLoadedLine != -1 )
    1524                 :     {
    1525                 :         
    1526                 :         void **papOutputLine;
    1527                 : 
    1528             200 :         papOutputLine = (void **) CPLMalloc(sizeof(void*) * nBands);
    1529             600 :         for( int i = 0; i < nBands; i++ )
    1530             400 :             papOutputLine[i] = 
    1531             400 :                 (void *) (pabyBILBuffer + i * nWordSize * nRasterXSize);
    1532                 :         
    1533                 : 
    1534             200 :         eErr =  oCompressor.WriteLineBIL( (UINT16) nBands, papOutputLine );
    1535             200 :         CPLFree( papOutputLine );
    1536             200 :         if (eErr!=CE_None){
    1537               0 :            return eErr;
    1538                 :         }
    1539                 :     }
    1540                 : 
    1541                 : /* -------------------------------------------------------------------- */
    1542                 : /*      Clear the buffer and increment the "current line" indicator.    */
    1543                 : /* -------------------------------------------------------------------- */
    1544             202 :     memset( pabyBILBuffer, 0, nWordSize * nRasterXSize * nBands );
    1545             202 :     nLoadedLine++;
    1546                 : 
    1547             202 :     return CE_None;
    1548                 : }
    1549                 : 
    1550                 : 
    1551                 : /************************************************************************/
    1552                 : /* ==================================================================== */
    1553                 : /*                          ECWWriteRasterBand                          */
    1554                 : /* ==================================================================== */
    1555                 : /************************************************************************/
    1556                 : 
    1557                 : /************************************************************************/
    1558                 : /*                         ECWWriteRasterBand()                         */
    1559                 : /************************************************************************/
    1560                 : 
    1561              59 : ECWWriteRasterBand::ECWWriteRasterBand( ECWWriteDataset *poDSIn,
    1562              59 :                                         int nBandIn )
    1563                 : 
    1564                 : {
    1565              59 :     nBand = nBandIn;
    1566              59 :     poDS = poDSIn;
    1567              59 :     poGDS = poDSIn;
    1568              59 :     nBlockXSize = poDSIn->GetRasterXSize();
    1569              59 :     nBlockYSize = 1;
    1570              59 :     eDataType = poDSIn->eDataType;
    1571              59 :     eInterp = GCI_Undefined;
    1572              59 : }
    1573                 : 
    1574                 : /************************************************************************/
    1575                 : /*                             IReadBlock()                             */
    1576                 : /************************************************************************/
    1577                 : 
    1578               0 : CPLErr ECWWriteRasterBand::IReadBlock( int nBlockX, int nBlockY, 
    1579                 :                                        void *pBuffer )
    1580                 : 
    1581                 : {
    1582               0 :     int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
    1583                 : 
    1584                 :     // We zero stuff out here, but we can't really read stuff from
    1585                 :     // a write only stream. 
    1586                 : 
    1587               0 :     memset( pBuffer, 0, nBlockXSize * nWordSize );
    1588                 : 
    1589               0 :     return CE_None;
    1590                 : }
    1591                 : 
    1592                 : /************************************************************************/
    1593                 : /*                            IWriteBlock()                             */
    1594                 : /************************************************************************/
    1595                 : 
    1596             400 : CPLErr ECWWriteRasterBand::IWriteBlock( int nBlockX, int nBlockY, 
    1597                 :                                         void *pBuffer )
    1598                 : 
    1599                 : {
    1600             400 :     int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
    1601                 :     CPLErr eErr;
    1602                 : 
    1603                 : /* -------------------------------------------------------------------- */
    1604                 : /*      Flush previous line if needed.                                  */
    1605                 : /* -------------------------------------------------------------------- */
    1606             400 :     if( nBlockY == poGDS->nLoadedLine + 1 )
    1607                 :     {
    1608             200 :         eErr = poGDS->FlushLine();
    1609             200 :         if( eErr != CE_None )
    1610               0 :             return eErr;
    1611                 :     }
    1612                 : 
    1613                 : /* -------------------------------------------------------------------- */
    1614                 : /*      Blow a gasket if we have been asked to write something out      */
    1615                 : /*      of order.                                                       */
    1616                 : /* -------------------------------------------------------------------- */
    1617             400 :     if( nBlockY != poGDS->nLoadedLine )
    1618                 :     {
    1619                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1620                 :                   "Apparent attempt to write to ECW non-sequentially.\n"
    1621                 :                   "Loaded line is %d, but %d of band %d was written to.",
    1622               0 :                   poGDS->nLoadedLine, nBlockY, nBand );
    1623               0 :         return CE_Failure;
    1624                 :     }
    1625                 : 
    1626                 : /* -------------------------------------------------------------------- */
    1627                 : /*      Copy passed data into current line buffer.                      */
    1628                 : /* -------------------------------------------------------------------- */
    1629                 :     memcpy( poGDS->pabyBILBuffer + (nBand-1) * nWordSize * nRasterXSize, 
    1630                 :             pBuffer, 
    1631             400 :             nWordSize * nRasterXSize );
    1632                 : 
    1633             400 :     return CE_None;
    1634                 : }
    1635                 : 
    1636                 : /************************************************************************/
    1637                 : /*                         ECWCreateJPEG2000()                          */
    1638                 : /************************************************************************/
    1639                 : 
    1640                 : GDALDataset *
    1641              28 : ECWCreateJPEG2000(const char *pszFilename, int nXSize, int nYSize, int nBands, 
    1642                 :                   GDALDataType eType, char **papszOptions )
    1643                 : 
    1644                 : {
    1645              28 :     ECWInitialize();
    1646                 : 
    1647                 :     return new ECWWriteDataset( pszFilename, nXSize, nYSize, nBands, 
    1648              28 :                                 eType, papszOptions, TRUE );
    1649                 : }
    1650                 : 
    1651                 : /************************************************************************/
    1652                 : /*                            ECWCreateECW()                            */
    1653                 : /************************************************************************/
    1654                 : 
    1655                 : GDALDataset *
    1656               0 : ECWCreateECW( const char *pszFilename, int nXSize, int nYSize, int nBands, 
    1657                 :               GDALDataType eType, char **papszOptions )
    1658                 : 
    1659                 : {
    1660               0 :     ECWInitialize();
    1661                 : 
    1662                 :     return new ECWWriteDataset( pszFilename, nXSize, nYSize, nBands, 
    1663               0 :                                 eType, papszOptions, FALSE );
    1664                 : }
    1665                 : 
    1666                 : #endif /* def FRMT_ecw && def HAVE_COMPRESS */

Generated by: LCOV version 1.7