~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to .pc/ecw-plugin/frmts/ecw/ecwdataset.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/******************************************************************************
2
 
 * $Id: ecwdataset.cpp 17906 2009-10-26 19:47:21Z rouault $
3
 
 *
4
 
 * Project:  GDAL 
5
 
 * Purpose:  ECW (ERMapper Wavelet Compression Format) Driver
6
 
 * Author:   Frank Warmerdam, warmerdam@pobox.com
7
 
 *
8
 
 ******************************************************************************
9
 
 * Copyright (c) 2001, 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_pam.h"
31
 
#include "gdaljp2metadata.h"
32
 
#include "ogr_spatialref.h"
33
 
#include "cpl_string.h"
34
 
#include "cpl_conv.h"
35
 
#include "vsiiostream.h"
36
 
#include "cpl_multiproc.h"
37
 
#include "cpl_minixml.h"
38
 
#include "ogr_api.h"
39
 
#include "ogr_geometry.h"
40
 
 
41
 
CPL_CVSID("$Id: ecwdataset.cpp 17906 2009-10-26 19:47:21Z rouault $");
42
 
 
43
 
#ifdef FRMT_ecw
44
 
 
45
 
static const unsigned char jpc_header[] = {0xff,0x4f};
46
 
static const unsigned char jp2_header[] = 
47
 
    {0x00,0x00,0x00,0x0c,0x6a,0x50,0x20,0x20,0x0d,0x0a,0x87,0x0a};
48
 
 
49
 
static void *hECWDatasetMutex = NULL;
50
 
static int    bNCSInitialized = FALSE;
51
 
 
52
 
CPL_C_START
53
 
CPLErr CPL_DLL GTIFMemBufFromWkt( const char *pszWKT, 
54
 
                                  const double *padfGeoTransform,
55
 
                                  int nGCPCount, const GDAL_GCP *pasGCPList,
56
 
                                  int *pnSize, unsigned char **ppabyBuffer );
57
 
CPLErr CPL_DLL GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer, 
58
 
                          char **ppszWKT, double *padfGeoTransform,
59
 
                          int *pnGCPCount, GDAL_GCP **ppasGCPList );
60
 
CPL_C_END
61
 
 
62
 
void ECWInitialize( void );
63
 
 
64
 
GDALDataset* ECWDatasetOpenJPEG2000(GDALOpenInfo* poOpenInfo);
65
 
 
66
 
/************************************************************************/
67
 
/* ==================================================================== */
68
 
/*                              ECWDataset                              */
69
 
/* ==================================================================== */
70
 
/************************************************************************/
71
 
 
72
 
class ECWRasterBand;
73
 
 
74
 
class CPL_DLL ECWDataset : public GDALPamDataset
75
 
{
76
 
    friend class ECWRasterBand;
77
 
 
78
 
    CNCSJP2FileView *poFileView;
79
 
    NCSFileViewFileInfoEx *psFileInfo;
80
 
 
81
 
    GDALDataType eRasterDataType;
82
 
    NCSEcwCellType eNCSRequestDataType;
83
 
 
84
 
    int         bUsingCustomStream;
85
 
 
86
 
    // Current view window. 
87
 
    int         bWinActive;
88
 
    int         nWinXOff, nWinYOff, nWinXSize, nWinYSize;
89
 
    int         nWinBufXSize, nWinBufYSize;
90
 
    int         nWinBandCount;
91
 
    int         *panWinBandList;
92
 
    int         nWinBufLoaded;
93
 
    void        **papCurLineBuf;
94
 
 
95
 
    int         bGeoTransformValid;
96
 
    double      adfGeoTransform[6];
97
 
    char        *pszProjection;
98
 
    int         nGCPCount;
99
 
    GDAL_GCP    *pasGCPList;
100
 
 
101
 
    char        **papszGMLMetadata;
102
 
 
103
 
    void        ECW2WKTProjection();
104
 
 
105
 
    void        CleanupWindow();
106
 
    int         TryWinRasterIO( GDALRWFlag, int, int, int, int,
107
 
                                GByte *, int, int, GDALDataType,
108
 
                                int, int *, int, int, int );
109
 
    CPLErr      LoadNextLine();
110
 
 
111
 
  public:
112
 
                ECWDataset(int bIsJPEG2000);
113
 
                ~ECWDataset();
114
 
                
115
 
    static GDALDataset *Open( GDALOpenInfo *, int bIsJPEG2000 );
116
 
    static int          IdentifyJPEG2000( GDALOpenInfo * poOpenInfo );
117
 
    static GDALDataset *OpenJPEG2000( GDALOpenInfo * );
118
 
    static int          IdentifyECW( GDALOpenInfo * poOpenInfo );
119
 
    static GDALDataset *OpenECW( GDALOpenInfo * );
120
 
 
121
 
    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
122
 
                              void *, int, int, GDALDataType,
123
 
                              int, int *, int, int, int );
124
 
 
125
 
    virtual CPLErr GetGeoTransform( double * );
126
 
    virtual const char *GetProjectionRef();
127
 
 
128
 
    virtual int    GetGCPCount();
129
 
    virtual const char *GetGCPProjection();
130
 
    virtual const GDAL_GCP *GetGCPs();
131
 
 
132
 
    virtual char      **GetMetadata( const char * pszDomain = "" );
133
 
 
134
 
    virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
135
 
                               int nBufXSize, int nBufYSize, 
136
 
                               GDALDataType eDT, 
137
 
                               int nBandCount, int *panBandList,
138
 
                               char **papszOptions );
139
 
};
140
 
 
141
 
/************************************************************************/
142
 
/* ==================================================================== */
143
 
/*                            ECWRasterBand                             */
144
 
/* ==================================================================== */
145
 
/************************************************************************/
146
 
 
147
 
class ECWRasterBand : public GDALPamRasterBand
148
 
{
149
 
    friend class ECWDataset;
150
 
    
151
 
    // NOTE: poDS may be altered for NITF/JPEG2000 files!
152
 
    ECWDataset     *poGDS;
153
 
 
154
 
    GDALColorInterp         eBandInterp;
155
 
 
156
 
    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
157
 
                              void *, int, int, GDALDataType,
158
 
                              int, int );
159
 
 
160
 
  public:
161
 
 
162
 
                   ECWRasterBand( ECWDataset *, int );
163
 
                   ~ECWRasterBand();
164
 
 
165
 
    virtual CPLErr IReadBlock( int, int, void * );
166
 
    virtual int    HasArbitraryOverviews() { return TRUE; }
167
 
    virtual GDALColorInterp GetColorInterpretation();
168
 
    virtual CPLErr SetColorInterpretation( GDALColorInterp );
169
 
 
170
 
    virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
171
 
                               int nBufXSize, int nBufYSize, 
172
 
                               GDALDataType eDT, char **papszOptions );
173
 
};
174
 
 
175
 
/************************************************************************/
176
 
/*                           ECWRasterBand()                            */
177
 
/************************************************************************/
178
 
 
179
 
ECWRasterBand::ECWRasterBand( ECWDataset *poDS, int nBand )
180
 
 
181
 
{
182
 
    this->poDS = poDS;
183
 
    poGDS = poDS;
184
 
 
185
 
    this->nBand = nBand;
186
 
    eDataType = poDS->eRasterDataType;
187
 
    nBlockXSize = poDS->GetRasterXSize();
188
 
    nBlockYSize = 1;
189
 
 
190
 
/* -------------------------------------------------------------------- */
191
 
/*      Work out band color interpretation.                             */
192
 
/* -------------------------------------------------------------------- */
193
 
    if( poDS->psFileInfo->eColorSpace == NCSCS_NONE )
194
 
        eBandInterp = GCI_Undefined;
195
 
    else if( poDS->psFileInfo->eColorSpace == NCSCS_GREYSCALE )
196
 
        eBandInterp = GCI_GrayIndex;
197
 
    else if( poDS->psFileInfo->eColorSpace == NCSCS_MULTIBAND )
198
 
        eBandInterp = GCI_Undefined;
199
 
    else if( poDS->psFileInfo->eColorSpace == NCSCS_sRGB )
200
 
    {
201
 
        if( nBand == 1 )
202
 
            eBandInterp = GCI_RedBand;
203
 
        else if( nBand == 2 )
204
 
            eBandInterp = GCI_GreenBand;
205
 
        else if( nBand == 3 )
206
 
            eBandInterp = GCI_BlueBand;
207
 
        else
208
 
            eBandInterp = GCI_Undefined;
209
 
    }
210
 
    else if( poDS->psFileInfo->eColorSpace == NCSCS_YCbCr )
211
 
    {
212
 
        if( CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB","YES") ))
213
 
        {
214
 
            if( nBand == 1 )
215
 
                eBandInterp = GCI_RedBand;
216
 
            else if( nBand == 2 )
217
 
                eBandInterp = GCI_GreenBand;
218
 
            else if( nBand == 3 )
219
 
                eBandInterp = GCI_BlueBand;
220
 
            else
221
 
                eBandInterp = GCI_Undefined;
222
 
        }
223
 
        else
224
 
        {
225
 
            if( nBand == 1 )
226
 
                eBandInterp = GCI_YCbCr_YBand;
227
 
            else if( nBand == 2 )
228
 
                eBandInterp = GCI_YCbCr_CbBand;
229
 
            else if( nBand == 3 )
230
 
                eBandInterp = GCI_YCbCr_CrBand;
231
 
            else
232
 
                eBandInterp = GCI_Undefined;
233
 
        }
234
 
    }
235
 
    else
236
 
        eBandInterp = GCI_Undefined;
237
 
}
238
 
 
239
 
/************************************************************************/
240
 
/*                          ~ECWRasterBand()                           */
241
 
/************************************************************************/
242
 
 
243
 
ECWRasterBand::~ECWRasterBand()
244
 
 
245
 
{
246
 
    FlushCache();
247
 
}
248
 
 
249
 
/************************************************************************/
250
 
/*                       GetColorInterpretation()                       */
251
 
/************************************************************************/
252
 
 
253
 
GDALColorInterp ECWRasterBand::GetColorInterpretation()
254
 
 
255
 
{
256
 
    return eBandInterp;
257
 
}
258
 
 
259
 
/************************************************************************/
260
 
/*                       SetColorInterpretation()                       */
261
 
/*                                                                      */
262
 
/*      This would normally just be used by folks using the ECW code    */
263
 
/*      to read JP2 streams in other formats (such as NITF) and         */
264
 
/*      providing their own color interpretation regardless of what     */
265
 
/*      ECW might think the stream itself says.                         */
266
 
/************************************************************************/
267
 
 
268
 
CPLErr ECWRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
269
 
 
270
 
{
271
 
    eBandInterp = eNewInterp;
272
 
 
273
 
    return CE_None;
274
 
}
275
 
 
276
 
/************************************************************************/
277
 
/*                             AdviseRead()                             */
278
 
/************************************************************************/
279
 
 
280
 
CPLErr ECWRasterBand::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
281
 
                                  int nBufXSize, int nBufYSize, 
282
 
                                  GDALDataType eDT, 
283
 
                                  char **papszOptions )
