1 : /******************************************************************************
2 : * $Id: ecwdataset.cpp 21486 2011-01-13 17:38:17Z warmerdam $
3 : *
4 : * Project: GDAL
5 : * Purpose: ECW (ERDAS Wavelet Compression Format) Driver Definitions
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2001-2011, 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 : #ifndef GDAL_ECW_H_INCLUDED
31 : #define GDAL_ECW_H_INCLUDED
32 :
33 : #include "gdal_pam.h"
34 : #include "gdal_frmts.h"
35 : #include "gdaljp2metadata.h"
36 : #include "cpl_string.h"
37 : #include "cpl_conv.h"
38 : #include "cpl_multiproc.h"
39 : #include "cpl_vsi.h"
40 :
41 : #undef NOISY_DEBUG
42 :
43 : #ifdef FRMT_ecw
44 :
45 : // The following is needed on 4.x+ to enable rw support.
46 : #if defined(HAVE_COMPRESS)
47 : # ifndef ECW_COMPRESS_RW_SDK_VERSION
48 : # define ECW_COMPRESS_RW_SDK_VERSION
49 : # endif
50 : #endif
51 :
52 : #if defined(_MSC_VER)
53 : # pragma warning(disable:4800)
54 : #endif
55 :
56 : #include <NCSECWClient.h>
57 : #include <NCSECWCompressClient.h>
58 : #include <NCSErrors.h>
59 : #include <NCSFile.h>
60 : #include <NCSJP2FileView.h>
61 :
62 : #ifdef HAVE_ECW_BUILDNUMBER_H
63 : # include <ECWJP2BuildNumber.h>
64 : # if !defined(ECW_VERSION)
65 : # define ECWSDK_VERSION (NCS_ECWJP2_VER_MAJOR*10+NCS_ECWJP2_VER_MINOR)
66 : # endif
67 : #else
68 : /* By default, assume 3.3 SDK Version. */
69 : # if !defined(ECWSDK_VERSION)
70 : # define ECWSDK_VERSION 33
71 : # endif
72 : #endif
73 :
74 : #if ECWSDK_VERSION < 40
75 :
76 : #if !defined(NO_COMPRESS)
77 : # define HAVE_COMPRESS
78 : #endif
79 :
80 : #else
81 : #if ECWSDK_VERSION>=50
82 : #include <NCSECWHeaderEditor.h>
83 : #include "NCSEcw/SDK/Box.h"
84 : #else
85 : #include <HeaderEditor.h>
86 : #endif
87 : # define NCS_FASTCALL
88 : #endif
89 :
90 : #if ECWSDK_VERSION >= 40
91 : #define SDK_CAN_DO_SUPERSAMPLING 1
92 : #endif
93 :
94 : #ifndef NCSFILEBASE_H
95 : # include <NCSJP2FileView.h>
96 : #else
97 : # undef CNCSJP2FileView
98 : # define CNCSJP2FileView CNCSFile
99 : #endif
100 :
101 : void ECWInitialize( void );
102 : GDALDataset* ECWDatasetOpenJPEG2000(GDALOpenInfo* poOpenInfo);
103 : const char* ECWGetColorInterpretationName(GDALColorInterp eColorInterpretation, int nBandNumber);
104 : GDALColorInterp ECWGetColorInterpretationByName(const char *pszName);
105 :
106 : #ifdef HAVE_COMPRESS
107 : GDALDataset *
108 : ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS,
109 : int bStrict, char ** papszOptions,
110 : GDALProgressFunc pfnProgress, void * pProgressData );
111 : GDALDataset *
112 : ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS,
113 : int bStrict, char ** papszOptions,
114 : GDALProgressFunc pfnProgress, void * pProgressData );
115 :
116 : GDALDataset *
117 : ECWCreateECW( const char * pszFilename, int nXSize, int nYSize, int nBands,
118 : GDALDataType eType, char **papszOptions );
119 : GDALDataset *
120 : ECWCreateJPEG2000(const char *pszFilename, int nXSize, int nYSize, int nBands,
121 : GDALDataType eType, char **papszOptions );
122 : #endif
123 :
124 : void ECWReportError(CNCSError& oErr, const char* pszMsg = "");
125 :
126 : /************************************************************************/
127 : /* ==================================================================== */
128 : /* JP2Userbox */
129 : /* ==================================================================== */
130 : /************************************************************************/
131 : #ifdef HAVE_COMPRESS
132 : #if ECWSDK_VERSION>=50
133 : class JP2UserBox : public CNCSSDKBox {
134 : #else
135 : class JP2UserBox : public CNCSJP2Box {
136 : #endif
137 : private:
138 : int nDataLength;
139 : unsigned char *pabyData;
140 :
141 : public:
142 : JP2UserBox();
143 :
144 : virtual ~JP2UserBox();
145 :
146 : #if ECWSDK_VERSION >= 40
147 : virtual CNCSError Parse(NCS::SDK::CFileBase &JP2File,
148 : NCS::CIOStream &Stream);
149 : virtual CNCSError UnParse(NCS::SDK::CFileBase &JP2File,
150 : NCS::CIOStream &Stream);
151 : #else
152 : virtual CNCSError Parse(class CNCSJP2File &JP2File,
153 : CNCSJPCIOStream &Stream);
154 : virtual CNCSError UnParse(class CNCSJP2File &JP2File,
155 : CNCSJPCIOStream &Stream);
156 : #endif
157 : virtual void UpdateXLBox(void);
158 :
159 : void SetData( int nDataLength, const unsigned char *pabyDataIn );
160 :
161 : int GetDataLength() { return nDataLength; }
162 : unsigned char *GetData() { return pabyData; }
163 : };
164 : #endif /* def HAVE_COMPRESS */
165 :
166 : /************************************************************************/
167 : /* ==================================================================== */
168 : /* VSIIOStream */
169 : /* ==================================================================== */
170 : /************************************************************************/
171 :
172 : class VSIIOStream : public CNCSJPCIOStream
173 :
174 : {
175 : private:
176 : char *m_Filename;
177 : public:
178 :
179 : INT64 startOfJPData;
180 : INT64 lengthOfJPData;
181 : VSILFILE *fpVSIL;
182 : BOOLEAN bWritable;
183 : int nFileViewCount;
184 :
185 66 : VSIIOStream() : m_Filename(NULL){
186 66 : nFileViewCount = 0;
187 66 : startOfJPData = 0;
188 66 : lengthOfJPData = -1;
189 66 : fpVSIL = NULL;
190 66 : }
191 66 : virtual ~VSIIOStream() {
192 66 : Close();
193 66 : if (m_Filename!=NULL){
194 35 : CPLFree(m_Filename);
195 : }
196 66 : }
197 :
198 121 : virtual CNCSError Close() {
199 121 : CNCSError oErr = CNCSJPCIOStream::Close();
200 121 : if( fpVSIL != NULL )
201 : {
202 35 : VSIFCloseL( fpVSIL );
203 35 : fpVSIL = NULL;
204 : }
205 0 : return oErr;
206 : }
207 :
208 : #if ECWSDK_VERSION >= 40
209 : virtual VSIIOStream *Clone() {
210 :
211 : VSILFILE *fpNewVSIL = VSIFOpenL( m_Filename, "rb" );
212 : if (fpNewVSIL == NULL)
213 : {
214 : return NULL;
215 : }else
216 : {
217 : VSIIOStream *pDst = new VSIIOStream();
218 : pDst->Access(fpNewVSIL, bWritable, m_Filename, startOfJPData, lengthOfJPData);
219 : return pDst;
220 : }
221 : }
222 : #endif /* ECWSDK_VERSION >= 4 */
223 :
224 35 : virtual CNCSError Access( VSILFILE *fpVSILIn, BOOLEAN bWrite,
225 : const char *pszFilename,
226 : INT64 start, INT64 size = -1) {
227 :
228 35 : fpVSIL = fpVSILIn;
229 35 : startOfJPData = start;
230 35 : lengthOfJPData = size;
231 35 : bWritable = bWrite;
232 35 : VSIFSeekL(fpVSIL, startOfJPData, SEEK_SET);
233 35 : m_Filename = CPLStrdup(pszFilename);
234 : // the filename is used to establish where to put temporary files.
235 : // if it does not have a path to a real directory, we will
236 : // substitute something.
237 35 : CPLString osFilenameUsed = pszFilename;
238 35 : CPLString osPath = CPLGetPath( pszFilename );
239 : struct stat sStatBuf;
240 35 : if( osPath != "" && stat( osPath, &sStatBuf ) != 0 )
241 : {
242 22 : osFilenameUsed = CPLGenerateTempFilename( NULL );
243 : // try to preserve the extension.
244 22 : if( strlen(CPLGetExtension(pszFilename)) > 0 )
245 : {
246 22 : osFilenameUsed += ".";
247 22 : osFilenameUsed += CPLGetExtension(pszFilename);
248 : }
249 22 : CPLDebug( "ECW", "Using filename '%s' for temporary directory determination purposes.", osFilenameUsed.c_str() );
250 : }
251 : return(CNCSJPCIOStream::Open((char *)osFilenameUsed.c_str(),
252 35 : (bool) bWrite));
253 : }
254 :
255 207 : virtual bool NCS_FASTCALL Seek() {
256 207 : return(true);
257 : }
258 :
259 877 : virtual bool NCS_FASTCALL Seek(INT64 offset, Origin origin = CURRENT) {
260 877 : bool success = false;
261 877 : switch(origin) {
262 : case START:
263 816 : success = (0 == VSIFSeekL(fpVSIL, offset+startOfJPData, SEEK_SET));
264 816 : break;
265 :
266 : case CURRENT:
267 0 : success = (0 == VSIFSeekL(fpVSIL, offset, SEEK_CUR));
268 0 : break;
269 :
270 : case END:
271 61 : success = (0 == VSIFSeekL(fpVSIL, offset, SEEK_END));
272 : break;
273 : }
274 877 : if( !success )
275 : CPLDebug( "ECW", "VSIIOStream::Seek(%d,%d) failed.",
276 1 : (int) offset, (int) origin );
277 877 : return(success);
278 : }
279 :
280 3715 : virtual INT64 NCS_FASTCALL Tell() {
281 3715 : return VSIFTellL( fpVSIL ) - startOfJPData;
282 : }
283 :
284 61 : virtual INT64 NCS_FASTCALL Size() {
285 61 : if( lengthOfJPData != -1 )
286 0 : return lengthOfJPData;
287 : else
288 : {
289 61 : INT64 curPos = Tell(), size;
290 :
291 61 : Seek( 0, END );
292 61 : size = Tell();
293 61 : Seek( curPos, START );
294 :
295 61 : return size;
296 : }
297 : }
298 :
299 6987 : virtual bool NCS_FASTCALL Read(void* buffer, UINT32 count) {
300 6987 : if( count == 0 )
301 366 : return true;
302 :
303 : // return(1 == VSIFReadL( buffer, count, 1, fpVSIL ) );
304 :
305 : // The following is a hack
306 6621 : if( VSIFReadL( buffer, count, 1, fpVSIL ) != 1 )
307 : {
308 : CPLDebug( "VSIIOSTREAM",
309 : "Read(%d) failed @ " CPL_FRMT_GIB ", ignoring failure.",
310 0 : count, (VSIFTellL( fpVSIL ) - startOfJPData) );
311 : }
312 :
313 6621 : return true;
314 : }
315 :
316 3312 : virtual bool NCS_FASTCALL Write(void* buffer, UINT32 count) {
317 3312 : if( count == 0 )
318 0 : return true;
319 3312 : if( 1 != VSIFWriteL(buffer, count, 1, fpVSIL) )
320 : {
321 : CPLDebug( "ECW", "VSIIOStream::Write(%d) failed.",
322 0 : (int) count );
323 0 : return false;
324 : }
325 : else
326 3312 : return true;
327 : }
328 : };
329 :
330 : /************************************************************************/
331 : /* ==================================================================== */
332 : /* ECWAsyncReader */
333 : /* ==================================================================== */
334 : /************************************************************************/
335 : class ECWDataset;
336 :
337 : #if ECWSDK_VERSION >= 40
338 :
339 : class ECWAsyncReader : public GDALAsyncReader
340 : {
341 : private:
342 : CNCSJP2FileView *poFileView;
343 : void *hMutex;
344 : int bUsingCustomStream;
345 :
346 : int bUpdateReady;
347 : int bComplete;
348 :
349 : static NCSEcwReadStatus RefreshCB( NCSFileView * );
350 : NCSEcwReadStatus ReadToBuffer();
351 :
352 : public:
353 : ECWAsyncReader();
354 : virtual ~ECWAsyncReader();
355 : virtual GDALAsyncStatusType GetNextUpdatedRegion(double dfTimeout,
356 : int* pnXBufOff,
357 : int* pnYBufOff,
358 : int* pnXBufSize,
359 : int* pnYBufSize);
360 :
361 : friend class ECWDataset;
362 : };
363 : #endif /* ECWSDK_VERSION >= 40 */
364 :
365 : /************************************************************************/
366 : /* ==================================================================== */
367 : /* ECWDataset */
368 : /* ==================================================================== */
369 : /************************************************************************/
370 :
371 : class ECWRasterBand;
372 :
373 : typedef struct
374 : {
375 : int bEnabled;
376 : int nBandsTried;
377 :
378 : int nXOff;
379 : int nYOff;
380 : int nXSize;
381 : int nYSize;
382 : int nBufXSize;
383 : int nBufYSize;
384 : GDALDataType eBufType;
385 : GByte* pabyData;
386 : } ECWCachedMultiBandIO;
387 :
388 : class CPL_DLL ECWDataset : public GDALPamDataset
389 : {
390 : friend class ECWRasterBand;
391 : friend class ECWAsyncReader;
392 :
393 : int bIsJPEG2000;
394 :
395 : CNCSJP2FileView *poFileView;
396 : NCSFileViewFileInfoEx *psFileInfo;
397 :
398 : GDALDataType eRasterDataType;
399 : NCSEcwCellType eNCSRequestDataType;
400 :
401 : int bUsingCustomStream;
402 :
403 : // Current view window.
404 : int bWinActive;
405 : int nWinXOff, nWinYOff, nWinXSize, nWinYSize;
406 : int nWinBufXSize, nWinBufYSize;
407 : int nWinBandCount;
408 : int *panWinBandList;
409 : int nWinBufLoaded;
410 : void **papCurLineBuf;
411 :
412 : int bGeoTransformValid;
413 : double adfGeoTransform[6];
414 : char *pszProjection;
415 : int nGCPCount;
416 : GDAL_GCP *pasGCPList;
417 :
418 : char **papszGMLMetadata;
419 :
420 : ECWCachedMultiBandIO sCachedMultiBandIO;
421 :
422 : void ECW2WKTProjection();
423 :
424 : void CleanupWindow();
425 : int TryWinRasterIO( GDALRWFlag, int, int, int, int,
426 : GByte *, int, int, GDALDataType,
427 : int, int *, int, int, int );
428 : CPLErr LoadNextLine();
429 :
430 : #if ECWSDK_VERSION>=50
431 :
432 : NCSFileStatistics* pStatistics;
433 : int bStatisticsDirty;
434 : int bStatisticsInitialized;
435 : NCS::CError StatisticsEnsureInitialized();
436 : NCS::CError StatisticsWrite();
437 : void CleanupStatistics();
438 :
439 : #endif
440 :
441 : static CNCSJP2FileView *OpenFileView( const char *pszDatasetName,
442 : bool bProgressive,
443 : int &bUsingCustomStream,
444 : bool bWrite=false);
445 :
446 : int bHdrDirty;
447 : CPLString m_osDatumCode;
448 : CPLString m_osProjCode;
449 : CPLString m_osUnitsCode;
450 : int bGeoTransformChanged;
451 : int bProjectionChanged;
452 : int bProjCodeChanged;
453 : int bDatumCodeChanged;
454 : int bUnitsCodeChanged;
455 : void WriteHeader();
456 :
457 : int bUseOldBandRasterIOImplementation;
458 :
459 : CPLStringList oECWMetadataList;
460 : CPLErr ReadBands(void * pData, int nBufXSize, int nBufYSize,
461 : GDALDataType eBufType,
462 : int nBandCount,
463 : int nPixelSpace, int nLineSpace, int nBandSpace);
464 : CPLErr ReadBandsDirectly(void * pData, int nBufXSize, int nBufYSize,
465 : GDALDataType eBufType,
466 : int nBandCount,
467 : int nPixelSpace, int nLineSpace, int nBandSpace);
468 : public:
469 : ECWDataset(int bIsJPEG2000);
470 : ~ECWDataset();
471 :
472 : static GDALDataset *Open( GDALOpenInfo *, int bIsJPEG2000 );
473 : static int IdentifyJPEG2000( GDALOpenInfo * poOpenInfo );
474 : static GDALDataset *OpenJPEG2000( GDALOpenInfo * );
475 : static int IdentifyECW( GDALOpenInfo * poOpenInfo );
476 : static GDALDataset *OpenECW( GDALOpenInfo * );
477 :
478 : virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
479 : void *, int, int, GDALDataType,
480 : int, int *, int, int, int );
481 :
482 : virtual CPLErr GetGeoTransform( double * );
483 : virtual const char *GetProjectionRef();
484 :
485 : virtual int GetGCPCount();
486 : virtual const char *GetGCPProjection();
487 : virtual const GDAL_GCP *GetGCPs();
488 :
489 : virtual const char *GetMetadataItem( const char * pszName,
490 : const char * pszDomain = "" );
491 : virtual char **GetMetadata( const char * pszDomain = "" );
492 :
493 : virtual CPLErr SetGeoTransform( double * padfGeoTransform );
494 : virtual CPLErr SetProjection( const char* pszProjection );
495 : virtual CPLErr SetMetadataItem( const char * pszName,
496 : const char * pszValue,
497 : const char * pszDomain = "" );
498 : virtual CPLErr SetMetadata( char ** papszMetadata,
499 : const char * pszDomain = "" );
500 :
501 : virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
502 : int nBufXSize, int nBufYSize,
503 : GDALDataType eDT,
504 : int nBandCount, int *panBandList,
505 : char **papszOptions );
506 :
507 : // progressive methods
508 : #if ECWSDK_VERSION >= 40
509 : virtual GDALAsyncReader* BeginAsyncReader( int nXOff, int nYOff,
510 : int nXSize, int nYSize,
511 : void *pBuf,
512 : int nBufXSize, int nBufYSize,
513 : GDALDataType eBufType,
514 : int nBandCount, int* panBandMap,
515 : int nPixelSpace, int nLineSpace,
516 : int nBandSpace,
517 : char **papszOptions);
518 :
519 : virtual void EndAsyncReader(GDALAsyncReader *);
520 : #endif /* ECWSDK_VERSION > 40 */
521 : };
522 :
523 : /************************************************************************/
524 : /* ==================================================================== */
525 : /* ECWRasterBand */
526 : /* ==================================================================== */
527 : /************************************************************************/
528 :
529 : class ECWRasterBand : public GDALPamRasterBand
530 : {
531 : friend class ECWDataset;
532 :
533 : // NOTE: poDS may be altered for NITF/JPEG2000 files!
534 : ECWDataset *poGDS;
535 :
536 : GDALColorInterp eBandInterp;
537 :
538 : int iOverview; // -1 for base.
539 :
540 : std::vector<ECWRasterBand*> apoOverviews;
541 :
542 : #if ECWSDK_VERSION>=50
543 :
544 : int nStatsBandIndex;
545 : int nStatsBandCount;
546 :
547 : #endif
548 :
549 : //#if !defined(SDK_CAN_DO_SUPERSAMPLING)
550 : CPLErr OldIRasterIO( GDALRWFlag, int, int, int, int,
551 : void *, int, int, GDALDataType,
552 : int, int );
553 : //#endif
554 :
555 : virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
556 : void *, int, int, GDALDataType,
557 : int, int );
558 :
559 : public:
560 :
561 : ECWRasterBand( ECWDataset *, int, int = -1 );
562 : ~ECWRasterBand();
563 :
564 : virtual CPLErr IReadBlock( int, int, void * );
565 0 : virtual int HasArbitraryOverviews() { return apoOverviews.size() == 0; }
566 1 : virtual int GetOverviewCount() { return (int)apoOverviews.size(); }
567 : virtual GDALRasterBand *GetOverview(int);
568 :
569 : virtual GDALColorInterp GetColorInterpretation();
570 : virtual CPLErr SetColorInterpretation( GDALColorInterp );
571 :
572 : virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
573 : int nBufXSize, int nBufYSize,
574 : GDALDataType eDT, char **papszOptions );
575 : #if ECWSDK_VERSION >= 50
576 : void GetBandIndexAndCountForStatistics(int &bandIndex, int &bandCount);
577 : virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
578 : int *pnBuckets, int ** ppanHistogram,
579 : int bForce,
580 : GDALProgressFunc, void *pProgressData);
581 : virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
582 : int nBuckets, int *panHistogram );
583 : virtual CPLErr GetStatistics( int bApproxOK, int bForce,
584 : double *pdfMin, double *pdfMax,
585 : double *pdfMean, double *padfStdDev );
586 : virtual CPLErr SetStatistics( double dfMin, double dfMax,
587 : double dfMean, double dfStdDev );
588 : #endif
589 :
590 : };
591 :
592 : int ECWTranslateFromWKT( const char *pszWKT,
593 : char *pszProjection,
594 : int nProjectionLen,
595 : char *pszDatum,
596 : int nDatumLen,
597 : char *pszUnits);
598 :
599 : CellSizeUnits ECWTranslateToCellSizeUnits(const char* pszUnits);
600 : const char* ECWTranslateFromCellSizeUnits(CellSizeUnits eUnits);
601 :
602 : #endif /* def FRMT_ecw */
603 :
604 : #endif /* ndef GDAL_ECW_H_INCLUDED */
|