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 : # define ECW_COMPRESS_RW_SDK_VERSION
48 : #endif
49 :
50 : #if defined(_MSC_VER)
51 : # pragma warning(disable:4800)
52 : #endif
53 :
54 : #include <NCSECWClient.h>
55 : #include <NCSECWCompressClient.h>
56 : #include <NCSErrors.h>
57 : #include <NCSFile.h>
58 : #include <NCSJP2FileView.h>
59 :
60 : /* By default, assume 3.3 SDK Version. */
61 : #if !defined(ECWSDK_VERSION)
62 : # define ECWSDK_VERSION 33
63 : #endif
64 :
65 : #if ECWSDK_VERSION < 40
66 :
67 : #if !defined(NO_COMPRESS)
68 : # define HAVE_COMPRESS
69 : #endif
70 :
71 : # include <NCSJP2File.h>
72 : #else
73 : # include <ECWJP2BuildNumber.h>
74 : # include <HeaderEditor.h>
75 : # define NCS_FASTCALL
76 : #endif
77 :
78 : #ifndef NCSFILEBASE_H
79 : # include <NCSJP2FileView.h>
80 : #else
81 : # undef CNCSJP2FileView
82 : # define CNCSJP2FileView CNCSFile
83 : #endif
84 :
85 : void ECWInitialize( void );
86 : GDALDataset* ECWDatasetOpenJPEG2000(GDALOpenInfo* poOpenInfo);
87 :
88 : #ifdef HAVE_COMPRESS
89 : GDALDataset *
90 : ECWCreateCopyECW( const char * pszFilename, GDALDataset *poSrcDS,
91 : int bStrict, char ** papszOptions,
92 : GDALProgressFunc pfnProgress, void * pProgressData );
93 : GDALDataset *
94 : ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS,
95 : int bStrict, char ** papszOptions,
96 : GDALProgressFunc pfnProgress, void * pProgressData );
97 :
98 : GDALDataset *
99 : ECWCreateECW( const char * pszFilename, int nXSize, int nYSize, int nBands,
100 : GDALDataType eType, char **papszOptions );
101 : GDALDataset *
102 : ECWCreateJPEG2000(const char *pszFilename, int nXSize, int nYSize, int nBands,
103 : GDALDataType eType, char **papszOptions );
104 : #endif
105 :
106 : /************************************************************************/
107 : /* ==================================================================== */
108 : /* JP2Userbox */
109 : /* ==================================================================== */
110 : /************************************************************************/
111 : #ifdef HAVE_COMPRESS
112 : class JP2UserBox : public CNCSJP2Box {
113 :
114 : private:
115 : int nDataLength;
116 : unsigned char *pabyData;
117 :
118 : public:
119 : JP2UserBox();
120 :
121 : virtual ~JP2UserBox();
122 :
123 : #if ECWSDK_VERSION >= 40
124 : virtual CNCSError Parse( NCS::JP2::CFile &JP2File,
125 : NCS::CIOStream &Stream);
126 : virtual CNCSError UnParse( NCS::JP2::CFile &JP2File,
127 : NCS::CIOStream &Stream);
128 : #else
129 : virtual CNCSError Parse(class CNCSJP2File &JP2File,
130 : CNCSJPCIOStream &Stream);
131 : virtual CNCSError UnParse(class CNCSJP2File &JP2File,
132 : CNCSJPCIOStream &Stream);
133 : #endif
134 : virtual void UpdateXLBox(void);
135 :
136 : void SetData( int nDataLength, const unsigned char *pabyDataIn );
137 :
138 : int GetDataLength() { return nDataLength; }
139 : unsigned char *GetData() { return pabyData; }
140 : };
141 : #endif /* def HAVE_COMPRESS */
142 :
143 : /************************************************************************/
144 : /* ==================================================================== */
145 : /* VSIIOStream */
146 : /* ==================================================================== */
147 : /************************************************************************/
148 :
149 : class VSIIOStream : public CNCSJPCIOStream
150 :
151 : {
152 : public:
153 :
154 : INT64 startOfJPData;
155 : INT64 lengthOfJPData;
156 : VSILFILE *fpVSIL;
157 : int bWritable;
158 : int nFileViewCount;
159 : char *pszFilename;
160 :
161 132 : VSIIOStream() {
162 132 : nFileViewCount = 0;
163 132 : startOfJPData = 0;
164 132 : lengthOfJPData = -1;
165 132 : fpVSIL = NULL;
166 132 : }
167 132 : virtual ~VSIIOStream() {
168 132 : Close();
169 132 : }
170 :
171 242 : virtual CNCSError Close() {
172 242 : CNCSError oErr = CNCSJPCIOStream::Close();
173 242 : if( fpVSIL != NULL )
174 : {
175 70 : VSIFCloseL( fpVSIL );
176 70 : fpVSIL = NULL;
177 : }
178 0 : return oErr;
179 : }
180 :
181 : #if ECWSDK_VERSION >= 40
182 : virtual NCS::CIOStream *Clone() { return NULL; }
183 : #endif /* ECWSDK_VERSION >= 4 */
184 :
185 70 : virtual CNCSError Access( VSILFILE *fpVSILIn, BOOLEAN bWrite,
186 : const char *pszFilename,
187 : INT64 start, INT64 size = -1) {
188 :
189 70 : fpVSIL = fpVSILIn;
190 70 : startOfJPData = start;
191 70 : lengthOfJPData = size;
192 70 : bWritable = bWrite;
193 70 : VSIFSeekL(fpVSIL, startOfJPData, SEEK_SET);
194 :
195 : // the filename is used to establish where to put temporary files.
196 : // if it does not have a path to a real directory, we will
197 : // substitute something.
198 70 : CPLString osFilenameUsed = pszFilename;
199 70 : CPLString osPath = CPLGetPath( pszFilename );
200 : struct stat sStatBuf;
201 70 : if( osPath != "" && stat( osPath, &sStatBuf ) != 0 )
202 : {
203 44 : osFilenameUsed = CPLGenerateTempFilename( NULL );
204 : // try to preserve the extension.
205 44 : if( strlen(CPLGetExtension(pszFilename)) > 0 )
206 : {
207 44 : osFilenameUsed += ".";
208 44 : osFilenameUsed += CPLGetExtension(pszFilename);
209 : }
210 44 : CPLDebug( "ECW", "Using filename '%s' for temporary directory determination purposes.", osFilenameUsed.c_str() );
211 : }
212 : return(CNCSJPCIOStream::Open((char *)osFilenameUsed.c_str(),
213 70 : (bool) bWrite));
214 : }
215 :
216 414 : virtual bool NCS_FASTCALL Seek() {
217 414 : return(true);
218 : }
219 :
220 1754 : virtual bool NCS_FASTCALL Seek(INT64 offset, Origin origin = CURRENT) {
221 1754 : bool success = false;
222 1754 : switch(origin) {
223 : case START:
224 1632 : success = (0 == VSIFSeekL(fpVSIL, offset+startOfJPData, SEEK_SET));
225 1632 : break;
226 :
227 : case CURRENT:
228 0 : success = (0 == VSIFSeekL(fpVSIL, offset, SEEK_CUR));
229 0 : break;
230 :
231 : case END:
232 122 : success = (0 == VSIFSeekL(fpVSIL, offset, SEEK_END));
233 : break;
234 : }
235 1754 : if( !success )
236 : CPLDebug( "ECW", "VSIIOStream::Seek(%d,%d) failed.",
237 2 : (int) offset, (int) origin );
238 1754 : return(success);
239 : }
240 :
241 7430 : virtual INT64 NCS_FASTCALL Tell() {
242 7430 : return VSIFTellL( fpVSIL ) - startOfJPData;
243 : }
244 :
245 122 : virtual INT64 NCS_FASTCALL Size() {
246 122 : if( lengthOfJPData != -1 )
247 0 : return lengthOfJPData;
248 : else
249 : {
250 122 : INT64 curPos = Tell(), size;
251 :
252 122 : Seek( 0, END );
253 122 : size = Tell();
254 122 : Seek( curPos, START );
255 :
256 122 : return size;
257 : }
258 : }
259 :
260 13974 : virtual bool NCS_FASTCALL Read(void* buffer, UINT32 count) {
261 13974 : if( count == 0 )
262 732 : return true;
263 :
264 : // return(1 == VSIFReadL( buffer, count, 1, fpVSIL ) );
265 :
266 : // The following is a hack
267 13242 : if( VSIFReadL( buffer, count, 1, fpVSIL ) != 1 )
268 : {
269 : CPLDebug( "VSIIOSTREAM",
270 : "Read(%d) failed @ " CPL_FRMT_GIB ", ignoring failure.",
271 0 : count, (VSIFTellL( fpVSIL ) - startOfJPData) );
272 : }
273 :
274 13242 : return true;
275 : }
276 :
277 6624 : virtual bool NCS_FASTCALL Write(void* buffer, UINT32 count) {
278 6624 : if( count == 0 )
279 0 : return true;
280 6624 : if( 1 != VSIFWriteL(buffer, count, 1, fpVSIL) )
281 : {
282 : CPLDebug( "ECW", "VSIIOStream::Write(%d) failed.",
283 0 : (int) count );
284 0 : return false;
285 : }
286 : else
287 6624 : return true;
288 : }
289 : };
290 :
291 : /************************************************************************/
292 : /* ==================================================================== */
293 : /* ECWAsyncReader */
294 : /* ==================================================================== */
295 : /************************************************************************/
296 : class ECWDataset;
297 :
298 : #if ECWSDK_VERSION >= 40
299 :
300 : class ECWAsyncReader : public GDALAsyncReader
301 : {
302 : private:
303 : CNCSJP2FileView *poFileView;
304 : void *hMutex;
305 : int bUsingCustomStream;
306 :
307 : int bUpdateReady;
308 : int bComplete;
309 :
310 : static NCSEcwReadStatus RefreshCB( NCSFileView * );
311 : NCSEcwReadStatus ReadToBuffer();
312 :
313 : public:
314 : ECWAsyncReader();
315 : virtual ~ECWAsyncReader();
316 : virtual GDALAsyncStatusType GetNextUpdatedRegion(double dfTimeout,
317 : int* pnXBufOff,
318 : int* pnYBufOff,
319 : int* pnXBufSize,
320 : int* pnYBufSize);
321 :
322 : friend class ECWDataset;
323 : };
324 : #endif /* ECWSDK_VERSION >= 40 */
325 :
326 : /************************************************************************/
327 : /* ==================================================================== */
328 : /* ECWDataset */
329 : /* ==================================================================== */
330 : /************************************************************************/
331 :
332 : class ECWRasterBand;
333 :
334 : class CPL_DLL ECWDataset : public GDALPamDataset
335 : {
336 : friend class ECWRasterBand;
337 : friend class ECWAsyncReader;
338 :
339 : int bIsJPEG2000;
340 :
341 : CNCSJP2FileView *poFileView;
342 : NCSFileViewFileInfoEx *psFileInfo;
343 :
344 : GDALDataType eRasterDataType;
345 : NCSEcwCellType eNCSRequestDataType;
346 :
347 : int bUsingCustomStream;
348 :
349 : // Current view window.
350 : int bWinActive;
351 : int nWinXOff, nWinYOff, nWinXSize, nWinYSize;
352 : int nWinBufXSize, nWinBufYSize;
353 : int nWinBandCount;
354 : int *panWinBandList;
355 : int nWinBufLoaded;
356 : void **papCurLineBuf;
357 :
358 : int bGeoTransformValid;
359 : double adfGeoTransform[6];
360 : char *pszProjection;
361 : int nGCPCount;
362 : GDAL_GCP *pasGCPList;
363 :
364 : char **papszGMLMetadata;
365 :
366 : void ECW2WKTProjection();
367 :
368 : void CleanupWindow();
369 : int TryWinRasterIO( GDALRWFlag, int, int, int, int,
370 : GByte *, int, int, GDALDataType,
371 : int, int *, int, int, int );
372 : CPLErr LoadNextLine();
373 :
374 : static CNCSJP2FileView *OpenFileView( const char *pszDatasetName,
375 : bool bProgressive,
376 : int &bUsingCustomStream );
377 :
378 : int bHdrDirty;
379 : CPLString m_osDatumCode;
380 : CPLString m_osProjCode;
381 : CPLString m_osUnitsCode;
382 : int bGeoTransformChanged;
383 : int bProjectionChanged;
384 : int bProjCodeChanged;
385 : int bDatumCodeChanged;
386 : int bUnitsCodeChanged;
387 : void WriteHeader();
388 :
389 : CPLStringList oECWMetadataList;
390 :
391 : public:
392 : ECWDataset(int bIsJPEG2000);
393 : ~ECWDataset();
394 :
395 : static GDALDataset *Open( GDALOpenInfo *, int bIsJPEG2000 );
396 : static int IdentifyJPEG2000( GDALOpenInfo * poOpenInfo );
397 : static GDALDataset *OpenJPEG2000( GDALOpenInfo * );
398 : static int IdentifyECW( GDALOpenInfo * poOpenInfo );
399 : static GDALDataset *OpenECW( GDALOpenInfo * );
400 :
401 : virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
402 : void *, int, int, GDALDataType,
403 : int, int *, int, int, int );
404 :
405 : virtual CPLErr GetGeoTransform( double * );
406 : virtual const char *GetProjectionRef();
407 :
408 : virtual int GetGCPCount();
409 : virtual const char *GetGCPProjection();
410 : virtual const GDAL_GCP *GetGCPs();
411 :
412 : virtual const char *GetMetadataItem( const char * pszName,
413 : const char * pszDomain = "" );
414 : virtual char **GetMetadata( const char * pszDomain = "" );
415 :
416 : virtual CPLErr SetGeoTransform( double * padfGeoTransform );
417 : virtual CPLErr SetProjection( const char* pszProjection );
418 : virtual CPLErr SetMetadataItem( const char * pszName,
419 : const char * pszValue,
420 : const char * pszDomain = "" );
421 : virtual CPLErr SetMetadata( char ** papszMetadata,
422 : const char * pszDomain = "" );
423 :
424 : virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
425 : int nBufXSize, int nBufYSize,
426 : GDALDataType eDT,
427 : int nBandCount, int *panBandList,
428 : char **papszOptions );
429 :
430 : // progressive methods
431 : #if ECWSDK_VERSION >= 40
432 : virtual GDALAsyncReader* BeginAsyncReader( int nXOff, int nYOff,
433 : int nXSize, int nYSize,
434 : void *pBuf,
435 : int nBufXSize, int nBufYSize,
436 : GDALDataType eBufType,
437 : int nBandCount, int* panBandMap,
438 : int nPixelSpace, int nLineSpace,
439 : int nBandSpace,
440 : char **papszOptions);
441 :
442 : virtual void EndAsyncReader(GDALAsyncReader *);
443 : #endif /* ECWSDK_VERSION > 40 */
444 : };
445 :
446 : /************************************************************************/
447 : /* ==================================================================== */
448 : /* ECWRasterBand */
449 : /* ==================================================================== */
450 : /************************************************************************/
451 :
452 : class ECWRasterBand : public GDALPamRasterBand
453 : {
454 : friend class ECWDataset;
455 :
456 : // NOTE: poDS may be altered for NITF/JPEG2000 files!
457 : ECWDataset *poGDS;
458 :
459 : GDALColorInterp eBandInterp;
460 :
461 : int iOverview; // -1 for base.
462 :
463 : std::vector<ECWRasterBand*> apoOverviews;
464 :
465 : virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
466 : void *, int, int, GDALDataType,
467 : int, int );
468 :
469 : public:
470 :
471 : ECWRasterBand( ECWDataset *, int, int = -1 );
472 : ~ECWRasterBand();
473 :
474 : virtual CPLErr IReadBlock( int, int, void * );
475 0 : virtual int HasArbitraryOverviews() { return apoOverviews.size() == 0; }
476 2 : virtual int GetOverviewCount() { return apoOverviews.size(); }
477 : virtual GDALRasterBand *GetOverview(int);
478 :
479 : virtual GDALColorInterp GetColorInterpretation();
480 : virtual CPLErr SetColorInterpretation( GDALColorInterp );
481 :
482 : virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
483 : int nBufXSize, int nBufYSize,
484 : GDALDataType eDT, char **papszOptions );
485 : };
486 :
487 : int ECWTranslateFromWKT( const char *pszWKT,
488 : char *pszProjection,
489 : int nProjectionLen,
490 : char *pszDatum,
491 : int nDatumLen,
492 : char *pszUnits);
493 :
494 : CellSizeUnits ECWTranslateToCellSizeUnits(const char* pszUnits);
495 : const char* ECWTranslateFromCellSizeUnits(CellSizeUnits eUnits);
496 :
497 : #endif /* def FRMT_ecw */
498 :
499 : #endif /* ndef GDAL_ECW_H_INCLUDED */
|