284
 
{
285
 
    return poGDS->AdviseRead( nXOff, nYOff, nXSize, nYSize, 
286
 
                              nBufXSize, nBufYSize, eDT, 
287
 
                              1, &nBand, papszOptions );
288
 
}
289
 
 
290
 
/************************************************************************/
291
 
/*                             IRasterIO()                              */
292
 
/************************************************************************/
293
 
 
294
 
CPLErr ECWRasterBand::IRasterIO( GDALRWFlag eRWFlag,
295
 
                                 int nXOff, int nYOff, int nXSize, int nYSize,
296
 
                                 void * pData, int nBufXSize, int nBufYSize,
297
 
                                 GDALDataType eBufType,
298
 
                                 int nPixelSpace, int nLineSpace )
299
 
    
300
 
{
301
 
    int          iBand, bDirect;
302
 
    int          nNewXSize = nBufXSize, nNewYSize = nBufYSize;
303
 
    GByte        *pabyWorkBuffer = NULL;
304
 
 
305
 
/* -------------------------------------------------------------------- */
306
 
/*      Try to do it based on existing "advised" access.                */
307
 
/* -------------------------------------------------------------------- */
308
 
    if( poGDS->TryWinRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
309
 
                               (GByte *) pData, nBufXSize, nBufYSize, 
310
 
                               eBufType, 1, &nBand, 
311
 
                               nPixelSpace, nLineSpace, 0 ) )
312
 
        return CE_None;
313
 
 
314
 
/* -------------------------------------------------------------------- */
315
 
/*      We will drop down to the block oriented API if only a single    */
316
 
/*      scanline was requested. This is based on the assumption that    */
317
 
/*      doing lots of single scanline windows is expensive.             */
318
 
/* -------------------------------------------------------------------- */
319
 
    if( nYSize == 1 )
320
 
    {
321
 
#ifdef notdef
322
 
        CPLDebug( "ECWRasterBand", 
323
 
                  "RasterIO(%d,%d,%d,%d -> %dx%d) - redirected.", 
324
 
                  nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize );
325
 
#endif
326
 
        return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
327
 
                                         pData, nBufXSize, nBufYSize, 
328
 
                                         eBufType, nPixelSpace, nLineSpace );
329
 
    }
330
 
 
331
 
    CPLDebug( "ECWRasterBand", 
332
 
              "RasterIO(nXOff=%d,nYOff=%d,nXSize=%d,nYSize=%d -> %dx%d)", 
333
 
              nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize );
334
 
 
335
 
 
336
 
    if ( nXSize < nBufXSize )
337
 
            nNewXSize = nXSize;
338
 
 
339
 
    if ( nYSize < nBufYSize )
340
 
            nNewYSize = nYSize;
341
 
 
342
 
/* -------------------------------------------------------------------- */
343
 
/*      Default line and pixel spacing if needed.                       */
344
 
/* -------------------------------------------------------------------- */
345
 
    if ( nPixelSpace == 0 )
346
 
        nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
347
 
 
348
 
    if ( nLineSpace == 0 )
349
 
        nLineSpace = nPixelSpace * nBufXSize;
350
 
 
351
 
/* -------------------------------------------------------------------- */
352
 
/*      Can we perform direct loads, or must we load into a working     */
353
 
/*      buffer, and transform?                                          */
354
 
/* -------------------------------------------------------------------- */
355
 
    int     nRawPixelSize = GDALGetDataTypeSize(poGDS->eRasterDataType) / 8;
356
 
 
357
 
    bDirect = nPixelSpace == 1 && eBufType == GDT_Byte
358
 
            && nNewXSize == nBufXSize && nNewYSize == nBufYSize;
359
 
    if( !bDirect )
360
 
        pabyWorkBuffer = (GByte *) CPLMalloc(nNewXSize * nRawPixelSize);
361
 
 
362
 
/* -------------------------------------------------------------------- */
363
 
/*      Establish access at the desired resolution.                     */
364
 
/* -------------------------------------------------------------------- */
365
 
    CNCSError oErr;
366
 
 
367
 
    poGDS->CleanupWindow();
368
 
 
369
 
    iBand = nBand-1;
370
 
    oErr = poGDS->poFileView->SetView( 1, (unsigned int *) (&iBand),
371
 
                                       nXOff, nYOff, 
372
 
                                       nXOff + nXSize - 1, 
373
 
                                       nYOff + nYSize - 1,
374
 
                                       nNewXSize, nNewYSize );
375
 
    if( oErr.GetErrorNumber() != NCS_SUCCESS )
376
 
    {
377
 
        CPLFree( pabyWorkBuffer );
378
 
        char* pszErrorMessage = oErr.GetErrorMessage();
379
 
        CPLError( CE_Failure, CPLE_AppDefined, 
380
 
                  "%s", pszErrorMessage );
381
 
        NCSFree(pszErrorMessage);
382
 
        
383
 
        return CE_Failure;
384
 
    }
385
 
 
386
 
/* -------------------------------------------------------------------- */
387
 
/*      Read back one scanline at a time, till request is satisfied.    */
388
 
/*      Supersampling is not supported by the ECW API, so we will do    */
389
 
/*      it ourselves.                                                   */
390
 
/* -------------------------------------------------------------------- */
391
 
    double      dfSrcYInc = (double)nNewYSize / nBufYSize;
392
 
    double      dfSrcXInc = (double)nNewXSize / nBufXSize;
393
 
    int         iSrcLine, iDstLine;
394
 
 
395
 
    for( iSrcLine = 0, iDstLine = 0; iDstLine < nBufYSize; iDstLine++ )
396
 
    {
397
 
        NCSEcwReadStatus eRStatus;
398
 
        int             iDstLineOff = iDstLine * nLineSpace;
399
 
        unsigned char   *pabySrcBuf;
400
 
 
401
 
        if( bDirect )
402
 
            pabySrcBuf = ((GByte *)pData) + iDstLineOff;
403
 
        else
404
 
            pabySrcBuf = pabyWorkBuffer;
405
 
 
406
 
        if ( nNewYSize == nBufYSize || iSrcLine == (int)(iDstLine * dfSrcYInc) )
407
 
        {
408
 
            eRStatus = poGDS->poFileView->ReadLineBIL( 
409
 
                poGDS->eNCSRequestDataType, 1, (void **) &pabySrcBuf );
410
 
 
411
 
            if( eRStatus != NCSECW_READ_OK )
412
 
            {
413
 
                CPLFree( pabyWorkBuffer );
414
 
                CPLError( CE_Failure, CPLE_AppDefined,
415
 
                          "NCScbmReadViewLineBIL failed." );
416
 
                return CE_Failure;
417
 
            }
418
 
 
419
 
            if( !bDirect )
420
 
            {
421
 
                if ( nNewXSize == nBufXSize )
422
 
                {
423
 
                    GDALCopyWords( pabyWorkBuffer, poGDS->eRasterDataType, 
424
 
                                   nRawPixelSize, 
425
 
                                   ((GByte *)pData) + iDstLine * nLineSpace, 
426
 
                                   eBufType, nPixelSpace, nBufXSize );
427
 
                }
428
 
                else
429
 
                {
430
 
                    int iPixel;
431
 
 
432
 
                    for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
433
 
                    {
434
 
                        GDALCopyWords( pabyWorkBuffer 
435
 
                                       + nRawPixelSize*((int)(iPixel*dfSrcXInc)),
436
 
                                       poGDS->eRasterDataType, nRawPixelSize,
437
 
                                       (GByte *)pData + iDstLineOff
438
 
                                       + iPixel * nPixelSpace,
439
 
                                       eBufType, nPixelSpace, 1 );
440
 
                    }
441
 
                }
442
 
            }
443
 
 
444
 
            iSrcLine++;
445
 
        }
446
 
        else
447
 
        {
448
 
            // Just copy the previous line in this case
449
 
            GDALCopyWords( (GByte *)pData + (iDstLineOff - nLineSpace),
450
 
                            eBufType, nPixelSpace,
451
 
                            (GByte *)pData + iDstLineOff,
452
 
                            eBufType, nPixelSpace, nBufXSize );
453
 
        }
454
 
    }
455
 
 
456
 
    CPLFree( pabyWorkBuffer );
457
 
 
458
 
    return CE_None;
459
 
}
460
 
 
461
 
/************************************************************************/
462
 
/*                             IReadBlock()                             */
463
 
