1 : /******************************************************************************
2 : * $Id: srpdataset.cpp 23124 2011-09-27 16:55:26Z rouault $
3 : * Purpose: ASRP/USRP Reader
4 : * Author: Frank Warmerdam (warmerdam@pobox.com)
5 : *
6 : * Derived from ADRG driver by Even Rouault, even.rouault at mines-paris.org.
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2007, Even Rouault
10 : * Copyright (c) 2009, Frank Warmerdam
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "gdal_pam.h"
32 : #include "ogr_spatialref.h"
33 : #include "cpl_string.h"
34 : #include "iso8211.h"
35 :
36 : CPL_CVSID("$Id: srpdataset.cpp 23124 2011-09-27 16:55:26Z rouault $");
37 :
38 : class SRPDataset : public GDALPamDataset
39 : {
40 : friend class SRPRasterBand;
41 :
42 : static CPLString ResetTo01( const char* str );
43 :
44 : VSILFILE* fdIMG;
45 : int* TILEINDEX;
46 : int offsetInIMG;
47 : CPLString osProduct;
48 : CPLString osSRS;
49 : CPLString osGENFilename;
50 : CPLString osQALFilename;
51 : int NFC;
52 : int NFL;
53 : int ZNA;
54 : double LSO;
55 : double PSO;
56 : double LOD;
57 : double LAD;
58 : int ARV;
59 : int BRV;
60 : int PCB;
61 : int PVB;
62 :
63 :
64 : int bGeoTransformValid;
65 : double adfGeoTransform[6];
66 :
67 : GDALColorTable oCT;
68 :
69 : public:
70 : SRPDataset();
71 : virtual ~SRPDataset();
72 :
73 : virtual const char *GetProjectionRef(void);
74 : virtual CPLErr GetGeoTransform( double * padfGeoTransform );
75 : virtual CPLErr SetGeoTransform( double * padfGeoTransform );
76 :
77 : virtual char **GetFileList();
78 :
79 : virtual char **GetMetadata( const char * pszDomain = "" );
80 :
81 : void AddSubDataset(const char* pszFilename);
82 :
83 : int GetFromRecord( const char* pszFileName,
84 : DDFRecord * record);
85 :
86 : static GDALDataset *Open( GDALOpenInfo * );
87 :
88 : static double GetLongitudeFromString(const char* str);
89 : static double GetLatitudeFromString(const char* str);
90 : };
91 :
92 : /************************************************************************/
93 : /* ==================================================================== */
94 : /* SRPRasterBand */
95 : /* ==================================================================== */
96 : /************************************************************************/
97 :
98 : class SRPRasterBand : public GDALPamRasterBand
99 0 : {
100 : friend class SRPDataset;
101 :
102 : public:
103 : SRPRasterBand( SRPDataset *, int );
104 :
105 : virtual CPLErr IReadBlock( int, int, void * );
106 :
107 : virtual double GetNoDataValue( int *pbSuccess = NULL );
108 :
109 : virtual GDALColorInterp GetColorInterpretation();
110 : virtual GDALColorTable *GetColorTable();
111 : };
112 :
113 :
114 : /************************************************************************/
115 : /* SRPRasterBand() */
116 : /************************************************************************/
117 :
118 0 : SRPRasterBand::SRPRasterBand( SRPDataset *poDS, int nBand )
119 :
120 : {
121 0 : this->poDS = poDS;
122 0 : this->nBand = nBand;
123 :
124 0 : eDataType = GDT_Byte;
125 :
126 0 : nBlockXSize = 128;
127 0 : nBlockYSize = 128;
128 0 : }
129 :
130 : /************************************************************************/
131 : /* GetNoDataValue() */
132 : /************************************************************************/
133 :
134 0 : double SRPRasterBand::GetNoDataValue( int *pbSuccess )
135 : {
136 0 : if (pbSuccess)
137 0 : *pbSuccess = TRUE;
138 :
139 0 : return 0;
140 : }
141 :
142 : /************************************************************************/
143 : /* GetColorInterpretation() */
144 : /************************************************************************/
145 :
146 0 : GDALColorInterp SRPRasterBand::GetColorInterpretation()
147 :
148 : {
149 0 : SRPDataset* poDS = (SRPDataset*)this->poDS;
150 :
151 0 : if( poDS->oCT.GetColorEntryCount() > 0 )
152 0 : return GCI_PaletteIndex;
153 : else
154 0 : return GCI_GrayIndex;
155 : }
156 :
157 : /************************************************************************/
158 : /* GetColorTable() */
159 : /************************************************************************/
160 :
161 0 : GDALColorTable *SRPRasterBand::GetColorTable()
162 :
163 : {
164 0 : SRPDataset* poDS = (SRPDataset*)this->poDS;
165 :
166 0 : if( poDS->oCT.GetColorEntryCount() > 0 )
167 0 : return &(poDS->oCT);
168 : else
169 0 : return NULL;
170 : }
171 :
172 : /************************************************************************/
173 : /* IReadBlock() */
174 : /************************************************************************/
175 :
176 0 : CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
177 : void * pImage )
178 :
179 : {
180 0 : SRPDataset* poDS = (SRPDataset*)this->poDS;
181 : int offset;
182 0 : int nBlock = nBlockYOff * poDS->NFC + nBlockXOff;
183 0 : if (nBlockXOff >= poDS->NFC || nBlockYOff >= poDS->NFL)
184 : {
185 : CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
186 0 : nBlockXOff, poDS->NFC, nBlockYOff, poDS->NFL);
187 0 : return CE_Failure;
188 : }
189 :
190 : /* -------------------------------------------------------------------- */
191 : /* Is this a null block? */
192 : /* -------------------------------------------------------------------- */
193 0 : if (poDS->TILEINDEX && poDS->TILEINDEX[nBlock] == 0)
194 : {
195 0 : memset(pImage, 0, 128 * 128);
196 0 : return CE_None;
197 : }
198 :
199 : /* -------------------------------------------------------------------- */
200 : /* Compute the offset to the block. */
201 : /* -------------------------------------------------------------------- */
202 0 : if (poDS->TILEINDEX)
203 : {
204 0 : if( poDS->PCB == 0 ) // uncompressed
205 0 : offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1) * 128 * 128;
206 : else // compressed
207 0 : offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1);
208 : }
209 : else
210 0 : offset = poDS->offsetInIMG + nBlock * 128 * 128;
211 :
212 : /* -------------------------------------------------------------------- */
213 : /* Seek to target location. */
214 : /* -------------------------------------------------------------------- */
215 0 : if (VSIFSeekL(poDS->fdIMG, offset, SEEK_SET) != 0)
216 : {
217 0 : CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
218 0 : return CE_Failure;
219 : }
220 :
221 : /* -------------------------------------------------------------------- */
222 : /* For uncompressed case we read the 128x128 and return with no */
223 : /* further processing. */
224 : /* -------------------------------------------------------------------- */
225 0 : if( poDS->PCB == 0 )
226 : {
227 0 : if( VSIFReadL(pImage, 1, 128 * 128, poDS->fdIMG) != 128*128 )
228 : {
229 : CPLError(CE_Failure, CPLE_FileIO,
230 0 : "Cannot read data at offset %d", offset);
231 0 : return CE_Failure;
232 : }
233 : }
234 :
235 : /* -------------------------------------------------------------------- */
236 : /* If this is compressed data, we read a goodly chunk of data */
237 : /* and then decode it. */
238 : /* -------------------------------------------------------------------- */
239 0 : else if( poDS->PCB != 0 )
240 : {
241 0 : int nBufSize = 128*128*2;
242 0 : int nBytesRead, iPixel, iSrc, bHalfByteUsed = FALSE;
243 0 : GByte *pabyCData = (GByte *) CPLCalloc(nBufSize,1);
244 :
245 0 : nBytesRead = VSIFReadL(pabyCData, 1, nBufSize, poDS->fdIMG);
246 0 : if( nBytesRead == 0 )
247 : {
248 : CPLError(CE_Failure, CPLE_FileIO,
249 0 : "Cannot read data at offset %d", offset);
250 0 : return CE_Failure;
251 : }
252 :
253 0 : CPLAssert( poDS->PVB == 8 );
254 0 : CPLAssert( poDS->PCB == 4 || poDS->PCB == 8 );
255 :
256 0 : for( iSrc = 0, iPixel = 0; iPixel < 128 * 128; )
257 : {
258 0 : if( iSrc + 2 > nBytesRead )
259 : {
260 0 : CPLFree( pabyCData );
261 : CPLError(CE_Failure, CPLE_AppDefined,
262 : "Out of data decoding image block, only %d available.",
263 0 : iSrc );
264 0 : return CE_Failure;
265 : }
266 :
267 0 : int nCount = 0;
268 0 : int nValue = 0;
269 :
270 0 : if( poDS->PCB == 8 )
271 : {
272 0 : nCount = pabyCData[iSrc++];
273 0 : nValue = pabyCData[iSrc++];
274 : }
275 0 : else if( poDS->PCB == 4 )
276 : {
277 0 : if( (iPixel % 128) == 0 && bHalfByteUsed )
278 : {
279 0 : iSrc++;
280 0 : bHalfByteUsed = FALSE;
281 : }
282 :
283 0 : if( bHalfByteUsed )
284 : {
285 0 : nCount = pabyCData[iSrc++] & 0xf;
286 0 : nValue = pabyCData[iSrc++];
287 0 : bHalfByteUsed = FALSE;
288 : }
289 : else
290 : {
291 0 : nCount = pabyCData[iSrc] >> 4;
292 0 : nValue = ((pabyCData[iSrc] & 0xf) << 4)
293 0 : + (pabyCData[iSrc+1] >> 4);
294 0 : bHalfByteUsed = TRUE;
295 0 : iSrc++;
296 : }
297 : }
298 :
299 0 : if( iPixel + nCount > 128 * 128 )
300 : {
301 0 : CPLFree( pabyCData );
302 : CPLError(CE_Failure, CPLE_AppDefined,
303 0 : "Too much data decoding image block, likely corrupt." );
304 0 : return CE_Failure;
305 : }
306 :
307 0 : while( nCount > 0 )
308 : {
309 0 : ((GByte *) pImage)[iPixel++] = (GByte) nValue;
310 0 : nCount--;
311 : }
312 : }
313 :
314 0 : CPLFree( pabyCData );
315 : }
316 :
317 0 : return CE_None;
318 : }
319 :
320 : /************************************************************************/
321 : /* SRPDataset() */
322 : /************************************************************************/
323 :
324 0 : SRPDataset::SRPDataset()
325 : {
326 0 : fdIMG = NULL;
327 0 : TILEINDEX = NULL;
328 0 : offsetInIMG = 0;
329 0 : }
330 :
331 : /************************************************************************/
332 : /* ~SRPDataset() */
333 : /************************************************************************/
334 :
335 0 : SRPDataset::~SRPDataset()
336 : {
337 0 : if (fdIMG)
338 : {
339 0 : VSIFCloseL(fdIMG);
340 : }
341 :
342 0 : if (TILEINDEX)
343 : {
344 0 : delete [] TILEINDEX;
345 : }
346 0 : }
347 :
348 : /************************************************************************/
349 : /* ResetTo01() */
350 : /* Replace the DD in ZZZZZZDD.XXX with 01. */
351 : /************************************************************************/
352 :
353 0 : CPLString SRPDataset::ResetTo01( const char* str )
354 : {
355 0 : CPLString osResult = str;
356 :
357 0 : osResult[6] = '0';
358 0 : osResult[7] = '1';
359 :
360 0 : return osResult;
361 : }
362 :
363 : /************************************************************************/
364 : /* GetMetadata() */
365 : /************************************************************************/
366 :
367 0 : char **SRPDataset::GetMetadata( const char *pszDomain )
368 :
369 : {
370 0 : return GDALPamDataset::GetMetadata( pszDomain );
371 : }
372 :
373 : /************************************************************************/
374 : /* GetProjectionRef() */
375 : /************************************************************************/
376 :
377 0 : const char* SRPDataset::GetProjectionRef()
378 : {
379 0 : return osSRS;
380 : }
381 :
382 : /************************************************************************/
383 : /* GetGeoTransform() */
384 : /************************************************************************/
385 :
386 0 : CPLErr SRPDataset::GetGeoTransform( double * padfGeoTransform)
387 : {
388 0 : if( EQUAL(osProduct,"ASRP") )
389 : {
390 0 : if( ZNA == 9 || ZNA == 18 )
391 : {
392 0 : padfGeoTransform[0] = -1152000.0;
393 0 : padfGeoTransform[1] = 500.0;
394 0 : padfGeoTransform[2] = 0.0;
395 0 : padfGeoTransform[3] = 1152000.0;
396 0 : padfGeoTransform[4] = 0.0;
397 0 : padfGeoTransform[5] = -500.0;
398 :
399 : }
400 : else
401 : {
402 0 : padfGeoTransform[0] = LSO/3600.0;
403 0 : padfGeoTransform[1] = 360. / ARV;
404 0 : padfGeoTransform[2] = 0.0;
405 0 : padfGeoTransform[3] = PSO/3600.0;
406 0 : padfGeoTransform[4] = 0.0;
407 0 : padfGeoTransform[5] = - 360. / BRV;
408 : }
409 :
410 0 : return CE_None;
411 : }
412 0 : else if( EQUAL(osProduct,"USRP") )
413 : {
414 0 : padfGeoTransform[0] = LSO;
415 0 : padfGeoTransform[1] = LOD;
416 0 : padfGeoTransform[2] = 0.0;
417 0 : padfGeoTransform[3] = PSO;
418 0 : padfGeoTransform[4] = 0.0;
419 0 : padfGeoTransform[5] = -LAD;
420 0 : return CE_None;
421 : }
422 :
423 0 : return CE_Failure;
424 : }
425 :
426 : /************************************************************************/
427 : /* SetGeoTransform() */
428 : /************************************************************************/
429 :
430 0 : CPLErr SRPDataset::SetGeoTransform( double * padfGeoTransform )
431 :
432 : {
433 0 : memcpy( adfGeoTransform, padfGeoTransform, sizeof(double)*6 );
434 0 : bGeoTransformValid = TRUE;
435 0 : return CE_None;
436 : }
437 :
438 : /************************************************************************/
439 : /* GetLongitudeFromString() */
440 : /************************************************************************/
441 :
442 0 : double SRPDataset::GetLongitudeFromString(const char* str)
443 : {
444 0 : char ddd[3+1] = { 0 };
445 0 : char mm[2+1] = { 0 };
446 0 : char ssdotss[5+1] = { 0 };
447 0 : int sign = (str[0] == '+') ? 1 : - 1;
448 0 : str++;
449 0 : strncpy(ddd, str, 3);
450 0 : str+=3;
451 0 : strncpy(mm, str, 2);
452 0 : str+=2;
453 0 : strncpy(ssdotss, str, 5);
454 0 : return sign * (atof(ddd) + atof(mm) / 60 + atof(ssdotss) / 3600);
455 : }
456 :
457 : /************************************************************************/
458 : /* GetLatitudeFromString() */
459 : /************************************************************************/
460 :
461 0 : double SRPDataset::GetLatitudeFromString(const char* str)
462 : {
463 0 : char ddd[2+1] = { 0 };
464 0 : char mm[2+1] = { 0 };
465 0 : char ssdotss[5+1] = { 0 };
466 0 : int sign = (str[0] == '+') ? 1 : - 1;
467 0 : str++;
468 0 : strncpy(ddd, str, 2);
469 0 : str+=2;
470 0 : strncpy(mm, str, 2);
471 0 : str+=2;
472 0 : strncpy(ssdotss, str, 5);
473 0 : return sign * (atof(ddd) + atof(mm) / 60 + atof(ssdotss) / 3600);
474 : }
475 :
476 :
477 : /************************************************************************/
478 : /* GetFromRecord() */
479 : /************************************************************************/
480 :
481 0 : int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
482 : {
483 0 : CPLString osBAD;
484 : int i;
485 :
486 : DDFField* field;
487 : DDFFieldDefn *fieldDefn;
488 : int bSuccess;
489 : int nSTR;
490 :
491 : /* -------------------------------------------------------------------- */
492 : /* Read a variety of header fields of interest from the .GEN */
493 : /* file. */
494 : /* -------------------------------------------------------------------- */
495 0 : nSTR = record->GetIntSubfield( "GEN", 0, "STR", 0, &bSuccess );
496 0 : if( !bSuccess || nSTR != 4 )
497 : {
498 0 : CPLDebug( "SRP", "Failed to extract STR, or not 4." );
499 0 : return FALSE;
500 : }
501 :
502 0 : int SCA = record->GetIntSubfield( "GEN", 0, "SCA", 0, &bSuccess );
503 0 : CPLDebug("SRP", "SCA=%d", SCA);
504 :
505 0 : ZNA = record->GetIntSubfield( "GEN", 0, "ZNA", 0, &bSuccess );
506 0 : CPLDebug("SRP", "ZNA=%d", ZNA);
507 :
508 0 : double PSP = record->GetFloatSubfield( "GEN", 0, "PSP", 0, &bSuccess );
509 0 : CPLDebug("SRP", "PSP=%f", PSP);
510 :
511 0 : ARV = record->GetIntSubfield( "GEN", 0, "ARV", 0, &bSuccess );
512 0 : CPLDebug("SRP", "ARV=%d", ARV);
513 :
514 0 : BRV = record->GetIntSubfield( "GEN", 0, "BRV", 0, &bSuccess );
515 0 : CPLDebug("SRP", "BRV=%d", BRV);
516 :
517 0 : LSO = record->GetFloatSubfield( "GEN", 0, "LSO", 0, &bSuccess );
518 0 : CPLDebug("SRP", "LSO=%f", LSO);
519 :
520 0 : PSO = record->GetFloatSubfield( "GEN", 0, "PSO", 0, &bSuccess );
521 0 : CPLDebug("SRP", "PSO=%f", PSO);
522 :
523 0 : LAD = record->GetFloatSubfield( "GEN", 0, "LAD", 0 );
524 0 : LOD = record->GetFloatSubfield( "GEN", 0, "LOD", 0 );
525 :
526 0 : NFL = record->GetIntSubfield( "SPR", 0, "NFL", 0, &bSuccess );
527 0 : CPLDebug("SRP", "NFL=%d", NFL);
528 :
529 0 : NFC = record->GetIntSubfield( "SPR", 0, "NFC", 0, &bSuccess );
530 0 : CPLDebug("SRP", "NFC=%d", NFC);
531 :
532 0 : int PNC = record->GetIntSubfield( "SPR", 0, "PNC", 0, &bSuccess );
533 0 : CPLDebug("SRP", "PNC=%d", PNC);
534 :
535 0 : int PNL = record->GetIntSubfield( "SPR", 0, "PNL", 0, &bSuccess );
536 0 : CPLDebug("SRP", "PNL=%d", PNL);
537 :
538 0 : if( PNL != 128 || PNC != 128 )
539 : {
540 0 : CPLError( CE_Failure, CPLE_AppDefined,"Unsupported PNL or PNC value.");
541 0 : return FALSE;
542 : }
543 :
544 0 : PCB = record->GetIntSubfield( "SPR", 0, "PCB", 0 );
545 0 : PVB = record->GetIntSubfield( "SPR", 0, "PVB", 0 );
546 0 : if( (PCB != 8 && PCB != 4 && PCB != 0) || PVB != 8 )
547 : {
548 : CPLError( CE_Failure, CPLE_AppDefined,
549 0 : "PCB(%d) or PVB(%d) value unsupported.", PCB, PVB );
550 0 : return FALSE;
551 : }
552 :
553 0 : osBAD = record->GetStringSubfield( "SPR", 0, "BAD", 0, &bSuccess );
554 : {
555 0 : char* c = (char*) strchr(osBAD, ' ');
556 0 : if (c)
557 0 : *c = 0;
558 : }
559 0 : CPLDebug("SRP", "BAD=%s", osBAD.c_str());
560 :
561 : /* -------------------------------------------------------------------- */
562 : /* Read the tile map if available. */
563 : /* -------------------------------------------------------------------- */
564 0 : int TIF = EQUAL(record->GetStringSubfield( "SPR", 0, "TIF", 0 ),"Y");
565 0 : CPLDebug("SRP", "TIF=%d", TIF);
566 :
567 0 : if (TIF)
568 : {
569 0 : field = record->FindField( "TIM" );
570 0 : if( field == NULL )
571 0 : return FALSE;
572 :
573 0 : fieldDefn = field->GetFieldDefn();
574 0 : DDFSubfieldDefn *subfieldDefn = fieldDefn->FindSubfieldDefn( "TSI" );
575 0 : if( subfieldDefn == NULL )
576 0 : return FALSE;
577 :
578 0 : int nIndexValueWidth = subfieldDefn->GetWidth();
579 :
580 : /* Should be strict comparison, but apparently a few datasets */
581 : /* have GetDataSize() greater than the required minimum (#3862) */
582 0 : if (field->GetDataSize() < nIndexValueWidth * NFL * NFC + 1)
583 : {
584 0 : return FALSE;
585 : }
586 :
587 0 : TILEINDEX = new int [NFL * NFC];
588 0 : const char* ptr = field->GetData();
589 0 : char offset[30]={0};
590 0 : offset[nIndexValueWidth] = '\0';
591 :
592 0 : for(i=0;i<NFL*NFC;i++)
593 : {
594 0 : strncpy(offset, ptr, nIndexValueWidth);
595 0 : ptr += nIndexValueWidth;
596 0 : TILEINDEX[i] = atoi(offset);
597 : //CPLDebug("SRP", "TSI[%d]=%d", i, TILEINDEX[i]);
598 : }
599 : }
600 :
601 : /* -------------------------------------------------------------------- */
602 : /* Open the .IMG file. Try to recover gracefully if the case */
603 : /* of the filename is wrong. */
604 : /* -------------------------------------------------------------------- */
605 0 : CPLString osDirname = CPLGetDirname(pszFileName);
606 0 : CPLString osImgName = CPLFormCIFilename(osDirname, osBAD, NULL);
607 :
608 0 : fdIMG = VSIFOpenL(osImgName, "rb");
609 0 : if (fdIMG == NULL)
610 : {
611 0 : CPLError( CE_Failure, CPLE_AppDefined, "Cannot find %s", osImgName.c_str());
612 0 : return FALSE;
613 : }
614 :
615 : /* -------------------------------------------------------------------- */
616 : /* Establish the offset to the first byte of actual image data */
617 : /* in the IMG file, skipping the ISO8211 header. */
618 : /* */
619 : /* This code is awfully fragile! */
620 : /* -------------------------------------------------------------------- */
621 : char c;
622 : char recordName[3];
623 0 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
624 : {
625 0 : return FALSE;
626 : }
627 0 : while (!VSIFEofL(fdIMG))
628 : {
629 0 : if (c == 30)
630 : {
631 0 : if (VSIFReadL(recordName, 1, 3, fdIMG) != 3)
632 : {
633 0 : return FALSE;
634 : }
635 0 : offsetInIMG += 3;
636 0 : if (strncmp(recordName,"IMG",3) == 0)
637 : {
638 0 : offsetInIMG += 4;
639 0 : if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0)
640 : {
641 0 : return FALSE;
642 : }
643 0 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
644 : {
645 0 : return FALSE;
646 : }
647 0 : while( c != 30 )
648 : {
649 0 : offsetInIMG ++;
650 0 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
651 : {
652 0 : return FALSE;
653 : }
654 : }
655 0 : offsetInIMG ++;
656 0 : break;
657 : }
658 : }
659 :
660 0 : offsetInIMG ++;
661 0 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
662 : {
663 0 : return FALSE;
664 : }
665 : }
666 :
667 0 : if (VSIFEofL(fdIMG))
668 : {
669 0 : return FALSE;
670 : }
671 :
672 0 : CPLDebug("SRP", "Img offset data = %d", offsetInIMG);
673 :
674 : /* -------------------------------------------------------------------- */
675 : /* Establish the SRP Dataset. */
676 : /* -------------------------------------------------------------------- */
677 0 : nRasterXSize = NFC * 128;
678 0 : nRasterYSize = NFL * 128;
679 :
680 : char pszValue[32];
681 0 : sprintf(pszValue, "%d", SCA);
682 0 : SetMetadataItem( "SRP_SCA", pszValue );
683 :
684 0 : nBands = 1;
685 0 : for( i = 0; i < nBands; i++ )
686 0 : SetBand( i+1, new SRPRasterBand( this, i+1 ) );
687 :
688 : /* -------------------------------------------------------------------- */
689 : /* Try to collect a color map from the .QAL file. */
690 : /* -------------------------------------------------------------------- */
691 0 : CPLString osBasename = CPLGetBasename(pszFileName);
692 0 : osQALFilename = CPLFormCIFilename(osDirname, osBasename, "QAL");
693 :
694 0 : DDFModule oQALModule;
695 :
696 0 : if( oQALModule.Open( osQALFilename, TRUE ) )
697 : {
698 0 : while( (record = oQALModule.ReadRecord()) != NULL
699 : && record->FindField( "COL" ) == NULL ) {}
700 :
701 0 : if( record != NULL )
702 : {
703 : int iColor;
704 : int nColorCount =
705 0 : record->FindField("COL")->GetRepeatCount();
706 :
707 0 : for( iColor = 0; iColor < nColorCount; iColor++ )
708 : {
709 : int bSuccess;
710 : int nCCD, nNSR, nNSG, nNSB;
711 : GDALColorEntry sEntry;
712 :
713 : nCCD = record->GetIntSubfield( "COL", 0, "CCD", iColor,
714 0 : &bSuccess );
715 0 : if( !bSuccess )
716 0 : break;
717 :
718 0 : nNSR = record->GetIntSubfield( "COL", 0, "NSR", iColor );
719 0 : nNSG = record->GetIntSubfield( "COL", 0, "NSG", iColor );
720 0 : nNSB = record->GetIntSubfield( "COL", 0, "NSB", iColor );
721 :
722 0 : sEntry.c1 = (short) nNSR;
723 0 : sEntry.c2 = (short) nNSG;
724 0 : sEntry.c3 = (short) nNSB;
725 0 : sEntry.c4 = 255;
726 :
727 0 : oCT.SetColorEntry( nCCD, &sEntry );
728 : }
729 : }
730 : }
731 : else
732 : {
733 0 : osQALFilename = "";
734 : CPLError( CE_Warning, CPLE_AppDefined,
735 0 : "Unable to find .QAL file, no color table applied." );
736 : }
737 :
738 : /* -------------------------------------------------------------------- */
739 : /* Derive the coordinate system. */
740 : /* -------------------------------------------------------------------- */
741 0 : if( EQUAL(osProduct,"ASRP") )
742 : {
743 0 : osSRS = SRS_WKT_WGS84;
744 :
745 0 : if( ZNA == 9 )
746 : {
747 0 : osSRS = "PROJCS[\"unnamed\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Azimuthal_Equidistant\"],PARAMETER[\"latitude_of_center\",90],PARAMETER[\"longitude_of_center\",0],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]";
748 : }
749 :
750 0 : if (ZNA == 18)
751 : {
752 0 : osSRS = "PROJCS[\"unnamed\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Azimuthal_Equidistant\"],PARAMETER[\"latitude_of_center\",-90],PARAMETER[\"longitude_of_center\",0],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]";
753 : }
754 : }
755 : else
756 : {
757 0 : OGRSpatialReference oSRS;
758 :
759 0 : if( ABS(ZNA) >= 1 && ABS(ZNA) <= 60 )
760 : {
761 0 : oSRS.SetUTM( ABS(ZNA), ZNA > 0 );
762 0 : oSRS.SetWellKnownGeogCS( "WGS84" );
763 : }
764 0 : else if( ZNA == 61 )
765 : {
766 0 : oSRS.importFromEPSG( 32661 ); // WGS84 UPS North
767 : }
768 0 : else if( ZNA == -61 )
769 : {
770 0 : oSRS.importFromEPSG( 32761 ); // WGS84 UPS South
771 : }
772 :
773 0 : char *pszWKT = NULL;
774 0 : oSRS.exportToWkt( &pszWKT );
775 0 : osSRS = pszWKT;
776 0 : CPLFree( pszWKT );
777 : }
778 :
779 0 : return TRUE;
780 : }
781 :
782 : /************************************************************************/
783 : /* GetFileList() */
784 : /************************************************************************/
785 :
786 0 : char **SRPDataset::GetFileList()
787 :
788 : {
789 0 : char **papszFileList = GDALPamDataset::GetFileList();
790 :
791 0 : papszFileList = CSLAddString( papszFileList, osGENFilename );
792 :
793 0 : if( strlen(osQALFilename) > 0 )
794 0 : papszFileList = CSLAddString( papszFileList, osQALFilename );
795 :
796 0 : return papszFileList;
797 : }
798 :
799 : /************************************************************************/
800 : /* Open() */
801 : /************************************************************************/
802 :
803 22208 : GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
804 : {
805 22208 : DDFModule module;
806 : DDFRecord * record;
807 22208 : CPLString osFileName(poOpenInfo->pszFilename);
808 22208 : CPLString osNAM;
809 :
810 : /* -------------------------------------------------------------------- */
811 : /* Verify that this appears to be a valid ISO8211 .IMG file. */
812 : /* -------------------------------------------------------------------- */
813 22208 : if( poOpenInfo->nHeaderBytes < 500 )
814 21400 : return NULL;
815 :
816 808 : if (!EQUAL(CPLGetExtension(osFileName), "img"))
817 808 : return NULL;
818 :
819 : static const size_t nLeaderSize = 24;
820 : int i;
821 :
822 0 : for( i = 0; i < (int)nLeaderSize; i++ )
823 : {
824 0 : if( poOpenInfo->pabyHeader[i] < 32
825 0 : || poOpenInfo->pabyHeader[i] > 126 )
826 0 : return NULL;
827 : }
828 :
829 0 : if( poOpenInfo->pabyHeader[5] != '1'
830 0 : && poOpenInfo->pabyHeader[5] != '2'
831 0 : && poOpenInfo->pabyHeader[5] != '3' )
832 0 : return NULL;
833 :
834 0 : if( poOpenInfo->pabyHeader[6] != 'L' )
835 0 : return NULL;
836 0 : if( poOpenInfo->pabyHeader[8] != '1' && poOpenInfo->pabyHeader[8] != ' ' )
837 0 : return NULL;
838 :
839 : /* -------------------------------------------------------------------- */
840 : /* Find and open the .GEN file. */
841 : /* -------------------------------------------------------------------- */
842 : VSIStatBufL sStatBuf;
843 :
844 0 : CPLString basename = CPLGetBasename( osFileName );
845 0 : if( basename.size() != 8 )
846 : {
847 0 : CPLDebug("SRP", "Invalid basename file");
848 0 : return NULL;
849 : }
850 :
851 0 : int zoneNumber = CPLScanLong( basename + 6, 2 );
852 :
853 0 : CPLString path = CPLGetDirname( osFileName );
854 0 : CPLString basename01 = ResetTo01( basename );
855 0 : osFileName = CPLFormFilename( path, basename01, ".IMG" );
856 :
857 0 : osFileName = CPLResetExtension( osFileName, "GEN" );
858 0 : if( VSIStatL( osFileName, &sStatBuf ) != 0 )
859 : {
860 0 : osFileName = CPLResetExtension( osFileName, "gen" );
861 0 : if( VSIStatL( osFileName, &sStatBuf ) != 0 )
862 0 : return NULL;
863 : }
864 :
865 0 : if (!module.Open(osFileName, TRUE))
866 0 : return NULL;
867 :
868 0 : if( poOpenInfo->eAccess == GA_Update )
869 : {
870 : CPLError( CE_Failure, CPLE_NotSupported,
871 : "The SRP driver does not support update access to existing"
872 0 : " datasets.\n" );
873 0 : return NULL;
874 : }
875 :
876 : /* -------------------------------------------------------------------- */
877 : /* Loop processing records - we are basically looking for the */
878 : /* GIN record which is normally first in the .GEN file. */
879 : /* -------------------------------------------------------------------- */
880 0 : int recordIndex = 0;
881 0 : while (TRUE)
882 : {
883 0 : CPLPushErrorHandler( CPLQuietErrorHandler );
884 0 : record = module.ReadRecord();
885 0 : CPLPopErrorHandler();
886 0 : CPLErrorReset();
887 0 : if (record == NULL)
888 : break;
889 0 : if ( ++recordIndex < zoneNumber )
890 0 : continue;
891 :
892 0 : const char* RTY = record->GetStringSubfield( "001", 0, "RTY", 0 );
893 0 : if( RTY == NULL || !EQUAL(RTY,"GIN") )
894 0 : continue;
895 :
896 0 : const char *PRT = record->GetStringSubfield( "DSI", 0, "PRT", 0 );
897 0 : if( PRT == NULL )
898 0 : continue;
899 :
900 0 : CPLString osPRT = PRT;
901 0 : osPRT.resize(4);
902 0 : if( !EQUAL(osPRT,"ASRP") && !EQUAL(osPRT,"USRP") )
903 0 : continue;
904 :
905 0 : osNAM = record->GetStringSubfield( "DSI", 0, "NAM", 0 );
906 0 : CPLDebug("SRP", "NAM=%s", osNAM.c_str());
907 :
908 0 : SRPDataset *poDS = new SRPDataset();
909 :
910 0 : poDS->osProduct = osPRT;
911 0 : poDS->osGENFilename = osFileName;
912 0 : poDS->SetMetadataItem( "SRP_NAM", osNAM );
913 0 : poDS->SetMetadataItem( "SRP_PRODUCT", osPRT );
914 :
915 0 : if (!poDS->GetFromRecord( osFileName, record ) )
916 : {
917 0 : delete poDS;
918 0 : continue;
919 : }
920 :
921 : /* ---------------------------------------------------------- */
922 : /* Initialize any PAM information. */
923 : /* ---------------------------------------------------------- */
924 0 : poDS->SetDescription( poOpenInfo->pszFilename );
925 0 : poDS->TryLoadXML();
926 :
927 : /* ---------------------------------------------------------- */
928 : /* Check for external overviews. */
929 : /* ---------------------------------------------------------- */
930 0 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
931 :
932 0 : return poDS;
933 : }
934 :
935 0 : return NULL;
936 : }
937 :
938 : /************************************************************************/
939 : /* GDALRegister_SRP() */
940 : /************************************************************************/
941 :
942 1135 : void GDALRegister_SRP()
943 :
944 : {
945 : GDALDriver *poDriver;
946 :
947 1135 : if( GDALGetDriverByName( "SRP" ) == NULL )
948 : {
949 1093 : poDriver = new GDALDriver();
950 :
951 1093 : poDriver->SetDescription( "SRP" );
952 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
953 1093 : "Standard Raster Product (ASRP/USRP)" );
954 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
955 1093 : "frmt_various.html#SRP" );
956 1093 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "img" );
957 1093 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
958 :
959 1093 : poDriver->pfnOpen = SRPDataset::Open;
960 :
961 1093 : GetGDALDriverManager()->RegisterDriver( poDriver );
962 : }
963 1135 : }
964 :
|