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