/************************************************************************/
464
 
 
465
 
CPLErr ECWRasterBand::IReadBlock( int, int nBlockYOff, void * pImage )
466
 
 
467
 
{
468
 
    CPLErr eErr = CE_None;
469
 
 
470
 
    if( poGDS->TryWinRasterIO( GF_Read, 0, nBlockYOff, nBlockXSize, 1, 
471
 
                               (GByte *) pImage, nBlockXSize, 1, 
472
 
                               eDataType, 1, &nBand, 0, 0, 0 ) )
473
 
        return CE_None;
474
 
 
475
 
    eErr = AdviseRead( 0, nBlockYOff, nRasterXSize, nRasterYSize - nBlockYOff,
476
 
                       nRasterXSize, nRasterYSize - nBlockYOff, 
477
 
                       eDataType, NULL );
478
 
    if( eErr != CE_None )
479
 
        return eErr;
480
 
 
481
 
    if( poGDS->TryWinRasterIO( GF_Read, 0, nBlockYOff, nBlockXSize, 1, 
482
 
                               (GByte *) pImage, nBlockXSize, 1, 
483
 
                               eDataType, 1, &nBand, 0, 0, 0 ) )
484
 
        return CE_None;
485
 
 
486
 
    CPLError( CE_Failure, CPLE_AppDefined, 
487
 
              "TryWinRasterIO() failed for blocked scanline %d of band %d.",
488
 
              nBlockYOff, nBand );
489
 
    return CE_Failure;
490
 
}
491
 
 
492
 
/************************************************************************/
493
 
/* ==================================================================== */
494
 
/*                            ECWDataset                               */
495
 
/* ==================================================================== */
496
 
/************************************************************************/
497
 
 
498
 
 
499
 
/************************************************************************/
500
 
/*                            ECWDataset()                              */
501
 
/************************************************************************/
502
 
 
503
 
ECWDataset::ECWDataset(int bIsJPEG2000)
504
 
 
505
 
{
506
 
    bUsingCustomStream = FALSE;
507
 
    pszProjection = NULL;
508
 
    poFileView = NULL;
509
 
    bWinActive = FALSE;
510
 
    panWinBandList = NULL;
511
 
    eRasterDataType = GDT_Byte;
512
 
    nGCPCount = 0;
513
 
    pasGCPList = NULL;
514
 
    papszGMLMetadata = NULL;
515
 
    
516
 
    bGeoTransformValid = FALSE;
517
 
    adfGeoTransform[0] = 0.0;
518
 
    adfGeoTransform[1] = 1.0;
519
 
    adfGeoTransform[2] = 0.0;
520
 
    adfGeoTransform[3] = 0.0;
521
 
    adfGeoTransform[4] = 0.0;
522
 
    adfGeoTransform[5] = 1.0;
523
 
    
524
 
    poDriver = (GDALDriver*) GDALGetDriverByName( bIsJPEG2000 ? "JP2ECW" : "ECW" );
525
 
}
526
 
 
527
 
/************************************************************************/
528
 
/*                           ~ECWDataset()                              */
529
 
/************************************************************************/
530
 
 
531
 
ECWDataset::~ECWDataset()
532
 
 
533
 
{
534
 
    FlushCache();
535
 
    CleanupWindow();
536
 
    CPLFree( pszProjection );
537
 
    CSLDestroy( papszGMLMetadata );
538
 
 
539
 
    if( nGCPCount > 0 )
540
 
    {
541
 
        GDALDeinitGCPs( nGCPCount, pasGCPList );
542
 
        CPLFree( pasGCPList );
543
 
    }
544
 
 
545
 
/* -------------------------------------------------------------------- */
546
 
/*      Release / dereference iostream.                                 */
547
 
/* -------------------------------------------------------------------- */
548
 
    // The underlying iostream of the CNCSJP2FileView (poFileView) object may 
549
 
    // also be the underlying iostream of other CNCSJP2FileView (poFileView) 
550
 
    // objects.  Consequently, when we delete the CNCSJP2FileView (poFileView) 
551
 
    // object, we must decrement the nFileViewCount attribute of the underlying
552
 
    // VSIIOStream object, and only delete the VSIIOStream object when 
553
 
    // nFileViewCount is equal to zero.
554
 
 
555
 
    CPLMutexHolder oHolder( &hECWDatasetMutex );
556
 
 
557
 
    if( poFileView != NULL )
558
 
    {
559
 
        VSIIOStream *poUnderlyingIOStream = (VSIIOStream *)NULL;
560
 
 
561
 
        poUnderlyingIOStream = ((VSIIOStream *)(poFileView->GetStream()));
562
 
        delete poFileView;
563
 
 
564
 
        if( bUsingCustomStream )
565
 
        {
566
 
            if( --poUnderlyingIOStream->nFileViewCount == 0 )
567
 
                delete poUnderlyingIOStream;
568
 
        }
569
 
    }
570
 
}
571
 
 
572
 
/************************************************************************/
573
 
/*                             AdviseRead()                             */
574
 
/************************************************************************/
575
 
 
576
 
CPLErr ECWDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
577
 
                               int nBufXSize, int nBufYSize, 
578
 
                               GDALDataType eDT, 
579
 
                               int nBandCount, int *panBandList,
580
 
                               char **papszOptions )
581
 
 
582
 
{
583
 
    int *panAdjustedBandList = NULL;
584
 
 
585
 
    CPLDebug( "ECW",
586
 
              "ECWDataset::AdviseRead(%d,%d,%d,%d->%d,%d)",
587
 
              nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize );
588
 
 
589
 
    if( nBufXSize > nXSize || nBufYSize > nYSize )
590
 
    {
591
 
        CPLError( CE_Warning, CPLE_AppDefined, 
592
 
                  "Supersampling not directly supported by ECW toolkit,\n"
593
 
                  "ignoring AdviseRead() request." );
594
 
        return CE_Warning; 
595
 
    }
596
 
 
597
 
/* -------------------------------------------------------------------- */
598
 
/*      Adjust band numbers to be zero based.                           */
599
 
/* -------------------------------------------------------------------- */
600
 
    panAdjustedBandList = (int *) 
601
 
        CPLMalloc(sizeof(int) * nBandCount );
602
 
    for( int ii= 0; ii < nBandCount; ii++ )
603
 
        panAdjustedBandList[ii] = panBandList[ii] - 1;
604
 
 
605
 
/* -------------------------------------------------------------------- */
606
 
/*      Cleanup old window cache information.                           */
607
 
/* -------------------------------------------------------------------- */
608
 
    CleanupWindow();
609
 
 
610
 
/* -------------------------------------------------------------------- */
611
 
/*      Set the new requested window.                                   */
612
 
/* -------------------------------------------------------------------- */
613
 
    CNCSError oErr;
614
 
    
615
 
    oErr = poFileView->SetView( nBandCount, (UINT32 *) panAdjustedBandList, 
616
 
                                nXOff, nYOff, 
617
 
                                nXOff + nXSize-1, nYOff + nYSize-1,
618
 
                                nBufXSize, nBufYSize );
619
 
 
620
 
    CPLFree( panAdjustedBandList );
621
 
    if( oErr.GetErrorNumber() != NCS_SUCCESS )
622
 
    {
623
 
        char* pszErrorMessage = oErr.GetErrorMessage();
624
 
        CPLError( CE_Failure, CPLE_AppDefined, 
625
 
                  "%s", pszErrorMessage );
626
 
        NCSFree(pszErrorMessage);
627
 
        bWinActive = FALSE;
628
 
        return CE_Failure;
629
 
    }
630
 
 
631
 
    bWinActive = TRUE;
632
 
 
633
 
/* -------------------------------------------------------------------- */
634
 
/*      Record selected window.                                         */
635
 
/* -------------------------------------------------------------------- */
636
 
    nWinXOff = nXOff;
637
 
    nWinYOff = nYOff;
638
 
    nWinXSize = nXSize;
639
 
    nWinYSize = nYSize;
640
 
    nWinBufXSize = nBufXSize;
641
 
    nWinBufYSize = nBufYSize;
642
 
 
643
 
    panWinBandList = (int *) CPLMalloc(sizeof(int)*nBandCount);
644
 
    memcpy( panWinBandList, panBandList, sizeof(int)* nBandCount);
645
 
    nWinBandCount = nBandCount;
646
 
 
647
 
    nWinBufLoaded = -1;
648
 
 
649
 
/* -------------------------------------------------------------------- */
650
 
/*      Allocate current scanline buffer.                               */
651
 
/* -------------------------------------------------------------------- */
652
 
    papCurLineBuf = (void **) CPLMalloc(sizeof(void*) * nWinBandCount );
653
 
    for( int iBand = 0; iBand < nWinBandCount; iBand++ )
654
 
        papCurLineBuf[iBand] = 
655
 
            CPLMalloc(nBufXSize * (GDALGetDataTypeSize(eRasterDataType)/8) );
656
 
        
657
 
    return CE_None;
658
 
}
659
 
 
660
 
/************************************************************************/
661
 
/*                           TryWinRasterIO()                           */
662
 
/*                                                                      */
663
 
/*      Try to satisfy the given request based on the currently         */
664
 
/*      defined window.  Return TRUE on success or FALSE on             */
665
 
/*      failure.  On failure, the caller should satisfy the request     */
666
 
/*      another way (not report an error).                              */
667
 
/************************************************************************/
668
 
 
669
 
int ECWDataset::TryWinRasterIO( GDALRWFlag eFlag, 
670
 
                                int nXOff, int nYOff, int nXSize, int nYSize,
671
 
                                GByte *pabyData, int nBufXSize, int nBufYSize, 
672
 
                                GDALDataType eDT,
673
 
                                int nBandCount, int *panBandList, 
674
 
                                int nPixelSpace, int nLineSpace, 
675
 
                                int nBandSpace )
