1 : /******************************************************************************
2 : * $Id: srpdataset.cpp 18436 2010-01-04 20:52:43Z 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 18436 2010-01-04 20:52:43Z rouault $");
37 :
38 : class SRPDataset : public GDALPamDataset
39 : {
40 : friend class SRPRasterBand;
41 :
42 : static CPLString ResetTo01( const char* str );
43 :
44 : FILE* 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 : CPLAssert( poDS->PVB == 8 );
254 : 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++] = 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 : padfGeoTransform[0] = LSO/3600.0;
391 0 : padfGeoTransform[1] = 360. / ARV;
392 0 : padfGeoTransform[2] = 0.0;
393 0 : padfGeoTransform[3] = PSO/3600.0;
394 0 : padfGeoTransform[4] = 0.0;
395 0 : padfGeoTransform[5] = - 360. / BRV;
396 :
397 0 : return CE_None;
398 : }
399 0 : else if( EQUAL(osProduct,"USRP") )
400 : {
401 0 : padfGeoTransform[0] = LSO;
402 0 : padfGeoTransform[1] = LOD;
403 0 : padfGeoTransform[2] = 0.0;
404 0 : padfGeoTransform[3] = PSO;
405 0 : padfGeoTransform[4] = 0.0;
406 0 : padfGeoTransform[5] = -LAD;
407 0 : return CE_None;
408 : }
409 :
410 0 : return CE_Failure;
411 : }
412 :
413 : /************************************************************************/
414 : /* SetGeoTransform() */
415 : /************************************************************************/
416 :
417 0 : CPLErr SRPDataset::SetGeoTransform( double * padfGeoTransform )
418 :
419 : {
420 0 : memcpy( adfGeoTransform, padfGeoTransform, sizeof(double)*6 );
421 0 : bGeoTransformValid = TRUE;
422 0 : return CE_None;
423 : }
424 :
425 : /************************************************************************/
426 : /* GetLongitudeFromString() */
427 : /************************************************************************/
428 :
429 0 : double SRPDataset::GetLongitudeFromString(const char* str)
430 : {
431 0 : char ddd[3+1] = { 0 };
432 0 : char mm[2+1] = { 0 };
433 0 : char ssdotss[5+1] = { 0 };
434 0 : int sign = (str[0] == '+') ? 1 : - 1;
435 0 : str++;
436 0 : strncpy(ddd, str, 3);
437 0 : str+=3;
438 0 : strncpy(mm, str, 2);
439 0 : str+=2;
440 0 : strncpy(ssdotss, str, 5);
441 0 : return sign * (atof(ddd) + atof(mm) / 60 + atof(ssdotss) / 3600);
442 : }
443 :
444 : /************************************************************************/
445 : /* GetLatitudeFromString() */
446 : /************************************************************************/
447 :
448 0 : double SRPDataset::GetLatitudeFromString(const char* str)
449 : {
450 0 : char ddd[2+1] = { 0 };
451 0 : char mm[2+1] = { 0 };
452 0 : char ssdotss[5+1] = { 0 };
453 0 : int sign = (str[0] == '+') ? 1 : - 1;
454 0 : str++;
455 0 : strncpy(ddd, str, 2);
456 0 : str+=2;
457 0 : strncpy(mm, str, 2);
458 0 : str+=2;
459 0 : strncpy(ssdotss, str, 5);
460 0 : return sign * (atof(ddd) + atof(mm) / 60 + atof(ssdotss) / 3600);
461 : }
462 :
463 :
464 : /************************************************************************/
465 : /* GetFromRecord() */
466 : /************************************************************************/
467 :
468 0 : int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
469 : {
470 0 : CPLString osBAD;
471 : int i;
472 :
473 : DDFField* field;
474 : DDFFieldDefn *fieldDefn;
475 : int bSuccess;
476 : int nSTR;
477 :
478 : /* -------------------------------------------------------------------- */
479 : /* Read a variety of header fields of interest from the .GEN */
480 : /* file. */
481 : /* -------------------------------------------------------------------- */
482 0 : nSTR = record->GetIntSubfield( "GEN", 0, "STR", 0, &bSuccess );
483 0 : if( !bSuccess || nSTR != 4 )
484 : {
485 0 : CPLDebug( "SRP", "Failed to extract STR, or not 4." );
486 0 : return FALSE;
487 : }
488 :
489 0 : int SCA = record->GetIntSubfield( "GEN", 0, "SCA", 0, &bSuccess );
490 0 : CPLDebug("SRP", "SCA=%d", SCA);
491 :
492 0 : ZNA = record->GetIntSubfield( "GEN", 0, "ZNA", 0, &bSuccess );
493 0 : CPLDebug("SRP", "ZNA=%d", ZNA);
494 :
495 0 : double PSP = record->GetFloatSubfield( "GEN", 0, "PSP", 0, &bSuccess );
496 0 : CPLDebug("SRP", "PSP=%f", PSP);
497 :
498 0 : ARV = record->GetIntSubfield( "GEN", 0, "ARV", 0, &bSuccess );
499 0 : CPLDebug("SRP", "ARV=%d", ARV);
500 :
501 0 : BRV = record->GetIntSubfield( "GEN", 0, "BRV", 0, &bSuccess );
502 0 : CPLDebug("SRP", "BRV=%d", BRV);
503 :
504 0 : LSO = record->GetFloatSubfield( "GEN", 0, "LSO", 0, &bSuccess );
505 0 : CPLDebug("SRP", "LSO=%f", LSO);
506 :
507 0 : PSO = record->GetFloatSubfield( "GEN", 0, "PSO", 0, &bSuccess );
508 0 : CPLDebug("SRP", "PSO=%f", PSO);
509 :
510 0 : LAD = record->GetFloatSubfield( "GEN", 0, "LAD", 0 );
511 0 : LOD = record->GetFloatSubfield( "GEN", 0, "LOD", 0 );
512 :
513 0 : NFL = record->GetIntSubfield( "SPR", 0, "NFL", 0, &bSuccess );
514 0 : CPLDebug("SRP", "NFL=%d", NFL);
515 :
516 0 : NFC = record->GetIntSubfield( "SPR", 0, "NFC", 0, &bSuccess );
517 0 : CPLDebug("SRP", "NFC=%d", NFC);
518 :
519 0 : int PNC = record->GetIntSubfield( "SPR", 0, "PNC", 0, &bSuccess );
520 0 : CPLDebug("SRP", "PNC=%d", PNC);
521 :
522 0 : int PNL = record->GetIntSubfield( "SPR", 0, "PNL", 0, &bSuccess );
523 0 : CPLDebug("SRP", "PNL=%d", PNL);
524 :
525 0 : if( PNL != 128 || PNC != 128 )
526 : {
527 0 : CPLError( CE_Failure, CPLE_AppDefined,"Unsupported PNL or PNC value.");
528 0 : return FALSE;
529 : }
530 :
531 0 : PCB = record->GetIntSubfield( "SPR", 0, "PCB", 0 );
532 0 : PVB = record->GetIntSubfield( "SPR", 0, "PVB", 0 );
533 0 : if( (PCB != 8 && PCB != 4 && PCB != 0) || PVB != 8 )
534 : {
535 : CPLError( CE_Failure, CPLE_AppDefined,
536 0 : "PCB(%d) or PVB(%d) value unsupported.", PCB, PVB );
537 0 : return FALSE;
538 : }
539 :
540 0 : osBAD = record->GetStringSubfield( "SPR", 0, "BAD", 0, &bSuccess );
541 : {
542 0 : char* c = (char*) strchr(osBAD, ' ');
543 0 : if (c)
544 0 : *c = 0;
545 : }
546 0 : CPLDebug("SRP", "BAD=%s", osBAD.c_str());
547 :
548 : /* -------------------------------------------------------------------- */
549 : /* Read the tile map if available. */
550 : /* -------------------------------------------------------------------- */
551 0 : int TIF = EQUAL(record->GetStringSubfield( "SPR", 0, "TIF", 0 ),"Y");
552 0 : CPLDebug("SRP", "TIF=%d", TIF);
553 :
554 0 : if (TIF)
555 : {
556 0 : field = record->FindField( "TIM" );
557 0 : if( field == NULL )
558 0 : return FALSE;
559 :
560 0 : fieldDefn = field->GetFieldDefn();
561 0 : DDFSubfieldDefn *subfieldDefn = fieldDefn->FindSubfieldDefn( "TSI" );
562 0 : if( subfieldDefn == NULL )
563 0 : return FALSE;
564 :
565 0 : int nIndexValueWidth = subfieldDefn->GetWidth();
566 :
567 0 : if (field->GetDataSize() != nIndexValueWidth * NFL * NFC + 1)
568 : {
569 0 : return FALSE;
570 : }
571 :
572 0 : TILEINDEX = new int [NFL * NFC];
573 0 : const char* ptr = field->GetData();
574 0 : char offset[30]={0};
575 0 : offset[nIndexValueWidth] = '\0';
576 :
577 0 : for(i=0;i<NFL*NFC;i++)
578 : {
579 0 : strncpy(offset, ptr, nIndexValueWidth);
580 0 : ptr += nIndexValueWidth;
581 0 : TILEINDEX[i] = atoi(offset);
582 : //CPLDebug("SRP", "TSI[%d]=%d", i, TILEINDEX[i]);
583 : }
584 : }
585 :
586 : /* -------------------------------------------------------------------- */
587 : /* Open the .IMG file. Try to recover gracefully if the case */
588 : /* of the filename is wrong. */
589 : /* -------------------------------------------------------------------- */
590 0 : CPLString osDirname = CPLGetDirname(pszFileName);
591 0 : CPLString osImgName = CPLFormCIFilename(osDirname, osBAD, NULL);
592 :
593 0 : fdIMG = VSIFOpenL(osImgName, "rb");
594 0 : if (fdIMG == NULL)
595 : {
596 0 : CPLError( CE_Failure, CPLE_AppDefined, "Cannot find %s", osImgName.c_str());
597 0 : return FALSE;
598 : }
599 :
600 : /* -------------------------------------------------------------------- */
601 : /* Establish the offset to the first byte of actual image data */
602 : /* in the IMG file, skipping the ISO8211 header. */
603 : /* */
604 : /* This code is awfully fragile! */
605 : /* -------------------------------------------------------------------- */
606 : char c;
607 : char recordName[3];
608 0 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
609 : {
610 0 : return FALSE;
611 : }
612 0 : while (!VSIFEofL(fdIMG))
613 : {
614 0 : if (c == 30)
615 : {
616 0 : if (VSIFReadL(recordName, 1, 3, fdIMG) != 3)
617 : {
618 0 : return FALSE;
619 : }
620 0 : offsetInIMG += 3;
621 0 : if (strncmp(recordName,"IMG",3) == 0)
622 : {
623 0 : offsetInIMG += 4;
624 0 : if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0)
625 : {
626 0 : return FALSE;
627 : }
628 0 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
629 : {
630 0 : return FALSE;
631 : }
632 0 : while(c ==' ' || c== '^')
633 : {
634 0 : offsetInIMG ++;
635 0 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
636 : {
637 0 : return FALSE;
638 : }
639 : }
640 0 : offsetInIMG ++;
641 0 : break;
642 : }
643 : }
644 :
645 0 : offsetInIMG ++;
646 0 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
647 : {
648 0 : return FALSE;
649 : }
650 : }
651 :
652 0 : if (VSIFEofL(fdIMG))
653 : {
654 0 : return FALSE;
655 : }
656 :
657 0 : CPLDebug("SRP", "Img offset data = %d", offsetInIMG);
658 :
659 : /* -------------------------------------------------------------------- */
660 : /* Establish the SRP Dataset. */
661 : /* -------------------------------------------------------------------- */
662 0 : nRasterXSize = NFC * 128;
663 0 : nRasterYSize = NFL * 128;
664 :
665 : char pszValue[32];
666 0 : sprintf(pszValue, "%d", SCA);
667 0 : SetMetadataItem( "SRP_SCA", pszValue );
668 :
669 0 : nBands = 1;
670 0 : for( i = 0; i < nBands; i++ )
671 0 : SetBand( i+1, new SRPRasterBand( this, i+1 ) );
672 :
673 : /* -------------------------------------------------------------------- */
674 : /* Try to collect a color map from the .QAL file. */
675 : /* -------------------------------------------------------------------- */
676 0 : CPLString osBasename = CPLGetBasename(pszFileName);
677 0 : osQALFilename = CPLFormCIFilename(osDirname, osBasename, "QAL");
678 :
679 0 : DDFModule oQALModule;
680 :
681 0 : if( oQALModule.Open( osQALFilename, TRUE ) )
682 : {
683 0 : while( (record = oQALModule.ReadRecord()) != NULL
684 : && record->FindField( "COL" ) == NULL ) {}
685 :
686 0 : if( record != NULL )
687 : {
688 : int iColor;
689 : int nColorCount =
690 0 : record->FindField("COL")->GetRepeatCount();
691 :
692 0 : for( iColor = 0; iColor < nColorCount; iColor++ )
693 : {
694 : int bSuccess;
695 : int nCCD, nNSR, nNSG, nNSB;
696 : GDALColorEntry sEntry;
697 :
698 : nCCD = record->GetIntSubfield( "COL", 0, "CCD", iColor,
699 0 : &bSuccess );
700 0 : if( !bSuccess )
701 0 : break;
702 :
703 0 : nNSR = record->GetIntSubfield( "COL", 0, "NSR", iColor );
704 0 : nNSG = record->GetIntSubfield( "COL", 0, "NSG", iColor );
705 0 : nNSB = record->GetIntSubfield( "COL", 0, "NSB", iColor );
706 :
707 0 : sEntry.c1 = nNSR;
708 0 : sEntry.c2 = nNSG;
709 0 : sEntry.c3 = nNSB;
710 0 : sEntry.c4 = 255;
711 :
712 0 : oCT.SetColorEntry( nCCD, &sEntry );
713 : }
714 : }
715 : }
716 : else
717 : {
718 0 : osQALFilename = "";
719 : CPLError( CE_Warning, CPLE_AppDefined,
720 0 : "Unable to find .QAL file, no color table applied." );
721 : }
722 :
723 : /* -------------------------------------------------------------------- */
724 : /* Derive the coordinate system. */
725 : /* -------------------------------------------------------------------- */
726 0 : if( EQUAL(osProduct,"ASRP") )
727 : {
728 0 : osSRS = SRS_WKT_WGS84;
729 :
730 0 : if (ZNA == 9 || ZNA == 18)
731 : {
732 0 : CPLError(CE_Failure, CPLE_AppDefined, "Polar cases are not handled by SRP driver");
733 0 : return FALSE;
734 : }
735 : }
736 : else
737 : {
738 0 : OGRSpatialReference oSRS;
739 :
740 0 : if( ABS(ZNA) >= 1 && ABS(ZNA) <= 60 )
741 : {
742 0 : oSRS.SetUTM( ABS(ZNA), ZNA > 0 );
743 0 : oSRS.SetWellKnownGeogCS( "WGS84" );
744 : }
745 0 : else if( ZNA == 61 )
746 : {
747 0 : oSRS.importFromEPSG( 32661 ); // WGS84 UPS North
748 : }
749 0 : else if( ZNA == -61 )
750 : {
751 0 : oSRS.importFromEPSG( 32761 ); // WGS84 UPS South
752 : }
753 :
754 0 : char *pszWKT = NULL;
755 0 : oSRS.exportToWkt( &pszWKT );
756 0 : osSRS = pszWKT;
757 0 : CPLFree( pszWKT );
758 : }
759 :
760 0 : return TRUE;
761 : }
762 :
763 : /************************************************************************/
764 : /* GetFileList() */
765 : /************************************************************************/
766 :
767 0 : char **SRPDataset::GetFileList()
768 :
769 : {
770 0 : char **papszFileList = GDALPamDataset::GetFileList();
771 :
772 0 : papszFileList = CSLAddString( papszFileList, osGENFilename );
773 :
774 0 : if( strlen(osQALFilename) > 0 )
775 0 : papszFileList = CSLAddString( papszFileList, osQALFilename );
776 :
777 0 : return papszFileList;
778 : }
779 :
780 : /************************************************************************/
781 : /* Open() */
782 : /************************************************************************/
783 :
784 8432 : GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
785 : {
786 8432 : DDFModule module;
787 : DDFRecord * record;
788 8432 : CPLString osFileName(poOpenInfo->pszFilename);
789 8432 : CPLString osNAM;
790 :
791 : /* -------------------------------------------------------------------- */
792 : /* Verify that this appears to be a valid ISO8211 .IMG file. */
793 : /* -------------------------------------------------------------------- */
794 8432 : if( poOpenInfo->nHeaderBytes < 500 )
795 8319 : return NULL;
796 :
797 113 : if (!EQUAL(CPLGetExtension(osFileName), "img"))
798 113 : return NULL;
799 :
800 : static const size_t nLeaderSize = 24;
801 : int i;
802 :
803 0 : for( i = 0; i < (int)nLeaderSize; i++ )
804 : {
805 0 : if( poOpenInfo->pabyHeader[i] < 32
806 0 : || poOpenInfo->pabyHeader[i] > 126 )
807 0 : return NULL;
808 : }
809 :
810 0 : if( poOpenInfo->pabyHeader[5] != '1'
811 0 : && poOpenInfo->pabyHeader[5] != '2'
812 0 : && poOpenInfo->pabyHeader[5] != '3' )
813 0 : return NULL;
814 :
815 0 : if( poOpenInfo->pabyHeader[6] != 'L' )
816 0 : return NULL;
817 0 : if( poOpenInfo->pabyHeader[8] != '1' && poOpenInfo->pabyHeader[8] != ' ' )
818 0 : return NULL;
819 :
820 : /* -------------------------------------------------------------------- */
821 : /* Find and open the .GEN file. */
822 : /* -------------------------------------------------------------------- */
823 : VSIStatBufL sStatBuf;
824 :
825 0 : CPLString basename = CPLGetBasename( osFileName );
826 0 : if( basename.size() != 8 )
827 : {
828 0 : CPLDebug("SRP", "Invalid basename file");
829 0 : return NULL;
830 : }
831 :
832 0 : int zoneNumber = CPLScanLong( basename + 6, 2 );
833 :
834 0 : CPLString path = CPLGetDirname( osFileName );
835 0 : CPLString basename01 = ResetTo01( basename );
836 0 : osFileName = CPLFormFilename( path, basename01, ".IMG" );
837 :
838 0 : osFileName = CPLResetExtension( osFileName, "GEN" );
839 0 : if( VSIStatL( osFileName, &sStatBuf ) != 0 )
840 : {
841 0 : osFileName = CPLResetExtension( osFileName, "gen" );
842 0 : if( VSIStatL( osFileName, &sStatBuf ) != 0 )
843 0 : return NULL;
844 : }
845 :
846 0 : if (!module.Open(osFileName, TRUE))
847 0 : return NULL;
848 :
849 0 : if( poOpenInfo->eAccess == GA_Update )
850 : {
851 : CPLError( CE_Failure, CPLE_NotSupported,
852 : "The SRP driver does not support update access to existing"
853 0 : " datasets.\n" );
854 0 : return NULL;
855 : }
856 :
857 : /* -------------------------------------------------------------------- */
858 : /* Loop processing records - we are basically looking for the */
859 : /* GIN record which is normally first in the .GEN file. */
860 : /* -------------------------------------------------------------------- */
861 0 : int recordIndex = 0;
862 0 : while (TRUE)
863 : {
864 0 : CPLPushErrorHandler( CPLQuietErrorHandler );
865 0 : record = module.ReadRecord();
866 0 : CPLPopErrorHandler();
867 0 : CPLErrorReset();
868 0 : if (record == NULL)
869 : break;
870 0 : if ( ++recordIndex < zoneNumber )
871 0 : continue;
872 :
873 0 : const char* RTY = record->GetStringSubfield( "001", 0, "RTY", 0 );
874 0 : if( RTY == NULL || !EQUAL(RTY,"GIN") )
875 0 : continue;
876 :
877 0 : const char *PRT = record->GetStringSubfield( "DSI", 0, "PRT", 0 );
878 0 : if( PRT == NULL )
879 0 : continue;
880 :
881 0 : CPLString osPRT = PRT;
882 0 : osPRT.resize(4);
883 0 : if( !EQUAL(osPRT,"ASRP") && !EQUAL(osPRT,"USRP") )
884 0 : continue;
885 :
886 0 : osNAM = record->GetStringSubfield( "DSI", 0, "NAM", 0 );
887 0 : CPLDebug("SRP", "NAM=%s", osNAM.c_str());
888 :
889 0 : SRPDataset *poDS = new SRPDataset();
890 :
891 0 : poDS->osProduct = osPRT;
892 0 : poDS->osGENFilename = osFileName;
893 0 : poDS->SetMetadataItem( "SRP_NAM", osNAM );
894 0 : poDS->SetMetadataItem( "SRP_PRODUCT", osPRT );
895 :
896 0 : if (!poDS->GetFromRecord( osFileName, record ) )
897 : {
898 0 : delete poDS;
899 0 : continue;
900 : }
901 :
902 : /* ---------------------------------------------------------- */
903 : /* Initialize any PAM information. */
904 : /* ---------------------------------------------------------- */
905 0 : poDS->SetDescription( poOpenInfo->pszFilename );
906 0 : poDS->TryLoadXML();
907 :
908 : /* ---------------------------------------------------------- */
909 : /* Check for external overviews. */
910 : /* ---------------------------------------------------------- */
911 0 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
912 :
913 0 : return poDS;
914 : }
915 :
916 0 : return NULL;
917 : }
918 :
919 : /************************************************************************/
920 : /* GDALRegister_SRP() */
921 : /************************************************************************/
922 :
923 338 : void GDALRegister_SRP()
924 :
925 : {
926 : GDALDriver *poDriver;
927 :
928 338 : if( GDALGetDriverByName( "SRP" ) == NULL )
929 : {
930 336 : poDriver = new GDALDriver();
931 :
932 336 : poDriver->SetDescription( "SRP" );
933 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
934 336 : "Standard Raster Product (ASRP/USRP)" );
935 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
936 336 : "frmt_various.html#SRP" );
937 336 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "img" );
938 336 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
939 :
940 336 : poDriver->pfnOpen = SRPDataset::Open;
941 :
942 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
943 : }
944 338 : }
945 :
|