root/tags/gdal_1_3_2/gcore/gdaljp2metadata.cpp

Revision 9537, 23.8 kB (checked in by fwarmerdam, 3 years ago)

Added ReadAndParse?() method, which includes worldfile reading.
Actually set HaveGeoTransform? flag properly.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /******************************************************************************
2  * $Id$
3  *
4  * Project:  GDAL
5  * Purpose:  GDALJP2Metadata - Read GeoTIFF and/or GML georef info.
6  * Author:   Frank Warmerdam, warmerdam@pobox.com
7  *
8  ******************************************************************************
9  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  *****************************************************************************
29  *
30  * $Log$
31  * Revision 1.6  2006/04/07 05:35:25  fwarmerdam
32  * Added ReadAndParse() method, which includes worldfile reading.
33  * Actually set HaveGeoTransform flag properly.
34  *
35  * Revision 1.5  2005/07/05 22:09:00  fwarmerdam
36  * add preliminary support for MSIG boxes
37  *
38  * Revision 1.4  2005/05/23 06:45:34  fwarmerdam
39  * make msi_uuid const
40  *
41  * Revision 1.3  2005/05/17 20:13:04  fwarmerdam
42  * fix up to support relative and absolute gmljp2:// uri format
43  *
44  * Revision 1.2  2005/05/05 20:17:15  fwarmerdam
45  * support dictionary lookups
46  *
47  * Revision 1.1  2005/05/03 21:10:59  fwarmerdam
48  * New
49  *
50  */
51
52 #include "gdaljp2metadata.h"
53 #include "cpl_string.h"
54 #include "cpl_minixml.h"
55 #include "ogr_spatialref.h"
56 #include "ogr_geometry.h"
57 #include "ogr_api.h"
58
59 CPL_CVSID("$Id$");
60
61 static const unsigned char msi_uuid2[16] =
62 {0xb1,0x4b,0xf8,0xbd,0x08,0x3d,0x4b,0x43,
63  0xa5,0xae,0x8c,0xd7,0xd5,0xa6,0xce,0x03};
64
65 static const unsigned char msig_uuid[16] =
66 { 0x96,0xA9,0xF1,0xF1,0xDC,0x98,0x40,0x2D,
67   0xA7,0xAE,0xD6,0x8E,0x34,0x45,0x18,0x09 };
68
69 CPL_C_START
70 CPLErr CPL_DLL GTIFMemBufFromWkt( const char *pszWKT,
71                                   const double *padfGeoTransform,
72                                   int nGCPCount, const GDAL_GCP *pasGCPList,
73                                   int *pnSize, unsigned char **ppabyBuffer );
74 CPLErr CPL_DLL GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer,
75                           char **ppszWKT, double *padfGeoTransform,
76                           int *pnGCPCount, GDAL_GCP **ppasGCPList );
77 CPL_C_END
78
79 /************************************************************************/
80 /*                          GDALJP2Metadata()                           */
81 /************************************************************************/
82
83 GDALJP2Metadata::GDALJP2Metadata()
84
85 {
86     pszProjection = NULL;
87
88     nGCPCount = 0;
89     pasGCPList = NULL;
90
91     papszGMLMetadata = NULL;
92
93     nGeoTIFFSize = 0;
94     pabyGeoTIFFData = NULL;
95
96     nMSIGSize = 0;
97     pabyMSIGData = NULL;
98
99     bHaveGeoTransform = FALSE;
100     adfGeoTransform[0] = 0.0;
101     adfGeoTransform[1] = 1.0;
102     adfGeoTransform[2] = 0.0;
103     adfGeoTransform[3] = 0.0;
104     adfGeoTransform[4] = 0.0;
105     adfGeoTransform[5] = 1.0;
106 }
107
108 /************************************************************************/
109 /*                          ~GDALJP2Metadata()                          */
110 /************************************************************************/
111
112 GDALJP2Metadata::~GDALJP2Metadata()
113
114 {
115     CPLFree( pszProjection );
116     if( nGCPCount > 0 )
117     {
118         GDALDeinitGCPs( nGCPCount, pasGCPList );
119         CPLFree( pasGCPList );
120     }
121
122     CPLFree( pabyGeoTIFFData );
123     CPLFree( pabyMSIGData );
124 }
125
126 /************************************************************************/
127 /*                            ReadAndParse()                            */
128 /*                                                                      */
129 /*      Read a JP2 file and try to collect georeferencing               */
130 /*      information from the various available forms.  Returns TRUE     */
131 /*      if anything useful is found.                                    */
132 /************************************************************************/
133
134 int GDALJP2Metadata::ReadAndParse( const char *pszFilename )
135
136 {
137     FILE *fpLL;
138        
139     fpLL = VSIFOpenL( pszFilename, "rb" );
140        
141     if( fpLL == NULL )
142     {
143         CPLDebug( "GDALJP2Metadata", "Could not even open %s.",
144                   pszFilename );
145
146         return FALSE;
147     }
148
149     ReadBoxes( fpLL );
150     VSIFCloseL( fpLL );
151            
152 /* -------------------------------------------------------------------- */
153 /*      Try JP2GeoTIFF, GML and finally MSIG to get something.          */
154 /* -------------------------------------------------------------------- */
155     if( !ParseJP2GeoTIFF() && !ParseGMLCoverageDesc() )
156         ParseMSIG();
157
158 /* -------------------------------------------------------------------- */
159 /*      If we still don't have a geotransform, look for a world         */
160 /*      file.                                                           */
161 /* -------------------------------------------------------------------- */
162     if( !bHaveGeoTransform )
163     {
164         bHaveGeoTransform =
165             GDALReadWorldFile( pszFilename, NULL, adfGeoTransform )
166             || GDALReadWorldFile( pszFilename, ".wld", adfGeoTransform );
167     }
168
169 /* -------------------------------------------------------------------- */
170 /*      Return success either either of projection or geotransform      */
171 /*      or gcps.                                                        */
172 /* -------------------------------------------------------------------- */
173     return bHaveGeoTransform
174         || nGCPCount > 0
175         || (pszProjection != NULL && strlen(pszProjection) > 0);
176 }
177
178 /************************************************************************/
179 /*                           CollectGMLData()                           */
180 /*                                                                      */
181 /*      Read all the asoc boxes after this node, and store the          */
182 /*      contain xml documents along with the name from the label.       */
183 /************************************************************************/
184
185 void GDALJP2Metadata::CollectGMLData( GDALJP2Box *poGMLData )
186
187 {
188     GDALJP2Box oChildBox( poGMLData->GetFILE() );
189
190     oChildBox.ReadFirstChild( poGMLData );
191
192     while( strlen(oChildBox.GetType()) > 0 )
193     {
194         if( EQUAL(oChildBox.GetType(),"asoc") )
195         {
196             GDALJP2Box oSubChildBox( oChildBox.GetFILE() );
197
198             char *pszLabel = NULL;
199             char *pszXML = NULL;
200
201             oSubChildBox.ReadFirstChild( &oChildBox );
202            
203             while( strlen(oSubChildBox.GetType()) > 0 )
204             {
205                 if( EQUAL(oSubChildBox.GetType(),"lbl ") )
206                     pszLabel = (char *)oSubChildBox.ReadBoxData();
207                 else if( EQUAL(oSubChildBox.GetType(),"xml ") )
208                     pszXML = (char *) oSubChildBox.ReadBoxData();
209
210                 oSubChildBox.ReadNextChild( &oChildBox );
211             }
212            
213             if( pszLabel != NULL && pszXML != NULL )
214                 papszGMLMetadata = CSLSetNameValue( papszGMLMetadata,
215                                                     pszLabel, pszXML );
216             CPLFree( pszLabel );
217             CPLFree( pszXML );
218         }
219        
220         oChildBox.ReadNextChild( poGMLData );
221     }
222 }
223
224 /************************************************************************/
225 /*                             ReadBoxes()                              */
226 /************************************************************************/
227
228 int GDALJP2Metadata::ReadBoxes( FILE *fpVSIL )
229
230 {
231     GDALJP2Box oBox( fpVSIL );
232
233     oBox.ReadFirst();
234
235     while( strlen(oBox.GetType()) > 0 )
236     {
237 /* -------------------------------------------------------------------- */
238 /*      Collect geotiff box.                                            */
239 /* -------------------------------------------------------------------- */
240         if( EQUAL(oBox.GetType(),"uuid")
241             && memcmp( oBox.GetUUID(), msi_uuid2, 16 ) == 0 )
242         {
243             nGeoTIFFSize = oBox.GetDataLength();
244             pabyGeoTIFFData = oBox.ReadBoxData();
245         }
246
247 /* -------------------------------------------------------------------- */
248 /*      Collect MSIG box.                                               */
249 /* -------------------------------------------------------------------- */
250         if( EQUAL(oBox.GetType(),"uuid")
251             && memcmp( oBox.GetUUID(), msig_uuid, 16 ) == 0 )
252         {
253             nMSIGSize = oBox.GetDataLength();
254             pabyMSIGData = oBox.ReadBoxData();
255
256             if( nMSIGSize < memcmp( pabyMSIGData, "MSIG/", 5 ) != 0
257                 || nMSIGSize < 70 )
258             {
259                 CPLFree( pabyMSIGData );
260                 pabyMSIGData = NULL;
261                 nMSIGSize = 0;
262             }
263         }
264
265 /* -------------------------------------------------------------------- */
266 /*      Process asoc box looking for Labelled GML data.                 */
267 /* -------------------------------------------------------------------- */
268         if( EQUAL(oBox.GetType(),"asoc") )
269         {
270             GDALJP2Box oSubBox( fpVSIL );
271
272             oSubBox.ReadFirstChild( &oBox );
273             if( EQUAL(oSubBox.GetType(),"lbl ") )
274             {
275                 char *pszLabel = (char *) oSubBox.ReadBoxData();
276                 if( EQUAL(pszLabel,"gml.data") )
277                 {
278                     CollectGMLData( &oBox );
279                 }
280                 CPLFree( pszLabel );
281             }
282         }
283
284         oBox.ReadNext();
285     }
286    
287     return TRUE;
288 }
289
290 /************************************************************************/
291 /*                          ParseJP2GeoTIFF()                           */
292 /************************************************************************/
293
294 int GDALJP2Metadata::ParseJP2GeoTIFF()
295
296 {
297     if( nGeoTIFFSize < 1 )
298         return FALSE;
299
300 /* -------------------------------------------------------------------- */
301 /*      Convert raw data into projection and geotransform.              */
302 /* -------------------------------------------------------------------- */
303     int bSuccess = TRUE;
304
305     if( GTIFWktFromMemBuf( nGeoTIFFSize, pabyGeoTIFFData,
306                            &pszProjection, adfGeoTransform,
307                            &nGCPCount, &pasGCPList ) != CE_None )
308     {
309         bSuccess = FALSE;
310     }
311
312     if( pszProjection == NULL || strlen(pszProjection) == 0 )
313         bSuccess = FALSE;
314
315     if( bSuccess )
316         CPLDebug( "GDALJP2Metadata",
317                   "Got projection from GeoJP2 (geotiff) box: %s",
318                  pszProjection );
319
320     if( adfGeoTransform[0] != 0
321         || adfGeoTransform[1] != 1
322         || adfGeoTransform[2] != 0
323         || adfGeoTransform[3] != 0
324         || adfGeoTransform[4] != 0
325         || adfGeoTransform[5] != 1 )
326         bHaveGeoTransform = TRUE;
327
328     return bSuccess;;
329 }
330
331 /************************************************************************/
332 /*                             ParseMSIG()                              */
333 /************************************************************************/
334
335 int GDALJP2Metadata::ParseMSIG()
336
337 {
338     if( nMSIGSize < 70 )
339         return FALSE;
340
341 /* -------------------------------------------------------------------- */
342 /*      Try and extract worldfile parameters and adjust.                */
343 /* -------------------------------------------------------------------- */
344     memcpy( adfGeoTransform + 0, pabyMSIGData + 22 + 8 * 4, 8 );
345     memcpy( adfGeoTransform + 1, pabyMSIGData + 22 + 8 * 0, 8 );
346     memcpy( adfGeoTransform + 2, pabyMSIGData + 22 + 8 * 2, 8 );
347     memcpy( adfGeoTransform + 3, pabyMSIGData + 22 + 8 * 5, 8 );
348     memcpy( adfGeoTransform + 4, pabyMSIGData + 22 + 8 * 1, 8 );
349     memcpy( adfGeoTransform + 5, pabyMSIGData + 22 + 8 * 3, 8 );
350
351     // data is in LSB (little endian) order in file.
352     CPL_LSBPTR64( adfGeoTransform + 0 );
353     CPL_LSBPTR64( adfGeoTransform + 1 );
354     CPL_LSBPTR64( adfGeoTransform + 2 );
355     CPL_LSBPTR64( adfGeoTransform + 3 );
356     CPL_LSBPTR64( adfGeoTransform + 4 );
357     CPL_LSBPTR64( adfGeoTransform + 5 );
358
359     // correct for center of pixel vs. top left of pixel
360     adfGeoTransform[0] -= 0.5 * adfGeoTransform[1];
361     adfGeoTransform[0] -= 0.5 * adfGeoTransform[2];
362     adfGeoTransform[3] -= 0.5 * adfGeoTransform[4];
363     adfGeoTransform[3] -= 0.5 * adfGeoTransform[5];
364
365     bHaveGeoTransform = TRUE;
366
367     return TRUE;
368 }
369
370 /************************************************************************/
371 /*                         GetDictionaryItem()                          */
372 /************************************************************************/
373
374 static CPLXMLNode *
375 GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
376
377 {
378     char *pszLabel;
379     const char *pszFragmentId = NULL;
380     int i;
381
382
383     if( EQUALN(pszURN,"urn:jp2k:xml:", 13) )
384         pszLabel = CPLStrdup( pszURN + 13 );
385     else if( EQUALN(pszURN,"urn:ogc:tc:gmljp2:xml:", 22) )
386         pszLabel = CPLStrdup( pszURN + 22 );
387     else if( EQUALN(pszURN,"gmljp2://xml/",13) )
388         pszLabel = CPLStrdup( pszURN + 13 );
389     else
390         pszLabel = CPLStrdup( pszURN );
391
392 /* -------------------------------------------------------------------- */
393 /*      Split out label and fragment id.                                */
394 /* -------------------------------------------------------------------- */
395     for( i = 0; pszLabel[i] != '#'; i++ )
396     {
397         if( pszLabel[i] == '\0' )
398             return NULL;
399     }
400
401     pszFragmentId = pszLabel + i + 1;
402     pszLabel[i] = '\0';
403
404 /* -------------------------------------------------------------------- */
405 /*      Can we find an XML box with the desired label?                  */
406 /* -------------------------------------------------------------------- */
407     const char *pszDictionary =
408         CSLFetchNameValue( papszGMLMetadata, pszLabel );
409
410     if( pszDictionary == NULL )
411         return NULL;
412
413 /* -------------------------------------------------------------------- */
414 /*      Try and parse the dictionary.                                   */
415 /* -------------------------------------------------------------------- */
416     CPLXMLNode *psDictTree = CPLParseXMLString( pszDictionary );
417
418     if( psDictTree == NULL )
419     {
420         CPLDestroyXMLNode( psDictTree );
421         return NULL;
422     }
423
424     CPLStripXMLNamespace( psDictTree, NULL, TRUE );
425
426     CPLXMLNode *psDictRoot = CPLSearchXMLNode( psDictTree, "=Dictionary" );
427    
428     if( psDictRoot == NULL )
429     {
430         CPLDestroyXMLNode( psDictTree );
431         return NULL;
432     }
433
434 /* -------------------------------------------------------------------- */
435 /*      Search for matching id.                                         */
436 /* -------------------------------------------------------------------- */
437     CPLXMLNode *psEntry, *psHit = NULL;
438     for( psEntry = psDictRoot->psChild;
439          psEntry != NULL && psHit == NULL;
440          psEntry = psEntry->psNext )
441     {
442         const char *pszId;
443
444         if( psEntry->eType != CXT_Element )
445             continue;
446
447         if( !EQUAL(psEntry->pszValue,"dictionaryEntry") )
448             continue;
449        
450         if( psEntry->psChild == NULL )
451             continue;
452
453         pszId = CPLGetXMLValue( psEntry->psChild, "id", "" );
454
455         if( EQUAL(pszId, pszFragmentId) )
456             psHit = CPLCloneXMLTree( psEntry->psChild );
457     }
458
459 /* -------------------------------------------------------------------- */
460 /*      Cleanup                                                         */
461 /* -------------------------------------------------------------------- */
462     CPLFree( pszLabel );
463     CPLDestroyXMLNode( psDictTree );
464
465     return psHit;
466 }
467
468        
469 /************************************************************************/
470 /*                            GMLSRSLookup()                            */
471 /*                                                                      */
472 /*      Lookup an SRS in a dictionary inside this file.  We will get    */
473 /*      something like:                                                 */
474 /*        urn:jp2k:xml:CRSDictionary.xml#crs1112                        */
475 /*                                                                      */
476 /*      We need to split the filename from the fragment id, and         */
477 /*      lookup the fragment in the file if we can find it our           */
478 /*      list of labelled xml boxes.                                     */
479 /************************************************************************/
480
481 int GDALJP2Metadata::GMLSRSLookup( const char *pszURN )
482
483 {
484     CPLXMLNode *psDictEntry = GetDictionaryItem( papszGMLMetadata, pszURN );
485
486     if( psDictEntry == NULL )
487         return FALSE;
488
489 /* -------------------------------------------------------------------- */
490 /*      Reserialize this fragment.                                      */
491 /* -------------------------------------------------------------------- */
492     char *pszDictEntryXML = CPLSerializeXMLTree( psDictEntry );
493     CPLDestroyXMLNode( psDictEntry );
494
495 /* -------------------------------------------------------------------- */
496 /*      Try to convert into an OGRSpatialReference.                     */
497 /* -------------------------------------------------------------------- */
498     OGRSpatialReference oSRS;
499     int bSuccess = FALSE;
500
501     if( oSRS.importFromXML( pszDictEntryXML ) == OGRERR_NONE )
502     {
503         CPLFree( pszProjection );
504         pszProjection = NULL;
505
506         oSRS.exportToWkt( &pszProjection );
507         bSuccess = TRUE;
508     }
509
510     CPLFree( pszDictEntryXML );
511
512     return bSuccess;
513 }
514
515 /************************************************************************/
516 /*                        ParseGMLCoverageDesc()                        */
517 /************************************************************************/
518
519 int GDALJP2Metadata::ParseGMLCoverageDesc()
520
521 {
522 /* -------------------------------------------------------------------- */
523 /*      Do we have an XML doc that is apparently a coverage             */
524 /*      description?                                                    */
525 /* -------------------------------------------------------------------- */
526     const char *pszCoverage = CSLFetchNameValue( papszGMLMetadata,
527                                                  "gml.root-instance" );
528
529     if( pszCoverage == NULL )
530         return FALSE;
531
532     CPLDebug( "GDALJP2Metadata", "Found GML Box:\n%s", pszCoverage );
533
534 /* -------------------------------------------------------------------- */
535 /*      Try parsing the XML.  Wipe any namespace prefixes.              */
536 /* -------------------------------------------------------------------- */
537     CPLXMLNode *psXML = CPLParseXMLString( pszCoverage );
538
539     if( psXML == NULL )
540         return FALSE;
541
542     CPLStripXMLNamespace( psXML, NULL, TRUE );
543
544 /* -------------------------------------------------------------------- */
545 /*      Isolate RectifiedGrid.  Eventually we will need to support      */
546 /*      other georeferencing objects.                                   */
547 /* -------------------------------------------------------------------- */
548     CPLXMLNode *psRG = CPLSearchXMLNode( psXML, "=RectifiedGrid" );
549     CPLXMLNode *psOriginPoint = NULL;
550     const char *pszOffset1=NULL, *pszOffset2=NULL;
551
552     if( psRG != NULL )
553     {
554         psOriginPoint = CPLGetXMLNode( psRG, "origin.Point" );
555
556        
557         CPLXMLNode *psOffset1 = CPLGetXMLNode( psRG, "offsetVector" );
558         if( psOffset1 != NULL )
559         {
560             pszOffset1 = CPLGetXMLValue( psOffset1, "", NULL );
561             pszOffset2 = CPLGetXMLValue( psOffset1->psNext, "=offsetVector",
562                                          NULL );
563         }
564     }
565
566 /* -------------------------------------------------------------------- */
567 /*      If we are missing any of the origin or 2 offsets then give up.  */
568 /* -------------------------------------------------------------------- */
569     if( psOriginPoint == NULL || pszOffset1 == NULL || pszOffset2 == NULL )
570     {
571         CPLDestroyXMLNode( psXML );
572         return FALSE;
573     }
574
575 /* -------------------------------------------------------------------- */
576 /*      Extract origin location.                                        */
577 /* -------------------------------------------------------------------- */
578     OGRPoint *poOriginGeometry = NULL;
579     const char *pszSRSName = NULL;
580
581     if( psOriginPoint != NULL )
582     {
583         poOriginGeometry = (OGRPoint *)
584             OGR_G_CreateFromGMLTree( psOriginPoint );
585
586         if( poOriginGeometry != NULL
587             && wkbFlatten(poOriginGeometry->getGeometryType()) != wkbPoint )
588         {
589             delete poOriginGeometry;
590             poOriginGeometry = NULL;
591         }
592
593         // SRS?
594         pszSRSName = CPLGetXMLValue( psOriginPoint, "srsName", NULL );
595     }
596
597 /* -------------------------------------------------------------------- */
598 /*      Extract offset(s)                                               */
599 /* -------------------------------------------------------------------- */
600     char **papszOffset1Tokens = NULL;
601     char **papszOffset2Tokens = NULL;
602     int bSuccess = FALSE;
603
604     papszOffset1Tokens =
605         CSLTokenizeStringComplex( pszOffset1, " ,", FALSE, FALSE );
606     papszOffset2Tokens =
607         CSLTokenizeStringComplex( pszOffset2, " ,", FALSE, FALSE );
608
609     if( CSLCount(papszOffset1Tokens) >= 2
610         && CSLCount(papszOffset2Tokens) >= 2
611         && poOriginGeometry != NULL )
612     {
613         adfGeoTransform[0] = poOriginGeometry->getX();
614         adfGeoTransform[1] = atof(papszOffset1Tokens[0]);
615         adfGeoTransform[2] = atof(papszOffset1Tokens[1]);
616         adfGeoTransform[3] = poOriginGeometry->getY();
617         adfGeoTransform[4] = atof(papszOffset2Tokens[0]);
618         adfGeoTransform[5] = atof(papszOffset2Tokens[1]);
619         bSuccess = TRUE;
620         bHaveGeoTransform = TRUE;
621     }
622
623     CSLDestroy( papszOffset1Tokens );
624     CSLDestroy( papszOffset2Tokens );
625
626     if( poOriginGeometry != NULL )
627         delete poOriginGeometry;
628
629 /* -------------------------------------------------------------------- */
630 /*      If we have gotten a geotransform, then try to interprete the    */
631 /*      srsName.                                                        */
632 /* -------------------------------------------------------------------- */
633     if( bSuccess && pszSRSName != NULL
634         && (pszProjection == NULL || strlen(pszProjection) == 0) )
635     {
636         if( EQUALN(pszSRSName,"epsg:",5) )
637         {
638             OGRSpatialReference oSRS;
639             if( oSRS.SetFromUserInput( pszSRSName ) == OGRERR_NONE )
640                 oSRS.exportToWkt( &pszProjection );
641         }
642         else if( EQUALN(pszSRSName,"urn:ogc:def:crs:EPSG::",22) )
643         {
644             OGRSpatialReference oSRS;
645             if( oSRS.importFromEPSG( atoi(pszSRSName + 22) ) == OGRERR_NONE )
646                 oSRS.exportToWkt( &pszProjection );
647         }
648         else if( EQUALN(pszSRSName,"urn:ogc:def:crs:EPSG:",21) )
649         {
650             const char *pszCode = pszSRSName+21;
651             while( *pszCode != ':' && *pszCode != '\0' )
652                 pszCode++;
653
654             OGRSpatialReference oSRS;
655             if( oSRS.importFromEPSG( atoi(pszCode+1) ) == OGRERR_NONE )
656                 oSRS.exportToWkt( &pszProjection );
657         }
658         else if( !GMLSRSLookup( pszSRSName ) )
659         {
660             CPLDebug( "GDALJP2Metadata",
661                       "Unable to evaluate SRSName=%s",
662                       pszSRSName );
663         }
664     }
665
666     if( pszProjection )
667         CPLDebug( "GDALJP2Metadata",
668                   "Got projection from GML box: %s",
669                  pszProjection );
670
671     return pszProjection != NULL && bSuccess;
672 }
673
Note: See TracBrowser for help on using the browser.