676
 
 
677
 
{
678
 
    int iBand, i;
679
 
 
680
 
/* -------------------------------------------------------------------- */
681
 
/*      Provide default buffer organization.                            */
682
 
/* -------------------------------------------------------------------- */
683
 
    if( nPixelSpace == 0 )
684
 
        nPixelSpace = GDALGetDataTypeSize( eDT ) / 8;
685
 
    if( nLineSpace == 0 )
686
 
        nLineSpace = nPixelSpace * nBufXSize;
687
 
    if( nBandSpace == 0 )
688
 
        nBandSpace = nLineSpace * nBufYSize;
689
 
 
690
 
/* -------------------------------------------------------------------- */
691
 
/*      Do some simple tests to see if the current window can           */
692
 
/*      satisfy our requirement.                                        */
693
 
/* -------------------------------------------------------------------- */
694
 
    if( !bWinActive )
695
 
        return FALSE;
696
 
    
697
 
    if( nXOff != nWinXOff || nXSize != nWinXSize )
698
 
        return FALSE;
699
 
 
700
 
    if( nBufXSize != nWinBufXSize )
701
 
        return FALSE;
702
 
 
703
 
    for( iBand = 0; iBand < nBandCount; iBand++ )
704
 
    {
705
 
        for( i = 0; i < nWinBandCount; i++ )
706
 
        {
707
 
            if( panWinBandList[iBand] == panBandList[iBand] )
708
 
                break;
709
 
        }
710
 
 
711
 
        if( i == nWinBandCount )
712
 
            return FALSE;
713
 
    }
714
 
 
715
 
    if( nYOff < nWinYOff || nYOff + nYSize > nWinYOff + nWinYSize )
716
 
        return FALSE;
717
 
 
718
 
/* -------------------------------------------------------------------- */
719
 
/*      Now we try more subtle tests.                                   */
720
 
/* -------------------------------------------------------------------- */
721
 
    {
722
 
        static int nDebugCount = 0;
723
 
 
724
 
        if( nDebugCount < 30 )
725
 
            CPLDebug( "ECWDataset", 
726
 
                      "TryWinRasterIO(%d,%d,%d,%d -> %dx%d) - doing advised read.", 
727
 
                      nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize );
728
 
 
729
 
        if( nDebugCount == 29 )
730
 
            CPLDebug( "ECWDataset", "No more TryWinRasterIO messages will be reported" );
731
 
        
732
 
        nDebugCount++;
733
 
    }
734
 
 
735
 
/* -------------------------------------------------------------------- */
736
 
/*      Actually load data one buffer line at a time.                   */
737
 
/* -------------------------------------------------------------------- */
738
 
    int iBufLine;
739
 
 
740
 
    for( iBufLine = 0; iBufLine < nBufYSize; iBufLine++ )
741
 
    {
742
 
        float fFileLine = ((iBufLine+0.5) / nBufYSize) * nYSize + nYOff;
743
 
        int iWinLine = 
744
 
            (int) (((fFileLine - nWinYOff) / nWinYSize) * nWinBufYSize);
745
 
        
746
 
        if( iWinLine == nWinBufLoaded + 1 )
747
 
            LoadNextLine();
748
 
 
749
 
        if( iWinLine != nWinBufLoaded )
750
 
            return FALSE;
751
 
 
752
 
/* -------------------------------------------------------------------- */
753
 
/*      Copy out all our target bands.                                  */
754
 
/* -------------------------------------------------------------------- */
755
 
        int iWinBand;
756
 
        for( iBand = 0; iBand < nBandCount; iBand++ )
757
 
        {
758
 
            for( iWinBand = 0; iWinBand < nWinBandCount; iWinBand++ )
759
 
            {
760
 
                if( panWinBandList[iWinBand] == panBandList[iBand] )
761
 
                    break;
762
 
            }
763
 
 
764
 
            GDALCopyWords( papCurLineBuf[iWinBand], eRasterDataType,
765
 
                           GDALGetDataTypeSize( eRasterDataType ) / 8, 
766
 
                           pabyData + nBandSpace * iBand 
767
 
                           + iBufLine * nLineSpace, eDT, nPixelSpace,
768
 
                           nBufXSize );
769
 
        }
770
 
    }
771
 
 
772
 
    return TRUE;
773
 
}
774
 
 
775
 
/************************************************************************/
776
 
/*                            LoadNextLine()                            */
777
 
/************************************************************************/
778
 
 
779
 
CPLErr ECWDataset::LoadNextLine()
780
 
 
781
 
{
782
 
    if( !bWinActive )
783
 
        return CE_Failure;
784
 
 
785
 
    if( nWinBufLoaded == nWinBufYSize-1 )
786
 
    {
787
 
        CleanupWindow();
788
 
        return CE_Failure;
789
 
    }
790
 
 
791
 
    NCSEcwReadStatus  eRStatus;
792
 
    eRStatus = poFileView->ReadLineBIL( eNCSRequestDataType, nWinBandCount,
793
 
                                        papCurLineBuf );
794
 
    if( eRStatus != NCSECW_READ_OK )
795
 
        return CE_Failure;
796
 
 
797
 
    nWinBufLoaded++;
798
 
 
799
 
    return CE_None;
800
 
}
801
 
 
802
 
/************************************************************************/
803
 
/*                           CleanupWindow()                            */
804
 
/************************************************************************/
805
 
 
806
 
void ECWDataset::CleanupWindow()
807
 
 
808
 
{
809
 
    if( !bWinActive )
810
 
        return;
811
 
 
812
 
    bWinActive = FALSE;
813
 
    CPLFree( panWinBandList );
814
 
    panWinBandList = NULL;
815
 
 
816
 
    for( int iBand = 0; iBand < nWinBandCount; iBand++ )
817
 
        CPLFree( papCurLineBuf[iBand] );
818
 
    CPLFree( papCurLineBuf );
819
 
    papCurLineBuf = NULL;
820
 
}
821
 
 
822
 
/************************************************************************/
823
 
/*                             IRasterIO()                              */
824
 
/************************************************************************/
825
 
 
826
 
CPLErr ECWDataset::IRasterIO( GDALRWFlag eRWFlag,
827
 
                              int nXOff, int nYOff, int nXSize, int nYSize,
828
 
                              void * pData, int nBufXSize, int nBufYSize,
829
 
                              GDALDataType eBufType, 
830
 
                              int nBandCount, int *panBandMap,
831
 
                              int nPixelSpace, int nLineSpace, int nBandSpace)
832
 
    
833
 
{
834
 
/* -------------------------------------------------------------------- */
835
 
/*      Try to do it based on existing "advised" access.                */
836
 
/* -------------------------------------------------------------------- */
837
 
    if( TryWinRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
838
 
                        (GByte *) pData, nBufXSize, nBufYSize, 
839
 
                        eBufType, nBandCount, panBandMap,
840
 
                        nPixelSpace, nLineSpace, nBandSpace ) )
841
 
        return CE_None;
842
 
 
843
 
/* -------------------------------------------------------------------- */
844
 
/*      If we are requesting a single line at 1:1, we do a multi-band   */
845
 
/*      AdviseRead() and then TryWinRasterIO() again.                   */
846
 
/* -------------------------------------------------------------------- */
847
 
    if( nYSize == 1 && nBufYSize == 1 && nBandCount > 1 )
848
 
    {
849
 
        CPLErr eErr;
850
 
 
851
 
        eErr = AdviseRead( nXOff, nYOff, nXSize, GetRasterYSize() - nYOff,
852
 
                           nBufXSize, GetRasterYSize() - nYOff, eBufType, 
853
 
                           nBandCount, panBandMap, NULL );
854
 
        if( eErr == CE_None 
855
 
            && TryWinRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
856
 
                               (GByte *) pData, nBufXSize, nBufYSize, 
857
 
                               eBufType, nBandCount, panBandMap,
858
 
                               nPixelSpace, nLineSpace, nBandSpace ) )
859
 
            return CE_None;
860
 
    }
861
 
 
862
 
/* -------------------------------------------------------------------- */
863
 
/*      If we are supersampling we need to fall into the general        */
864
 
/*      purpose logic.  We also use the general logic if we are in      */
865
 
/*      some cases unlikely to benefit from interleaved access.         */
866
 
/*                                                                      */
867
 
/*      The one case we would like to handle better here is the         */
868
 
/*      nBufYSize == 1 case (requesting a scanline at a time).  We      */
869
 
/*      should eventually have some logic similiar to the band by       */
870
 
/*      band case where we post a big window for the view, and allow    */
871
 
/*      sequential reads.                                               */
872
 
/* -------------------------------------------------------------------- */
873
 
    if( nXSize < nBufXSize || nYSize < nBufYSize || nYSize == 1 
874
 
        || nBandCount > 100 || nBandCount == 1 || nBufYSize == 1 
875
 
        || nBandCount > GetRasterCount() )
876
 
    {
877
 
        return 
878
 
            GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
879
 
                                    pData, nBufXSize, nBufYSize,
880
 
                                    eBufType, 
881
 
                                    nBandCount, panBandMap,
882
 
                                    nPixelSpace, nLineSpace, nBandSpace);
883
 
    }
884
 
 
885
 
    CPLDebug( "ECWDataset", 
886
 
              "RasterIO(%d,%d,%d,%d -> %dx%d) - doing interleaved read.", 
887
 
              nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize );
888
 
 
889
 
/* -------------------------------------------------------------------- */
890
 
/*      Setup view.                                                     */
891
 
/* -------------------------------------------------------------------- */
892
 
    UINT32 anBandIndices[100];
893
 
    int    i;
894
 
    NCSError     eNCSErr;
