1 : /******************************************************************************
2 : * $Id: mrsiddataset.cpp 17906 2009-10-26 19:47:21Z rouault $
3 : *
4 : * Project: Multi-resolution Seamless Image Database (MrSID)
5 : * Purpose: Read/write LizardTech's MrSID file format - Version 4+ SDK.
6 : * Author: Andrey Kiselev, dron@ak4719.spb.edu
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2003, Andrey Kiselev <dron@ak4719.spb.edu>
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 : #define NO_DELETE
31 :
32 : #include "gdal_pam.h"
33 : #include "ogr_spatialref.h"
34 : #include "cpl_string.h"
35 : #include <string>
36 :
37 : #include <geo_normalize.h>
38 : #include <geovalues.h>
39 :
40 : CPL_CVSID("$Id: mrsiddataset.cpp 17906 2009-10-26 19:47:21Z rouault $");
41 :
42 : CPL_C_START
43 : double GTIFAngleToDD( double dfAngle, int nUOMAngle );
44 : CPL_C_END
45 :
46 : // Key Macros from Makefile:
47 : // MRSID_ESDK: Means we have the encoding SDK (version 5 or newer required)
48 : // MRSID_J2K: Means we are enabling MrSID SDK JPEG2000 support.
49 :
50 : #include "lt_types.h"
51 : #include "lt_base.h"
52 : #include "lt_fileSpec.h"
53 : #include "lt_ioFileStream.h"
54 : #include "lt_utilStatusStrings.h"
55 : #include "lti_geoCoord.h"
56 : #include "lti_pixel.h"
57 : #include "lti_navigator.h"
58 : #include "lti_sceneBuffer.h"
59 : #include "lti_metadataDatabase.h"
60 : #include "lti_metadataRecord.h"
61 : #include "lti_utils.h"
62 : #include "lt_utilStatus.h"
63 : #include "MrSIDImageReader.h"
64 :
65 : #ifdef MRSID_J2K
66 : # include "J2KImageReader.h"
67 : #endif
68 :
69 : // It seems that LT_STS_UTIL_TimeUnknown was added in version 6, also
70 : // the first version with lti_version.h
71 : #ifdef LT_STS_UTIL_TimeUnknown
72 : # include "lti_version.h"
73 : #endif
74 :
75 : // Are we using version 6 or newer?
76 : #if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 6
77 : # define MRSID_POST5
78 : #endif
79 :
80 : #ifdef MRSID_ESDK
81 : # include "MG3ImageWriter.h"
82 : # include "MG3WriterParams.h"
83 : # include "MG2ImageWriter.h"
84 : # include "MG2WriterParams.h"
85 : # ifdef MRSID_J2K
86 : # ifdef MRSID_POST5
87 : # include "JP2WriterManager.h"
88 : # include "JPCWriterParams.h"
89 : # else
90 : # include "J2KImageWriter.h"
91 : # include "J2KWriterParams.h"
92 : # endif
93 : # endif
94 : #endif /* MRSID_ESDK */
95 :
96 : #ifdef MRSID_POST5
97 : # define MRSID_HAVE_GETWKT
98 : #endif
99 :
100 : #include "mrsidstream.h"
101 :
102 : LT_USE_NAMESPACE(LizardTech)
103 :
104 : /* -------------------------------------------------------------------- */
105 : /* Various wrapper templates used to force new/delete to happen */
106 : /* in the same heap. See bug 1213 and MSDN knowledgebase */
107 : /* article 122675. */
108 : /* -------------------------------------------------------------------- */
109 :
110 : template <class T>
111 : class LTIDLLPixel : public T
112 : {
113 : public:
114 : LTIDLLPixel(LTIColorSpace colorSpace,
115 : lt_uint16 numBands,
116 178 : LTIDataType dataType) : T(colorSpace,numBands,dataType) {}
117 178 : virtual ~LTIDLLPixel() {};
118 : };
119 :
120 : template <class T>
121 : class LTIDLLReader : public T
122 : {
123 : public:
124 : LTIDLLReader(const LTFileSpec& fileSpec,
125 : bool useWorldFile = false) : T(fileSpec, useWorldFile) {}
126 : LTIDLLReader(LTIOStreamInf &oStream,
127 : bool useWorldFile = false) : T(oStream, useWorldFile) {}
128 : LTIDLLReader(LTIOStreamInf *poStream,
129 : LTIOStreamInf *poWorldFile = NULL) : T(poStream, poWorldFile) {}
130 : virtual ~LTIDLLReader() {};
131 : };
132 :
133 : template <class T>
134 : class LTIDLLNavigator : public T
135 : {
136 : public:
137 106 : LTIDLLNavigator(const LTIImage& image ) : T(image) {}
138 106 : virtual ~LTIDLLNavigator() {};
139 : };
140 :
141 : template <class T>
142 : class LTIDLLBuffer : public T
143 : {
144 : public:
145 : LTIDLLBuffer(const LTIPixel& pixelProps,
146 : lt_uint32 totalNumCols,
147 : lt_uint32 totalNumRows,
148 13 : void** data ) : T(pixelProps,totalNumCols,totalNumRows,data) {}
149 13 : virtual ~LTIDLLBuffer() {};
150 : };
151 :
152 : template <class T>
153 : class LTIDLLCopy : public T
154 : {
155 : public:
156 19 : LTIDLLCopy(const T& original) : T(original) {}
157 19 : virtual ~LTIDLLCopy() {};
158 : };
159 :
160 : /************************************************************************/
161 : /* ==================================================================== */
162 : /* MrSIDDataset */
163 : /* ==================================================================== */
164 : /************************************************************************/
165 :
166 : class MrSIDDataset : public GDALPamDataset
167 : {
168 : friend class MrSIDRasterBand;
169 :
170 : LTIVSIStream oStream;
171 :
172 : #if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 7
173 : LTIImageFilter *poImageReader;
174 : #else
175 : LTIImageReader *poImageReader;
176 : #endif
177 :
178 : #ifdef MRSID_ESDK
179 : LTIGeoFileImageWriter *poImageWriter;
180 : #endif
181 :
182 : LTIDLLNavigator<LTINavigator> *poLTINav;
183 : LTIDLLCopy<LTIMetadataDatabase> *poMetadata;
184 : const LTIPixel *poNDPixel;
185 :
186 : LTIDLLBuffer<LTISceneBuffer> *poBuffer;
187 : int nBlockXSize, nBlockYSize;
188 : int bPrevBlockRead;
189 : int nPrevBlockXOff, nPrevBlockYOff;
190 :
191 : LTIDataType eSampleType;
192 : GDALDataType eDataType;
193 : LTIColorSpace eColorSpace;
194 :
195 : double dfCurrentMag;
196 :
197 : int bHasGeoTransform;
198 : double adfGeoTransform[6];
199 : char *pszProjection;
200 : GTIFDefn *psDefn;
201 :
202 : MrSIDDataset *poParentDS;
203 : int bIsOverview;
204 : int nOverviewCount;
205 : MrSIDDataset **papoOverviewDS;
206 :
207 : CPLErr OpenZoomLevel( lt_int32 iZoom );
208 : char *SerializeMetadataRec( const LTIMetadataRecord* );
209 : int GetMetadataElement( const char *, void *, int=0 );
210 : void FetchProjParms();
211 : void GetGTIFDefn();
212 : char *GetOGISDefn( GTIFDefn * );
213 :
214 : virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int, void *,
215 : int, int, GDALDataType, int, int *,int,
216 : int, int );
217 :
218 : public:
219 : MrSIDDataset(int bIsJPEG2000);
220 : ~MrSIDDataset();
221 :
222 : static GDALDataset *Open( GDALOpenInfo * poOpenInfo, int bIsJP2 );
223 : virtual CPLErr GetGeoTransform( double * padfTransform );
224 : const char *GetProjectionRef();
225 :
226 : #ifdef MRSID_ESDK
227 : static GDALDataset *Create( const char * pszFilename,
228 : int nXSize, int nYSize, int nBands,
229 : GDALDataType eType, char ** papszParmList );
230 : virtual void FlushCache( void );
231 : #endif
232 : };
233 :
234 : /************************************************************************/
235 : /* ==================================================================== */
236 : /* MrSIDRasterBand */
237 : /* ==================================================================== */
238 : /************************************************************************/
239 :
240 : class MrSIDRasterBand : public GDALPamRasterBand
241 : {
242 : friend class MrSIDDataset;
243 :
244 : LTIPixel *poPixel;
245 :
246 : int nBlockSize;
247 :
248 : int bNoDataSet;
249 : double dfNoDataValue;
250 :
251 : MrSIDDataset *poGDS;
252 :
253 : GDALColorInterp eBandInterp;
254 :
255 : public:
256 :
257 : MrSIDRasterBand( MrSIDDataset *, int );
258 : ~MrSIDRasterBand();
259 :
260 : virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
261 : void *, int, int, GDALDataType,
262 : int, int );
263 :
264 : virtual CPLErr IReadBlock( int, int, void * );
265 : virtual GDALColorInterp GetColorInterpretation();
266 : CPLErr SetColorInterpretation( GDALColorInterp eNewInterp );
267 : virtual double GetNoDataValue( int * );
268 : virtual int GetOverviewCount();
269 : virtual GDALRasterBand *GetOverview( int );
270 :
271 : virtual CPLErr GetStatistics( int bApproxOK, int bForce,
272 : double *pdfMin, double *pdfMax,
273 : double *pdfMean, double *pdfStdDev );
274 :
275 : #ifdef MRSID_ESDK
276 : virtual CPLErr IWriteBlock( int, int, void * );
277 : #endif
278 : };
279 :
280 : /************************************************************************/
281 : /* MrSIDRasterBand() */
282 : /************************************************************************/
283 :
284 178 : MrSIDRasterBand::MrSIDRasterBand( MrSIDDataset *poDS, int nBand )
285 : {
286 178 : this->poDS = poDS;
287 178 : poGDS = poDS;
288 178 : this->nBand = nBand;
289 178 : this->eDataType = poDS->eDataType;
290 :
291 : /* -------------------------------------------------------------------- */
292 : /* Set the block sizes and buffer parameters. */
293 : /* -------------------------------------------------------------------- */
294 178 : nBlockXSize = poDS->nBlockXSize;
295 178 : nBlockYSize = poDS->nBlockYSize;
296 : //#ifdef notdef
297 178 : if( poDS->GetRasterXSize() > 2048 )
298 6 : nBlockXSize = 1024;
299 178 : if( poDS->GetRasterYSize() > 128 )
300 81 : nBlockYSize = 128;
301 : else
302 97 : nBlockYSize = poDS->GetRasterYSize();
303 : //#endif
304 :
305 178 : nBlockSize = nBlockXSize * nBlockYSize;
306 : poPixel = new LTIDLLPixel<LTIPixel>( poDS->eColorSpace, poDS->nBands,
307 178 : poDS->eSampleType );
308 :
309 :
310 : /* -------------------------------------------------------------------- */
311 : /* Set NoData values. */
312 : /* */
313 : /* This logic is disabled for now since the MrSID nodata */
314 : /* semantics are different than GDAL. In MrSID all bands must */
315 : /* match the nodata value for that band in order for the pixel */
316 : /* to be considered nodata, otherwise all values are valid. */
317 : /* -------------------------------------------------------------------- */
318 : #ifdef notdef
319 : if ( poDS->poNDPixel )
320 : {
321 : switch( poDS->eSampleType )
322 : {
323 : case LTI_DATATYPE_UINT8:
324 : case LTI_DATATYPE_SINT8:
325 : dfNoDataValue = (double)
326 : poDS->poNDPixel->getSampleValueUint8( nBand - 1 );
327 : break;
328 : case LTI_DATATYPE_UINT16:
329 : dfNoDataValue = (double)
330 : poDS->poNDPixel->getSampleValueUint16( nBand - 1 );
331 : break;
332 : case LTI_DATATYPE_FLOAT32:
333 : dfNoDataValue =
334 : poDS->poNDPixel->getSampleValueFloat32( nBand - 1 );
335 : break;
336 : case LTI_DATATYPE_SINT16:
337 : dfNoDataValue = (double)
338 : *(GInt16 *)poDS->poNDPixel->getSampleValueAddr( nBand - 1 );
339 : break;
340 : case LTI_DATATYPE_UINT32:
341 : dfNoDataValue = (double)
342 : *(GUInt32 *)poDS->poNDPixel->getSampleValueAddr( nBand - 1 );
343 : break;
344 : case LTI_DATATYPE_SINT32:
345 : dfNoDataValue = (double)
346 : *(GInt32 *)poDS->poNDPixel->getSampleValueAddr( nBand - 1 );
347 : break;
348 : case LTI_DATATYPE_FLOAT64:
349 : dfNoDataValue =
350 : *(double *)poDS->poNDPixel->getSampleValueAddr( nBand - 1 );
351 : break;
352 :
353 : case LTI_DATATYPE_INVALID:
354 : CPLAssert( FALSE );
355 : break;
356 : }
357 : bNoDataSet = TRUE;
358 : }
359 : else
360 : #endif
361 : {
362 178 : dfNoDataValue = 0.0;
363 178 : bNoDataSet = FALSE;
364 : }
365 :
366 178 : switch( poGDS->eColorSpace )
367 : {
368 : case LTI_COLORSPACE_RGB:
369 108 : if( nBand == 1 )
370 36 : eBandInterp = GCI_RedBand;
371 72 : else if( nBand == 2 )
372 36 : eBandInterp = GCI_GreenBand;
373 36 : else if( nBand == 3 )
374 36 : eBandInterp = GCI_BlueBand;
375 : else
376 0 : eBandInterp = GCI_Undefined;
377 108 : break;
378 :
379 : case LTI_COLORSPACE_RGBK:
380 0 : if( nBand == 1 )
381 0 : eBandInterp = GCI_RedBand;
382 0 : else if( nBand == 2 )
383 0 : eBandInterp = GCI_GreenBand;
384 0 : else if( nBand == 3 )
385 0 : eBandInterp = GCI_BlueBand;
386 0 : else if( nBand == 4 )
387 0 : eBandInterp = GCI_AlphaBand;
388 : else
389 0 : eBandInterp = GCI_Undefined;
390 0 : break;
391 :
392 : case LTI_COLORSPACE_CMYK:
393 0 : if( nBand == 1 )
394 0 : eBandInterp = GCI_CyanBand;
395 0 : else if( nBand == 2 )
396 0 : eBandInterp = GCI_MagentaBand;
397 0 : else if( nBand == 3 )
398 0 : eBandInterp = GCI_YellowBand;
399 0 : else if( nBand == 4 )
400 0 : eBandInterp = GCI_BlackBand;
401 : else
402 0 : eBandInterp = GCI_Undefined;
403 0 : break;
404 :
405 : case LTI_COLORSPACE_GRAYSCALE:
406 64 : eBandInterp = GCI_GrayIndex;
407 64 : break;
408 :
409 : default:
410 6 : eBandInterp = GCI_Undefined;
411 : break;
412 : }
413 178 : }
414 :
415 : /************************************************************************/
416 : /* ~MrSIDRasterBand() */
417 : /************************************************************************/
418 :
419 178 : MrSIDRasterBand::~MrSIDRasterBand()
420 : {
421 178 : if ( poPixel )
422 178 : delete poPixel;
423 178 : }
424 :
425 : /************************************************************************/
426 : /* IReadBlock() */
427 : /************************************************************************/
428 :
429 : CPLErr MrSIDRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
430 88 : void * pImage )
431 : {
432 : #ifdef MRSID_ESDK
433 : if( poGDS->eAccess == GA_Update )
434 : {
435 : CPLDebug( "MrSID",
436 : "IReadBlock() - DSDK - read on updatable file fails." );
437 : memset( pImage, 0, nBlockSize * GDALGetDataTypeSize(eDataType) / 8 );
438 : return CE_None;
439 : }
440 : #endif /* MRSID_ESDK */
441 :
442 88 : CPLDebug( "MrSID", "IReadBlock(%d,%d)", nBlockXOff, nBlockYOff );
443 :
444 88 : if ( !poGDS->bPrevBlockRead
445 : || poGDS->nPrevBlockXOff != nBlockXOff
446 : || poGDS->nPrevBlockYOff != nBlockYOff )
447 : {
448 88 : GInt32 nLine = nBlockYOff * nBlockYSize;
449 88 : GInt32 nCol = nBlockXOff * nBlockXSize;
450 :
451 : // XXX: The scene, passed to LTIImageStage::read() call must be
452 : // inside the image boundaries. So we should detect the last strip and
453 : // form the scene properly.
454 : CPLDebug( "MrSID",
455 : "IReadBlock - read() %dx%d block at %d,%d.",
456 88 : nBlockXSize, nBlockYSize, nCol, nLine );
457 :
458 88 : if(!LT_SUCCESS( poGDS->poLTINav->setSceneAsULWH(
459 : nCol, nLine,
460 : (nCol+nBlockXSize>poGDS->GetRasterXSize())?
461 : (poGDS->GetRasterXSize()-nCol):nBlockXSize,
462 : (nLine+nBlockYSize>poGDS->GetRasterYSize())?
463 : (poGDS->GetRasterYSize()-nLine):nBlockYSize,
464 : poGDS->dfCurrentMag) ))
465 :
466 : {
467 : CPLError( CE_Failure, CPLE_AppDefined,
468 0 : "MrSIDRasterBand::IReadBlock(): Failed to set scene position." );
469 0 : return CE_Failure;
470 : }
471 :
472 88 : if ( !poGDS->poBuffer )
473 : {
474 : poGDS->poBuffer =
475 13 : new LTIDLLBuffer<LTISceneBuffer>( *poPixel, nBlockXSize, nBlockYSize, NULL );
476 : // poGDS->poBuffer =
477 : // new LTISceneBuffer( *poPixel, nBlockXSize, nBlockYSize, NULL );
478 : }
479 :
480 88 : if(!LT_SUCCESS(poGDS->poImageReader->read(poGDS->poLTINav->getScene(),
481 : *poGDS->poBuffer)))
482 : {
483 : CPLError( CE_Failure, CPLE_AppDefined,
484 0 : "MrSIDRasterBand::IReadBlock(): Failed to load image." );
485 0 : return CE_Failure;
486 : }
487 :
488 88 : poGDS->bPrevBlockRead = TRUE;
489 88 : poGDS->nPrevBlockXOff = nBlockXOff;
490 88 : poGDS->nPrevBlockYOff = nBlockYOff;
491 : }
492 :
493 : memcpy( pImage, poGDS->poBuffer->getTotalBandData(nBand - 1),
494 88 : nBlockSize * (GDALGetDataTypeSize(poGDS->eDataType) / 8) );
495 :
496 88 : return CE_None;
497 : }
498 :
499 : #ifdef MRSID_ESDK
500 :
501 : /************************************************************************/
502 : /* IWriteBlock() */
503 : /************************************************************************/
504 :
505 : CPLErr MrSIDRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
506 : void * pImage )
507 : {
508 : CPLAssert( poGDS != NULL
509 : && nBlockXOff >= 0
510 : && nBlockYOff >= 0
511 : && pImage != NULL );
512 :
513 : #if DEBUG
514 : CPLDebug( "MrSID", "IWriteBlock(): nBlockXOff=%d, nBlockYOff=%d",
515 : nBlockXOff, nBlockYOff );
516 : #endif
517 :
518 : LTIScene oScene( nBlockXOff * nBlockXSize,
519 : nBlockYOff * nBlockYSize,
520 : nBlockXSize, nBlockYSize, 1.0);
521 : LTISceneBuffer oSceneBuf( *poPixel, poGDS->nBlockXSize,
522 : poGDS->nBlockYSize, &pImage );
523 :
524 : if( !LT_SUCCESS(poGDS->poImageWriter->writeBegin(oScene)) )
525 : {
526 : CPLError( CE_Failure, CPLE_AppDefined,
527 : "MrSIDRasterBand::IWriteBlock(): writeBegin failed." );
528 : return CE_Failure;
529 : }
530 :
531 : if( !LT_SUCCESS(poGDS->poImageWriter->writeStrip(oSceneBuf, oScene)) )
532 : {
533 : CPLError( CE_Failure, CPLE_AppDefined,
534 : "MrSIDRasterBand::IWriteBlock(): writeStrip failed." );
535 : return CE_Failure;
536 : }
537 :
538 : if( !LT_SUCCESS(poGDS->poImageWriter->writeEnd()) )
539 : {
540 : CPLError( CE_Failure, CPLE_AppDefined,
541 : "MrSIDRasterBand::IWriteBlock(): writeEnd failed." );
542 : return CE_Failure;
543 : }
544 :
545 : return CE_None;
546 : }
547 :
548 : #endif /* MRSID_ESDK */
549 :
550 : /************************************************************************/
551 : /* IRasterIO() */
552 : /************************************************************************/
553 :
554 : CPLErr MrSIDRasterBand::IRasterIO( GDALRWFlag eRWFlag,
555 : int nXOff, int nYOff, int nXSize, int nYSize,
556 : void * pData, int nBufXSize, int nBufYSize,
557 : GDALDataType eBufType,
558 5977 : int nPixelSpace, int nLineSpace )
559 :
560 : {
561 : /* -------------------------------------------------------------------- */
562 : /* Fallback to default implementation if the whole scanline */
563 : /* without subsampling requested. */
564 : /* -------------------------------------------------------------------- */
565 5977 : if ( nXSize == poGDS->GetRasterXSize()
566 : && nXSize == nBufXSize
567 : && nYSize == nBufYSize )
568 : {
569 : return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
570 : nXSize, nYSize, pData,
571 : nBufXSize, nBufYSize, eBufType,
572 5976 : nPixelSpace, nLineSpace );
573 : }
574 :
575 : /* -------------------------------------------------------------------- */
576 : /* Handle via the dataset level IRasterIO() */
577 : /* -------------------------------------------------------------------- */
578 : return poGDS->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
579 : nBufXSize, nBufYSize, eBufType,
580 1 : 1, &nBand, nPixelSpace, nLineSpace, 0 );
581 : }
582 :
583 : /************************************************************************/
584 : /* GetColorInterpretation() */
585 : /************************************************************************/
586 :
587 3 : GDALColorInterp MrSIDRasterBand::GetColorInterpretation()
588 :
589 : {
590 3 : return eBandInterp;
591 : }
592 :
593 : /************************************************************************/
594 : /* SetColorInterpretation() */
595 : /* */
596 : /* This would normally just be used by folks using the MrSID code */
597 : /* to read JP2 streams in other formats (such as NITF) and */
598 : /* providing their own color interpretation regardless of what */
599 : /* MrSID might think the stream itself says. */
600 : /************************************************************************/
601 :
602 0 : CPLErr MrSIDRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
603 :
604 : {
605 0 : eBandInterp = eNewInterp;
606 :
607 0 : return CE_None;
608 : }
609 :
610 : /************************************************************************/
611 : /* GetStatistics() */
612 : /* */
613 : /* We override this method so that we can force generation of */
614 : /* statistics if approx ok is true since we know that a small */
615 : /* overview is always available, and that computing statistics */
616 : /* from it is very fast. */
617 : /************************************************************************/
618 :
619 : CPLErr MrSIDRasterBand::GetStatistics( int bApproxOK, int bForce,
620 : double *pdfMin, double *pdfMax,
621 4 : double *pdfMean, double *pdfStdDev )
622 :
623 : {
624 4 : if( bApproxOK )
625 2 : bForce = TRUE;
626 :
627 : return GDALPamRasterBand::GetStatistics( bApproxOK, bForce,
628 : pdfMin, pdfMax,
629 4 : pdfMean, pdfStdDev );
630 : }
631 :
632 : /************************************************************************/
633 : /* GetNoDataValue() */
634 : /************************************************************************/
635 :
636 5 : double MrSIDRasterBand::GetNoDataValue( int * pbSuccess )
637 :
638 : {
639 5 : if( bNoDataSet )
640 : {
641 0 : if( pbSuccess )
642 0 : *pbSuccess = bNoDataSet;
643 :
644 0 : return dfNoDataValue;
645 : }
646 :
647 5 : return GDALPamRasterBand::GetNoDataValue( pbSuccess );
648 : }
649 :
650 : /************************************************************************/
651 : /* GetOverviewCount() */
652 : /************************************************************************/
653 :
654 15 : int MrSIDRasterBand::GetOverviewCount()
655 :
656 : {
657 15 : return poGDS->nOverviewCount;
658 : }
659 :
660 : /************************************************************************/
661 : /* GetOverview() */
662 : /************************************************************************/
663 :
664 11 : GDALRasterBand *MrSIDRasterBand::GetOverview( int i )
665 :
666 : {
667 11 : if( i < 0 || i >= poGDS->nOverviewCount )
668 0 : return NULL;
669 : else
670 11 : return poGDS->papoOverviewDS[i]->GetRasterBand( nBand );
671 : }
672 :
673 : /************************************************************************/
674 : /* MrSIDDataset() */
675 : /************************************************************************/
676 :
677 106 : MrSIDDataset::MrSIDDataset(int bIsJPEG2000)
678 : {
679 106 : poImageReader = NULL;
680 : #ifdef MRSID_ESDK
681 : poImageWriter = NULL;
682 : #endif
683 106 : poLTINav = NULL;
684 106 : poMetadata = NULL;
685 106 : poNDPixel = NULL;
686 106 : eSampleType = LTI_DATATYPE_UINT8;
687 106 : nBands = 0;
688 106 : eDataType = GDT_Byte;
689 :
690 106 : poBuffer = NULL;
691 106 : bPrevBlockRead = FALSE;
692 106 : nPrevBlockXOff = 0;
693 106 : nPrevBlockYOff = 0;
694 :
695 106 : pszProjection = CPLStrdup( "" );
696 106 : bHasGeoTransform = FALSE;
697 106 : adfGeoTransform[0] = 0.0;
698 106 : adfGeoTransform[1] = 1.0;
699 106 : adfGeoTransform[2] = 0.0;
700 106 : adfGeoTransform[3] = 0.0;
701 106 : adfGeoTransform[4] = 0.0;
702 106 : adfGeoTransform[5] = 1.0;
703 106 : psDefn = NULL;
704 :
705 106 : dfCurrentMag = 1.0;
706 106 : bIsOverview = FALSE;
707 106 : poParentDS = this;
708 106 : nOverviewCount = 0;
709 106 : papoOverviewDS = NULL;
710 :
711 106 : poDriver = (GDALDriver*) GDALGetDriverByName( bIsJPEG2000 ? "JP2MrSID" : "MrSID" );
712 106 : }
713 :
714 : /************************************************************************/
715 : /* ~MrSIDDataset() */
716 : /************************************************************************/
717 :
718 106 : MrSIDDataset::~MrSIDDataset()
719 : {
720 106 : FlushCache();
721 :
722 : #ifdef MRSID_ESDK
723 : if ( poImageWriter )
724 : delete poImageWriter;
725 : #endif
726 :
727 106 : if ( poBuffer )
728 13 : delete poBuffer;
729 106 : if ( poMetadata )
730 19 : delete poMetadata;
731 106 : if ( poLTINav )
732 106 : delete poLTINav;
733 106 : if ( poImageReader && !bIsOverview )
734 : #if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 7
735 : {
736 19 : poImageReader->release();
737 19 : poImageReader = NULL;
738 : }
739 : #else
740 : delete poImageReader;
741 : #endif
742 :
743 106 : if ( pszProjection )
744 106 : CPLFree( pszProjection );
745 106 : if ( psDefn )
746 19 : delete psDefn;
747 106 : if ( papoOverviewDS )
748 : {
749 106 : for( int i = 0; i < nOverviewCount; i++ )
750 87 : delete papoOverviewDS[i];
751 19 : CPLFree( papoOverviewDS );
752 : }
753 106 : }
754 :
755 : /************************************************************************/
756 : /* IRasterIO() */
757 : /************************************************************************/
758 :
759 : CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
760 : int nXOff, int nYOff, int nXSize, int nYSize,
761 : void * pData, int nBufXSize, int nBufYSize,
762 : GDALDataType eBufType,
763 : int nBandCount, int *panBandMap,
764 2 : int nPixelSpace, int nLineSpace, int nBandSpace )
765 :
766 : {
767 : /* -------------------------------------------------------------------- */
768 : /* We need various criteria to skip out to block based methods. */
769 : /* -------------------------------------------------------------------- */
770 2 : int bUseBlockedIO = bForceCachedIO;
771 :
772 2 : if( nYSize == 1 || nXSize * ((double) nYSize) < 100.0 )
773 0 : bUseBlockedIO = TRUE;
774 :
775 2 : if( nBufYSize == 1 || nBufXSize * ((double) nBufYSize) < 100.0 )
776 0 : bUseBlockedIO = TRUE;
777 :
778 2 : if( CSLTestBoolean( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) )
779 0 : bUseBlockedIO = FALSE;
780 :
781 2 : if( bUseBlockedIO )
782 : return GDALDataset::BlockBasedRasterIO(
783 : eRWFlag, nXOff, nYOff, nXSize, nYSize,
784 : pData, nBufXSize, nBufYSize, eBufType,
785 0 : nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace );
786 2 : CPLDebug( "MrSID", "RasterIO() - using optimized dataset level IO." );
787 :
788 : /* -------------------------------------------------------------------- */
789 : /* What is our requested window relative to the base dataset. */
790 : /* We want to operate from here on as if we were operating on */
791 : /* the full res band. */
792 : /* -------------------------------------------------------------------- */
793 2 : int nZoomMag = (int) ((1/dfCurrentMag) * 1.0000001);
794 :
795 2 : nXOff *= nZoomMag;
796 2 : nYOff *= nZoomMag;
797 2 : nXSize *= nZoomMag;
798 2 : nYSize *= nZoomMag;
799 :
800 : /* -------------------------------------------------------------------- */
801 : /* We need to figure out the best zoom level to use for this */
802 : /* request. We apply a small fudge factor to make sure that */
803 : /* request just very, very slightly larger than a zoom level do */
804 : /* not force us to the next level. */
805 : /* -------------------------------------------------------------------- */
806 2 : int iOverview = 0;
807 2 : double dfZoomMag = MIN((nXSize / (double)nBufXSize),
808 : (nYSize / (double)nBufYSize));
809 :
810 2 : for( nZoomMag = 1;
811 : nZoomMag * 2 < (dfZoomMag + 0.1)
812 : && iOverview < poParentDS->nOverviewCount;
813 : nZoomMag *= 2, iOverview++ ) {}
814 :
815 : /* -------------------------------------------------------------------- */
816 : /* Work out the size of the temporary buffer and allocate it. */
817 : /* The temporary buffer will generally be at a moderately */
818 : /* higher resolution than the buffer of data requested. */
819 : /* -------------------------------------------------------------------- */
820 : int nTmpPixelSize;
821 2 : LTIPixel oPixel( eColorSpace, nBands, eSampleType );
822 :
823 : LT_STATUS eLTStatus;
824 : unsigned int maxWidth;
825 : unsigned int maxHeight;
826 :
827 2 : eLTStatus = poImageReader->getDimsAtMag(1.0/nZoomMag,maxWidth,maxHeight);
828 :
829 2 : if( !LT_SUCCESS(eLTStatus)) {
830 : CPLError( CE_Failure, CPLE_AppDefined,
831 : "MrSIDDataset::IRasterIO(): Failed to get zoomed image dimensions.\n%s",
832 0 : getLastStatusString( eLTStatus ) );
833 2 : return CE_Failure;
834 : }
835 :
836 2 : int maxWidthAtL0 = bIsOverview?poParentDS->GetRasterXSize():this->GetRasterXSize();
837 2 : int maxHeightAtL0 = bIsOverview?poParentDS->GetRasterYSize():this->GetRasterYSize();
838 :
839 2 : int sceneUlXOff = nXOff / nZoomMag;
840 2 : int sceneUlYOff = nYOff / nZoomMag;
841 2 : int sceneWidth = (int)(nXSize * (double) maxWidth / (double)maxWidthAtL0 + 0.99);
842 2 : int sceneHeight = (int)(nYSize * (double) maxHeight / (double)maxHeightAtL0 + 0.99);
843 :
844 2 : if( (sceneUlXOff + sceneWidth) > (int) maxWidth )
845 0 : sceneWidth = maxWidth - sceneUlXOff;
846 :
847 2 : if( (sceneUlYOff + sceneHeight) > (int) maxHeight )
848 0 : sceneHeight = maxHeight - sceneUlYOff;
849 :
850 2 : LTISceneBuffer oLTIBuffer( oPixel, sceneWidth, sceneHeight, NULL );
851 :
852 2 : nTmpPixelSize = GDALGetDataTypeSize( eDataType ) / 8;
853 :
854 : /* -------------------------------------------------------------------- */
855 : /* Create navigator, and move to the requested scene area. */
856 : /* -------------------------------------------------------------------- */
857 2 : LTINavigator oNav( *poImageReader );
858 :
859 2 : if( !LT_SUCCESS(oNav.setSceneAsULWH( sceneUlXOff, sceneUlYOff,
860 : sceneWidth, sceneHeight,
861 : 1.0 / nZoomMag )) )
862 : {
863 : CPLError( CE_Failure, CPLE_AppDefined,
864 0 : "MrSIDDataset::IRasterIO(): Failed to set scene position." );
865 :
866 0 : return CE_Failure;
867 : }
868 :
869 : CPLDebug( "MrSID",
870 : "Dataset:IRasterIO(%d,%d %dx%d -> %dx%d -> %dx%d, zoom=%d)",
871 : nXOff, nYOff, nXSize, nYSize,
872 : sceneWidth, sceneHeight,
873 : nBufXSize, nBufYSize,
874 2 : nZoomMag );
875 :
876 2 : if( !oNav.isSceneValid() )
877 0 : CPLDebug( "MrSID", "LTINavigator in invalid state." );
878 :
879 : /* -------------------------------------------------------------------- */
880 : /* Read into the buffer. */
881 : /* -------------------------------------------------------------------- */
882 :
883 2 : eLTStatus = poImageReader->read(oNav.getScene(),oLTIBuffer);
884 2 : if(!LT_SUCCESS(eLTStatus) )
885 : {
886 : CPLError( CE_Failure, CPLE_AppDefined,
887 : "MrSIDRasterBand::IRasterIO(): Failed to load image.\n%s",
888 0 : getLastStatusString( eLTStatus ) );
889 0 : return CE_Failure;
890 : }
891 :
892 : /* -------------------------------------------------------------------- */
893 : /* If we are pulling the data at a matching resolution, try to */
894 : /* do a more direct copy without subsampling. */
895 : /* -------------------------------------------------------------------- */
896 : int iBufLine, iBufPixel;
897 :
898 3 : if( nBufXSize == sceneWidth && nBufYSize == sceneHeight )
899 : {
900 2 : for( int iBand = 0; iBand < nBandCount; iBand++ )
901 : {
902 : GByte *pabySrcBand = (GByte *)
903 1 : oLTIBuffer.getTotalBandData( panBandMap[iBand] - 1 );
904 :
905 257 : for( int iLine = 0; iLine < nBufYSize; iLine++ )
906 : {
907 : GDALCopyWords( pabySrcBand + iLine*nTmpPixelSize*sceneWidth,
908 : eDataType, nTmpPixelSize,
909 : ((GByte *)pData) + iLine*nLineSpace
910 : + iBand * nBandSpace,
911 : eBufType, nPixelSpace,
912 256 : nBufXSize );
913 : }
914 : }
915 : }
916 :
917 : /* -------------------------------------------------------------------- */
918 : /* Manually resample to our target buffer. */
919 : /* -------------------------------------------------------------------- */
920 : else
921 : {
922 11 : for( iBufLine = 0; iBufLine < nBufYSize; iBufLine++ )
923 : {
924 10 : int iTmpLine = (int) floor(((iBufLine+0.5) / nBufYSize)*sceneHeight);
925 :
926 110 : for( iBufPixel = 0; iBufPixel < nBufXSize; iBufPixel++ )
927 : {
928 : int iTmpPixel = (int)
929 100 : floor(((iBufPixel+0.5) / nBufXSize) * sceneWidth);
930 :
931 200 : for( int iBand = 0; iBand < nBandCount; iBand++ )
932 : {
933 : GByte *pabySrc, *pabyDst;
934 :
935 : pabyDst = ((GByte *) pData)
936 : + nPixelSpace * iBufPixel
937 : + nLineSpace * iBufLine
938 100 : + nBandSpace * iBand;
939 :
940 : pabySrc = (GByte *) oLTIBuffer.getTotalBandData(
941 100 : panBandMap[iBand] - 1 );
942 100 : pabySrc += (iTmpLine * sceneWidth + iTmpPixel) * nTmpPixelSize;
943 :
944 100 : if( eDataType == eBufType )
945 100 : memcpy( pabyDst, pabySrc, nTmpPixelSize );
946 : else
947 : GDALCopyWords( pabySrc, eDataType, 0,
948 0 : pabyDst, eBufType, 0, 1 );
949 : }
950 : }
951 : }
952 : }
953 :
954 2 : return CE_None;
955 : }
956 :
957 : /************************************************************************/
958 : /* GetGeoTransform() */
959 : /************************************************************************/
960 :
961 2 : CPLErr MrSIDDataset::GetGeoTransform( double * padfTransform )
962 : {
963 2 : if( strlen(GDALPamDataset::GetProjectionRef()) > 0
964 : || !bHasGeoTransform )
965 : {
966 1 : return GDALPamDataset::GetGeoTransform( padfTransform );
967 : }
968 : else
969 : {
970 1 : memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
971 1 : return( CE_None );
972 : }
973 : }
974 :
975 : /************************************************************************/
976 : /* GetProjectionRef() */
977 : /************************************************************************/
978 :
979 4 : const char *MrSIDDataset::GetProjectionRef()
980 : {
981 4 : const char* pszPamPrj = GDALPamDataset::GetProjectionRef();
982 :
983 4 : if( strlen(pszProjection) > 0 && strlen(pszPamPrj) == 0 )
984 3 : return pszProjection;
985 : else
986 1 : return pszPamPrj;
987 : }
988 :
989 : /************************************************************************/
990 : /* SerializeMetadataRec() */
991 : /************************************************************************/
992 :
993 244 : char *MrSIDDataset::SerializeMetadataRec( const LTIMetadataRecord *poMetadataRec )
994 : {
995 244 : GUInt32 iNumDims = 0;
996 244 : const GUInt32 *paiDims = NULL;
997 244 : const void *pData = poMetadataRec->getArrayData( iNumDims, paiDims );
998 244 : GUInt32 i, j, k = 0, iLength;
999 244 : char *pszMetadata = CPLStrdup( "" );
1000 :
1001 488 : for ( i = 0; i < iNumDims; i++ )
1002 : {
1003 : // stops on large binary data
1004 244 : if ( poMetadataRec->getDataType() == LTI_METADATA_DATATYPE_UINT8
1005 : && paiDims[i] > 1024 )
1006 0 : return pszMetadata;
1007 :
1008 620 : for ( j = 0; j < paiDims[i]; j++ )
1009 : {
1010 376 : CPLString osTemp;
1011 :
1012 376 : switch( poMetadataRec->getDataType() )
1013 : {
1014 : case LTI_METADATA_DATATYPE_UINT8:
1015 : case LTI_METADATA_DATATYPE_SINT8:
1016 0 : osTemp.Printf( "%d", ((GByte *)pData)[k++] );
1017 0 : break;
1018 : case LTI_METADATA_DATATYPE_UINT16:
1019 76 : osTemp.Printf( "%u", ((GUInt16 *)pData)[k++] );
1020 76 : break;
1021 : case LTI_METADATA_DATATYPE_SINT16:
1022 0 : osTemp.Printf( "%d", ((GInt16 *)pData)[k++] );
1023 0 : break;
1024 : case LTI_METADATA_DATATYPE_UINT32:
1025 12 : osTemp.Printf( "%u", ((GUInt32 *)pData)[k++] );
1026 12 : break;
1027 : case LTI_METADATA_DATATYPE_SINT32:
1028 18 : osTemp.Printf( "%d", ((GInt32 *)pData)[k++] );
1029 18 : break;
1030 : case LTI_METADATA_DATATYPE_FLOAT32:
1031 18 : osTemp.Printf( "%f", ((float *)pData)[k++] );
1032 18 : break;
1033 : case LTI_METADATA_DATATYPE_FLOAT64:
1034 169 : osTemp.Printf( "%lf", ((double *)pData)[k++] );
1035 169 : break;
1036 : case LTI_METADATA_DATATYPE_ASCII:
1037 83 : osTemp = ((const char **)pData)[k++];
1038 83 : break;
1039 : default:
1040 0 : osTemp = "";
1041 : break;
1042 : }
1043 :
1044 376 : iLength = strlen(pszMetadata) + strlen(osTemp) + 2;
1045 :
1046 376 : pszMetadata = (char *)CPLRealloc( pszMetadata, iLength );
1047 376 : if ( !EQUAL( pszMetadata, "" ) )
1048 132 : strncat( pszMetadata, ",", 1 );
1049 376 : strncat( pszMetadata, osTemp, iLength );
1050 : }
1051 : }
1052 :
1053 244 : return pszMetadata;
1054 : }
1055 :
1056 : /************************************************************************/
1057 : /* GetMetadataElement() */
1058 : /************************************************************************/
1059 :
1060 : int MrSIDDataset::GetMetadataElement( const char *pszKey, void *pValue,
1061 337 : int iLength )
1062 : {
1063 337 : if ( !poMetadata->has( pszKey ) )
1064 258 : return FALSE;
1065 :
1066 79 : const LTIMetadataRecord *poMetadataRec = NULL;
1067 79 : poMetadata->get( pszKey, poMetadataRec );
1068 :
1069 79 : if ( !poMetadataRec->isScalar() )
1070 24 : return FALSE;
1071 :
1072 : // XXX: return FALSE if we have more than one element in metadata record
1073 : int iSize;
1074 55 : switch( poMetadataRec->getDataType() )
1075 : {
1076 : case LTI_METADATA_DATATYPE_UINT8:
1077 : case LTI_METADATA_DATATYPE_SINT8:
1078 0 : iSize = 1;
1079 0 : break;
1080 : case LTI_METADATA_DATATYPE_UINT16:
1081 : case LTI_METADATA_DATATYPE_SINT16:
1082 49 : iSize = 2;
1083 49 : break;
1084 : case LTI_METADATA_DATATYPE_UINT32:
1085 : case LTI_METADATA_DATATYPE_SINT32:
1086 : case LTI_METADATA_DATATYPE_FLOAT32:
1087 0 : iSize = 4;
1088 0 : break;
1089 : case LTI_METADATA_DATATYPE_FLOAT64:
1090 0 : iSize = 8;
1091 0 : break;
1092 : case LTI_METADATA_DATATYPE_ASCII:
1093 6 : iSize = iLength;
1094 6 : break;
1095 : default:
1096 0 : iSize = 0;
1097 : break;
1098 : }
1099 :
1100 55 : if ( poMetadataRec->getDataType() == LTI_METADATA_DATATYPE_ASCII )
1101 : {
1102 : strncpy( (char *)pValue,
1103 6 : ((const char**)poMetadataRec->getScalarData())[0], iSize );
1104 6 : ((char *)pValue)[iSize - 1] = '\0';
1105 : }
1106 : else
1107 49 : memcpy( pValue, poMetadataRec->getScalarData(), iSize );
1108 :
1109 55 : return TRUE;
1110 : }
1111 :
1112 : /************************************************************************/
1113 : /* OpenZoomLevel() */
1114 : /************************************************************************/
1115 :
1116 106 : CPLErr MrSIDDataset::OpenZoomLevel( lt_int32 iZoom )
1117 : {
1118 : /* -------------------------------------------------------------------- */
1119 : /* Get image geometry. */
1120 : /* -------------------------------------------------------------------- */
1121 106 : if ( iZoom != 0 )
1122 : {
1123 : lt_uint32 iWidth, iHeight;
1124 87 : dfCurrentMag = LTIUtils::levelToMag( iZoom );
1125 87 : poImageReader->getDimsAtMag( dfCurrentMag, iWidth, iHeight );
1126 87 : nRasterXSize = iWidth;
1127 87 : nRasterYSize = iHeight;
1128 : }
1129 : else
1130 : {
1131 19 : dfCurrentMag = 1.0;
1132 19 : nRasterXSize = poImageReader->getWidth();
1133 19 : nRasterYSize = poImageReader->getHeight();
1134 : }
1135 :
1136 106 : nBands = poImageReader->getNumBands();
1137 106 : nBlockXSize = nRasterXSize;
1138 106 : nBlockYSize = poImageReader->getStripHeight();
1139 :
1140 : CPLDebug( "MrSID", "Opened zoom level %d with size %dx%d.",
1141 106 : iZoom, nRasterXSize, nRasterYSize );
1142 :
1143 : try
1144 : {
1145 106 : poLTINav = new LTIDLLNavigator<LTINavigator>( *poImageReader );
1146 : }
1147 0 : catch ( ... )
1148 : {
1149 : CPLError( CE_Failure, CPLE_AppDefined,
1150 : "MrSIDDataset::OpenZoomLevel(): "
1151 0 : "Failed to create LTINavigator object." );
1152 0 : return CE_Failure;
1153 : }
1154 :
1155 : /* -------------------------------------------------------------------- */
1156 : /* Handle sample type and color space. */
1157 : /* -------------------------------------------------------------------- */
1158 106 : eColorSpace = poImageReader->getColorSpace();
1159 106 : eSampleType = poImageReader->getDataType();
1160 106 : switch ( eSampleType )
1161 : {
1162 : case LTI_DATATYPE_UINT16:
1163 12 : eDataType = GDT_UInt16;
1164 12 : break;
1165 : case LTI_DATATYPE_SINT16:
1166 0 : eDataType = GDT_Int16;
1167 0 : break;
1168 : case LTI_DATATYPE_UINT32:
1169 0 : eDataType = GDT_UInt32;
1170 0 : break;
1171 : case LTI_DATATYPE_SINT32:
1172 0 : eDataType = GDT_Int32;
1173 0 : break;
1174 : case LTI_DATATYPE_FLOAT32:
1175 0 : eDataType = GDT_Float32;
1176 0 : break;
1177 : case LTI_DATATYPE_FLOAT64:
1178 0 : eDataType = GDT_Float64;
1179 0 : break;
1180 : case LTI_DATATYPE_UINT8:
1181 : case LTI_DATATYPE_SINT8:
1182 : default:
1183 94 : eDataType = GDT_Byte;
1184 : break;
1185 : }
1186 :
1187 : /* -------------------------------------------------------------------- */
1188 : /* Read georeferencing. */
1189 : /* -------------------------------------------------------------------- */
1190 106 : if ( !poImageReader->isGeoCoordImplicit() )
1191 : {
1192 42 : const LTIGeoCoord& oGeo = poImageReader->getGeoCoord();
1193 : oGeo.get( adfGeoTransform[0], adfGeoTransform[3],
1194 : adfGeoTransform[1], adfGeoTransform[5],
1195 42 : adfGeoTransform[2], adfGeoTransform[4] );
1196 :
1197 42 : adfGeoTransform[0] = adfGeoTransform[0] - adfGeoTransform[1] / 2;
1198 42 : adfGeoTransform[3] = adfGeoTransform[3] - adfGeoTransform[5] / 2;
1199 42 : bHasGeoTransform = TRUE;
1200 : }
1201 64 : else if( iZoom == 0 )
1202 : {
1203 : bHasGeoTransform =
1204 : GDALReadWorldFile( GetDescription(), ".sdw",
1205 : adfGeoTransform )
1206 : || GDALReadWorldFile( GetDescription(), ".sidw",
1207 : adfGeoTransform )
1208 : || GDALReadWorldFile( GetDescription(), ".wld",
1209 11 : adfGeoTransform );
1210 : }
1211 :
1212 : /* -------------------------------------------------------------------- */
1213 : /* Read wkt. */
1214 : /* -------------------------------------------------------------------- */
1215 : #ifdef MRSID_HAVE_GETWKT
1216 106 : if( !poImageReader->isGeoCoordImplicit() )
1217 : {
1218 42 : const LTIGeoCoord& oGeo = poImageReader->getGeoCoord();
1219 :
1220 42 : if( oGeo.getWKT() )
1221 : {
1222 42 : CPLFree( pszProjection );
1223 42 : pszProjection = CPLStrdup( oGeo.getWKT() );
1224 : }
1225 : }
1226 : #endif // HAVE_MRSID_GETWKT
1227 :
1228 : /* -------------------------------------------------------------------- */
1229 : /* Read NoData value. */
1230 : /* -------------------------------------------------------------------- */
1231 106 : poNDPixel = poImageReader->getNoDataPixel();
1232 :
1233 : /* -------------------------------------------------------------------- */
1234 : /* Create band information objects. */
1235 : /* -------------------------------------------------------------------- */
1236 : int iBand;
1237 :
1238 568 : for( iBand = 1; iBand <= nBands; iBand++ )
1239 178 : SetBand( iBand, new MrSIDRasterBand( this, iBand ) );
1240 :
1241 106 : return CE_None;
1242 : }
1243 :
1244 : /************************************************************************/
1245 : /* MrSIDIdentify() */
1246 : /* */
1247 : /* Identify method that only supports MrSID files. */
1248 : /************************************************************************/
1249 :
1250 10199 : static int MrSIDIdentify( GDALOpenInfo * poOpenInfo )
1251 : {
1252 10199 : if( poOpenInfo->nHeaderBytes < 32 )
1253 9525 : return FALSE;
1254 :
1255 674 : if ( !EQUALN((const char *) poOpenInfo->pabyHeader, "msid", 4) )
1256 667 : return FALSE;
1257 :
1258 7 : return TRUE;
1259 : }
1260 :
1261 : /************************************************************************/
1262 : /* MrSIDOpen() */
1263 : /* */
1264 : /* Open method that only supports MrSID files. */
1265 : /************************************************************************/
1266 :
1267 1954 : static GDALDataset* MrSIDOpen( GDALOpenInfo *poOpenInfo )
1268 : {
1269 1954 : if (!MrSIDIdentify(poOpenInfo))
1270 1947 : return NULL;
1271 :
1272 7 : return MrSIDDataset::Open( poOpenInfo, FALSE );
1273 : }
1274 :
1275 :
1276 : #ifdef MRSID_J2K
1277 :
1278 : static const unsigned char jpc_header[] =
1279 : {0xff,0x4f};
1280 :
1281 : /************************************************************************/
1282 : /* JP2Identify() */
1283 : /* */
1284 : /* Identify method that only supports JPEG2000 files. */
1285 : /************************************************************************/
1286 :
1287 9792 : static int JP2Identify( GDALOpenInfo *poOpenInfo )
1288 : {
1289 9792 : if( poOpenInfo->nHeaderBytes < 32 )
1290 9442 : return FALSE;
1291 :
1292 350 : if( memcmp( poOpenInfo->pabyHeader, jpc_header, sizeof(jpc_header) ) == 0 )
1293 : {
1294 : const char *pszExtension;
1295 :
1296 8 : pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
1297 :
1298 8 : if( !EQUAL(pszExtension,"jpc") && !EQUAL(pszExtension,"j2k")
1299 : && !EQUAL(pszExtension,"jp2") && !EQUAL(pszExtension,"jpx")
1300 : && !EQUAL(pszExtension,"j2c") && !EQUAL(pszExtension,"ntf"))
1301 0 : return FALSE;
1302 : }
1303 342 : else if( !EQUALN((const char *) poOpenInfo->pabyHeader + 4, "jP ", 4) )
1304 338 : return FALSE;
1305 :
1306 12 : return TRUE;
1307 : }
1308 :
1309 : /************************************************************************/
1310 : /* JP2Open() */
1311 : /* */
1312 : /* Open method that only supports JPEG2000 files. */
1313 : /************************************************************************/
1314 :
1315 1561 : static GDALDataset* JP2Open( GDALOpenInfo *poOpenInfo )
1316 : {
1317 1561 : if (!JP2Identify(poOpenInfo))
1318 1549 : return NULL;
1319 :
1320 12 : return MrSIDDataset::Open( poOpenInfo, TRUE );
1321 : }
1322 :
1323 : #endif // MRSID_J2K
1324 :
1325 : /************************************************************************/
1326 : /* Open() */
1327 : /************************************************************************/
1328 :
1329 19 : GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
1330 : {
1331 19 : if(poOpenInfo->fp)
1332 : {
1333 16 : VSIFClose( poOpenInfo->fp );
1334 16 : poOpenInfo->fp = NULL;
1335 : }
1336 :
1337 : /* -------------------------------------------------------------------- */
1338 : /* Create a corresponding GDALDataset. */
1339 : /* -------------------------------------------------------------------- */
1340 : MrSIDDataset *poDS;
1341 : LT_STATUS eStat;
1342 :
1343 19 : poDS = new MrSIDDataset(bIsJP2);
1344 19 : eStat = poDS->oStream.initialize( poOpenInfo->pszFilename, "rb" );
1345 19 : if ( !LT_SUCCESS(eStat) )
1346 : {
1347 : CPLError( CE_Failure, CPLE_AppDefined,
1348 : "MrSIDStream::initialize(): "
1349 : "failed to open file \"%s\".\n%s",
1350 0 : poOpenInfo->pszFilename, getLastStatusString( eStat ) );
1351 0 : delete poDS;
1352 0 : return NULL;
1353 : }
1354 :
1355 19 : poDS->oStream.open();
1356 :
1357 : #if defined(LTI_SDK_MAJOR) && LTI_SDK_MAJOR >= 7
1358 :
1359 : #ifdef MRSID_J2K
1360 19 : if ( bIsJP2 )
1361 : {
1362 12 : J2KImageReader *reader = J2KImageReader::create();
1363 12 : eStat = reader->initialize( poDS->oStream );
1364 12 : poDS->poImageReader = reader;
1365 : }
1366 : else
1367 : #endif /* MRSID_J2K */
1368 : {
1369 7 : MrSIDImageReader *reader = MrSIDImageReader::create();
1370 7 : eStat = reader->initialize( &poDS->oStream, NULL );
1371 7 : poDS->poImageReader = reader;
1372 : }
1373 :
1374 : #else /* LTI_SDK_MAJOR < 7 */
1375 :
1376 : #ifdef MRSID_J2K
1377 : if ( bIsJP2 )
1378 : {
1379 : poDS->poImageReader =
1380 : new LTIDLLReader<J2KImageReader>( poDS->oStream, true );
1381 : eStat = poDS->poImageReader->initialize();
1382 : }
1383 : else
1384 : #endif /* MRSID_J2K */
1385 : {
1386 : poDS->poImageReader =
1387 : new LTIDLLReader<MrSIDImageReader>( &poDS->oStream, NULL );
1388 : eStat = poDS->poImageReader->initialize();
1389 : }
1390 :
1391 : #endif /* LTI_SDK_MAJOR >= 7 */
1392 :
1393 19 : if ( !LT_SUCCESS(eStat) )
1394 : {
1395 : CPLError( CE_Failure, CPLE_AppDefined,
1396 : "LTIImageReader::initialize(): "
1397 : "failed to initialize reader from the stream \"%s\".\n%s",
1398 0 : poOpenInfo->pszFilename, getLastStatusString( eStat ) );
1399 0 : delete poDS;
1400 0 : return NULL;
1401 : }
1402 :
1403 : /* -------------------------------------------------------------------- */
1404 : /* Read metadata. */
1405 : /* -------------------------------------------------------------------- */
1406 : poDS->poMetadata = new LTIDLLCopy<LTIMetadataDatabase>(
1407 19 : poDS->poImageReader->getMetadata() );
1408 19 : const GUInt32 iNumRecs = poDS->poMetadata->getIndexCount();
1409 : GUInt32 i;
1410 :
1411 263 : for ( i = 0; i < iNumRecs; i++ )
1412 : {
1413 244 : const LTIMetadataRecord *poMetadataRec = NULL;
1414 244 : if ( LT_SUCCESS(poDS->poMetadata->getDataByIndex(i, poMetadataRec)) )
1415 : {
1416 244 : char *pszElement = poDS->SerializeMetadataRec( poMetadataRec );
1417 244 : char *pszKey = CPLStrdup( poMetadataRec->getTagName() );
1418 244 : char *pszTemp = pszKey;
1419 :
1420 : // GDAL metadata keys should not contain ':' and '=' characters.
1421 : // We will replace them with '_'.
1422 7925 : do
1423 : {
1424 7925 : if ( *pszTemp == ':' || *pszTemp == '=' )
1425 690 : *pszTemp = '_';
1426 : }
1427 : while ( *++pszTemp );
1428 :
1429 244 : poDS->SetMetadataItem( pszKey, pszElement );
1430 :
1431 244 : CPLFree( pszElement );
1432 244 : CPLFree( pszKey );
1433 : }
1434 : }
1435 :
1436 : /* -------------------------------------------------------------------- */
1437 : /* Add MrSID version. */
1438 : /* -------------------------------------------------------------------- */
1439 : #ifdef MRSID_J2K
1440 19 : if( !bIsJP2 )
1441 : #endif
1442 : {
1443 : lt_uint8 major;
1444 : lt_uint8 minor;
1445 : char letter;
1446 7 : MrSIDImageReader* poMrSIDImageReader = (MrSIDImageReader*)poDS->poImageReader;
1447 7 : poMrSIDImageReader->getVersion(major, minor, minor, letter);
1448 7 : if (major < 2)
1449 6 : major = 2;
1450 :
1451 7 : poDS->SetMetadataItem( "VERSION", CPLString().Printf("MG%d", major) );
1452 : }
1453 :
1454 19 : poDS->GetGTIFDefn();
1455 :
1456 : /* -------------------------------------------------------------------- */
1457 : /* Get number of resolution levels (we will use them as overviews).*/
1458 : /* -------------------------------------------------------------------- */
1459 : #ifdef MRSID_J2K
1460 19 : if( bIsJP2 )
1461 : poDS->nOverviewCount
1462 12 : = ((J2KImageReader *) (poDS->poImageReader))->getNumLevels();
1463 : else
1464 : #endif
1465 : poDS->nOverviewCount
1466 7 : = ((MrSIDImageReader *) (poDS->poImageReader))->getNumLevels();
1467 :
1468 19 : if ( poDS->nOverviewCount > 0 )
1469 : {
1470 : lt_int32 i;
1471 :
1472 : poDS->papoOverviewDS = (MrSIDDataset **)
1473 19 : CPLMalloc( poDS->nOverviewCount * (sizeof(void*)) );
1474 :
1475 212 : for ( i = 0; i < poDS->nOverviewCount; i++ )
1476 : {
1477 87 : poDS->papoOverviewDS[i] = new MrSIDDataset(bIsJP2);
1478 87 : poDS->papoOverviewDS[i]->poImageReader = poDS->poImageReader;
1479 87 : poDS->papoOverviewDS[i]->OpenZoomLevel( i + 1 );
1480 87 : poDS->papoOverviewDS[i]->bIsOverview = TRUE;
1481 87 : poDS->papoOverviewDS[i]->poParentDS = poDS;
1482 : }
1483 : }
1484 :
1485 : /* -------------------------------------------------------------------- */
1486 : /* Create object for the whole image. */
1487 : /* -------------------------------------------------------------------- */
1488 19 : poDS->SetDescription( poOpenInfo->pszFilename );
1489 19 : poDS->OpenZoomLevel( 0 );
1490 :
1491 : CPLDebug( "MrSID",
1492 : "Opened image: width %d, height %d, bands %d",
1493 19 : poDS->nRasterXSize, poDS->nRasterYSize, poDS->nBands );
1494 :
1495 19 : if( poDS->nBands > 1 )
1496 6 : poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
1497 :
1498 : /* -------------------------------------------------------------------- */
1499 : /* Initialize any PAM information. */
1500 : /* -------------------------------------------------------------------- */
1501 19 : poDS->TryLoadXML();
1502 :
1503 19 : return( poDS );
1504 : }
1505 :
1506 : /************************************************************************/
1507 : /* EPSGProjMethodToCTProjMethod() */
1508 : /* */
1509 : /* Convert between the EPSG enumeration for projection methods, */
1510 : /* and the GeoTIFF CT codes. */
1511 : /* Explicitly copied from geo_normalize.c of the GeoTIFF package */
1512 : /************************************************************************/
1513 :
1514 1 : static int EPSGProjMethodToCTProjMethod( int nEPSG )
1515 :
1516 : {
1517 : /* see trf_method.csv for list of EPSG codes */
1518 :
1519 1 : switch( nEPSG )
1520 : {
1521 : case 9801:
1522 0 : return( CT_LambertConfConic_1SP );
1523 :
1524 : case 9802:
1525 0 : return( CT_LambertConfConic_2SP );
1526 :
1527 : case 9803:
1528 0 : return( CT_LambertConfConic_2SP ); /* Belgian variant not supported */
1529 :
1530 : case 9804:
1531 0 : return( CT_Mercator ); /* 1SP and 2SP not differentiated */
1532 :
1533 : case 9805:
1534 0 : return( CT_Mercator ); /* 1SP and 2SP not differentiated */
1535 :
1536 : case 9806:
1537 0 : return( CT_CassiniSoldner );
1538 :
1539 : case 9807:
1540 1 : return( CT_TransverseMercator );
1541 :
1542 : case 9808:
1543 0 : return( CT_TransvMercator_SouthOriented );
1544 :
1545 : case 9809:
1546 0 : return( CT_ObliqueStereographic );
1547 :
1548 : case 9810:
1549 0 : return( CT_PolarStereographic );
1550 :
1551 : case 9811:
1552 0 : return( CT_NewZealandMapGrid );
1553 :
1554 : case 9812:
1555 0 : return( CT_ObliqueMercator ); /* is hotine actually different? */
1556 :
1557 : case 9813:
1558 0 : return( CT_ObliqueMercator_Laborde );
1559 :
1560 : case 9814:
1561 0 : return( CT_ObliqueMercator_Rosenmund ); /* swiss */
1562 :
1563 : case 9815:
1564 0 : return( CT_ObliqueMercator );
1565 :
1566 : case 9816: /* tunesia mining grid has no counterpart */
1567 0 : return( KvUserDefined );
1568 : }
1569 :
1570 0 : return( KvUserDefined );
1571 : }
1572 :
1573 : /* EPSG Codes for projection parameters. Unfortunately, these bear no
1574 : relationship to the GeoTIFF codes even though the names are so similar. */
1575 :
1576 : #define EPSGNatOriginLat 8801
1577 : #define EPSGNatOriginLong 8802
1578 : #define EPSGNatOriginScaleFactor 8805
1579 : #define EPSGFalseEasting 8806
1580 : #define EPSGFalseNorthing 8807
1581 : #define EPSGProjCenterLat 8811
1582 : #define EPSGProjCenterLong 8812
1583 : #define EPSGAzimuth 8813
1584 : #define EPSGAngleRectifiedToSkewedGrid 8814
1585 : #define EPSGInitialLineScaleFactor 8815
1586 : #define EPSGProjCenterEasting 8816
1587 : #define EPSGProjCenterNorthing 8817
1588 : #define EPSGPseudoStdParallelLat 8818
1589 : #define EPSGPseudoStdParallelScaleFactor 8819
1590 : #define EPSGFalseOriginLat 8821
1591 : #define EPSGFalseOriginLong 8822
1592 : #define EPSGStdParallel1Lat 8823
1593 : #define EPSGStdParallel2Lat 8824
1594 : #define EPSGFalseOriginEasting 8826
1595 : #define EPSGFalseOriginNorthing 8827
1596 : #define EPSGSphericalOriginLat 8828
1597 : #define EPSGSphericalOriginLong 8829
1598 : #define EPSGInitialLongitude 8830
1599 : #define EPSGZoneWidth 8831
1600 :
1601 : /************************************************************************/
1602 : /* SetGTParmIds() */
1603 : /* */
1604 : /* This is hardcoded logic to set the GeoTIFF parameter */
1605 : /* identifiers for all the EPSG supported projections. As the */
1606 : /* trf_method.csv table grows with new projections, this code */
1607 : /* will need to be updated. */
1608 : /* Explicitly copied from geo_normalize.c of the GeoTIFF package. */
1609 : /************************************************************************/
1610 :
1611 : static int SetGTParmIds( int nCTProjection,
1612 : int *panProjParmId,
1613 1 : int *panEPSGCodes )
1614 :
1615 : {
1616 : int anWorkingDummy[7];
1617 :
1618 1 : if( panEPSGCodes == NULL )
1619 1 : panEPSGCodes = anWorkingDummy;
1620 1 : if( panProjParmId == NULL )
1621 0 : panProjParmId = anWorkingDummy;
1622 :
1623 1 : memset( panEPSGCodes, 0, sizeof(int) * 7 );
1624 :
1625 : /* psDefn->nParms = 7; */
1626 :
1627 1 : switch( nCTProjection )
1628 : {
1629 : case CT_CassiniSoldner:
1630 : case CT_NewZealandMapGrid:
1631 0 : panProjParmId[0] = ProjNatOriginLatGeoKey;
1632 0 : panProjParmId[1] = ProjNatOriginLongGeoKey;
1633 0 : panProjParmId[5] = ProjFalseEastingGeoKey;
1634 0 : panProjParmId[6] = ProjFalseNorthingGeoKey;
1635 :
1636 0 : panEPSGCodes[0] = EPSGNatOriginLat;
1637 0 : panEPSGCodes[1] = EPSGNatOriginLong;
1638 0 : panEPSGCodes[5] = EPSGFalseEasting;
1639 0 : panEPSGCodes[6] = EPSGFalseNorthing;
1640 0 : return TRUE;
1641 :
1642 : case CT_ObliqueMercator:
1643 0 : panProjParmId[0] = ProjCenterLatGeoKey;
1644 0 : panProjParmId[1] = ProjCenterLongGeoKey;
1645 0 : panProjParmId[2] = ProjAzimuthAngleGeoKey;
1646 0 : panProjParmId[3] = ProjRectifiedGridAngleGeoKey;
1647 0 : panProjParmId[4] = ProjScaleAtCenterGeoKey;
1648 0 : panProjParmId[5] = ProjFalseEastingGeoKey;
1649 0 : panProjParmId[6] = ProjFalseNorthingGeoKey;
1650 :
1651 0 : panEPSGCodes[0] = EPSGProjCenterLat;
1652 0 : panEPSGCodes[1] = EPSGProjCenterLong;
1653 0 : panEPSGCodes[2] = EPSGAzimuth;
1654 0 : panEPSGCodes[3] = EPSGAngleRectifiedToSkewedGrid;
1655 0 : panEPSGCodes[4] = EPSGInitialLineScaleFactor;
1656 0 : panEPSGCodes[5] = EPSGProjCenterEasting;
1657 0 : panEPSGCodes[6] = EPSGProjCenterNorthing;
1658 0 : return TRUE;
1659 :
1660 : case CT_ObliqueMercator_Laborde:
1661 0 : panProjParmId[0] = ProjCenterLatGeoKey;
1662 0 : panProjParmId[1] = ProjCenterLongGeoKey;
1663 0 : panProjParmId[2] = ProjAzimuthAngleGeoKey;
1664 0 : panProjParmId[4] = ProjScaleAtCenterGeoKey;
1665 0 : panProjParmId[5] = ProjFalseEastingGeoKey;
1666 0 : panProjParmId[6] = ProjFalseNorthingGeoKey;
1667 :
1668 0 : panEPSGCodes[0] = EPSGProjCenterLat;
1669 0 : panEPSGCodes[1] = EPSGProjCenterLong;
1670 0 : panEPSGCodes[2] = EPSGAzimuth;
1671 0 : panEPSGCodes[4] = EPSGInitialLineScaleFactor;
1672 0 : panEPSGCodes[5] = EPSGProjCenterEasting;
1673 0 : panEPSGCodes[6] = EPSGProjCenterNorthing;
1674 0 : return TRUE;
1675 :
1676 : case CT_LambertConfConic_1SP:
1677 : case CT_Mercator:
1678 : case CT_ObliqueStereographic:
1679 : case CT_PolarStereographic:
1680 : case CT_TransverseMercator:
1681 : case CT_TransvMercator_SouthOriented:
1682 1 : panProjParmId[0] = ProjNatOriginLatGeoKey;
1683 1 : panProjParmId[1] = ProjNatOriginLongGeoKey;
1684 1 : panProjParmId[4] = ProjScaleAtNatOriginGeoKey;
1685 1 : panProjParmId[5] = ProjFalseEastingGeoKey;
1686 1 : panProjParmId[6] = ProjFalseNorthingGeoKey;
1687 :
1688 1 : panEPSGCodes[0] = EPSGNatOriginLat;
1689 1 : panEPSGCodes[1] = EPSGNatOriginLong;
1690 1 : panEPSGCodes[4] = EPSGNatOriginScaleFactor;
1691 1 : panEPSGCodes[5] = EPSGFalseEasting;
1692 1 : panEPSGCodes[6] = EPSGFalseNorthing;
1693 1 : return TRUE;
1694 :
1695 : case CT_LambertConfConic_2SP:
1696 0 : panProjParmId[0] = ProjFalseOriginLatGeoKey;
1697 0 : panProjParmId[1] = ProjFalseOriginLongGeoKey;
1698 0 : panProjParmId[2] = ProjStdParallel1GeoKey;
1699 0 : panProjParmId[3] = ProjStdParallel2GeoKey;
1700 0 : panProjParmId[5] = ProjFalseEastingGeoKey;
1701 0 : panProjParmId[6] = ProjFalseNorthingGeoKey;
1702 :
1703 0 : panEPSGCodes[0] = EPSGFalseOriginLat;
1704 0 : panEPSGCodes[1] = EPSGFalseOriginLong;
1705 0 : panEPSGCodes[2] = EPSGStdParallel1Lat;
1706 0 : panEPSGCodes[3] = EPSGStdParallel2Lat;
1707 0 : panEPSGCodes[5] = EPSGFalseOriginEasting;
1708 0 : panEPSGCodes[6] = EPSGFalseOriginNorthing;
1709 0 : return TRUE;
1710 :
1711 : case CT_SwissObliqueCylindrical:
1712 0 : panProjParmId[0] = ProjCenterLatGeoKey;
1713 0 : panProjParmId[1] = ProjCenterLongGeoKey;
1714 0 : panProjParmId[5] = ProjFalseEastingGeoKey;
1715 0 : panProjParmId[6] = ProjFalseNorthingGeoKey;
1716 :
1717 : /* EPSG codes? */
1718 0 : return TRUE;
1719 :
1720 : default:
1721 0 : return( FALSE );
1722 : }
1723 : }
1724 :
1725 : static const char *papszDatumEquiv[] =
1726 : {
1727 : "Militar_Geographische_Institut",
1728 : "Militar_Geographische_Institute",
1729 : "World_Geodetic_System_1984",
1730 : "WGS_1984",
1731 : "WGS_72_Transit_Broadcast_Ephemeris",
1732 : "WGS_1972_Transit_Broadcast_Ephemeris",
1733 : "World_Geodetic_System_1972",
1734 : "WGS_1972",
1735 : "European_Terrestrial_Reference_System_89",
1736 : "European_Reference_System_1989",
1737 : NULL
1738 : };
1739 :
1740 : /************************************************************************/
1741 : /* WKTMassageDatum() */
1742 : /* */
1743 : /* Massage an EPSG datum name into WMT format. Also transform */
1744 : /* specific exception cases into WKT versions. */
1745 : /* Explicitly copied from the gt_wkt_srs.cpp. */
1746 : /************************************************************************/
1747 :
1748 9 : static void WKTMassageDatum( char ** ppszDatum )
1749 :
1750 : {
1751 : int i, j;
1752 : char *pszDatum;
1753 :
1754 : /* -------------------------------------------------------------------- */
1755 : /* First copy string and allocate with our CPLStrdup() to so we */
1756 : /* know when we are done this function we will have a CPL */
1757 : /* string, not a GTIF one. */
1758 : /* -------------------------------------------------------------------- */
1759 9 : pszDatum = CPLStrdup(*ppszDatum);
1760 9 : GTIFFreeMemory( *ppszDatum );
1761 9 : *ppszDatum = pszDatum;
1762 9 : if (pszDatum[0] == '\0')
1763 0 : return;
1764 :
1765 : /* -------------------------------------------------------------------- */
1766 : /* Translate non-alphanumeric values to underscores. */
1767 : /* -------------------------------------------------------------------- */
1768 236 : for( i = 0; pszDatum[i] != '\0'; i++ )
1769 : {
1770 227 : if( !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z')
1771 : && !(pszDatum[i] >= 'a' && pszDatum[i] <= 'z')
1772 : && !(pszDatum[i] >= '0' && pszDatum[i] <= '9') )
1773 : {
1774 27 : pszDatum[i] = '_';
1775 : }
1776 : }
1777 :
1778 : /* -------------------------------------------------------------------- */
1779 : /* Remove repeated and trailing underscores. */
1780 : /* -------------------------------------------------------------------- */
1781 227 : for( i = 1, j = 0; pszDatum[i] != '\0'; i++ )
1782 : {
1783 218 : if( pszDatum[j] == '_' && pszDatum[i] == '_' )
1784 0 : continue;
1785 :
1786 218 : pszDatum[++j] = pszDatum[i];
1787 : }
1788 9 : if( pszDatum[j] == '_' )
1789 0 : pszDatum[j] = '\0';
1790 : else
1791 9 : pszDatum[j+1] = '\0';
1792 :
1793 : /* -------------------------------------------------------------------- */
1794 : /* Search for datum equivelences. Specific massaged names get */
1795 : /* mapped to OpenGIS specified names. */
1796 : /* -------------------------------------------------------------------- */
1797 46 : for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
1798 : {
1799 39 : if( EQUAL(*ppszDatum,papszDatumEquiv[i]) )
1800 : {
1801 2 : CPLFree( *ppszDatum );
1802 2 : *ppszDatum = CPLStrdup( papszDatumEquiv[i+1] );
1803 2 : return;
1804 : }
1805 : }
1806 : }
1807 :
1808 : /************************************************************************/
1809 : /* FetchProjParms() */
1810 : /* */
1811 : /* Fetch the projection parameters for a particular projection */
1812 : /* from MrSID metadata, and fill the GTIFDefn structure out */
1813 : /* with them. */
1814 : /* Copied from geo_normalize.c of the GeoTIFF package. */
1815 : /************************************************************************/
1816 :
1817 6 : void MrSIDDataset::FetchProjParms()
1818 : {
1819 6 : double dfNatOriginLong = 0.0, dfNatOriginLat = 0.0, dfRectGridAngle = 0.0;
1820 6 : double dfFalseEasting = 0.0, dfFalseNorthing = 0.0, dfNatOriginScale = 1.0;
1821 6 : double dfStdParallel1 = 0.0, dfStdParallel2 = 0.0, dfAzimuth = 0.0;
1822 :
1823 : /* -------------------------------------------------------------------- */
1824 : /* Get the false easting, and northing if available. */
1825 : /* -------------------------------------------------------------------- */
1826 6 : if( !GetMetadataElement( "GEOTIFF_NUM::3082::ProjFalseEastingGeoKey",
1827 : &dfFalseEasting )
1828 : && !GetMetadataElement( "GEOTIFF_NUM::3090:ProjCenterEastingGeoKey",
1829 : &dfFalseEasting ) )
1830 6 : dfFalseEasting = 0.0;
1831 :
1832 6 : if( !GetMetadataElement( "GEOTIFF_NUM::3083::ProjFalseNorthingGeoKey",
1833 : &dfFalseNorthing )
1834 : && !GetMetadataElement( "GEOTIFF_NUM::3091::ProjCenterNorthingGeoKey",
1835 : &dfFalseNorthing ) )
1836 6 : dfFalseNorthing = 0.0;
1837 :
1838 6 : switch( psDefn->CTProjection )
1839 : {
1840 : /* -------------------------------------------------------------------- */
1841 : case CT_Stereographic:
1842 : /* -------------------------------------------------------------------- */
1843 0 : if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
1844 : &dfNatOriginLong ) == 0
1845 : && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
1846 : &dfNatOriginLong ) == 0
1847 : && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
1848 : &dfNatOriginLong ) == 0 )
1849 0 : dfNatOriginLong = 0.0;
1850 :
1851 0 : if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
1852 : &dfNatOriginLat ) == 0
1853 : && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
1854 : &dfNatOriginLat ) == 0
1855 : && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
1856 : &dfNatOriginLat ) == 0 )
1857 0 : dfNatOriginLat = 0.0;
1858 :
1859 0 : if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
1860 : &dfNatOriginScale ) == 0 )
1861 0 : dfNatOriginScale = 1.0;
1862 :
1863 : /* notdef: should transform to decimal degrees at this point */
1864 :
1865 0 : psDefn->ProjParm[0] = dfNatOriginLat;
1866 0 : psDefn->ProjParmId[0] = ProjCenterLatGeoKey;
1867 0 : psDefn->ProjParm[1] = dfNatOriginLong;
1868 0 : psDefn->ProjParmId[1] = ProjCenterLongGeoKey;
1869 0 : psDefn->ProjParm[4] = dfNatOriginScale;
1870 0 : psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
1871 0 : psDefn->ProjParm[5] = dfFalseEasting;
1872 0 : psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
1873 0 : psDefn->ProjParm[6] = dfFalseNorthing;
1874 0 : psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
1875 :
1876 0 : psDefn->nParms = 7;
1877 0 : break;
1878 :
1879 : /* -------------------------------------------------------------------- */
1880 : case CT_LambertConfConic_1SP:
1881 : case CT_Mercator:
1882 : case CT_ObliqueStereographic:
1883 : case CT_TransverseMercator:
1884 : case CT_TransvMercator_SouthOriented:
1885 : /* -------------------------------------------------------------------- */
1886 6 : if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
1887 : &dfNatOriginLong ) == 0
1888 : && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
1889 : &dfNatOriginLong ) == 0
1890 : && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
1891 : &dfNatOriginLong ) == 0 )
1892 6 : dfNatOriginLong = 0.0;
1893 :
1894 6 : if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
1895 : &dfNatOriginLat ) == 0
1896 : && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
1897 : &dfNatOriginLat ) == 0
1898 : && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
1899 : &dfNatOriginLat ) == 0 )
1900 6 : dfNatOriginLat = 0.0;
1901 :
1902 6 : if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
1903 : &dfNatOriginScale ) == 0 )
1904 6 : dfNatOriginScale = 1.0;
1905 :
1906 : /* notdef: should transform to decimal degrees at this point */
1907 :
1908 6 : psDefn->ProjParm[0] = dfNatOriginLat;
1909 6 : psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;
1910 6 : psDefn->ProjParm[1] = dfNatOriginLong;
1911 6 : psDefn->ProjParmId[1] = ProjNatOriginLongGeoKey;
1912 6 : psDefn->ProjParm[4] = dfNatOriginScale;
1913 6 : psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
1914 6 : psDefn->ProjParm[5] = dfFalseEasting;
1915 6 : psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
1916 6 : psDefn->ProjParm[6] = dfFalseNorthing;
1917 6 : psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
1918 :
1919 6 : psDefn->nParms = 7;
1920 6 : break;
1921 :
1922 : /* -------------------------------------------------------------------- */
1923 : case CT_ObliqueMercator: /* hotine */
1924 : /* -------------------------------------------------------------------- */
1925 0 : if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
1926 : &dfNatOriginLong ) == 0
1927 : && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
1928 : &dfNatOriginLong ) == 0
1929 : && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
1930 : &dfNatOriginLong ) == 0 )
1931 0 : dfNatOriginLong = 0.0;
1932 :
1933 0 : if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
1934 : &dfNatOriginLat ) == 0
1935 : && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
1936 : &dfNatOriginLat ) == 0
1937 : && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
1938 : &dfNatOriginLat ) == 0 )
1939 0 : dfNatOriginLat = 0.0;
1940 :
1941 0 : if( GetMetadataElement( "GEOTIFF_NUM::3094::ProjAzimuthAngleGeoKey",
1942 : &dfAzimuth ) == 0 )
1943 0 : dfAzimuth = 0.0;
1944 :
1945 0 : if( GetMetadataElement( "GEOTIFF_NUM::3096::ProjRectifiedGridAngleGeoKey",
1946 : &dfRectGridAngle ) == 0 )
1947 0 : dfRectGridAngle = 90.0;
1948 :
1949 0 : if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
1950 : &dfNatOriginScale ) == 0
1951 : && GetMetadataElement( "GEOTIFF_NUM::3093::ProjScaleAtCenterGeoKey",
1952 : &dfNatOriginScale ) == 0 )
1953 0 : dfNatOriginScale = 1.0;
1954 :
1955 : /* notdef: should transform to decimal degrees at this point */
1956 :
1957 0 : psDefn->ProjParm[0] = dfNatOriginLat;
1958 0 : psDefn->ProjParmId[0] = ProjCenterLatGeoKey;
1959 0 : psDefn->ProjParm[1] = dfNatOriginLong;
1960 0 : psDefn->ProjParmId[1] = ProjCenterLongGeoKey;
1961 0 : psDefn->ProjParm[2] = dfAzimuth;
1962 0 : psDefn->ProjParmId[2] = ProjAzimuthAngleGeoKey;
1963 0 : psDefn->ProjParm[3] = dfRectGridAngle;
1964 0 : psDefn->ProjParmId[3] = ProjRectifiedGridAngleGeoKey;
1965 0 : psDefn->ProjParm[4] = dfNatOriginScale;
1966 0 : psDefn->ProjParmId[4] = ProjScaleAtCenterGeoKey;
1967 0 : psDefn->ProjParm[5] = dfFalseEasting;
1968 0 : psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
1969 0 : psDefn->ProjParm[6] = dfFalseNorthing;
1970 0 : psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
1971 :
1972 0 : psDefn->nParms = 7;
1973 0 : break;
1974 :
1975 : /* -------------------------------------------------------------------- */
1976 : case CT_CassiniSoldner:
1977 : case CT_Polyconic:
1978 : /* -------------------------------------------------------------------- */
1979 0 : if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
1980 : &dfNatOriginLong ) == 0
1981 : && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
1982 : &dfNatOriginLong ) == 0
1983 : && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
1984 : &dfNatOriginLong ) == 0 )
1985 0 : dfNatOriginLong = 0.0;
1986 :
1987 0 : if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
1988 : &dfNatOriginLat ) == 0
1989 : && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
1990 : &dfNatOriginLat ) == 0
1991 : && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
1992 : &dfNatOriginLat ) == 0 )
1993 0 : dfNatOriginLat = 0.0;
1994 :
1995 :
1996 0 : if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
1997 : &dfNatOriginScale ) == 0
1998 : && GetMetadataElement( "GEOTIFF_NUM::3093::ProjScaleAtCenterGeoKey",
1999 : &dfNatOriginScale ) == 0 )
2000 0 : dfNatOriginScale = 1.0;
2001 :
2002 : /* notdef: should transform to decimal degrees at this point */
2003 :
2004 0 : psDefn->ProjParm[0] = dfNatOriginLat;
2005 0 : psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;
2006 0 : psDefn->ProjParm[1] = dfNatOriginLong;
2007 0 : psDefn->ProjParmId[1] = ProjNatOriginLongGeoKey;
2008 0 : psDefn->ProjParm[4] = dfNatOriginScale;
2009 0 : psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
2010 0 : psDefn->ProjParm[5] = dfFalseEasting;
2011 0 : psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
2012 0 : psDefn->ProjParm[6] = dfFalseNorthing;
2013 0 : psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
2014 :
2015 0 : psDefn->nParms = 7;
2016 0 : break;
2017 :
2018 : /* -------------------------------------------------------------------- */
2019 : case CT_AzimuthalEquidistant:
2020 : case CT_MillerCylindrical:
2021 : case CT_Equirectangular:
2022 : case CT_Gnomonic:
2023 : case CT_LambertAzimEqualArea:
2024 : case CT_Orthographic:
2025 : /* -------------------------------------------------------------------- */
2026 0 : if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
2027 : &dfNatOriginLong ) == 0
2028 : && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
2029 : &dfNatOriginLong ) == 0
2030 : && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
2031 : &dfNatOriginLong ) == 0 )
2032 0 : dfNatOriginLong = 0.0;
2033 :
2034 0 : if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
2035 : &dfNatOriginLat ) == 0
2036 : && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
2037 : &dfNatOriginLat ) == 0
2038 : && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
2039 : &dfNatOriginLat ) == 0 )
2040 0 : dfNatOriginLat = 0.0;
2041 :
2042 : /* notdef: should transform to decimal degrees at this point */
2043 :
2044 0 : psDefn->ProjParm[0] = dfNatOriginLat;
2045 0 : psDefn->ProjParmId[0] = ProjCenterLatGeoKey;
2046 0 : psDefn->ProjParm[1] = dfNatOriginLong;
2047 0 : psDefn->ProjParmId[1] = ProjCenterLongGeoKey;
2048 0 : psDefn->ProjParm[5] = dfFalseEasting;
2049 0 : psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
2050 0 : psDefn->ProjParm[6] = dfFalseNorthing;
2051 0 : psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
2052 :
2053 0 : psDefn->nParms = 7;
2054 0 : break;
2055 :
2056 : /* -------------------------------------------------------------------- */
2057 : case CT_Robinson:
2058 : case CT_Sinusoidal:
2059 : case CT_VanDerGrinten:
2060 : /* -------------------------------------------------------------------- */
2061 0 : if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
2062 : &dfNatOriginLong ) == 0
2063 : && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
2064 : &dfNatOriginLong ) == 0
2065 : && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
2066 : &dfNatOriginLong ) == 0 )
2067 0 : dfNatOriginLong = 0.0;
2068 :
2069 : /* notdef: should transform to decimal degrees at this point */
2070 :
2071 0 : psDefn->ProjParm[1] = dfNatOriginLong;
2072 0 : psDefn->ProjParmId[1] = ProjCenterLongGeoKey;
2073 0 : psDefn->ProjParm[5] = dfFalseEasting;
2074 0 : psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
2075 0 : psDefn->ProjParm[6] = dfFalseNorthing;
2076 0 : psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
2077 :
2078 0 : psDefn->nParms = 7;
2079 0 : break;
2080 :
2081 : /* -------------------------------------------------------------------- */
2082 : case CT_PolarStereographic:
2083 : /* -------------------------------------------------------------------- */
2084 0 : if( GetMetadataElement( "GEOTIFF_NUM::3095::ProjStraightVertPoleLongGeoKey",
2085 : &dfNatOriginLong ) == 0
2086 : && GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
2087 : &dfNatOriginLong ) == 0
2088 : && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
2089 : &dfNatOriginLong ) == 0
2090 : && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
2091 : &dfNatOriginLong ) == 0 )
2092 0 : dfNatOriginLong = 0.0;
2093 :
2094 0 : if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
2095 : &dfNatOriginLat ) == 0
2096 : && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
2097 : &dfNatOriginLat ) == 0
2098 : && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
2099 : &dfNatOriginLat ) == 0 )
2100 0 : dfNatOriginLat = 0.0;
2101 :
2102 0 : if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
2103 : &dfNatOriginScale ) == 0
2104 : && GetMetadataElement( "GEOTIFF_NUM::3093::ProjScaleAtCenterGeoKey",
2105 : &dfNatOriginScale ) == 0 )
2106 0 : dfNatOriginScale = 1.0;
2107 :
2108 : /* notdef: should transform to decimal degrees at this point */
2109 :
2110 0 : psDefn->ProjParm[0] = dfNatOriginLat;
2111 0 : psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;;
2112 0 : psDefn->ProjParm[1] = dfNatOriginLong;
2113 0 : psDefn->ProjParmId[1] = ProjStraightVertPoleLongGeoKey;
2114 0 : psDefn->ProjParm[4] = dfNatOriginScale;
2115 0 : psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
2116 0 : psDefn->ProjParm[5] = dfFalseEasting;
2117 0 : psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
2118 0 : psDefn->ProjParm[6] = dfFalseNorthing;
2119 0 : psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
2120 :
2121 0 : psDefn->nParms = 7;
2122 0 : break;
2123 :
2124 : /* -------------------------------------------------------------------- */
2125 : case CT_LambertConfConic_2SP:
2126 : /* -------------------------------------------------------------------- */
2127 0 : if( GetMetadataElement( "GEOTIFF_NUM::3078::ProjStdParallel1GeoKey",
2128 : &dfStdParallel1 ) == 0 )
2129 0 : dfStdParallel1 = 0.0;
2130 :
2131 0 : if( GetMetadataElement( "GEOTIFF_NUM::3079::ProjStdParallel2GeoKey",
2132 : &dfStdParallel2 ) == 0 )
2133 0 : dfStdParallel1 = 0.0;
2134 :
2135 0 : if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
2136 : &dfNatOriginLong ) == 0
2137 : && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
2138 : &dfNatOriginLong ) == 0
2139 : && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
2140 : &dfNatOriginLong ) == 0 )
2141 0 : dfNatOriginLong = 0.0;
2142 :
2143 0 : if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
2144 : &dfNatOriginLat ) == 0
2145 : && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
2146 : &dfNatOriginLat ) == 0
2147 : && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
2148 : &dfNatOriginLat ) == 0 )
2149 0 : dfNatOriginLat = 0.0;
2150 :
2151 : /* notdef: should transform to decimal degrees at this point */
2152 :
2153 0 : psDefn->ProjParm[0] = dfNatOriginLat;
2154 0 : psDefn->ProjParmId[0] = ProjFalseOriginLatGeoKey;
2155 0 : psDefn->ProjParm[1] = dfNatOriginLong;
2156 0 : psDefn->ProjParmId[1] = ProjFalseOriginLongGeoKey;
2157 0 : psDefn->ProjParm[2] = dfStdParallel1;
2158 0 : psDefn->ProjParmId[2] = ProjStdParallel1GeoKey;
2159 0 : psDefn->ProjParm[3] = dfStdParallel2;
2160 0 : psDefn->ProjParmId[3] = ProjStdParallel2GeoKey;
2161 0 : psDefn->ProjParm[5] = dfFalseEasting;
2162 0 : psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
2163 0 : psDefn->ProjParm[6] = dfFalseNorthing;
2164 0 : psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
2165 :
2166 0 : psDefn->nParms = 7;
2167 0 : break;
2168 :
2169 : /* -------------------------------------------------------------------- */
2170 : case CT_AlbersEqualArea:
2171 : case CT_EquidistantConic:
2172 : /* -------------------------------------------------------------------- */
2173 0 : if( GetMetadataElement( "GEOTIFF_NUM::3078::ProjStdParallel1GeoKey",
2174 : &dfStdParallel1 ) == 0 )
2175 0 : dfStdParallel1 = 0.0;
2176 :
2177 0 : if( GetMetadataElement( "GEOTIFF_NUM::3079::ProjStdParallel2GeoKey",
2178 : &dfStdParallel2 ) == 0 )
2179 0 : dfStdParallel1 = 0.0;
2180 :
2181 0 : if( GetMetadataElement( "GEOTIFF_NUM::3080::ProjNatOriginLongGeoKey",
2182 : &dfNatOriginLong ) == 0
2183 : && GetMetadataElement( "GEOTIFF_NUM::3084::ProjFalseOriginLongGeoKey",
2184 : &dfNatOriginLong ) == 0
2185 : && GetMetadataElement( "GEOTIFF_NUM::3088::ProjCenterLongGeoKey",
2186 : &dfNatOriginLong ) == 0 )
2187 0 : dfNatOriginLong = 0.0;
2188 :
2189 0 : if( GetMetadataElement( "GEOTIFF_NUM::3081::ProjNatOriginLatGeoKey",
2190 : &dfNatOriginLat ) == 0
2191 : && GetMetadataElement( "GEOTIFF_NUM::3085::ProjFalseOriginLatGeoKey",
2192 : &dfNatOriginLat ) == 0
2193 : && GetMetadataElement( "GEOTIFF_NUM::3089::ProjCenterLatGeoKey",
2194 : &dfNatOriginLat ) == 0 )
2195 0 : dfNatOriginLat = 0.0;
2196 :
2197 : /* notdef: should transform to decimal degrees at this point */
2198 :
2199 0 : psDefn->ProjParm[0] = dfStdParallel1;
2200 0 : psDefn->ProjParmId[0] = ProjStdParallel1GeoKey;
2201 0 : psDefn->ProjParm[1] = dfStdParallel2;
2202 0 : psDefn->ProjParmId[1] = ProjStdParallel2GeoKey;
2203 0 : psDefn->ProjParm[2] = dfNatOriginLat;
2204 0 : psDefn->ProjParmId[2] = ProjNatOriginLatGeoKey;
2205 0 : psDefn->ProjParm[3] = dfNatOriginLong;
2206 0 : psDefn->ProjParmId[3] = ProjNatOriginLongGeoKey;
2207 0 : psDefn->ProjParm[5] = dfFalseEasting;
2208 0 : psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
2209 0 : psDefn->ProjParm[6] = dfFalseNorthing;
2210 0 : psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
2211 :
2212 0 : psDefn->nParms = 7;
2213 : break;
2214 : }
2215 6 : }
2216 :
2217 : /************************************************************************/
2218 : /* GetGTIFDefn() */
2219 : /* This function borrowed from the GTIFGetDefn() function. */
2220 : /* See geo_normalize.c from the GeoTIFF package. */
2221 : /************************************************************************/
2222 :
2223 19 : void MrSIDDataset::GetGTIFDefn()
2224 : {
2225 : double dfInvFlattening;
2226 :
2227 : /* -------------------------------------------------------------------- */
2228 : /* Initially we default all the information we can. */
2229 : /* -------------------------------------------------------------------- */
2230 19 : psDefn = new( GTIFDefn );
2231 19 : psDefn->Model = KvUserDefined;
2232 19 : psDefn->PCS = KvUserDefined;
2233 19 : psDefn->GCS = KvUserDefined;
2234 19 : psDefn->UOMLength = KvUserDefined;
2235 19 : psDefn->UOMLengthInMeters = 1.0;
2236 19 : psDefn->UOMAngle = KvUserDefined;
2237 19 : psDefn->UOMAngleInDegrees = 1.0;
2238 19 : psDefn->Datum = KvUserDefined;
2239 19 : psDefn->Ellipsoid = KvUserDefined;
2240 19 : psDefn->SemiMajor = 0.0;
2241 19 : psDefn->SemiMinor = 0.0;
2242 19 : psDefn->PM = KvUserDefined;
2243 19 : psDefn->PMLongToGreenwich = 0.0;
2244 :
2245 19 : psDefn->ProjCode = KvUserDefined;
2246 19 : psDefn->Projection = KvUserDefined;
2247 19 : psDefn->CTProjection = KvUserDefined;
2248 :
2249 19 : psDefn->nParms = 0;
2250 209 : for( int i = 0; i < MAX_GTIF_PROJPARMS; i++ )
2251 : {
2252 190 : psDefn->ProjParm[i] = 0.0;
2253 190 : psDefn->ProjParmId[i] = 0;
2254 : }
2255 :
2256 19 : psDefn->MapSys = KvUserDefined;
2257 19 : psDefn->Zone = 0;
2258 :
2259 : /* -------------------------------------------------------------------- */
2260 : /* Try to get the overall model type. */
2261 : /* -------------------------------------------------------------------- */
2262 : GetMetadataElement( "GEOTIFF_NUM::1024::GTModelTypeGeoKey",
2263 19 : &(psDefn->Model) );
2264 :
2265 : /* -------------------------------------------------------------------- */
2266 : /* Try to get a PCS. */
2267 : /* -------------------------------------------------------------------- */
2268 19 : if( GetMetadataElement( "GEOTIFF_NUM::3072::ProjectedCSTypeGeoKey",
2269 : &(psDefn->PCS) )
2270 : && psDefn->PCS != KvUserDefined )
2271 : {
2272 : /*
2273 : * Translate this into useful information.
2274 : */
2275 : GTIFGetPCSInfo( psDefn->PCS, NULL, &(psDefn->ProjCode),
2276 1 : &(psDefn->UOMLength), &(psDefn->GCS) );
2277 : }
2278 :
2279 : /* -------------------------------------------------------------------- */
2280 : /* If we have the PCS code, but didn't find it in the CSV files */
2281 : /* (likely because we can't find them) we will try some ``jiffy */
2282 : /* rules'' for UTM and state plane. */
2283 : /* -------------------------------------------------------------------- */
2284 19 : if( psDefn->PCS != KvUserDefined && psDefn->ProjCode == KvUserDefined )
2285 : {
2286 : int nMapSys, nZone;
2287 0 : int nGCS = psDefn->GCS;
2288 :
2289 0 : nMapSys = GTIFPCSToMapSys( psDefn->PCS, &nGCS, &nZone );
2290 0 : if( nMapSys != KvUserDefined )
2291 : {
2292 0 : psDefn->ProjCode = (short) GTIFMapSysToProj( nMapSys, nZone );
2293 0 : psDefn->GCS = (short) nGCS;
2294 : }
2295 : }
2296 :
2297 : /* -------------------------------------------------------------------- */
2298 : /* If the Proj_ code is specified directly, use that. */
2299 : /* -------------------------------------------------------------------- */
2300 19 : if( psDefn->ProjCode == KvUserDefined )
2301 : GetMetadataElement( "GEOTIFF_NUM::3074::ProjectionGeoKey",
2302 18 : &(psDefn->ProjCode) );
2303 :
2304 19 : if( psDefn->ProjCode != KvUserDefined )
2305 : {
2306 : /*
2307 : * We have an underlying projection transformation value. Look
2308 : * this up. For a PCS of ``WGS 84 / UTM 11'' the transformation
2309 : * would be Transverse Mercator, with a particular set of options.
2310 : * The nProjTRFCode itself would correspond to the name
2311 : * ``UTM zone 11N'', and doesn't include datum info.
2312 : */
2313 : GTIFGetProjTRFInfo( psDefn->ProjCode, NULL, &(psDefn->Projection),
2314 1 : psDefn->ProjParm );
2315 :
2316 : /*
2317 : * Set the GeoTIFF identity of the parameters.
2318 : */
2319 : psDefn->CTProjection = (short)
2320 1 : EPSGProjMethodToCTProjMethod( psDefn->Projection );
2321 :
2322 1 : SetGTParmIds( psDefn->CTProjection, psDefn->ProjParmId, NULL);
2323 1 : psDefn->nParms = 7;
2324 : }
2325 :
2326 : /* -------------------------------------------------------------------- */
2327 : /* Try to get a GCS. If found, it will override any implied by */
2328 : /* the PCS. */
2329 : /* -------------------------------------------------------------------- */
2330 : GetMetadataElement( "GEOTIFF_NUM::2048::GeographicTypeGeoKey",
2331 19 : &(psDefn->GCS) );
2332 :
2333 : /* -------------------------------------------------------------------- */
2334 : /* Derive the datum, and prime meridian from the GCS. */
2335 : /* -------------------------------------------------------------------- */
2336 19 : if( psDefn->GCS != KvUserDefined )
2337 : {
2338 : GTIFGetGCSInfo( psDefn->GCS, NULL, &(psDefn->Datum), &(psDefn->PM),
2339 9 : &(psDefn->UOMAngle) );
2340 : }
2341 :
2342 : /* -------------------------------------------------------------------- */
2343 : /* Handle the GCS angular units. GeogAngularUnitsGeoKey */
2344 : /* overrides the GCS or PCS setting. */
2345 : /* -------------------------------------------------------------------- */
2346 : GetMetadataElement( "GEOTIFF_NUM::2054::GeogAngularUnitsGeoKey",
2347 19 : &(psDefn->UOMAngle) );
2348 19 : if( psDefn->UOMAngle != KvUserDefined )
2349 : {
2350 : GTIFGetUOMAngleInfo( psDefn->UOMAngle, NULL,
2351 9 : &(psDefn->UOMAngleInDegrees) );
2352 : }
2353 :
2354 : /* -------------------------------------------------------------------- */
2355 : /* Check for a datum setting, and then use the datum to derive */
2356 : /* an ellipsoid. */
2357 : /* -------------------------------------------------------------------- */
2358 : GetMetadataElement( "GEOTIFF_NUM::2050::GeogGeodeticDatumGeoKey",
2359 19 : &(psDefn->Datum) );
2360 :
2361 19 : if( psDefn->Datum != KvUserDefined )
2362 : {
2363 9 : GTIFGetDatumInfo( psDefn->Datum, NULL, &(psDefn->Ellipsoid) );
2364 : }
2365 :
2366 : /* -------------------------------------------------------------------- */
2367 : /* Check for an explicit ellipsoid. Use the ellipsoid to */
2368 : /* derive the ellipsoid characteristics, if possible. */
2369 : /* -------------------------------------------------------------------- */
2370 : GetMetadataElement( "GEOTIFF_NUM::2056::GeogEllipsoidGeoKey",
2371 19 : &(psDefn->Ellipsoid) );
2372 :
2373 19 : if( psDefn->Ellipsoid != KvUserDefined )
2374 : {
2375 : GTIFGetEllipsoidInfo( psDefn->Ellipsoid, NULL,
2376 9 : &(psDefn->SemiMajor), &(psDefn->SemiMinor) );
2377 : }
2378 :
2379 : /* -------------------------------------------------------------------- */
2380 : /* Check for overridden ellipsoid parameters. It would be nice */
2381 : /* to warn if they conflict with provided information, but for */
2382 : /* now we just override. */
2383 : /* -------------------------------------------------------------------- */
2384 : GetMetadataElement( "GEOTIFF_NUM::2057::GeogSemiMajorAxisGeoKey",
2385 19 : &(psDefn->SemiMajor) );
2386 : GetMetadataElement( "GEOTIFF_NUM::2058::GeogSemiMinorAxisGeoKey",
2387 19 : &(psDefn->SemiMinor) );
2388 :
2389 19 : if( GetMetadataElement( "GEOTIFF_NUM::2059::GeogInvFlatteningGeoKey",
2390 : &dfInvFlattening ) == 1 )
2391 : {
2392 0 : if( dfInvFlattening != 0.0 )
2393 : psDefn->SemiMinor =
2394 0 : psDefn->SemiMajor * (1 - 1.0/dfInvFlattening);
2395 : }
2396 :
2397 : /* -------------------------------------------------------------------- */
2398 : /* Get the prime meridian info. */
2399 : /* -------------------------------------------------------------------- */
2400 : GetMetadataElement( "GEOTIFF_NUM::2051::GeogPrimeMeridianGeoKey",
2401 19 : &(psDefn->PM) );
2402 :
2403 19 : if( psDefn->PM != KvUserDefined )
2404 : {
2405 9 : GTIFGetPMInfo( psDefn->PM, NULL, &(psDefn->PMLongToGreenwich) );
2406 : }
2407 : else
2408 : {
2409 : GetMetadataElement( "GEOTIFF_NUM::2061::GeogPrimeMeridianLongGeoKey",
2410 10 : &(psDefn->PMLongToGreenwich) );
2411 :
2412 : psDefn->PMLongToGreenwich =
2413 : GTIFAngleToDD( psDefn->PMLongToGreenwich,
2414 10 : psDefn->UOMAngle );
2415 : }
2416 :
2417 : /* -------------------------------------------------------------------- */
2418 : /* Have the projection units of measure been overridden? We */
2419 : /* should likely be doing something about angular units too, */
2420 : /* but these are very rarely not decimal degrees for actual */
2421 : /* file coordinates. */
2422 : /* -------------------------------------------------------------------- */
2423 : GetMetadataElement( "GEOTIFF_NUM::3076::ProjLinearUnitsGeoKey",
2424 19 : &(psDefn->UOMLength) );
2425 :
2426 19 : if( psDefn->UOMLength != KvUserDefined )
2427 : {
2428 : GTIFGetUOMLengthInfo( psDefn->UOMLength, NULL,
2429 7 : &(psDefn->UOMLengthInMeters) );
2430 : }
2431 :
2432 : /* -------------------------------------------------------------------- */
2433 : /* Handle a variety of user defined transform types. */
2434 : /* -------------------------------------------------------------------- */
2435 19 : if( GetMetadataElement( "GEOTIFF_NUM::3075::ProjCoordTransGeoKey",
2436 : &(psDefn->CTProjection) ) )
2437 : {
2438 6 : FetchProjParms();
2439 : }
2440 :
2441 : /* -------------------------------------------------------------------- */
2442 : /* Try to set the zoned map system information. */
2443 : /* -------------------------------------------------------------------- */
2444 19 : psDefn->MapSys = GTIFProjToMapSys( psDefn->ProjCode, &(psDefn->Zone) );
2445 :
2446 : /* -------------------------------------------------------------------- */
2447 : /* If this is UTM, and we were unable to extract the projection */
2448 : /* parameters from the CSV file, just set them directly now, */
2449 : /* since it's pretty easy, and a common case. */
2450 : /* -------------------------------------------------------------------- */
2451 19 : if( (psDefn->MapSys == MapSys_UTM_North
2452 : || psDefn->MapSys == MapSys_UTM_South)
2453 : && psDefn->CTProjection == KvUserDefined )
2454 : {
2455 0 : psDefn->CTProjection = CT_TransverseMercator;
2456 0 : psDefn->nParms = 7;
2457 0 : psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;
2458 0 : psDefn->ProjParm[0] = 0.0;
2459 :
2460 0 : psDefn->ProjParmId[1] = ProjNatOriginLongGeoKey;
2461 0 : psDefn->ProjParm[1] = psDefn->Zone*6 - 183.0;
2462 :
2463 0 : psDefn->ProjParmId[4] = ProjScaleAtNatOriginGeoKey;
2464 0 : psDefn->ProjParm[4] = 0.9996;
2465 :
2466 0 : psDefn->ProjParmId[5] = ProjFalseEastingGeoKey;
2467 0 : psDefn->ProjParm[5] = 500000.0;
2468 :
2469 0 : psDefn->ProjParmId[6] = ProjFalseNorthingGeoKey;
2470 :
2471 0 : if( psDefn->MapSys == MapSys_UTM_North )
2472 0 : psDefn->ProjParm[6] = 0.0;
2473 : else
2474 0 : psDefn->ProjParm[6] = 10000000.0;
2475 : }
2476 :
2477 19 : if ( pszProjection )
2478 19 : CPLFree( pszProjection );
2479 19 : pszProjection = GetOGISDefn( psDefn );
2480 19 : }
2481 :
2482 : /************************************************************************/
2483 : /* GetOGISDefn() */
2484 : /* Copied from the gt_wkt_srs.cpp. */
2485 : /************************************************************************/
2486 :
2487 19 : char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefn )
2488 : {
2489 19 : OGRSpatialReference oSRS;
2490 :
2491 19 : if( psDefn->Model != ModelTypeProjected
2492 : && psDefn->Model != ModelTypeGeographic )
2493 10 : return CPLStrdup("");
2494 :
2495 : /* -------------------------------------------------------------------- */
2496 : /* If this is a projected SRS we set the PROJCS keyword first */
2497 : /* to ensure that the GEOGCS will be a child. */
2498 : /* -------------------------------------------------------------------- */
2499 9 : if( psDefn->Model == ModelTypeProjected )
2500 : {
2501 : char *pszPCSName;
2502 7 : int bPCSNameSet = FALSE;
2503 :
2504 7 : if( psDefn->PCS != KvUserDefined )
2505 : {
2506 :
2507 1 : if( GTIFGetPCSInfo( psDefn->PCS, &pszPCSName, NULL, NULL, NULL ) )
2508 1 : bPCSNameSet = TRUE;
2509 :
2510 1 : oSRS.SetNode( "PROJCS", bPCSNameSet ? pszPCSName : "unnamed" );
2511 1 : if( bPCSNameSet )
2512 1 : GTIFFreeMemory( pszPCSName );
2513 :
2514 1 : oSRS.SetAuthority( "PROJCS", "EPSG", psDefn->PCS );
2515 : }
2516 : else
2517 : {
2518 : char szPCSName[200];
2519 6 : strcpy( szPCSName, "unnamed" );
2520 6 : if ( GetMetadataElement( "GEOTIFF_NUM::1026::GTCitationGeoKey",
2521 : szPCSName, sizeof(szPCSName) ) )
2522 6 : oSRS.SetNode( "PROJCS", szPCSName );
2523 : }
2524 : }
2525 :
2526 : /* ==================================================================== */
2527 : /* Setup the GeogCS */
2528 : /* ==================================================================== */
2529 9 : char *pszGeogName = NULL;
2530 9 : char *pszDatumName = NULL;
2531 9 : char *pszPMName = NULL;
2532 9 : char *pszSpheroidName = NULL;
2533 9 : char *pszAngularUnits = NULL;
2534 : double dfInvFlattening, dfSemiMajor;
2535 : char szGCSName[200];
2536 :
2537 9 : if( GetMetadataElement( "GEOTIFF_NUM::2049::GeogCitationGeoKey",
2538 : szGCSName, sizeof(szGCSName) ) )
2539 0 : pszGeogName = CPLStrdup(szGCSName);
2540 9 : GTIFGetGCSInfo( psDefn->GCS, &pszGeogName, NULL, NULL, NULL );
2541 9 : GTIFGetDatumInfo( psDefn->Datum, &pszDatumName, NULL );
2542 9 : GTIFGetPMInfo( psDefn->PM, &pszPMName, NULL );
2543 9 : GTIFGetEllipsoidInfo( psDefn->Ellipsoid, &pszSpheroidName, NULL, NULL );
2544 :
2545 9 : GTIFGetUOMAngleInfo( psDefn->UOMAngle, &pszAngularUnits, NULL );
2546 9 : if( pszAngularUnits == NULL )
2547 0 : pszAngularUnits = CPLStrdup("unknown");
2548 :
2549 9 : if( pszDatumName != NULL )
2550 9 : WKTMassageDatum( &pszDatumName );
2551 :
2552 9 : dfSemiMajor = psDefn->SemiMajor;
2553 9 : if( psDefn->SemiMajor == 0.0 )
2554 : {
2555 0 : pszSpheroidName = CPLStrdup("unretrievable - using WGS84");
2556 0 : dfSemiMajor = SRS_WGS84_SEMIMAJOR;
2557 0 : dfInvFlattening = SRS_WGS84_INVFLATTENING;
2558 : }
2559 18 : else if( (psDefn->SemiMinor / psDefn->SemiMajor) < 0.99999999999999999
2560 : || (psDefn->SemiMinor / psDefn->SemiMajor) > 1.00000000000000001 )
2561 9 : dfInvFlattening = -1.0 / (psDefn->SemiMinor/psDefn->SemiMajor - 1.0);
2562 : else
2563 0 : dfInvFlattening = 0.0; /* special flag for infinity */
2564 :
2565 : oSRS.SetGeogCS( pszGeogName, pszDatumName,
2566 : pszSpheroidName, dfSemiMajor, dfInvFlattening,
2567 : pszPMName,
2568 : psDefn->PMLongToGreenwich / psDefn->UOMAngleInDegrees,
2569 : pszAngularUnits,
2570 9 : psDefn->UOMAngleInDegrees * 0.0174532925199433 );
2571 :
2572 9 : if( psDefn->GCS != KvUserDefined )
2573 9 : oSRS.SetAuthority( "GEOGCS", "EPSG", psDefn->GCS );
2574 :
2575 9 : if( psDefn->Datum != KvUserDefined )
2576 9 : oSRS.SetAuthority( "DATUM", "EPSG", psDefn->Datum );
2577 :
2578 9 : if( psDefn->Ellipsoid != KvUserDefined )
2579 9 : oSRS.SetAuthority( "SPHEROID", "EPSG", psDefn->Ellipsoid );
2580 :
2581 9 : GTIFFreeMemory( pszGeogName );
2582 9 : CPLFree( pszDatumName );
2583 9 : GTIFFreeMemory( pszPMName );
2584 9 : GTIFFreeMemory( pszSpheroidName );
2585 9 : GTIFFreeMemory( pszAngularUnits );
2586 :
2587 : /* ==================================================================== */
2588 : /* Handle projection parameters. */
2589 : /* ==================================================================== */
2590 9 : if( psDefn->Model == ModelTypeProjected )
2591 : {
2592 : /* -------------------------------------------------------------------- */
2593 : /* Make a local copy of parms, and convert back into the */
2594 : /* angular units of the GEOGCS and the linear units of the */
2595 : /* projection. */
2596 : /* -------------------------------------------------------------------- */
2597 : double adfParm[10];
2598 : int i;
2599 :
2600 56 : for( i = 0; i < MIN(10,psDefn->nParms); i++ )
2601 49 : adfParm[i] = psDefn->ProjParm[i];
2602 :
2603 7 : adfParm[0] /= psDefn->UOMAngleInDegrees;
2604 7 : adfParm[1] /= psDefn->UOMAngleInDegrees;
2605 7 : adfParm[2] /= psDefn->UOMAngleInDegrees;
2606 7 : adfParm[3] /= psDefn->UOMAngleInDegrees;
2607 :
2608 7 : adfParm[5] /= psDefn->UOMLengthInMeters;
2609 7 : adfParm[6] /= psDefn->UOMLengthInMeters;
2610 :
2611 : /* -------------------------------------------------------------------- */
2612 : /* Translation the fundamental projection. */
2613 : /* -------------------------------------------------------------------- */
2614 7 : switch( psDefn->CTProjection )
2615 : {
2616 : case CT_TransverseMercator:
2617 : oSRS.SetTM( adfParm[0], adfParm[1],
2618 : adfParm[4],
2619 1 : adfParm[5], adfParm[6] );
2620 1 : break;
2621 :
2622 : case CT_TransvMercator_SouthOriented:
2623 : oSRS.SetTMSO( adfParm[0], adfParm[1],
2624 : adfParm[4],
2625 0 : adfParm[5], adfParm[6] );
2626 0 : break;
2627 :
2628 : case CT_Mercator:
2629 : oSRS.SetMercator( adfParm[0], adfParm[1],
2630 : adfParm[4],
2631 6 : adfParm[5], adfParm[6] );
2632 6 : break;
2633 :
2634 : case CT_ObliqueStereographic:
2635 : oSRS.SetOS( adfParm[0], adfParm[1],
2636 : adfParm[4],
2637 0 : adfParm[5], adfParm[6] );
2638 0 : break;
2639 :
2640 : case CT_Stereographic:
2641 : oSRS.SetOS( adfParm[0], adfParm[1],
2642 : adfParm[4],
2643 0 : adfParm[5], adfParm[6] );
2644 0 : break;
2645 :
2646 : case CT_ObliqueMercator: /* hotine */
2647 : oSRS.SetHOM( adfParm[0], adfParm[1],
2648 : adfParm[2], adfParm[3],
2649 : adfParm[4],
2650 0 : adfParm[5], adfParm[6] );
2651 0 : break;
2652 :
2653 : case CT_EquidistantConic:
2654 : oSRS.SetEC( adfParm[0], adfParm[1],
2655 : adfParm[2], adfParm[3],
2656 0 : adfParm[5], adfParm[6] );
2657 0 : break;
2658 :
2659 : case CT_CassiniSoldner:
2660 : oSRS.SetCS( adfParm[0], adfParm[1],
2661 0 : adfParm[5], adfParm[6] );
2662 0 : break;
2663 :
2664 : case CT_Polyconic:
2665 : oSRS.SetPolyconic( adfParm[0], adfParm[1],
2666 0 : adfParm[5], adfParm[6] );
2667 0 : break;
2668 :
2669 : case CT_AzimuthalEquidistant:
2670 : oSRS.SetAE( adfParm[0], adfParm[1],
2671 0 : adfParm[5], adfParm[6] );
2672 0 : break;
2673 :
2674 : case CT_MillerCylindrical:
2675 : oSRS.SetMC( adfParm[0], adfParm[1],
2676 0 : adfParm[5], adfParm[6] );
2677 0 : break;
2678 :
2679 : case CT_Equirectangular:
2680 : oSRS.SetEquirectangular( adfParm[0], adfParm[1],
2681 0 : adfParm[5], adfParm[6] );
2682 0 : break;
2683 :
2684 : case CT_Gnomonic:
2685 : oSRS.SetGnomonic( adfParm[0], adfParm[1],
2686 0 : adfParm[5], adfParm[6] );
2687 0 : break;
2688 :
2689 : case CT_LambertAzimEqualArea:
2690 : oSRS.SetLAEA( adfParm[0], adfParm[1],
2691 0 : adfParm[5], adfParm[6] );
2692 0 : break;
2693 :
2694 : case CT_Orthographic:
2695 : oSRS.SetOrthographic( adfParm[0], adfParm[1],
2696 0 : adfParm[5], adfParm[6] );
2697 0 : break;
2698 :
2699 : case CT_Robinson:
2700 : oSRS.SetRobinson( adfParm[1],
2701 0 : adfParm[5], adfParm[6] );
2702 0 : break;
2703 :
2704 : case CT_Sinusoidal:
2705 : oSRS.SetSinusoidal( adfParm[1],
2706 0 : adfParm[5], adfParm[6] );
2707 0 : break;
2708 :
2709 : case CT_VanDerGrinten:
2710 : oSRS.SetVDG( adfParm[1],
2711 0 : adfParm[5], adfParm[6] );
2712 0 : break;
2713 :
2714 : case CT_PolarStereographic:
2715 : oSRS.SetPS( adfParm[0], adfParm[1],
2716 : adfParm[4],
2717 0 : adfParm[5], adfParm[6] );
2718 0 : break;
2719 :
2720 : case CT_LambertConfConic_2SP:
2721 : oSRS.SetLCC( adfParm[2], adfParm[3],
2722 : adfParm[0], adfParm[1],
2723 0 : adfParm[5], adfParm[6] );
2724 0 : break;
2725 :
2726 : case CT_LambertConfConic_1SP:
2727 : oSRS.SetLCC1SP( adfParm[0], adfParm[1],
2728 : adfParm[4],
2729 0 : adfParm[5], adfParm[6] );
2730 0 : break;
2731 :
2732 : case CT_AlbersEqualArea:
2733 : oSRS.SetACEA( adfParm[0], adfParm[1],
2734 : adfParm[2], adfParm[3],
2735 0 : adfParm[5], adfParm[6] );
2736 0 : break;
2737 :
2738 : case CT_NewZealandMapGrid:
2739 : oSRS.SetNZMG( adfParm[0], adfParm[1],
2740 0 : adfParm[5], adfParm[6] );
2741 : break;
2742 : }
2743 :
2744 : /* -------------------------------------------------------------------- */
2745 : /* Set projection units. */
2746 : /* -------------------------------------------------------------------- */
2747 7 : char *pszUnitsName = NULL;
2748 :
2749 7 : GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
2750 :
2751 14 : if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
2752 : {
2753 7 : oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
2754 7 : oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", psDefn->UOMLength );
2755 : }
2756 : else
2757 0 : oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
2758 :
2759 7 : GTIFFreeMemory( pszUnitsName );
2760 : }
2761 :
2762 : /* -------------------------------------------------------------------- */
2763 : /* Return the WKT serialization of the object. */
2764 : /* -------------------------------------------------------------------- */
2765 : char *pszWKT;
2766 :
2767 9 : oSRS.FixupOrdering();
2768 :
2769 9 : if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
2770 9 : return pszWKT;
2771 : else
2772 0 : return NULL;
2773 : }
2774 :
2775 : #ifdef MRSID_ESDK
2776 :
2777 : /************************************************************************/
2778 : /* ==================================================================== */
2779 : /* MrSIDDummyImageReader */
2780 : /* */
2781 : /* This is a helper class to wrap GDAL calls in MrSID interface. */
2782 : /* ==================================================================== */
2783 : /************************************************************************/
2784 :
2785 : class MrSIDDummyImageReader : public LTIImageReader
2786 : {
2787 : public:
2788 :
2789 : MrSIDDummyImageReader( GDALDataset *poSrcDS );
2790 : ~MrSIDDummyImageReader();
2791 : LT_STATUS initialize();
2792 : lt_int64 getPhysicalFileSize(void) const { return 0; };
2793 :
2794 : private:
2795 : GDALDataset *poDS;
2796 : GDALDataType eDataType;
2797 : LTIDataType eSampleType;
2798 : const LTIPixel *poPixel;
2799 :
2800 : double adfGeoTransform[6];
2801 :
2802 : virtual LT_STATUS decodeStrip( LTISceneBuffer& stripBuffer,
2803 : const LTIScene& stripScene );
2804 : virtual LT_STATUS decodeBegin( const LTIScene& scene )
2805 : { return LT_STS_Success; };
2806 : virtual LT_STATUS decodeEnd() { return LT_STS_Success; };
2807 : };
2808 :
2809 : /************************************************************************/
2810 : /* MrSIDDummyImageReader() */
2811 : /************************************************************************/
2812 :
2813 : MrSIDDummyImageReader::MrSIDDummyImageReader( GDALDataset *poSrcDS ) :
2814 : LTIImageReader(), poDS(poSrcDS)
2815 : {
2816 : poPixel = NULL;
2817 : }
2818 :
2819 : /************************************************************************/
2820 : /* ~MrSIDDummyImageReader() */
2821 : /************************************************************************/
2822 :
2823 : MrSIDDummyImageReader::~MrSIDDummyImageReader()
2824 : {
2825 : if ( poPixel )
2826 : delete poPixel;
2827 : }
2828 :
2829 : /************************************************************************/
2830 : /* initialize() */
2831 : /************************************************************************/
2832 :
2833 : LT_STATUS MrSIDDummyImageReader::initialize()
2834 : {
2835 : if ( !LT_SUCCESS(LTIImageReader::initialize()) )
2836 : return LT_STS_Failure;
2837 :
2838 : lt_uint16 nBands = (lt_uint16)poDS->GetRasterCount();
2839 : LTIColorSpace eColorSpace = LTI_COLORSPACE_RGB;
2840 : switch ( nBands )
2841 : {
2842 : case 1:
2843 : eColorSpace = LTI_COLORSPACE_GRAYSCALE;
2844 : break;
2845 : case 3:
2846 : eColorSpace = LTI_COLORSPACE_RGB;
2847 : break;
2848 : default:
2849 : eColorSpace = LTI_COLORSPACE_MULTISPECTRAL;
2850 : break;
2851 : }
2852 :
2853 : eDataType = poDS->GetRasterBand(1)->GetRasterDataType();
2854 : switch ( eDataType )
2855 : {
2856 : case GDT_UInt16:
2857 : eSampleType = LTI_DATATYPE_UINT16;
2858 : break;
2859 : case GDT_Int16:
2860 : eSampleType = LTI_DATATYPE_SINT16;
2861 : break;
2862 : case GDT_UInt32:
2863 : eSampleType = LTI_DATATYPE_UINT32;
2864 : break;
2865 : case GDT_Int32:
2866 : eSampleType = LTI_DATATYPE_SINT32;
2867 : break;
2868 : case GDT_Float32:
2869 : eSampleType = LTI_DATATYPE_FLOAT32;
2870 : break;
2871 : case GDT_Float64:
2872 : eSampleType = LTI_DATATYPE_FLOAT64;
2873 : break;
2874 : case GDT_Byte:
2875 : default:
2876 : eSampleType = LTI_DATATYPE_UINT8;
2877 : break;
2878 : }
2879 :
2880 : poPixel = new LTIDLLPixel<LTIPixel>( eColorSpace, nBands, eSampleType );
2881 : if ( !LT_SUCCESS(setPixelProps(*poPixel)) )
2882 : return LT_STS_Failure;
2883 :
2884 : if ( !LT_SUCCESS(setDimensions(poDS->GetRasterXSize(),
2885 : poDS->GetRasterYSize())) )
2886 : return LT_STS_Failure;
2887 :
2888 : if ( poDS->GetGeoTransform( adfGeoTransform ) == CE_None )
2889 : {
2890 : #ifdef MRSID_SDK_40
2891 : LTIGeoCoord oGeo( adfGeoTransform[0] + adfGeoTransform[1] / 2,
2892 : adfGeoTransform[3] + adfGeoTransform[5] / 2,
2893 : adfGeoTransform[1], adfGeoTransform[5],
2894 : adfGeoTransform[2], adfGeoTransform[4], NULL,
2895 : poDS->GetProjectionRef() );
2896 : #else
2897 : LTIGeoCoord oGeo( adfGeoTransform[0] + adfGeoTransform[1] / 2,
2898 : adfGeoTransform[3] + adfGeoTransform[5] / 2,
2899 : adfGeoTransform[1], adfGeoTransform[5],
2900 : adfGeoTransform[2], adfGeoTransform[4],
2901 : poDS->GetProjectionRef() );
2902 : #endif
2903 : if ( !LT_SUCCESS(setGeoCoord( oGeo )) )
2904 : return LT_STS_Failure;
2905 : }
2906 :
2907 : /*int bSuccess;
2908 : double dfNoDataValue = poDS->GetNoDataValue( &bSuccess );
2909 : if ( bSuccess )
2910 : {
2911 : LTIPixel oNoDataPixel( *poPixel );
2912 : lt_uint16 iBand;
2913 :
2914 : for (iBand = 0; iBand < (lt_uint16)poDS->GetRasterCount(); iBand++)
2915 : oNoDataPixel.setSampleValueFloat32( iBand, dfNoDataValue );
2916 : if ( !LT_SUCCESS(setNoDataPixel( &oNoDataPixel )) )
2917 : return LT_STS_Failure;
2918 : }*/
2919 :
2920 : setDefaultDynamicRange();
2921 : setClassicalMetadata();
2922 :
2923 : return LT_STS_Success;
2924 : }
2925 :
2926 : /************************************************************************/
2927 : /* decodeStrip() */
2928 : /************************************************************************/
2929 :
2930 : LT_STATUS MrSIDDummyImageReader::decodeStrip(LTISceneBuffer& stripData,
2931 : const LTIScene& stripScene)
2932 :
2933 : {
2934 : const lt_int32 nXOff = stripScene.getUpperLeftCol();
2935 : const lt_int32 nYOff = stripScene.getUpperLeftRow();
2936 : const lt_int32 nBufXSize = stripScene.getNumCols();
2937 : const lt_int32 nBufYSize = stripScene.getNumRows();
2938 : const lt_int32 nDataBufXSize = stripData.getTotalNumCols();
2939 : const lt_int32 nDataBufYSize = stripData.getTotalNumRows();
2940 : const lt_uint16 nBands = poPixel->getNumBands();
2941 :
2942 : void *pData = CPLMalloc(nDataBufXSize * nDataBufYSize * poPixel->getNumBytes());
2943 : if ( !pData )
2944 : {
2945 : CPLError( CE_Failure, CPLE_AppDefined,
2946 : "MrSIDDummyImageReader::decodeStrip(): "
2947 : "Cannot allocate enough space for scene buffer" );
2948 : return LT_STS_Failure;
2949 : }
2950 :
2951 : poDS->RasterIO( GF_Read, nXOff, nYOff, nBufXSize, nBufYSize,
2952 : pData, nBufXSize, nBufYSize, eDataType, nBands, NULL,
2953 : 0, 0, 0 );
2954 :
2955 : stripData.importDataBSQ( pData );
2956 : CPLFree( pData );
2957 : return LT_STS_Success;
2958 : }
2959 :
2960 : /************************************************************************/
2961 : /* FlushCache() */
2962 : /************************************************************************/
2963 :
2964 : void MrSIDDataset::FlushCache()
2965 :
2966 : {
2967 : GDALDataset::FlushCache();
2968 : }
2969 :
2970 : /************************************************************************/
2971 : /* MrSIDCreateCopy() */
2972 : /************************************************************************/
2973 :
2974 : static GDALDataset *
2975 : MrSIDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
2976 : int bStrict, char ** papszOptions,
2977 : GDALProgressFunc pfnProgress, void * pProgressData )
2978 :
2979 : {
2980 : const char* pszVersion = CSLFetchNameValue(papszOptions, "VERSION");
2981 : LT_STATUS eStat;
2982 :
2983 : #ifdef DEBUG
2984 : bool bMeter = false;
2985 : #else
2986 : bool bMeter = true;
2987 : #endif
2988 :
2989 : if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
2990 : {
2991 : CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
2992 : "MrSID driver ignores color table. "
2993 : "The source raster band will be considered as grey level.\n"
2994 : "Consider using color table expansion (-expand option in gdal_translate)\n");
2995 : if (bStrict)
2996 : return NULL;
2997 : }
2998 :
2999 : // Output Mrsid Version 2 file.
3000 : if( pszVersion && atoi(pszVersion) == 2 )
3001 : {
3002 : int nXSize = poSrcDS->GetRasterXSize();
3003 : int nYSize = poSrcDS->GetRasterYSize();
3004 :
3005 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
3006 : return NULL;
3007 :
3008 : // Create the file.
3009 : MrSIDDummyImageReader oImageReader( poSrcDS );
3010 : eStat = oImageReader.initialize();
3011 : if( eStat != LT_STS_Success )
3012 : {
3013 : CPLError( CE_Failure, CPLE_AppDefined,
3014 : "MrSIDDummyImageReader.Initialize failed.\n%s",
3015 : getLastStatusString( eStat ) );
3016 : return NULL;
3017 : }
3018 :
3019 : MG2ImageWriter oImageWriter(&oImageReader);
3020 : eStat = oImageWriter.initialize();
3021 : if( eStat != LT_STS_Success )
3022 : {
3023 : CPLError( CE_Failure, CPLE_AppDefined,
3024 : "MG3ImageWriter.initialize() failed.\n%s",
3025 : getLastStatusString( eStat ) );
3026 : return NULL;
3027 : }
3028 :
3029 : oImageWriter.setUsageMeterEnabled(bMeter);
3030 :
3031 : // set output filename
3032 : oImageWriter.setOutputFileSpec( pszFilename );
3033 :
3034 : // Set defaults
3035 : oImageWriter.params().setBlockSize(oImageWriter.params().getBlockSize());
3036 : oImageWriter.setStripHeight(oImageWriter.getStripHeight());
3037 :
3038 : // check for compression option
3039 : const char* pszValue = CSLFetchNameValue(papszOptions, "COMPRESSION");
3040 : if( pszValue != NULL )
3041 : oImageWriter.params().setCompressionRatio( atof(pszValue) );
3042 :
3043 : // set MrSID world file
3044 : if( CSLFetchNameValue(papszOptions, "WORLDFILE") != NULL )
3045 : oImageWriter.setWorldFileSupport( true );
3046 :
3047 : // write the scene
3048 : const LTIScene oScene( 0, 0, nXSize, nYSize, 1.0 );
3049 : eStat = oImageWriter.write( oScene );
3050 : if( eStat != LT_STS_Success )
3051 : {
3052 : CPLError( CE_Failure, CPLE_AppDefined,
3053 : "MG2ImageWriter.write() failed.\n%s",
3054 : getLastStatusString( eStat ) );
3055 : return NULL;
3056 : }
3057 : }
3058 : // Output Mrsid Version 3 file.
3059 : else
3060 : {
3061 : int nXSize = poSrcDS->GetRasterXSize();
3062 : int nYSize = poSrcDS->GetRasterYSize();
3063 :
3064 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
3065 : return NULL;
3066 :
3067 : // Create the file.
3068 : MrSIDDummyImageReader oImageReader( poSrcDS );
3069 : eStat = oImageReader.initialize();
3070 : if( eStat != LT_STS_Success )
3071 : {
3072 : CPLError( CE_Failure, CPLE_AppDefined,
3073 : "MrSIDDummyImageReader.Initialize failed.\n%s",
3074 : getLastStatusString( eStat ) );
3075 : return NULL;
3076 : }
3077 :
3078 : MG3ImageWriter oImageWriter(&oImageReader);
3079 : eStat = oImageWriter.initialize();
3080 : if( eStat != LT_STS_Success )
3081 : {
3082 : CPLError( CE_Failure, CPLE_AppDefined,
3083 : "MG3ImageWriter.initialize() failed.\n%s",
3084 : getLastStatusString( eStat ) );
3085 : return NULL;
3086 : }
3087 :
3088 : // Set 64-bit Interface for large files.
3089 : oImageWriter.setFileStream64(true);
3090 :
3091 : oImageWriter.setUsageMeterEnabled(bMeter);
3092 :
3093 : // set output filename
3094 : oImageWriter.setOutputFileSpec( pszFilename );
3095 :
3096 : // Set defaults
3097 : oImageWriter.setStripHeight(oImageWriter.getStripHeight());
3098 :
3099 : // set 2 pass optimizer option
3100 : if( CSLFetchNameValue(papszOptions, "TWOPASS") != NULL )
3101 : oImageWriter.params().setTwoPassOptimizer( true );
3102 :
3103 : // set MrSID world file
3104 : if( CSLFetchNameValue(papszOptions, "WORLDFILE") != NULL )
3105 : oImageWriter.setWorldFileSupport( true );
3106 :
3107 : const char* pszValue;
3108 :
3109 : // set filesize in KB
3110 : pszValue = CSLFetchNameValue(papszOptions, "FILESIZE");
3111 : if( pszValue != NULL )
3112 : oImageWriter.params().setTargetFilesize( atoi(pszValue) );
3113 :
3114 : // write the scene
3115 : const LTIScene oScene( 0, 0, nXSize, nYSize, 1.0 );
3116 : eStat = oImageWriter.write( oScene );
3117 : if( eStat != LT_STS_Success )
3118 : {
3119 : CPLError( CE_Failure, CPLE_AppDefined,
3120 : "MG2ImageWriter.write() failed.\n%s",
3121 : getLastStatusString( eStat ) );
3122 : return NULL;
3123 : }
3124 : }
3125 :
3126 : /* -------------------------------------------------------------------- */
3127 : /* Re-open dataset, and copy any auxilary pam information. */
3128 : /* -------------------------------------------------------------------- */
3129 : GDALPamDataset *poDS = (GDALPamDataset *)
3130 : GDALOpen( pszFilename, GA_ReadOnly );
3131 :
3132 : if( poDS )
3133 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
3134 :
3135 : return poDS;
3136 : }
3137 :
3138 : #ifdef MRSID_J2K
3139 : /************************************************************************/
3140 : /* JP2CreateCopy() */
3141 : /************************************************************************/
3142 :
3143 : static GDALDataset *
3144 : JP2CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
3145 : int bStrict, char ** papszOptions,
3146 : GDALProgressFunc pfnProgress, void * pProgressData )
3147 :
3148 : {
3149 : #ifdef DEBUG
3150 : bool bMeter = false;
3151 : #else
3152 : bool bMeter = true;
3153 : #endif
3154 :
3155 : int nXSize = poSrcDS->GetRasterXSize();
3156 : int nYSize = poSrcDS->GetRasterYSize();
3157 : LT_STATUS eStat;
3158 :
3159 : if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
3160 : {
3161 : CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
3162 : "MrSID driver ignores color table. "
3163 : "The source raster band will be considered as grey level.\n"
3164 : "Consider using color table expansion (-expand option in gdal_translate)\n");
3165 : if (bStrict)
3166 : return NULL;
3167 : }
3168 :
3169 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
3170 : return NULL;
3171 :
3172 : // Create the file.
3173 : MrSIDDummyImageReader oImageReader( poSrcDS );
3174 : eStat = oImageReader.initialize();
3175 : if( eStat != LT_STS_Success )
3176 : {
3177 : CPLError( CE_Failure, CPLE_AppDefined,
3178 : "MrSIDDummyImageReader.Initialize failed.\n%s",
3179 : getLastStatusString( eStat ) );
3180 : return NULL;
3181 : }
3182 :
3183 : #ifdef MRSID_POST5
3184 : JP2WriterManager oImageWriter(&oImageReader);
3185 : #else
3186 : J2KImageWriter oImageWriter(&oImageReader);
3187 : #endif
3188 : eStat = oImageWriter.initialize();
3189 : if( eStat != LT_STS_Success )
3190 : {
3191 : CPLError( CE_Failure, CPLE_AppDefined,
3192 : "J2KImageWriter.Initialize failed.\n%s",
3193 : getLastStatusString( eStat ) );
3194 : return NULL;
3195 : }
3196 :
3197 : // Set 64-bit Interface for large files.
3198 : oImageWriter.setFileStream64(true);
3199 :
3200 : oImageWriter.setUsageMeterEnabled(bMeter);
3201 :
3202 : // set output filename
3203 : oImageWriter.setOutputFileSpec( pszFilename );
3204 :
3205 : // Set defaults
3206 : //oImageWriter.setStripHeight(oImageWriter.getStripHeight());
3207 :
3208 : // set MrSID world file
3209 : if( CSLFetchNameValue(papszOptions, "WORLDFILE") != NULL )
3210 : oImageWriter.setWorldFileSupport( true );
3211 :
3212 : // check for compression option
3213 : const char* pszValue = CSLFetchNameValue(papszOptions, "COMPRESSION");
3214 : if( pszValue != NULL )
3215 : oImageWriter.params().setCompressionRatio( atof(pszValue) );
3216 :
3217 : pszValue = CSLFetchNameValue(papszOptions, "XMLPROFILE");
3218 : if( pszValue != NULL )
3219 : {
3220 : LTFileSpec xmlprofile(pszValue);
3221 : eStat = oImageWriter.params().readProfile(xmlprofile);
3222 : if( eStat != LT_STS_Success )
3223 : {
3224 : CPLError( CE_Failure, CPLE_AppDefined,
3225 : "JPCWriterParams.readProfile failed.\n%s",
3226 : getLastStatusString( eStat ) );
3227 : return NULL;
3228 : }
3229 : }
3230 :
3231 : // write the scene
3232 : const LTIScene oScene( 0, 0, nXSize, nYSize, 1.0 );
3233 : eStat = oImageWriter.write( oScene );
3234 : if( eStat != LT_STS_Success )
3235 : {
3236 : CPLError( CE_Failure, CPLE_AppDefined,
3237 : "J2KImageWriter.write() failed.\n%s",
3238 : getLastStatusString( eStat ) );
3239 : return NULL;
3240 : }
3241 :
3242 : /* -------------------------------------------------------------------- */
3243 : /* Re-open dataset, and copy any auxilary pam information. */
3244 : /* -------------------------------------------------------------------- */
3245 : GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
3246 : GDALPamDataset *poDS = (GDALPamDataset*) JP2Open(&oOpenInfo);
3247 :
3248 : if( poDS )
3249 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
3250 :
3251 : return poDS;
3252 : }
3253 : #endif /* MRSID_J2K */
3254 : #endif /* MRSID_ESDK */
3255 :
3256 : /************************************************************************/
3257 : /* GDALRegister_MrSID() */
3258 : /************************************************************************/
3259 :
3260 409 : void GDALRegister_MrSID()
3261 :
3262 : {
3263 : GDALDriver *poDriver;
3264 :
3265 409 : if (! GDAL_CHECK_VERSION("MrSID driver"))
3266 0 : return;
3267 :
3268 : /* -------------------------------------------------------------------- */
3269 : /* MrSID driver. */
3270 : /* -------------------------------------------------------------------- */
3271 409 : if( GDALGetDriverByName( "MrSID" ) == NULL )
3272 : {
3273 392 : poDriver = new GDALDriver();
3274 :
3275 392 : poDriver->SetDescription( "MrSID" );
3276 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
3277 392 : "Multi-resolution Seamless Image Database (MrSID)" );
3278 392 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_mrsid.html" );
3279 392 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sid" );
3280 :
3281 : #ifdef MRSID_ESDK
3282 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
3283 : "Byte Int16 UInt16 Int32 UInt32 Float32 Float64" );
3284 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
3285 : "<CreationOptionList>"
3286 : // Version 2 Options
3287 : " <Option name='COMPRESSION' type='double' description='Set compression ratio (0.0 default is meant to be lossless)'/>"
3288 : // Version 3 Options
3289 : " <Option name='TWOPASS' type='int' description='Use twopass optimizer algorithm'/>"
3290 : " <Option name='FILESIZE' type='int' description='Set target file size (0 implies lossless compression)'/>"
3291 : // Version 2 and 3 Option
3292 : " <Option name='WORLDFILE' type='boolean' description='Write out world file'/>"
3293 : // Version Type
3294 : " <Option name='VERSION' type='int' description='Valid versions are 2 and 3, default = 3'/>"
3295 : "</CreationOptionList>" );
3296 :
3297 : poDriver->pfnCreateCopy = MrSIDCreateCopy;
3298 : #endif
3299 392 : poDriver->pfnIdentify = MrSIDIdentify;
3300 392 : poDriver->pfnOpen = MrSIDOpen;
3301 :
3302 392 : GetGDALDriverManager()->RegisterDriver( poDriver );
3303 : }
3304 :
3305 : /* -------------------------------------------------------------------- */
3306 : /* JP2MRSID driver. */
3307 : /* -------------------------------------------------------------------- */
3308 : #ifdef MRSID_J2K
3309 409 : if( GDALGetDriverByName( "JP2MrSID" ) == NULL )
3310 : {
3311 392 : poDriver = new GDALDriver();
3312 :
3313 392 : poDriver->SetDescription( "JP2MrSID" );
3314 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
3315 392 : "MrSID JPEG2000" );
3316 392 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jp2mrsid.html" );
3317 392 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
3318 :
3319 : #ifdef MRSID_ESDK
3320 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
3321 : "Byte Int16 UInt16" );
3322 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
3323 : "<CreationOptionList>"
3324 : " <Option name='COMPRESSION' type='double' description='Set compression ratio (0.0 default is meant to be lossless)'/>"
3325 : " <Option name='WORLDFILE' type='boolean' description='Write out world file'/>"
3326 : " <Option name='XMLPROFILE' type='string' description='Use named xml profile file'/>"
3327 : "</CreationOptionList>" );
3328 :
3329 : poDriver->pfnCreateCopy = JP2CreateCopy;
3330 : #endif
3331 392 : poDriver->pfnIdentify = JP2Identify;
3332 392 : poDriver->pfnOpen = JP2Open;
3333 :
3334 392 : GetGDALDriverManager()->RegisterDriver( poDriver );
3335 : }
3336 : #endif /* def MRSID_J2K */
3337 : }
|