1 : /******************************************************************************
2 : * $Id: ersdataset.cpp 17867 2009-10-21 21:04:49Z rouault $
3 : *
4 : * Project: ERMapper .ers Driver
5 : * Purpose: Implementation of .ers driver.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "rawdataset.h"
31 : #include "ogr_spatialref.h"
32 : #include "cpl_string.h"
33 : #include "ershdrnode.h"
34 :
35 : CPL_CVSID("$Id: ersdataset.cpp 17867 2009-10-21 21:04:49Z rouault $");
36 :
37 : /************************************************************************/
38 : /* ==================================================================== */
39 : /* ERSDataset */
40 : /* ==================================================================== */
41 : /************************************************************************/
42 :
43 : class ERSRasterBand;
44 :
45 : class ERSDataset : public RawDataset
46 : {
47 : FILE *fpImage; // image data file.
48 : GDALDataset *poDepFile;
49 :
50 : int bGotTransform;
51 : double adfGeoTransform[6];
52 : char *pszProjection;
53 :
54 : CPLString osRawFilename;
55 :
56 : int bHDRDirty;
57 : ERSHdrNode *poHeader;
58 :
59 : const char *Find( const char *, const char * );
60 :
61 : int nGCPCount;
62 : GDAL_GCP *pasGCPList;
63 : char *pszGCPProjection;
64 :
65 : void ReadGCPs();
66 : public:
67 : ERSDataset();
68 : ~ERSDataset();
69 :
70 : virtual void FlushCache(void);
71 : virtual CPLErr GetGeoTransform( double * padfTransform );
72 : virtual CPLErr SetGeoTransform( double *padfTransform );
73 : virtual const char *GetProjectionRef(void);
74 : virtual CPLErr SetProjection( const char * );
75 : virtual char **GetFileList(void);
76 :
77 : virtual int GetGCPCount();
78 : virtual const char *GetGCPProjection();
79 : virtual const GDAL_GCP *GetGCPs();
80 : virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
81 : const char *pszGCPProjection );
82 :
83 : static GDALDataset *Open( GDALOpenInfo * );
84 : static GDALDataset *Create( const char * pszFilename,
85 : int nXSize, int nYSize, int nBands,
86 : GDALDataType eType, char ** papszParmList );
87 : };
88 :
89 : /************************************************************************/
90 : /* ==================================================================== */
91 : /* ERSDataset */
92 : /* ==================================================================== */
93 : /************************************************************************/
94 :
95 : /************************************************************************/
96 : /* ERSDataset() */
97 : /************************************************************************/
98 :
99 40 : ERSDataset::ERSDataset()
100 : {
101 40 : fpImage = NULL;
102 40 : poDepFile = NULL;
103 40 : pszProjection = CPLStrdup("");
104 40 : bGotTransform = FALSE;
105 40 : adfGeoTransform[0] = 0.0;
106 40 : adfGeoTransform[1] = 1.0;
107 40 : adfGeoTransform[2] = 0.0;
108 40 : adfGeoTransform[3] = 0.0;
109 40 : adfGeoTransform[4] = 0.0;
110 40 : adfGeoTransform[5] = 1.0;
111 40 : poHeader = NULL;
112 40 : bHDRDirty = FALSE;
113 :
114 40 : nGCPCount = 0;
115 40 : pasGCPList = NULL;
116 40 : pszGCPProjection = CPLStrdup("");
117 40 : }
118 :
119 : /************************************************************************/
120 : /* ~ERSDataset() */
121 : /************************************************************************/
122 :
123 40 : ERSDataset::~ERSDataset()
124 :
125 : {
126 40 : FlushCache();
127 :
128 40 : if( fpImage != NULL )
129 : {
130 40 : VSIFCloseL( fpImage );
131 : }
132 :
133 40 : if( poDepFile != NULL )
134 : {
135 : int iBand;
136 :
137 0 : for( iBand = 0; iBand < nBands; iBand++ )
138 0 : papoBands[iBand] = NULL;
139 :
140 0 : GDALClose( (GDALDatasetH) poDepFile );
141 : }
142 :
143 40 : CPLFree( pszProjection );
144 :
145 40 : CPLFree( pszGCPProjection );
146 40 : if( nGCPCount > 0 )
147 : {
148 0 : GDALDeinitGCPs( nGCPCount, pasGCPList );
149 0 : CPLFree( pasGCPList );
150 : }
151 :
152 40 : if( poHeader != NULL )
153 40 : delete poHeader;
154 40 : }
155 :
156 : /************************************************************************/
157 : /* FlushCache() */
158 : /************************************************************************/
159 :
160 40 : void ERSDataset::FlushCache()
161 :
162 : {
163 40 : if( bHDRDirty )
164 : {
165 30 : FILE * fpERS = VSIFOpenL( GetDescription(), "w" );
166 30 : if( fpERS == NULL )
167 : {
168 : CPLError( CE_Failure, CPLE_OpenFailed,
169 : "Unable to rewrite %s header.",
170 0 : GetDescription() );
171 : }
172 : else
173 : {
174 30 : VSIFPrintfL( fpERS, "DatasetHeader Begin\n" );
175 30 : poHeader->WriteSelf( fpERS, 1 );
176 30 : VSIFPrintfL( fpERS, "DatasetHeader End\n" );
177 30 : VSIFCloseL( fpERS );
178 : }
179 : }
180 :
181 40 : RawDataset::FlushCache();
182 40 : }
183 :
184 : /************************************************************************/
185 : /* GetGCPCount() */
186 : /************************************************************************/
187 :
188 1 : int ERSDataset::GetGCPCount()
189 :
190 : {
191 1 : return nGCPCount;
192 : }
193 :
194 : /************************************************************************/
195 : /* GetGCPProjection() */
196 : /************************************************************************/
197 :
198 0 : const char *ERSDataset::GetGCPProjection()
199 :
200 : {
201 0 : return pszGCPProjection;
202 : }
203 :
204 : /************************************************************************/
205 : /* GetGCPs() */
206 : /************************************************************************/
207 :
208 0 : const GDAL_GCP *ERSDataset::GetGCPs()
209 :
210 : {
211 0 : return pasGCPList;
212 : }
213 :
214 : /************************************************************************/
215 : /* SetGCPs() */
216 : /************************************************************************/
217 :
218 : CPLErr ERSDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
219 0 : const char *pszGCPProjectionIn )
220 :
221 : {
222 : /* -------------------------------------------------------------------- */
223 : /* Clean old gcps. */
224 : /* -------------------------------------------------------------------- */
225 0 : CPLFree( pszGCPProjection );
226 0 : pszGCPProjection = NULL;
227 :
228 0 : if( nGCPCount > 0 )
229 : {
230 0 : GDALDeinitGCPs( nGCPCount, pasGCPList );
231 0 : CPLFree( pasGCPList );
232 :
233 0 : pasGCPList = NULL;
234 0 : nGCPCount = 0;
235 : }
236 :
237 : /* -------------------------------------------------------------------- */
238 : /* Copy new ones. */
239 : /* -------------------------------------------------------------------- */
240 0 : nGCPCount = nGCPCountIn;
241 0 : pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPListIn );
242 0 : pszGCPProjection = CPLStrdup( pszGCPProjectionIn );
243 :
244 : /* -------------------------------------------------------------------- */
245 : /* Setup the header contents corresponding to these GCPs. */
246 : /* -------------------------------------------------------------------- */
247 0 : bHDRDirty = TRUE;
248 :
249 0 : poHeader->Set( "RasterInfo.WarpControl.WarpType", "Polynomial" );
250 0 : if( nGCPCount > 6 )
251 0 : poHeader->Set( "RasterInfo.WarpControl.WarpOrder", "2" );
252 : else
253 0 : poHeader->Set( "RasterInfo.WarpControl.WarpOrder", "1" );
254 0 : poHeader->Set( "RasterInfo.WarpControl.WarpSampling", "Nearest" );
255 :
256 : /* -------------------------------------------------------------------- */
257 : /* Translate the projection. */
258 : /* -------------------------------------------------------------------- */
259 0 : OGRSpatialReference oSRS( pszGCPProjection );
260 : char szERSProj[32], szERSDatum[32], szERSUnits[32];
261 :
262 0 : oSRS.exportToERM( szERSProj, szERSDatum, szERSUnits );
263 :
264 : poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Datum",
265 0 : CPLString().Printf( "\"%s\"", szERSDatum ) );
266 : poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Projection",
267 0 : CPLString().Printf( "\"%s\"", szERSProj ) );
268 : poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.CoordinateType",
269 0 : CPLString().Printf( "EN" ) );
270 : poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Units",
271 0 : CPLString().Printf( "\"%s\"", szERSUnits ) );
272 : poHeader->Set( "RasterInfo.WarpControl.CoordinateSpace.Rotation",
273 0 : "0:0:0.0" );
274 :
275 : /* -------------------------------------------------------------------- */
276 : /* Translate the GCPs. */
277 : /* -------------------------------------------------------------------- */
278 0 : CPLString osControlPoints = "{\n";
279 : int iGCP;
280 :
281 0 : for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
282 : {
283 0 : CPLString osLine;
284 :
285 0 : CPLString osId = pasGCPList[iGCP].pszId;
286 0 : if( strlen(osId) == 0 )
287 0 : osId.Printf( "%d", iGCP + 1 );
288 :
289 : osLine.Printf( "\t\t\t\t\"%s\"\tYes\tYes\t%.6f\t%.6f\t%.15g\t%.15g\t%.15g\n",
290 : osId.c_str(),
291 : pasGCPList[iGCP].dfGCPPixel,
292 : pasGCPList[iGCP].dfGCPLine,
293 : pasGCPList[iGCP].dfGCPX,
294 : pasGCPList[iGCP].dfGCPY,
295 0 : pasGCPList[iGCP].dfGCPZ );
296 0 : osControlPoints += osLine;
297 : }
298 0 : osControlPoints += "\t\t}";
299 :
300 0 : poHeader->Set( "RasterInfo.WarpControl.ControlPoints", osControlPoints );
301 :
302 0 : return CE_None;
303 : }
304 :
305 : /************************************************************************/
306 : /* GetProjectionRef() */
307 : /************************************************************************/
308 :
309 5 : const char *ERSDataset::GetProjectionRef()
310 :
311 : {
312 : // try xml first
313 5 : const char* pszPrj = GDALPamDataset::GetProjectionRef();
314 5 : if(pszPrj && strlen(pszPrj) > 0)
315 0 : return pszPrj;
316 :
317 5 : return pszProjection;
318 : }
319 :
320 : /************************************************************************/
321 : /* SetProjection() */
322 : /************************************************************************/
323 :
324 30 : CPLErr ERSDataset::SetProjection( const char *pszSRS )
325 :
326 : {
327 30 : if( pszProjection && EQUAL(pszSRS,pszProjection) )
328 0 : return CE_None;
329 :
330 30 : if( pszSRS == NULL )
331 0 : pszSRS = "";
332 :
333 30 : CPLFree( pszProjection );
334 30 : pszProjection = CPLStrdup(pszSRS);
335 :
336 30 : OGRSpatialReference oSRS( pszSRS );
337 : char szERSProj[32], szERSDatum[32], szERSUnits[32];
338 :
339 30 : oSRS.exportToERM( szERSProj, szERSDatum, szERSUnits );
340 :
341 30 : bHDRDirty = TRUE;
342 : poHeader->Set( "CoordinateSpace.Datum",
343 30 : CPLString().Printf( "\"%s\"", szERSDatum ) );
344 : poHeader->Set( "CoordinateSpace.Projection",
345 30 : CPLString().Printf( "\"%s\"", szERSProj ) );
346 : poHeader->Set( "CoordinateSpace.CoordinateType",
347 30 : CPLString().Printf( "EN" ) );
348 : poHeader->Set( "CoordinateSpace.Units",
349 30 : CPLString().Printf( "\"%s\"", szERSUnits ) );
350 : poHeader->Set( "CoordinateSpace.Rotation",
351 30 : "0:0:0.0" );
352 :
353 : /* -------------------------------------------------------------------- */
354 : /* It seems that CoordinateSpace needs to come before */
355 : /* RasterInfo. Try moving it up manually. */
356 : /* -------------------------------------------------------------------- */
357 30 : int iRasterInfo = -1;
358 30 : int iCoordSpace = -1;
359 : int i;
360 :
361 210 : for( i = 0; i < poHeader->nItemCount; i++ )
362 : {
363 210 : if( EQUAL(poHeader->papszItemName[i],"RasterInfo") )
364 30 : iRasterInfo = i;
365 :
366 210 : if( EQUAL(poHeader->papszItemName[i],"CoordinateSpace") )
367 : {
368 30 : iCoordSpace = i;
369 30 : break;
370 : }
371 : }
372 :
373 30 : if( iCoordSpace > iRasterInfo && iRasterInfo != -1 )
374 : {
375 60 : for( i = iCoordSpace; i > 0 && i != iRasterInfo; i-- )
376 : {
377 : char *pszTemp;
378 :
379 30 : ERSHdrNode *poTemp = poHeader->papoItemChild[i];
380 30 : poHeader->papoItemChild[i] = poHeader->papoItemChild[i-1];
381 30 : poHeader->papoItemChild[i-1] = poTemp;
382 :
383 30 : pszTemp = poHeader->papszItemName[i];
384 30 : poHeader->papszItemName[i] = poHeader->papszItemName[i-1];
385 30 : poHeader->papszItemName[i-1] = pszTemp;
386 :
387 30 : pszTemp = poHeader->papszItemValue[i];
388 30 : poHeader->papszItemValue[i] = poHeader->papszItemValue[i-1];
389 30 : poHeader->papszItemValue[i-1] = pszTemp;
390 : }
391 : }
392 :
393 30 : return CE_None;
394 : }
395 :
396 : /************************************************************************/
397 : /* GetGeoTransform() */
398 : /************************************************************************/
399 :
400 3 : CPLErr ERSDataset::GetGeoTransform( double * padfTransform )
401 :
402 : {
403 3 : if( bGotTransform )
404 : {
405 3 : memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
406 3 : return CE_None;
407 : }
408 : else
409 : {
410 0 : return GDALPamDataset::GetGeoTransform( padfTransform );
411 : }
412 : }
413 :
414 : /************************************************************************/
415 : /* SetGeoTransform() */
416 : /************************************************************************/
417 :
418 30 : CPLErr ERSDataset::SetGeoTransform( double *padfTransform )
419 :
420 : {
421 30 : if( memcmp( padfTransform, adfGeoTransform, sizeof(double)*6 ) == 0 )
422 0 : return CE_None;
423 :
424 30 : if( adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0 )
425 : {
426 : CPLError( CE_Failure, CPLE_AppDefined,
427 0 : "Rotated and skewed geotransforms not currently supported for ERS driver." );
428 0 : return CE_Failure;
429 : }
430 :
431 30 : bGotTransform = TRUE;
432 30 : memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
433 :
434 30 : bHDRDirty = TRUE;
435 :
436 : poHeader->Set( "RasterInfo.CellInfo.Xdimension",
437 30 : CPLString().Printf( "%.15g", fabs(adfGeoTransform[1]) ) );
438 : poHeader->Set( "RasterInfo.CellInfo.Ydimension",
439 60 : CPLString().Printf( "%.15g", fabs(adfGeoTransform[5]) ) );
440 : poHeader->Set( "RasterInfo.RegistrationCoord.Eastings",
441 60 : CPLString().Printf( "%.15g", adfGeoTransform[0] ) );
442 : poHeader->Set( "RasterInfo.RegistrationCoord.Northings",
443 60 : CPLString().Printf( "%.15g", adfGeoTransform[3] ) );
444 :
445 30 : return CE_None;
446 : }
447 :
448 : /************************************************************************/
449 : /* ERSDMS2Dec() */
450 : /* */
451 : /* Convert ERS DMS format to decimal degrees. Input is like */
452 : /* "-180:00:00". */
453 : /************************************************************************/
454 :
455 4 : static double ERSDMS2Dec( const char *pszDMS )
456 :
457 : {
458 4 : char **papszTokens = CSLTokenizeStringComplex( pszDMS, ":", FALSE, FALSE );
459 :
460 4 : if( CSLCount(papszTokens) != 3 )
461 : {
462 0 : return CPLAtof( pszDMS );
463 : }
464 : else
465 : {
466 : double dfResult = fabs(CPLAtof(papszTokens[0]))
467 : + CPLAtof(papszTokens[1]) / 60.0
468 4 : + CPLAtof(papszTokens[2]) / 3600.0;
469 :
470 4 : if( CPLAtof(papszTokens[0]) < 0 )
471 3 : dfResult *= -1;
472 :
473 4 : CSLDestroy( papszTokens );
474 4 : return dfResult;
475 : }
476 : }
477 :
478 : /************************************************************************/
479 : /* GetFileList() */
480 : /************************************************************************/
481 :
482 3 : char **ERSDataset::GetFileList()
483 :
484 : {
485 3 : char **papszFileList = NULL;
486 :
487 : // Main data file, etc.
488 3 : papszFileList = GDALPamDataset::GetFileList();
489 :
490 : // Add raw data file if we have one.
491 3 : if( strlen(osRawFilename) > 0 )
492 3 : papszFileList = CSLAddString( papszFileList, osRawFilename );
493 :
494 : // If we have a dependent file, merge it's list of files in.
495 3 : if( poDepFile )
496 : {
497 0 : char **papszDepFiles = poDepFile->GetFileList();
498 : papszFileList =
499 0 : CSLInsertStrings( papszFileList, -1, papszDepFiles );
500 0 : CSLDestroy( papszDepFiles );
501 : }
502 :
503 3 : return papszFileList;
504 : }
505 :
506 : /************************************************************************/
507 : /* ReadGCPs() */
508 : /* */
509 : /* Read the GCPs from the header. */
510 : /************************************************************************/
511 :
512 0 : void ERSDataset::ReadGCPs()
513 :
514 : {
515 : const char *pszCP =
516 0 : poHeader->Find( "RasterInfo.WarpControl.ControlPoints", NULL );
517 :
518 0 : if( pszCP == NULL )
519 0 : return;
520 :
521 : /* -------------------------------------------------------------------- */
522 : /* Parse the control points. They will look something like: */
523 : /* */
524 : /* "1035" Yes No 2344.650885 3546.419458 483270.73 3620906.21 3.105 */
525 : /* -------------------------------------------------------------------- */
526 0 : char **papszTokens = CSLTokenizeStringComplex( pszCP, "{ \t}", TRUE,FALSE);
527 : int nItemsPerLine;
528 0 : int nItemCount = CSLCount(papszTokens);
529 :
530 : /* -------------------------------------------------------------------- */
531 : /* Work out if we have elevation values or not. */
532 : /* -------------------------------------------------------------------- */
533 0 : if( nItemCount == 7 )
534 0 : nItemsPerLine = 7;
535 0 : else if( nItemCount == 8 )
536 0 : nItemsPerLine = 8;
537 0 : else if( nItemCount < 14 )
538 : {
539 0 : CPLAssert( FALSE );
540 0 : return;
541 : }
542 0 : else if( EQUAL(papszTokens[8],"Yes") || EQUAL(papszTokens[8],"No") )
543 0 : nItemsPerLine = 7;
544 0 : else if( EQUAL(papszTokens[9],"Yes") || EQUAL(papszTokens[9],"No") )
545 0 : nItemsPerLine = 8;
546 : else
547 : {
548 0 : CPLAssert( FALSE );
549 0 : return;
550 : }
551 :
552 : /* -------------------------------------------------------------------- */
553 : /* Setup GCPs. */
554 : /* -------------------------------------------------------------------- */
555 : int iGCP;
556 :
557 0 : CPLAssert( nGCPCount == 0 );
558 :
559 0 : nGCPCount = nItemCount / nItemsPerLine;
560 0 : pasGCPList = (GDAL_GCP *) CPLCalloc(nGCPCount,sizeof(GDAL_GCP));
561 0 : GDALInitGCPs( nGCPCount, pasGCPList );
562 :
563 0 : for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
564 : {
565 0 : GDAL_GCP *psGCP = pasGCPList + iGCP;
566 :
567 0 : CPLFree( psGCP->pszId );
568 0 : psGCP->pszId = CPLStrdup(papszTokens[iGCP*nItemsPerLine+0]);
569 0 : psGCP->dfGCPPixel = atof(papszTokens[iGCP*nItemsPerLine+3]);
570 0 : psGCP->dfGCPLine = atof(papszTokens[iGCP*nItemsPerLine+4]);
571 0 : psGCP->dfGCPX = atof(papszTokens[iGCP*nItemsPerLine+5]);
572 0 : psGCP->dfGCPY = atof(papszTokens[iGCP*nItemsPerLine+6]);
573 0 : if( nItemsPerLine == 8 )
574 0 : psGCP->dfGCPZ = atof(papszTokens[iGCP*nItemsPerLine+7]);
575 : }
576 :
577 0 : CSLDestroy( papszTokens );
578 :
579 : /* -------------------------------------------------------------------- */
580 : /* Parse the GCP projection. */
581 : /* -------------------------------------------------------------------- */
582 0 : OGRSpatialReference oSRS;
583 :
584 : CPLString osProjection = poHeader->Find(
585 0 : "RasterInfo.WarpControl.CoordinateSpace.Projection", "RAW" );
586 : CPLString osDatum = poHeader->Find(
587 0 : "RasterInfo.WarpControl.CoordinateSpace.Datum", "WGS84" );
588 : CPLString osUnits = poHeader->Find(
589 0 : "RasterInfo.WarpControl.CoordinateSpace.Units", "METERS" );
590 :
591 0 : oSRS.importFromERM( osProjection, osDatum, osUnits );
592 :
593 0 : CPLFree( pszGCPProjection );
594 0 : oSRS.exportToWkt( &pszGCPProjection );
595 : }
596 :
597 : /************************************************************************/
598 : /* Open() */
599 : /************************************************************************/
600 :
601 10286 : GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
602 :
603 : {
604 : /* -------------------------------------------------------------------- */
605 : /* We assume the user selects the .ers file. */
606 : /* -------------------------------------------------------------------- */
607 10286 : if( poOpenInfo->nHeaderBytes > 15
608 : && EQUALN((const char *) poOpenInfo->pabyHeader,"Algorithm Begin",15) )
609 : {
610 : CPLError( CE_Failure, CPLE_OpenFailed,
611 : "%s appears to be an algorithm ERS file, which is not currently supported.",
612 0 : poOpenInfo->pszFilename );
613 0 : return NULL;
614 : }
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* We assume the user selects the .ers file. */
618 : /* -------------------------------------------------------------------- */
619 10286 : if( poOpenInfo->nHeaderBytes < 15
620 : || !EQUALN((const char *) poOpenInfo->pabyHeader,"DatasetHeader ",14) )
621 10246 : return NULL;
622 :
623 : /* -------------------------------------------------------------------- */
624 : /* Open the .ers file, and read the first line. */
625 : /* -------------------------------------------------------------------- */
626 40 : FILE *fpERS = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
627 :
628 40 : if( fpERS == NULL )
629 0 : return NULL;
630 :
631 40 : CPLReadLineL( fpERS );
632 :
633 : /* -------------------------------------------------------------------- */
634 : /* Now ingest the rest of the file as a tree of header nodes. */
635 : /* -------------------------------------------------------------------- */
636 40 : ERSHdrNode *poHeader = new ERSHdrNode();
637 :
638 40 : if( !poHeader->ParseChildren( fpERS ) )
639 : {
640 0 : delete poHeader;
641 0 : VSIFCloseL( fpERS );
642 0 : return NULL;
643 : }
644 :
645 40 : VSIFCloseL( fpERS );
646 :
647 : /* -------------------------------------------------------------------- */
648 : /* Do we have the minimum required information from this header? */
649 : /* -------------------------------------------------------------------- */
650 40 : if( poHeader->Find( "RasterInfo.NrOfLines" ) == NULL
651 : || poHeader->Find( "RasterInfo.NrOfCellsPerLine" ) == NULL
652 : || poHeader->Find( "RasterInfo.NrOfBands" ) == NULL )
653 : {
654 0 : if( poHeader->FindNode( "Algorithm" ) != NULL )
655 : {
656 : CPLError( CE_Failure, CPLE_OpenFailed,
657 : "%s appears to be an algorithm ERS file, which is not currently supported.",
658 0 : poOpenInfo->pszFilename );
659 : }
660 0 : delete poHeader;
661 0 : return NULL;
662 : }
663 :
664 : /* -------------------------------------------------------------------- */
665 : /* Create a corresponding GDALDataset. */
666 : /* -------------------------------------------------------------------- */
667 : ERSDataset *poDS;
668 :
669 40 : poDS = new ERSDataset();
670 40 : poDS->poHeader = poHeader;
671 40 : poDS->eAccess = poOpenInfo->eAccess;
672 :
673 : /* -------------------------------------------------------------------- */
674 : /* Capture some information from the file that is of interest. */
675 : /* -------------------------------------------------------------------- */
676 40 : int nBands = atoi(poHeader->Find( "RasterInfo.NrOfBands" ));
677 40 : poDS->nRasterXSize = atoi(poHeader->Find( "RasterInfo.NrOfCellsPerLine" ));
678 40 : poDS->nRasterYSize = atoi(poHeader->Find( "RasterInfo.NrOfLines" ));
679 :
680 80 : if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
681 : !GDALCheckBandCount(nBands, FALSE))
682 : {
683 0 : delete poDS;
684 0 : return NULL;
685 : }
686 :
687 : /* -------------------------------------------------------------------- */
688 : /* Get the HeaderOffset if it exists in the header */
689 : /* -------------------------------------------------------------------- */
690 40 : GIntBig nHeaderOffset = 0;
691 40 : if( poHeader->Find( "HeaderOffset" ) != NULL )
692 : {
693 1 : nHeaderOffset = atoi(poHeader->Find( "HeaderOffset" ));
694 : }
695 :
696 : /* -------------------------------------------------------------------- */
697 : /* Establish the data type. */
698 : /* -------------------------------------------------------------------- */
699 : GDALDataType eType;
700 : CPLString osCellType = poHeader->Find( "RasterInfo.CellType",
701 40 : "Unsigned8BitInteger" );
702 40 : if( EQUAL(osCellType,"Unsigned8BitInteger") )
703 13 : eType = GDT_Byte;
704 27 : else if( EQUAL(osCellType,"Signed8BitInteger") )
705 4 : eType = GDT_Byte;
706 23 : else if( EQUAL(osCellType,"Unsigned16BitInteger") )
707 3 : eType = GDT_UInt16;
708 20 : else if( EQUAL(osCellType,"Signed16BitInteger") )
709 4 : eType = GDT_Int16;
710 16 : else if( EQUAL(osCellType,"Unsigned32BitInteger") )
711 3 : eType = GDT_UInt32;
712 13 : else if( EQUAL(osCellType,"Signed32BitInteger") )
713 3 : eType = GDT_Int32;
714 10 : else if( EQUAL(osCellType,"IEEE4ByteReal") )
715 7 : eType = GDT_Float32;
716 3 : else if( EQUAL(osCellType,"IEEE8ByteReal") )
717 3 : eType = GDT_Float64;
718 : else
719 : {
720 0 : CPLDebug( "ERS", "Unknown CellType '%s'", osCellType.c_str() );
721 0 : eType = GDT_Byte;
722 : }
723 :
724 : /* -------------------------------------------------------------------- */
725 : /* Pick up the word order. */
726 : /* -------------------------------------------------------------------- */
727 : int bNative;
728 :
729 : #ifdef CPL_LSB
730 40 : bNative = EQUAL(poHeader->Find( "ByteOrder", "LSBFirst" ),
731 : "LSBFirst");
732 : #else
733 : bNative = EQUAL(poHeader->Find( "ByteOrder", "MSBFirst" ),
734 : "MSBFirst");
735 : #endif
736 :
737 : /* -------------------------------------------------------------------- */
738 : /* Figure out the name of the target file. */
739 : /* -------------------------------------------------------------------- */
740 40 : CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
741 40 : CPLString osDataFile = poHeader->Find( "DataFile", "" );
742 40 : CPLString osDataFilePath;
743 :
744 40 : if( osDataFile.length() == 0 ) // just strip off extension.
745 : {
746 40 : osDataFile = CPLGetFilename( poOpenInfo->pszFilename );
747 40 : osDataFile = osDataFile.substr( 0, osDataFile.find_last_of('.') );
748 : }
749 :
750 40 : osDataFilePath = CPLFormFilename( osPath, osDataFile, NULL );
751 :
752 : /* -------------------------------------------------------------------- */
753 : /* DataSetType = Translated files are links to things like ecw */
754 : /* files. */
755 : /* -------------------------------------------------------------------- */
756 40 : if( EQUAL(poHeader->Find("DataSetType",""),"Translated") )
757 : {
758 : poDS->poDepFile = (GDALDataset *)
759 0 : GDALOpenShared( osDataFilePath, poOpenInfo->eAccess );
760 :
761 0 : if( poDS->poDepFile != NULL
762 : && poDS->poDepFile->GetRasterCount() >= nBands )
763 : {
764 : int iBand;
765 :
766 0 : for( iBand = 0; iBand < nBands; iBand++ )
767 : {
768 : // Assume pixel interleaved.
769 : poDS->SetBand( iBand+1,
770 0 : poDS->poDepFile->GetRasterBand( iBand+1 ) );
771 : }
772 : }
773 : }
774 :
775 : /* ==================================================================== */
776 : /* While ERStorage indicates a raw file. */
777 : /* ==================================================================== */
778 40 : else if( EQUAL(poHeader->Find("DataSetType",""),"ERStorage") )
779 : {
780 : // Open data file.
781 40 : if( poOpenInfo->eAccess == GA_Update )
782 31 : poDS->fpImage = VSIFOpenL( osDataFilePath, "r+" );
783 : else
784 9 : poDS->fpImage = VSIFOpenL( osDataFilePath, "r" );
785 :
786 40 : poDS->osRawFilename = osDataFilePath;
787 :
788 40 : if( poDS->fpImage != NULL )
789 : {
790 40 : int iWordSize = GDALGetDataTypeSize(eType) / 8;
791 : int iBand;
792 :
793 126 : for( iBand = 0; iBand < nBands; iBand++ )
794 : {
795 : // Assume pixel interleaved.
796 : poDS->SetBand(
797 : iBand+1,
798 : new RawRasterBand( poDS, iBand+1, poDS->fpImage,
799 : nHeaderOffset
800 : + iWordSize * iBand * poDS->nRasterXSize,
801 : iWordSize,
802 : iWordSize * nBands * poDS->nRasterXSize,
803 86 : eType, bNative, TRUE ));
804 86 : if( EQUAL(osCellType,"Signed8BitInteger") )
805 : poDS->GetRasterBand(iBand+1)->
806 : SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE",
807 12 : "IMAGE_STRUCTURE" );
808 : }
809 : }
810 : }
811 :
812 : /* -------------------------------------------------------------------- */
813 : /* Otherwise we have an error! */
814 : /* -------------------------------------------------------------------- */
815 40 : if( poDS->nBands == 0 )
816 : {
817 0 : delete poDS;
818 40 : return NULL;
819 : }
820 :
821 : /* -------------------------------------------------------------------- */
822 : /* Look for band descriptions. */
823 : /* -------------------------------------------------------------------- */
824 40 : int iChild, iBand = 0;
825 40 : ERSHdrNode *poRI = poHeader->FindNode( "RasterInfo" );
826 :
827 227 : for( iChild = 0;
828 : poRI != NULL && iChild < poRI->nItemCount && iBand < poDS->nBands;
829 : iChild++ )
830 : {
831 187 : if( poRI->papoItemChild[iChild] != NULL
832 : && EQUAL(poRI->papszItemName[iChild],"BandId") )
833 : {
834 : const char *pszValue =
835 8 : poRI->papoItemChild[iChild]->Find( "Value", NULL );
836 :
837 8 : iBand++;
838 8 : if( pszValue )
839 : {
840 8 : CPLPushErrorHandler( CPLQuietErrorHandler );
841 8 : poDS->GetRasterBand( iBand )->SetDescription( pszValue );
842 8 : CPLPopErrorHandler();
843 : }
844 : }
845 : }
846 :
847 : /* -------------------------------------------------------------------- */
848 : /* Look for projection. */
849 : /* -------------------------------------------------------------------- */
850 40 : OGRSpatialReference oSRS;
851 :
852 : CPLString osProjection = poHeader->Find( "CoordinateSpace.Projection",
853 40 : "RAW" );
854 40 : CPLString osDatum = poHeader->Find( "CoordinateSpace.Datum", "WGS84" );
855 40 : CPLString osUnits = poHeader->Find( "CoordinateSpace.Units", "METERS" );
856 :
857 40 : oSRS.importFromERM( osProjection, osDatum, osUnits );
858 :
859 40 : CPLFree( poDS->pszProjection );
860 40 : oSRS.exportToWkt( &(poDS->pszProjection) );
861 :
862 : /* -------------------------------------------------------------------- */
863 : /* Look for the geotransform. */
864 : /* -------------------------------------------------------------------- */
865 40 : if( poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", NULL )
866 : && poHeader->Find( "RasterInfo.CellInfo.Xdimension", NULL ) )
867 : {
868 5 : poDS->bGotTransform = TRUE;
869 : poDS->adfGeoTransform[0] = CPLAtof(
870 5 : poHeader->Find( "RasterInfo.RegistrationCoord.Eastings", "" ));
871 : poDS->adfGeoTransform[1] = CPLAtof(
872 5 : poHeader->Find( "RasterInfo.CellInfo.Xdimension", "" ));
873 5 : poDS->adfGeoTransform[2] = 0.0;
874 : poDS->adfGeoTransform[3] = CPLAtof(
875 5 : poHeader->Find( "RasterInfo.RegistrationCoord.Northings", "" ));
876 5 : poDS->adfGeoTransform[4] = 0.0;
877 : poDS->adfGeoTransform[5] = -CPLAtof(
878 5 : poHeader->Find( "RasterInfo.CellInfo.Ydimension", "" ));
879 : }
880 35 : else if( poHeader->Find( "RasterInfo.RegistrationCoord.Latitude", NULL )
881 : && poHeader->Find( "RasterInfo.CellInfo.Xdimension", NULL ) )
882 : {
883 2 : poDS->bGotTransform = TRUE;
884 : poDS->adfGeoTransform[0] = ERSDMS2Dec(
885 2 : poHeader->Find( "RasterInfo.RegistrationCoord.Longitude", "" ));
886 : poDS->adfGeoTransform[1] = CPLAtof(
887 2 : poHeader->Find( "RasterInfo.CellInfo.Xdimension", "" ));
888 2 : poDS->adfGeoTransform[2] = 0.0;
889 : poDS->adfGeoTransform[3] = ERSDMS2Dec(
890 2 : poHeader->Find( "RasterInfo.RegistrationCoord.Latitude", "" ));
891 2 : poDS->adfGeoTransform[4] = 0.0;
892 : poDS->adfGeoTransform[5] = -CPLAtof(
893 2 : poHeader->Find( "RasterInfo.CellInfo.Ydimension", "" ));
894 : }
895 :
896 : /* -------------------------------------------------------------------- */
897 : /* Adjust if we have a registration cell. */
898 : /* -------------------------------------------------------------------- */
899 40 : int iCellX = atoi(poHeader->Find("RasterInfo.RegistrationCellX", "1"));
900 40 : int iCellY = atoi(poHeader->Find("RasterInfo.RegistrationCellY", "1"));
901 :
902 40 : if( poDS->bGotTransform )
903 : {
904 : poDS->adfGeoTransform[0] -=
905 : (iCellX-1) * poDS->adfGeoTransform[1]
906 7 : + (iCellY-1) * poDS->adfGeoTransform[2];
907 : poDS->adfGeoTransform[3] -=
908 : (iCellX-1) * poDS->adfGeoTransform[4]
909 7 : + (iCellY-1) * poDS->adfGeoTransform[5];
910 : }
911 :
912 : /* -------------------------------------------------------------------- */
913 : /* Check for null values. */
914 : /* -------------------------------------------------------------------- */
915 40 : if( poHeader->Find( "RasterInfo.NullCellValue", NULL ) )
916 : {
917 2 : CPLPushErrorHandler( CPLQuietErrorHandler );
918 :
919 4 : for( iBand = 1; iBand <= poDS->nBands; iBand++ )
920 : poDS->GetRasterBand(iBand)->SetNoDataValue(
921 2 : CPLAtofM(poHeader->Find( "RasterInfo.NullCellValue" )) );
922 :
923 2 : CPLPopErrorHandler();
924 : }
925 :
926 : /* -------------------------------------------------------------------- */
927 : /* Do we have an "All" region? */
928 : /* -------------------------------------------------------------------- */
929 40 : ERSHdrNode *poAll = NULL;
930 :
931 229 : for( iChild = 0;
932 : poRI != NULL && iChild < poRI->nItemCount;
933 : iChild++ )
934 : {
935 189 : if( poRI->papoItemChild[iChild] != NULL
936 : && EQUAL(poRI->papszItemName[iChild],"RegionInfo") )
937 : {
938 0 : if( EQUAL(poRI->papoItemChild[iChild]->Find("RegionName",""),
939 : "All") )
940 0 : poAll = poRI->papoItemChild[iChild];
941 : }
942 : }
943 :
944 : /* -------------------------------------------------------------------- */
945 : /* Do we have statistics? */
946 : /* -------------------------------------------------------------------- */
947 40 : if( poAll && poAll->FindNode( "Stats" ) )
948 : {
949 0 : CPLPushErrorHandler( CPLQuietErrorHandler );
950 :
951 0 : for( iBand = 1; iBand <= poDS->nBands; iBand++ )
952 : {
953 : const char *pszValue =
954 0 : poAll->FindElem( "Stats.MinimumValue", iBand-1 );
955 :
956 0 : if( pszValue )
957 : poDS->GetRasterBand(iBand)->SetMetadataItem(
958 0 : "STATISTICS_MINIMUM", pszValue );
959 :
960 0 : pszValue = poAll->FindElem( "Stats.MaximumValue", iBand-1 );
961 :
962 0 : if( pszValue )
963 : poDS->GetRasterBand(iBand)->SetMetadataItem(
964 0 : "STATISTICS_MAXIMUM", pszValue );
965 :
966 0 : pszValue = poAll->FindElem( "Stats.MeanValue", iBand-1 );
967 :
968 0 : if( pszValue )
969 : poDS->GetRasterBand(iBand)->SetMetadataItem(
970 0 : "STATISTICS_MEAN", pszValue );
971 :
972 0 : pszValue = poAll->FindElem( "Stats.MedianValue", iBand-1 );
973 :
974 0 : if( pszValue )
975 : poDS->GetRasterBand(iBand)->SetMetadataItem(
976 0 : "STATISTICS_MEDIAN", pszValue );
977 : }
978 :
979 0 : CPLPopErrorHandler();
980 :
981 : }
982 :
983 : /* -------------------------------------------------------------------- */
984 : /* Do we have GCPs. */
985 : /* -------------------------------------------------------------------- */
986 40 : if( poHeader->FindNode( "RasterInfo.WarpControl" ) )
987 0 : poDS->ReadGCPs();
988 :
989 : /* -------------------------------------------------------------------- */
990 : /* Initialize any PAM information. */
991 : /* -------------------------------------------------------------------- */
992 40 : poDS->SetDescription( poOpenInfo->pszFilename );
993 40 : poDS->TryLoadXML();
994 :
995 : // if no SR in xml, try aux
996 40 : const char* pszPrj = poDS->GDALPamDataset::GetProjectionRef();
997 40 : if( !pszPrj || strlen(pszPrj) == 0 )
998 : {
999 : // try aux
1000 40 : GDALDataset* poAuxDS = GDALFindAssociatedAuxFile( poOpenInfo->pszFilename, GA_ReadOnly, poDS );
1001 40 : if( poAuxDS )
1002 : {
1003 0 : pszPrj = poAuxDS->GetProjectionRef();
1004 0 : if( pszPrj && strlen(pszPrj) > 0 )
1005 : {
1006 0 : CPLFree( poDS->pszProjection );
1007 0 : poDS->pszProjection = CPLStrdup(pszPrj);
1008 : }
1009 :
1010 0 : GDALClose( poAuxDS );
1011 : }
1012 : }
1013 : /* -------------------------------------------------------------------- */
1014 : /* Check for overviews. */
1015 : /* -------------------------------------------------------------------- */
1016 40 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
1017 :
1018 40 : return( poDS );
1019 : }
1020 :
1021 : /************************************************************************/
1022 : /* Create() */
1023 : /************************************************************************/
1024 :
1025 : GDALDataset *ERSDataset::Create( const char * pszFilename,
1026 : int nXSize, int nYSize, int nBands,
1027 44 : GDALDataType eType, char ** papszOptions )
1028 :
1029 : {
1030 : /* -------------------------------------------------------------------- */
1031 : /* Verify settings. */
1032 : /* -------------------------------------------------------------------- */
1033 44 : if (nBands <= 0)
1034 : {
1035 : CPLError( CE_Failure, CPLE_NotSupported,
1036 1 : "ERS driver does not support %d bands.\n", nBands);
1037 1 : return NULL;
1038 : }
1039 :
1040 43 : if( eType != GDT_Byte && eType != GDT_Int16 && eType != GDT_UInt16
1041 : && eType != GDT_Int32 && eType != GDT_UInt32
1042 : && eType != GDT_Float32 && eType != GDT_Float64 )
1043 : {
1044 : CPLError( CE_Failure, CPLE_AppDefined,
1045 : "The ERS driver does not supporting creating files of types %s.",
1046 12 : GDALGetDataTypeName( eType ) );
1047 12 : return NULL;
1048 : }
1049 :
1050 : /* -------------------------------------------------------------------- */
1051 : /* Work out the name we want to use for the .ers and binary */
1052 : /* data files. */
1053 : /* -------------------------------------------------------------------- */
1054 31 : CPLString osBinFile, osErsFile;
1055 :
1056 31 : if( EQUAL(CPLGetExtension( pszFilename ), "ers") )
1057 : {
1058 3 : osErsFile = pszFilename;
1059 3 : osBinFile = osErsFile.substr(0,osErsFile.length()-4);
1060 : }
1061 : else
1062 : {
1063 28 : osBinFile = pszFilename;
1064 28 : osErsFile = osBinFile + ".ers";
1065 : }
1066 :
1067 : /* -------------------------------------------------------------------- */
1068 : /* Work out some values we will write. */
1069 : /* -------------------------------------------------------------------- */
1070 31 : const char *pszCellType = "Unsigned8BitInteger";
1071 :
1072 31 : if( eType == GDT_Byte )
1073 12 : pszCellType = "Unsigned8BitInteger";
1074 19 : else if( eType == GDT_Int16 )
1075 3 : pszCellType = "Signed16BitInteger";
1076 16 : else if( eType == GDT_UInt16 )
1077 3 : pszCellType = "Unsigned16BitInteger";
1078 13 : else if( eType == GDT_Int32 )
1079 3 : pszCellType = "Signed32BitInteger";
1080 10 : else if( eType == GDT_UInt32 )
1081 3 : pszCellType = "Unsigned32BitInteger";
1082 7 : else if( eType == GDT_Float32 )
1083 4 : pszCellType = "IEEE4ByteReal";
1084 3 : else if( eType == GDT_Float64 )
1085 3 : pszCellType = "IEEE8ByteReal";
1086 : else
1087 : {
1088 0 : CPLAssert( FALSE );
1089 : }
1090 :
1091 : /* -------------------------------------------------------------------- */
1092 : /* Handling for signed eight bit data. */
1093 : /* -------------------------------------------------------------------- */
1094 31 : const char *pszPixelType = CSLFetchNameValue( papszOptions, "PIXELTYPE" );
1095 31 : if( pszPixelType
1096 : && EQUAL(pszPixelType,"SIGNEDBYTE")
1097 : && eType == GDT_Byte )
1098 1 : pszCellType = "Signed8BitInteger";
1099 :
1100 : /* -------------------------------------------------------------------- */
1101 : /* Write binary file. */
1102 : /* -------------------------------------------------------------------- */
1103 : GUIntBig nSize;
1104 31 : GByte byZero = 0;
1105 :
1106 31 : FILE *fpBin = VSIFOpenL( osBinFile, "w" );
1107 :
1108 31 : if( fpBin == NULL )
1109 : {
1110 : CPLError( CE_Failure, CPLE_FileIO,
1111 : "Failed to create %s:\n%s",
1112 0 : osBinFile.c_str(), VSIStrerror( errno ) );
1113 31 : return NULL;
1114 : }
1115 :
1116 : nSize = nXSize * (GUIntBig) nYSize
1117 31 : * nBands * (GDALGetDataTypeSize(eType) / 8);
1118 31 : if( VSIFSeekL( fpBin, nSize-1, SEEK_SET ) != 0
1119 : || VSIFWriteL( &byZero, 1, 1, fpBin ) != 1 )
1120 : {
1121 : CPLError( CE_Failure, CPLE_FileIO,
1122 : "Failed to write %s:\n%s",
1123 0 : osBinFile.c_str(), VSIStrerror( errno ) );
1124 0 : VSIFCloseL( fpBin );
1125 0 : return NULL;
1126 : }
1127 31 : VSIFCloseL( fpBin );
1128 :
1129 :
1130 : /* -------------------------------------------------------------------- */
1131 : /* Try writing header file. */
1132 : /* -------------------------------------------------------------------- */
1133 31 : FILE *fpERS = VSIFOpenL( osErsFile, "w" );
1134 :
1135 31 : if( fpERS == NULL )
1136 : {
1137 : CPLError( CE_Failure, CPLE_FileIO,
1138 : "Failed to create %s:\n%s",
1139 0 : osErsFile.c_str(), VSIStrerror( errno ) );
1140 0 : return NULL;
1141 : }
1142 :
1143 31 : VSIFPrintfL( fpERS, "DatasetHeader Begin\n" );
1144 31 : VSIFPrintfL( fpERS, "\tVersion\t\t = \"6.0\"\n" );
1145 31 : VSIFPrintfL( fpERS, "\tName\t\t= \"%s\"\n", CPLGetFilename(osErsFile) );
1146 :
1147 : // Last updated requires timezone info which we don't necessarily get
1148 : // get from VSICTime() so perhaps it is better to omit this.
1149 : // VSIFPrintfL( fpERS, "\tLastUpdated\t= %s",
1150 : // VSICTime( VSITime( NULL ) ) );
1151 :
1152 31 : VSIFPrintfL( fpERS, "\tDataSetType\t= ERStorage\n" );
1153 31 : VSIFPrintfL( fpERS, "\tDataType\t= Raster\n" );
1154 31 : VSIFPrintfL( fpERS, "\tByteOrder\t= LSBFirst\n" );
1155 31 : VSIFPrintfL( fpERS, "\tRasterInfo Begin\n" );
1156 31 : VSIFPrintfL( fpERS, "\t\tCellType\t= %s\n", pszCellType );
1157 31 : VSIFPrintfL( fpERS, "\t\tNrOfLines\t= %d\n", nYSize );
1158 31 : VSIFPrintfL( fpERS, "\t\tNrOfCellsPerLine\t= %d\n", nXSize );
1159 31 : VSIFPrintfL( fpERS, "\t\tNrOfBands\t= %d\n", nBands );
1160 31 : VSIFPrintfL( fpERS, "\tRasterInfo End\n" );
1161 31 : if( VSIFPrintfL( fpERS, "DatasetHeader End\n" ) < 17 )
1162 : {
1163 : CPLError( CE_Failure, CPLE_FileIO,
1164 : "Failed to write %s:\n%s",
1165 0 : osErsFile.c_str(), VSIStrerror( errno ) );
1166 0 : return NULL;
1167 : }
1168 :
1169 31 : VSIFCloseL( fpERS );
1170 :
1171 : /* -------------------------------------------------------------------- */
1172 : /* Reopen. */
1173 : /* -------------------------------------------------------------------- */
1174 31 : return (GDALDataset *) GDALOpen( osErsFile, GA_Update );
1175 : }
1176 :
1177 : /************************************************************************/
1178 : /* GDALRegister_ERS() */
1179 : /************************************************************************/
1180 :
1181 409 : void GDALRegister_ERS()
1182 :
1183 : {
1184 : GDALDriver *poDriver;
1185 :
1186 409 : if( GDALGetDriverByName( "ERS" ) == NULL )
1187 : {
1188 392 : poDriver = new GDALDriver();
1189 :
1190 392 : poDriver->SetDescription( "ERS" );
1191 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1192 392 : "ERMapper .ers Labelled" );
1193 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1194 392 : "frmt_ers.html" );
1195 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
1196 392 : "Byte Int16 UInt16 Int32 UInt32 Float32 Float64" );
1197 :
1198 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
1199 : "<CreationOptionList>"
1200 : " <Option name='PIXELTYPE' type='string' description='By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte'/>"
1201 392 : "</CreationOptionList>" );
1202 :
1203 392 : poDriver->pfnOpen = ERSDataset::Open;
1204 392 : poDriver->pfnCreate = ERSDataset::Create;
1205 :
1206 392 : GetGDALDriverManager()->RegisterDriver( poDriver );
1207 : }
1208 409 : }
|