895
 
    CNCSError    oErr;
896
 
    
897
 
    for( i = 0; i < nBandCount; i++ )
898
 
        anBandIndices[i] = panBandMap[i] - 1;
899
 
 
900
 
    CleanupWindow();
901
 
 
902
 
    oErr = poFileView->SetView( nBandCount, anBandIndices,
903
 
                                nXOff, nYOff, 
904
 
                                nXOff + nXSize - 1, 
905
 
                                nYOff + nYSize - 1,
906
 
                                nBufXSize, nBufYSize );
907
 
    eNCSErr = oErr.GetErrorNumber();
908
 
    
909
 
    if( eNCSErr != NCS_SUCCESS )
910
 
    {
911
 
        CPLError( CE_Failure, CPLE_AppDefined, 
912
 
                  "%s", NCSGetErrorText(eNCSErr) );
913
 
        
914
 
        return CE_Failure;
915
 
    }
916
 
 
917
 
/* -------------------------------------------------------------------- */
918
 
/*      Setup working scanline, and the pointers into it.               */
919
 
/* -------------------------------------------------------------------- */
920
 
    int nDataTypeSize = (GDALGetDataTypeSize(eRasterDataType) / 8);
921
 
    GByte *pabyBILScanline = (GByte *) CPLMalloc(nBufXSize * nDataTypeSize *
922
 
                                                 nBandCount);
923
 
    GByte **papabyBIL = (GByte **) CPLMalloc(nBandCount * sizeof(void*));
924
 
 
925
 
    for( i = 0; i < nBandCount; i++ )
926
 
        papabyBIL[i] = pabyBILScanline + i * nBufXSize * nDataTypeSize;
927
 
 
928
 
/* -------------------------------------------------------------------- */
929
 
/*      Read back all the data for the requested view.                  */
930
 
/* -------------------------------------------------------------------- */
931
 
    for( int iScanline = 0; iScanline < nBufYSize; iScanline++ )
932
 
    {
933
 
        NCSEcwReadStatus  eRStatus;
934
 
 
935
 
        eRStatus = poFileView->ReadLineBIL( eNCSRequestDataType, nBandCount,
936
 
                                            (void **) papabyBIL );
937
 
        if( eRStatus != NCSECW_READ_OK )
938
 
        {
939
 
            CPLFree( papabyBIL );
940
 
            CPLFree( pabyBILScanline );
941
 
            CPLError( CE_Failure, CPLE_AppDefined,
942
 
                      "NCScbmReadViewLineBIL failed." );
943
 
            return CE_Failure;
944
 
        }
945
 
 
946
 
        for( i = 0; i < nBandCount; i++ )
947
 
        {
948
 
            GDALCopyWords( 
949
 
                pabyBILScanline + i * nDataTypeSize * nBufXSize,
950
 
                eRasterDataType, nDataTypeSize, 
951
 
                ((GByte *) pData) + nLineSpace * iScanline + nBandSpace * i, 
952
 
                eBufType, nPixelSpace, 
953
 
                nBufXSize );
954
 
        }
955
 
    }
956
 
 
957
 
    CPLFree( pabyBILScanline );
958
 
    CPLFree( papabyBIL );
959
 
 
960
 
    return CE_None;
961
 
}
962
 
 
963
 
/************************************************************************/
964
 
/*                        IdentifyJPEG2000()                            */
965
 
/*                                                                      */
966
 
/*          Open method that only supports JPEG2000 files.              */
967
 
/************************************************************************/
968
 
 
969
 
int ECWDataset::IdentifyJPEG2000( GDALOpenInfo * poOpenInfo )
970
 
 
971
 
{
972
 
    if( EQUALN(poOpenInfo->pszFilename,"J2K_SUBFILE:",12) )
973
 
        return TRUE;
974
 
 
975
 
    else if( poOpenInfo->nHeaderBytes >= 16 
976
 
        && (memcmp( poOpenInfo->pabyHeader, jpc_header, 
977
 
                    sizeof(jpc_header) ) == 0
978
 
            || memcmp( poOpenInfo->pabyHeader, jp2_header, 
979
 
                    sizeof(jp2_header) ) == 0) )
980
 
        return TRUE;
981
 
    
982
 
    else
983
 
        return FALSE;
984
 
}
985
 
 
986
 
/************************************************************************/
987
 
/*                            OpenJPEG2000()                            */
988
 
/*                                                                      */
989
 
/*          Open method that only supports JPEG2000 files.              */
990
 
/************************************************************************/
991
 
 
992
 
GDALDataset *ECWDataset::OpenJPEG2000( GDALOpenInfo * poOpenInfo )
993
 
 
994
 
{
995
 
    if (!IdentifyJPEG2000(poOpenInfo))
996
 
        return NULL;
997
 
 
998
 
    return Open( poOpenInfo, TRUE );
999
 
}
1000
 
    
1001
 
/************************************************************************/
1002
 
/*                           IdentifyECW()                              */
1003
 
/*                                                                      */
1004
 
/*      Identify method that only supports ECW files.                   */
1005
 
/************************************************************************/
1006
 
 
1007
 
int ECWDataset::IdentifyECW( GDALOpenInfo * poOpenInfo )
1008
 
 
1009
 
{
1010
 
/* -------------------------------------------------------------------- */
1011
 
/*      This has to either be a file on disk ending in .ecw or a        */
1012
 
/*      ecwp: protocol url.                                             */
1013
 
/* -------------------------------------------------------------------- */
1014
 
    if( (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"ecw")
1015
 
         || poOpenInfo->nHeaderBytes == 0)
1016
 
        && !EQUALN(poOpenInfo->pszFilename,"ecwp:",5) )
1017
 
        return FALSE;
1018
 
 
1019
 
    return TRUE;
1020
 
}
1021
 
 
1022
 
/************************************************************************/
1023
 
/*                              OpenECW()                               */
1024
 
/*                                                                      */
1025
 
/*      Open method that only supports ECW files.                       */
1026
 
/************************************************************************/
1027
 
 
1028
 
GDALDataset *ECWDataset::OpenECW( GDALOpenInfo * poOpenInfo )
1029
 
 
1030
 
{
1031
 
    if (!IdentifyECW(poOpenInfo))
1032
 
        return NULL;
1033
 
 
1034
 
    return Open( poOpenInfo, FALSE );
1035
 
}
1036
 
    
1037
 
/************************************************************************/
1038
 
/*                                Open()                                */
1039
 
/************************************************************************/
1040
 
 
1041
 
GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
1042
 
 
1043
 
{
1044
 
    CNCSJP2FileView *poFileView = NULL;
1045
 
    NCSError         eErr;
1046
 
    CNCSError        oErr;
1047
 
    int              i;
1048
 
    FILE            *fpVSIL = NULL;
1049
 
    VSIIOStream *poIOStream = NULL;
1050
 
    int              bUsingCustomStream = FALSE;
1051
 
 
1052
 
    ECWInitialize();
1053
 
 
1054
 
/* -------------------------------------------------------------------- */
1055
 
/*      This will disable automatic conversion of YCbCr to RGB by       */
1056
 
/*      the toolkit.                                                    */
1057
 
/* -------------------------------------------------------------------- */
1058
 
    if( !CSLTestBoolean( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB","YES") ) )
1059
 
        NCSecwSetConfig(NCSCFG_JP2_MANAGE_ICC, FALSE);
1060
 
 
1061
 
/* -------------------------------------------------------------------- */
1062
 
/*      Handle special case of a JPEG2000 data stream in another file.  */
1063
 
/* -------------------------------------------------------------------- */
1064
 
    int bIsVirtualFile = FALSE;
1065
 
try_again:
1066
 
    if( EQUALN(poOpenInfo->pszFilename,"J2K_SUBFILE:",12) ||
1067
 
        bIsVirtualFile )
1068
 
    {
1069
 
        GIntBig            subfile_offset=-1, subfile_size=-1;
1070
 
        const char *real_filename = NULL;
1071
 
 
1072
 
          if (EQUALN(poOpenInfo->pszFilename,"J2K_SUBFILE:",12))
1073
 
          {
1074
 
            char** papszTokens = CSLTokenizeString2(poOpenInfo->pszFilename + 12, ",", 0);
1075
 
            if (CSLCount(papszTokens) >= 2)
1076
 
            {
1077
 
                subfile_offset = CPLScanUIntBig(papszTokens[0], strlen(papszTokens[0]));
1078
 
                subfile_size = CPLScanUIntBig(papszTokens[1], strlen(papszTokens[1]));
1079
 
            }
1080
 
            else
1081
 
            {
1082
 
                CPLError( CE_Failure, CPLE_OpenFailed, 
1083
 
                            "Failed to parse J2K_SUBFILE specification." );
1084
 
                CSLDestroy(papszTokens);
1085
 
                return NULL;
1086
 
            }
1087
 
            CSLDestroy(papszTokens);
1088
 
 
1089
 
            real_filename = strstr(poOpenInfo->pszFilename,",");
1090
 
            if( real_filename != NULL )
1091
 
                real_filename = strstr(real_filename+1,",");
1092
 
            if( real_filename != NULL )
1093
 
                real_filename++;
1094
 
            else
1095
 
            {
1096
 
                CPLError( CE_Failure, CPLE_OpenFailed, 
1097
 
                            "Failed to parse J2K_SUBFILE specification." );
1098
 
                return NULL;
1099
 
            }
1100
 
 
1101
 
          }
1102
 
          else
1103
 
          {
1104
 
              real_filename = poOpenInfo->pszFilename;
1105
 
              subfile_offset = 0;
1106
 
          }
1107
 
 
1108
 
          fpVSIL = VSIFOpenL( real_filename, "rb" );
1109
 
          if( fpVSIL == NULL )
1110
 
          {
1111
 
              CPLError( CE_Failure, CPLE_OpenFailed, 
1112
 
                        "Failed to open %s.",  real_filename );
1113
 
              return NULL;
1114
 
          }
1115
 
 
1116
 
          if( hECWDatasetMutex == NULL )
1117
 
          {
1118
 
              hECWDatasetMutex = CPLCreateMutex();
1119
 
          }
1120
 
          else if( !CPLAcquireMutex( hECWDatasetMutex, 60.0 ) )
1121
 
          {
1122
 
              CPLDebug( "ECW", "Failed to acquire mutex in 60s." );
1123
 
          }
1124
 
          else
1125
 
          {
1126
 
              CPLDebug( "ECW", "Got mutex." );
1127
 
          }
1128
 
          poIOStream = new VSIIOStream();
1129
 
          poIOStream->Access( fpVSIL, FALSE, real_filename,
1130
 
                              subfile_offset, subfile_size );
1131
 
 
1132
 
          poFileView = new CNCSJP2FileView();
1133
 
          oErr = poFileView->Open( poIOStream, false );
1134
 
 
1135
 
          // The CNCSJP2FileView (poFileView) object may not use the iostream 
1136
 
          // (poIOStream) passed to the CNCSJP2FileView::Open() method if an 
1137
 
          // iostream is already available to the ECW JPEG 2000 SDK for a given
1138
 
          // file.  Consequently, if the iostream passed to 
1139
 
          // CNCSJP2FileView::Open() does not become the underlying iostream 
1140
 
          // of the CNCSJP2FileView object, then it should be deleted.
1141
 
          //
1142
 
          // In addition, the underlying iostream of the CNCSJP2FileView object
1143
 
          // should not be deleted until all CNCSJP2FileView objects using the 
1144
 
          // underlying iostream are deleted. Consequently, each time a 
1145
 
          // CNCSJP2FileView object is created, the nFileViewCount attribute 
1146
 
          // of the underlying VSIIOStream object must be incremented for use 
1147
 
          // in the ECWDataset destructor.
1148
 
                  
1149
 
          VSIIOStream * poUnderlyingIOStream = 
1150
 
              ((VSIIOStream *)(poFileView->GetStream()));
1151
 
 
1152
 
          if ( poUnderlyingIOStream )
1153
 
              poUnderlyingIOStream->nFileViewCount++;
1154
 
 
1155
 
          if ( poIOStream != poUnderlyingIOStream ) 
1156
 
          {
1157
 
              delete poIOStream;
1158
 
          }
1159
 
          else
1160
 
          {
1161
 
              bUsingCustomStream = TRUE;
1162
 
          }
1163
 
 
1164
 
          CPLReleaseMutex( hECWDatasetMutex );
1165
 
 
1166
 
          if( oErr.GetErrorNumber() != NCS_SUCCESS )
1167
 
          {
1168
 
              if (poFileView)
1169
 
                  delete poFileView;
1170
 
 
1171
 
              char* pszErrorMessage = oErr.GetErrorMessage();
1172
 
              CPLError( CE_Failure, CPLE_AppDefined, 
1173
 
                        "%s", pszErrorMessage );
1174
 
              NCSFree(pszErrorMessage);
1175
 
 
1176
 
              return NULL;
1177
 
          }
1178
 
    }
1179
 
 
1180
 
/* -------------------------------------------------------------------- */
1181
 
/*      This has to either be a file on disk ending in .ecw or a        */
1182
 
/*      ecwp: protocol url.                                             */
1183
 
/* -------------------------------------------------------------------- */
1184
 
    else if( poOpenInfo->nHeaderBytes >= 16 
1185
 
        && (memcmp( poOpenInfo->pabyHeader, jpc_header, 
1186
 
                    sizeof(jpc_header) ) == 0
1187
 
            || memcmp( poOpenInfo->pabyHeader, jp2_header, 
1188
 
                    sizeof(jp2_header) ) == 0) )
1189
 
    {
1190
 
        /* accept JPEG2000 files */
1191
 
    }
1192
 
    else if( (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"ecw")
1193
 
              || poOpenInfo->nHeaderBytes == 0)
1194
 
             && !EQUALN(poOpenInfo->pszFilename,"ecwp:",5) )
1195
 
        return( NULL );
1196
 
    
1197
 
/* -------------------------------------------------------------------- */
1198
 
/*      Open the client interface.                                      */
1199
 
/* -------------------------------------------------------------------- */
1200
 
    if( poFileView == NULL )
1201
 
    {
1202
 
        poFileView = new CNCSFile();
1203
 
        oErr = poFileView->Open( (char *) poOpenInfo->pszFilename, FALSE );
1204
 
        eErr = oErr.GetErrorNumber();
1205
 
        CPLDebug( "ECW", "NCScbmOpenFileView(%s): eErr = %d", 
1206
 
                  poOpenInfo->pszFilename, (int) eErr );
1207
 
        if( eErr != NCS_SUCCESS )
1208
 
        {
1209
 
            delete poFileView;
1210
 
 
1211
 
            /* If the file is not a 'real' file but recognized as a */
1212
 
            /* virtual file by the VSIL API, try again by using a */
1213
 
            /* VSIIOStream object, like in the J2K_SUBFILE case */
1214
 
            VSIStatBuf sBuf;
1215
 
            VSIStatBufL sBufL;
1216
 
            if (!bIsVirtualFile &&
1217
 
                VSIStat(poOpenInfo->pszFilename, &sBuf) != 0 &&
1218
 
                VSIStatL(poOpenInfo->pszFilename, &sBufL) == 0)
1219
 
            {
1220
 
                bIsVirtualFile = TRUE;
1221
 
                goto try_again;
1222
 
            }
1223
 
 
1224
 
            CPLError( CE_Failure, CPLE_AppDefined, 
1225
 
                      "%s", NCSGetErrorText(eErr) );
1226
 
            return NULL;
1227
 
        }
1228
 
    }
1229
 
 
1230
 
    if( poOpenInfo->eAccess == GA_Update )
1231
 
    {
1232
 
        CPLError( CE_Failure, CPLE_NotSupported, 
1233
 
                  "The DIMAP driver does not support update access to existing"
1234
 
                  " datasets.\n" );
1235
 
        return NULL;
1236
 
    }
1237
 
    
1238
 
/* -------------------------------------------------------------------- */
1239
 
/*      Create a corresponding GDALDataset.                             */
1240
 
/* -------------------------------------------------------------------- */
1241
 
    ECWDataset  *poDS;
1242
 
 
1243
 
    poDS = new ECWDataset(bIsJPEG2000);
1244
 
 
1245
 
    poDS->poFileView = poFileView;
1246
 
 
1247
 
    if( fpVSIL != NULL )
1248
 
        poDS->nPamFlags |= GPF_DISABLED;
1249
 
 
1250
 
    poDS->bUsingCustomStream = bUsingCustomStream;
1251
 
 
1252
 
/* -------------------------------------------------------------------- */
1253
 
/*      Fetch general file information.                                 */
1254
 
/* -------------------------------------------------------------------- */
1255
 
    poDS->psFileInfo = poFileView->GetFileInfo();
1256
 
 
1257
 
    CPLDebug( "ECW", "FileInfo: SizeXY=%d,%d Bands=%d\n"
1258
 
              "       OriginXY=%g,%g  CellIncrementXY=%g,%g\n",
1259
 
              poDS->psFileInfo->nSizeX,
1260
 
              poDS->psFileInfo->nSizeY,
1261
 
              poDS->psFileInfo->nBands,
1262
 
              poDS->psFileInfo->fOriginX,
1263
 
              poDS->psFileInfo->fOriginY,
1264
 
              poDS->psFileInfo->fCellIncrementX,
1265
 
              poDS->psFileInfo->fCellIncrementY );
1266
 
 
1267
 
/* -------------------------------------------------------------------- */
1268
 
/*      Establish raster info.                                          */
1269
 
/* -------------------------------------------------------------------- */
1270
 
    poDS->nRasterXSize = poDS->psFileInfo->nSizeX; 
1271
 
    poDS->nRasterYSize = poDS->psFileInfo->nSizeY;
1272
 
 
1273
 
/* -------------------------------------------------------------------- */
1274
 
/*      Establish the GDAL data type that corresponds.  A few NCS       */
1275
 
/*      data types have no direct corresponding value in GDAL so we     */
1276
 
/*      will coerce to something sufficiently similar.                  */
1277
 
/* -------------------------------------------------------------------- */
1278
 
    poDS->eNCSRequestDataType = poDS->psFileInfo->eCellType;
1279
 
    switch( poDS->psFileInfo->eCellType )
1280
 
    {
1281
 
        case NCSCT_UINT8:
1282
 
            poDS->eRasterDataType = GDT_Byte;
1283
 
            break;
1284
 
 
1285
 
        case NCSCT_UINT16:
1286
 
            poDS->eRasterDataType = GDT_UInt16;
1287
 
            break;
1288
 
 
1289
 
        case NCSCT_UINT32:
1290
 
        case NCSCT_UINT64:
1291
 
            poDS->eRasterDataType = GDT_UInt32;
1292
 
            poDS->eNCSRequestDataType = NCSCT_UINT32;
1293
 
            break;
1294
 
 
1295
 
        case NCSCT_INT8:
1296
 
        case NCSCT_INT16:
1297
 
            poDS->eRasterDataType = GDT_Int16;
1298
 
            poDS->eNCSRequestDataType = NCSCT_INT16;
1299
 
            break;
1300
 
 
1301
 
        case NCSCT_INT32:
1302
 
        case NCSCT_INT64:
1303
 
            poDS->eRasterDataType = GDT_Int32;
1304
 
            poDS->eNCSRequestDataType = NCSCT_INT32;
1305
 
            break;
1306
 
 
1307
 
        case NCSCT_IEEE4:
1308
 
            poDS->eRasterDataType = GDT_Float32;
1309
 
            break;
1310
 
 
1311
 
        case NCSCT_IEEE8:
1312
 
            poDS->eRasterDataType = GDT_Float64;
1313
 
            break;
1314
 
    }
1315
 
 
1316
 
/* -------------------------------------------------------------------- */
1317
 
/*      Create band information objects.                                */
1318
 
/* -------------------------------------------------------------------- */
1319
 
    for( i=0; i < poDS->psFileInfo->nBands; i++ )
1320
 
        poDS->SetBand( i+1, new ECWRasterBand( poDS, i+1 ) );
1321
 
 
1322
 
/* -------------------------------------------------------------------- */
1323
 
/*      Look for supporting coordinate system information.              */
1324
 
/* -------------------------------------------------------------------- */
1325
 
    GDALJP2Metadata oJP2Geo;
1326
 
 
1327
 
    if( oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
1328
 
    {
1329
 
        poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
1330
 
        poDS->bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
1331
 
        memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform, 
1332
 
                sizeof(double) * 6 );
1333
 
        poDS->nGCPCount = oJP2Geo.nGCPCount;
1334
 
        poDS->pasGCPList = oJP2Geo.pasGCPList;
1335
 
        oJP2Geo.pasGCPList = NULL;
1336
 
        oJP2Geo.nGCPCount = 0;
1337
 
    }
1338
 
    else
1339
 
    {
1340
 
        poDS->ECW2WKTProjection();
1341
 
    }
1342
 
 
1343
 
/* -------------------------------------------------------------------- */
1344
 
/*      Check for world file for ecw files.                             */
1345
 
/* -------------------------------------------------------------------- */
1346
 
    if( !poDS->bGeoTransformValid 
1347
 
        && EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"ecw") )
1348
 
    {
1349
 
        poDS->bGeoTransformValid |= 
1350
 
            GDALReadWorldFile( poOpenInfo->pszFilename, ".eww", 
1351
 
                               poDS->adfGeoTransform )
1352
 
            || GDALReadWorldFile( poOpenInfo->pszFilename, ".ecww", 
1353
 
                                  poDS->adfGeoTransform )
1354
 
            || GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
1355
 
                                  poDS->adfGeoTransform );
1356
 
    }
1357
 
 
1358
 
/* -------------------------------------------------------------------- */
1359
 
/*      Initialize any PAM information.                                 */
1360
 
/* -------------------------------------------------------------------- */
1361
 
    poDS->SetDescription( poOpenInfo->pszFilename );
1362
 
    poDS->TryLoadXML();
1363
 
    
1364
 
/* -------------------------------------------------------------------- */
1365
 
/*      Confirm the requested access is supported.                      */
1366
 
/* -------------------------------------------------------------------- */
1367
 
    if( poOpenInfo->eAccess == GA_Update )
1368
 
    {
1369
 
        delete poDS;
1370
 
        CPLError( CE_Failure, CPLE_NotSupported, 
1371
 
                  "The ECW driver does not support update access to existing"
1372
 
                  " datasets.\n" );
1373
 
        return NULL;
1374
 
    }
1375
 
    
1376
 
    return( poDS );
1377
 
}
1378
 
 
1379
 
/************************************************************************/
1380
 
/*                            GetGCPCount()                             */
1381
 
/************************************************************************/
1382
 
 
1383
 
int ECWDataset::GetGCPCount()
1384
 
 
1385
 
{
1386
 
    if( nGCPCount != 0 )
1387
 
        return nGCPCount;
1388
 
    else
1389
 
        return GDALPamDataset::GetGCPCount();
1390
 
}
1391
 
 
1392
 
/************************************************************************/
1393
 
/*                          GetGCPProjection()                          */
1394
 
/************************************************************************/
1395
 
 
1396
 
const char *ECWDataset::GetGCPProjection()
1397
 
 
1398
 
{
1399
 
    if( nGCPCount > 0 )
1400
 
        return pszProjection;
1401
 
    else
1402
 
        return GDALPamDataset::GetGCPProjection();
1403
 
}
1404
 
 
1405
 
/************************************************************************/
1406
 
/*                               GetGCP()                               */
1407
 
/************************************************************************/
1408
 
 
1409
 
const GDAL_GCP *ECWDataset::GetGCPs()
1410
 
 
1411
 
{
1412
 
    if( nGCPCount != 0 )
1413
 
        return pasGCPList;
1414
 
    else
1415
 
        return GDALPamDataset::GetGCPs();
1416
 
}
1417
 
 
1418
 
/************************************************************************/
1419
 
/*                          GetProjectionRef()                          */
1420
 
/*                                                                      */
1421
 
/*      We let PAM coordinate system override the one stored inside     */
1422
 
/*      our file.                                                       */
1423
 
/************************************************************************/
1424
 
 
1425
 
const char *ECWDataset::GetProjectionRef() 
1426
 
 
1427
 
{
1428
 
    const char* pszPamPrj = GDALPamDataset::GetProjectionRef();
1429
 
 
1430
 
    if( pszProjection != NULL && strlen(pszPamPrj) == 0 )
1431
 
        return pszProjection;
1432
 
    else
1433
 
        return pszPamPrj;
1434
 
}
1435
 
 
1436
 
/************************************************************************/
1437
 
/*                          GetGeoTransform()                           */
1438
 
/*                                                                      */
1439
 
/*      Only return the native geotransform if we appear to be          */
1440
 
/*      returning the native coordinate system, otherwise defer to      */
1441
 
/*      the PAM geotransform.                                           */
1442
 
/************************************************************************/
1443
 
 
1444
 
CPLErr ECWDataset::GetGeoTransform( double * padfTransform )
1445
 
 
1446
 
{
1447
 
    if( (GetProjectionRef() != pszProjection  
1448
 
         && strlen(GetProjectionRef()) > 0)
1449
 
        || !bGeoTransformValid )
1450
 
    {
1451
 
        return GDALPamDataset::GetGeoTransform( padfTransform );
1452
 
    }
1453
 
    else
1454
 
    {
1455
 
        memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
1456
 
        return( CE_None );
1457
 
    }
1458
 
}
1459
 
 
1460
 
/************************************************************************/
1461
 
/*                            GetMetadata()                             */
1462
 
/************************************************************************/
1463
 
 
1464
 
char **ECWDataset::GetMetadata( const char *pszDomain )
1465
 
 
1466
 
{
1467
 
    if( pszDomain == NULL || !EQUAL(pszDomain,"GML") )
1468
 
        return GDALPamDataset::GetMetadata( pszDomain );
1469
 
    else
1470
 
        return papszGMLMetadata;
1471
 
}
1472
 
 
1473
 
/************************************************************************/
1474
 
/*                         ECW2WKTProjection()                          */
1475
 
/*                                                                      */
1476
 
/*      Set the dataset pszProjection string in OGC WKT format by       */
1477
 
/*      looking up the ECW (GDT) coordinate system info in              */
1478
 
/*      ecw_cs.dat support data file.                                   */
1479
 
/*                                                                      */
1480
 
/*      This code is likely still broken in some circumstances.  For    */
1481
 
/*      instance, I haven't been careful about changing the linear      */
1482
 
/*      projection parameters (false easting/northing) if the units     */
1483
 
/*      is feet.  Lots of cases missing here, and in ecw_cs.dat.        */
1484
 
/************************************************************************/
1485
 
 
1486
 
void ECWDataset::ECW2WKTProjection()
1487
 
 
1488
 
{
1489
 
    if( psFileInfo == NULL )
1490
 
        return;
1491
 
 
1492
 
/* -------------------------------------------------------------------- */
1493
 
/*      Capture Geotransform.                                           */
1494
 
/*                                                                      */
1495
 
/*      We will try to ignore the provided file information if it is    */
1496
 
/*      origin (0,0) and pixel size (1,1).  I think sometimes I have    */
1497
 
/*      also seen pixel increments of 0 on invalid datasets.            */
1498
 
/* -------------------------------------------------------------------- */
1499
 
    if( psFileInfo->fOriginX != 0.0 
1500
 
        || psFileInfo->fOriginY != 0.0 
1501
 
        || (psFileInfo->fCellIncrementX != 0.0 
1502
 
            && psFileInfo->fCellIncrementX != 1.0)
1503
 
        || (psFileInfo->fCellIncrementY != 0.0 
1504
 
            && psFileInfo->fCellIncrementY != 1.0) )
1505
 
    {
1506
 
        bGeoTransformValid = TRUE;
1507
 
        
1508
 
        adfGeoTransform[0] = psFileInfo->fOriginX;
1509
 
        adfGeoTransform[1] = psFileInfo->fCellIncrementX;
1510
 
        adfGeoTransform[2] = 0.0;
1511
 
        
1512
 
        adfGeoTransform[3] = psFileInfo->fOriginY;
1513
 
        adfGeoTransform[4] = 0.0;
1514
 
        adfGeoTransform[5] = psFileInfo->fCellIncrementY;
1515
 
    }
1516
 
 
1517
 
/* -------------------------------------------------------------------- */
1518
 
/*      do we have projection and datum?                                */
1519
 
/* -------------------------------------------------------------------- */
1520
 
    CPLDebug( "ECW", "projection=%s, datum=%s",
1521
 
              psFileInfo->szProjection, psFileInfo->szDatum );
1522
 
 
1523
 
    if( EQUAL(psFileInfo->szProjection,"RAW") )
1524
 
        return;
1525
 
 
1526
 
/* -------------------------------------------------------------------- */
1527
 
/*      Set projection if we have it.                                   */
1528
 
/* -------------------------------------------------------------------- */
1529
 
    OGRSpatialReference oSRS;
1530
 
    CPLString osUnits = "METERS";
1531
 
 
1532
 
    if( psFileInfo->eCellSizeUnits == ECW_CELL_UNITS_FEET )
1533
 
        osUnits = "FEET";
1534
 
 
1535
 
    if( oSRS.importFromERM( psFileInfo->szProjection, 
1536
 
                            psFileInfo->szDatum, 
1537
 
                            osUnits ) != OGRERR_NONE )
1538
 
        return;
1539
 
 
1540
 
    oSRS.exportToWkt( &pszProjection );
1541
 
}
1542
 
 
1543
 
#endif /* def FRMT_ecw */
1544
 
 
1545
 
/************************************************************************/
1546
 
/*                           ECWInitialize()                            */
1547
 
/*                                                                      */
1548
 
/*      Initialize NCS library.  We try to defer this as late as        */
1549
 
/*      possible since de-initializing it seems to be expensive/slow    */
1550
 
/*      on some system.                                                 */
1551
 
/************************************************************************/
1552
 
 
1553
 
void ECWInitialize()
1554
 
 
1555
 
{
1556
 
    CPLMutexHolder oHolder( &hECWDatasetMutex );
1557
 
 
1558
 
    if( bNCSInitialized )
1559
 
        return;
1560
 
 
1561
 
    NCSecwInit();
1562
 
    bNCSInitialized = TRUE;
1563
 
 
1564
 
    const char *pszEcwCacheSize = 
1565
 
        CPLGetConfigOption("GDAL_ECW_CACHE_MAXMEM",NULL);
1566
 
 
1567
 
    if( pszEcwCacheSize != NULL )
1568
 
        NCSecwSetConfig(NCSCFG_CACHE_MAXMEM, atoi(pszEcwCacheSize) );
1569
 
}
1570
 
 
1571
 
/************************************************************************/
1572
 
/*                         GDALDeregister_ECW()                         */
1573
 
/************************************************************************/
1574
 
 
1575
 
void GDALDeregister_ECW( GDALDriver * )
1576
 
 
1577
 
{
1578
 
    /* For unknown reason, this cleanup can take up to 3 seconds (see #3134). */
1579
 
    /* Not worth it */
1580
 
#ifdef notdef
1581
 
    if( bNCSInitialized )
1582
 
    {
1583
 
        bNCSInitialized = FALSE;
1584
 
        NCSecwShutdown();
1585
 
    }
1586
 
 
1587
 
    if( hECWDatasetMutex != NULL )
1588
 
    {
1589
 
        CPLDestroyMutex( hECWDatasetMutex );
1590
 
        hECWDatasetMutex = NULL;
1591
 
    }
1592
 
#endif
1593
 
}
1594
 
 
1595
 
/************************************************************************/
1596
 
/*                          GDALRegister_ECW()                        */
1597
 
/************************************************************************/
1598
 
 
1599
 
void GDALRegister_ECW()
1600
 
 
1601
 
{
1602
 
#ifdef FRMT_ecw 
1603
 
    GDALDriver  *poDriver;
1604
 
 
1605
 
    if (! GDAL_CHECK_VERSION("ECW driver"))
1606
 
        return;
1607
 
 
1608
 
    if( GDALGetDriverByName( "ECW" ) == NULL )
1609
 
    {
1610
 
        poDriver = new GDALDriver();
1611
 
        
1612
 
        poDriver->SetDescription( "ECW" );
1613
 
        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
1614
 
                                   "ERMapper Compressed Wavelets" );
1615
 
        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
1616
 
                                   "frmt_ecw.html" );
1617
 
        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "ecw" );
1618
 
        
1619
 
        poDriver->pfnIdentify = ECWDataset::IdentifyECW;
1620
 
        poDriver->pfnOpen = ECWDataset::OpenECW;
1621
 
        poDriver->pfnUnloadDriver = GDALDeregister_ECW;
1622
 
#ifdef HAVE_COMPRESS
1623
 
// The create method seems not to work properly.
1624
 
//        poDriver->pfnCreate = ECWCreateECW;  
1625
 
        poDriver->pfnCreateCopy = ECWCreateCopyECW;
1626
 
        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
1627
 
                                   "Byte" );
1628
 
        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
1629
 
"<CreationOptionList>"
1630
 
"   <Option name='TARGET' type='float' description='Compression Percentage' />"
1631
 
"   <Option name='PROJ' type='string' description='ERMapper Projection Name'/>"
1632
 
"   <Option name='DATUM' type='string' description='ERMapper Datum Name' />"
1633
 
"   <Option name='LARGE_OK' type='boolean' description='Enable compressing 500+MB files'/>"
1634
 
"</CreationOptionList>" );
1635
 
#endif
1636
 
 
1637
 
        GetGDALDriverManager()->RegisterDriver( poDriver );
1638
 
    }
1639
 
#endif /* def FRMT_ecw */
1640
 
}
1641
 
 
1642
 
/************************************************************************/
1643
 
/*                      GDALRegister_ECW_JP2ECW()                       */
1644
 
/*                                                                      */
1645
 
/*      This function exists so that when built as a plugin, there      */
1646
 
/*      is a function that will register both drivers.                  */
1647
 
/************************************************************************/
1648
 
 
1649
 
void GDALRegister_ECW_JP2ECW()
1650
 
 
1651
 
{
1652
 
    GDALRegister_ECW();
1653
 
    GDALRegister_JP2ECW();
1654
 
}
1655
 
 
1656
 
/************************************************************************/
1657
 
/*                     ECWDatasetOpenJPEG2000()                         */
1658
 
/************************************************************************/
1659
 
GDALDataset* ECWDatasetOpenJPEG2000(GDALOpenInfo* poOpenInfo)
1660
 
{
1661
 
    return ECWDataset::OpenJPEG2000(poOpenInfo);
1662
 
}
1663
 
 
1664
 
/************************************************************************/
1665
 
/*                        GDALRegister_JP2ECW()                         */
1666
 
/************************************************************************/
1667
 
void GDALRegister_JP2ECW()
1668
 
 
1669
 
{
1670
 
#ifdef FRMT_ecw 
1671
 
    GDALDriver  *poDriver;
1672
 
 
1673
 
    if (! GDAL_CHECK_VERSION("JP2ECW driver"))
1674
 
        return;
1675
 
 
1676
 
    if( GDALGetDriverByName( "JP2ECW" ) == NULL )
1677
 
    {
1678
 
        poDriver = new GDALDriver();
1679
 
        
1680
 
        poDriver->SetDescription( "JP2ECW" );
1681
 
        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
1682
 
                                   "ERMapper JPEG2000" );
1683
 
        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
1684
 
                                   "frmt_jp2ecw.html" );
1685
 
        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
1686
 
        
1687
 
        poDriver->pfnIdentify = ECWDataset::IdentifyJPEG2000;
1688
 
        poDriver->pfnOpen = ECWDataset::OpenJPEG2000;
1689
 
#ifdef HAVE_COMPRESS
1690
 
        poDriver->pfnCreate = ECWCreateJPEG2000;
1691
 
        poDriver->pfnCreateCopy = ECWCreateCopyJPEG2000;
1692
 
        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
1693
 
                                   "Byte UInt16 Int16 UInt32 Int32 Float32 Float64" );
1694
 
        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, 
1695
 
"<CreationOptionList>"
1696
 
"   <Option name='TARGET' type='float' description='Compression Percentage' />"
1697
 
"   <Option name='PROJ' type='string' description='ERMapper Projection Name'/>"
1698
 
"   <Option name='DATUM' type='string' description='ERMapper Datum Name' />"
1699
 
"   <Option name='LARGE_OK' type='boolean' description='Enable compressing 500+MB files'/>"
1700
 
"   <Option name='GeoJP2' type='boolean' description='defaults to ON'/>"
1701
 
"   <Option name='GMLJP2' type='boolean' description='defaults to ON'/>"
1702
 
"   <Option name='PROFILE' type='string-select'>"
1703
 
"       <Value>BASELINE_0</Value>"
1704
 
"       <Value>BASELINE_1</Value>"
1705
 
"       <Value>BASELINE_2</Value>"
1706
 
"       <Value>NPJE</Value>"
1707
 
"       <Value>EPJE</Value>"
1708
 
"   </Option>"
1709
 
"   <Option name='PROGRESSION' type='string-select'>"
1710
 
"       <Value>LRCP</Value>"
1711
 
"       <Value>RLCP</Value>"
1712
 
"       <Value>RPCL</Value>"
1713
 
"   </Option>"
1714
 
"   <Option name='CODESTREAM_ONLY' type='boolean' description='No JP2 wrapper'/>"
1715
 
"   <Option name='LEVELS' type='int'/>"
1716
 
"   <Option name='LAYERS' type='int'/>"
1717
 
"   <Option name='PRECINCT_WIDTH' type='int'/>"
1718
 
"   <Option name='PRECINCT_HEIGHT' type='int'/>"
1719
 
"   <Option name='TILE_WIDTH' type='int'/>"
1720
 
"   <Option name='TILE_HEIGHT' type='int'/>"
1721
 
"   <Option name='INCLUDE_SOP' type='boolean'/>"
1722
 
"   <Option name='INCLUDE_EPH' type='boolean'/>"
1723
 
"   <Option name='DECOMPRESS_LAYERS' type='int'/>"
1724
 
"   <Option name='DECOMPRESS_RECONSTRUCTION_PARAMETER' type='float'/>"
1725
 
"</CreationOptionList>" );
1726
 
#endif
1727
 
 
1728
 
        GetGDALDriverManager()->RegisterDriver( poDriver );
1729
 
    }
1730
 
#endif /* def FRMT_ecw */
1731
 
}
1732
 
 
1733
 
 
1734
 
 
1735