1 : /******************************************************************************
2 : * $Id: adrgdataset.cpp 18407 2009-12-28 16:15:36Z rouault $
3 : *
4 : * Purpose: ADRG reader
5 : * Author: Even Rouault, even.rouault at mines-paris.org
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2007, Even Rouault
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "gdal_pam.h"
30 : #include "ogr_spatialref.h"
31 : #include "cpl_string.h"
32 : #include "iso8211.h"
33 :
34 : CPL_CVSID("$Id: adrgdataset.cpp 18407 2009-12-28 16:15:36Z rouault $");
35 :
36 : #define N_ELEMENTS(x) (sizeof(x)/sizeof(x[0]))
37 :
38 : class ADRGDataset : public GDALPamDataset
39 : {
40 : friend class ADRGRasterBand;
41 :
42 : CPLString osGENFileName;
43 : CPLString osIMGFileName;
44 :
45 : FILE* fdIMG;
46 : int* TILEINDEX;
47 : int offsetInIMG;
48 : int NFC;
49 : int NFL;
50 : double LSO;
51 : double PSO;
52 : int ARV;
53 : int BRV;
54 :
55 : char** papszSubDatasets;
56 :
57 : ADRGDataset* poOverviewDS;
58 :
59 : /* For creation */
60 : int bCreation;
61 : FILE* fdGEN;
62 : FILE* fdTHF;
63 : int bGeoTransformValid;
64 : double adfGeoTransform[6];
65 : int nNextAvailableBlock;
66 : CPLString osBaseFileName;
67 :
68 : static char** GetGENListFromTHF(const char* pszFileName);
69 : static char** GetIMGListFromGEN(const char* pszFileName, int* pnRecordIndex = NULL);
70 : static ADRGDataset* OpenDataset(const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record = NULL);
71 : static DDFRecord* FindRecordInGENForIMG(DDFModule& module,
72 : const char* pszGENFileName, const char* pszIMGFileName);
73 :
74 : public:
75 : ADRGDataset();
76 : virtual ~ADRGDataset();
77 :
78 : virtual const char *GetProjectionRef(void);
79 : virtual CPLErr GetGeoTransform( double * padfGeoTransform );
80 : virtual CPLErr SetGeoTransform( double * padfGeoTransform );
81 :
82 : virtual char **GetMetadata( const char * pszDomain = "" );
83 :
84 : virtual char **GetFileList();
85 :
86 : void AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName );
87 :
88 : static GDALDataset *Open( GDALOpenInfo * );
89 : static GDALDataset *Create(const char* pszFilename, int nXSize, int nYSize,
90 : int nBands, GDALDataType eType, char **papszOptions);
91 :
92 : static double GetLongitudeFromString(const char* str);
93 : static double GetLatitudeFromString(const char* str);
94 :
95 : void WriteGENFile();
96 : void WriteTHFFile();
97 : };
98 :
99 : /************************************************************************/
100 : /* ==================================================================== */
101 : /* ADRGRasterBand */
102 : /* ==================================================================== */
103 : /************************************************************************/
104 :
105 : class ADRGRasterBand : public GDALPamRasterBand
106 45 : {
107 : friend class ADRGDataset;
108 :
109 : public:
110 : ADRGRasterBand( ADRGDataset *, int );
111 :
112 : virtual GDALColorInterp GetColorInterpretation();
113 : virtual CPLErr IReadBlock( int, int, void * );
114 : virtual CPLErr IWriteBlock( int, int, void * );
115 :
116 : virtual double GetNoDataValue( int *pbSuccess = NULL );
117 :
118 : // virtual int GetOverviewCount();
119 : // virtual GDALRasterBand* GetOverview(int i);
120 : };
121 :
122 :
123 : /************************************************************************/
124 : /* ADRGRasterBand() */
125 : /************************************************************************/
126 :
127 45 : ADRGRasterBand::ADRGRasterBand( ADRGDataset *poDS, int nBand )
128 :
129 : {
130 45 : this->poDS = poDS;
131 45 : this->nBand = nBand;
132 :
133 45 : eDataType = GDT_Byte;
134 :
135 45 : nBlockXSize = 128;
136 45 : nBlockYSize = 128;
137 45 : }
138 :
139 : #if 0
140 :
141 : /* We have a problem with the overview. Its geo bounding box doesn't match */
142 : /* exactly the one of the main image. We should handle the shift between */
143 : /* the two top level corners... */
144 :
145 : /************************************************************************/
146 : /* GetOverviewCount() */
147 : /************************************************************************/
148 :
149 : int ADRGRasterBand::GetOverviewCount()
150 :
151 : {
152 : ADRGDataset* poDS = (ADRGDataset*)this->poDS;
153 : if( poDS->poOverviewDS )
154 : return 1;
155 : else
156 : return GDALRasterBand::GetOverviewCount();
157 : }
158 :
159 : /************************************************************************/
160 : /* GetOverview() */
161 : /************************************************************************/
162 :
163 : GDALRasterBand *ADRGRasterBand::GetOverview( int i )
164 :
165 : {
166 : ADRGDataset* poDS = (ADRGDataset*)this->poDS;
167 : if( poDS->poOverviewDS )
168 : {
169 : if( i < 0 || i >= 1 )
170 : return NULL;
171 : else
172 : return poDS->poOverviewDS->GetRasterBand(nBand);
173 : }
174 : else
175 : return GDALRasterBand::GetOverview( i );
176 : }
177 : #endif
178 :
179 : /************************************************************************/
180 : /* GetNoDataValue() */
181 : /************************************************************************/
182 :
183 27 : double ADRGRasterBand::GetNoDataValue( int *pbSuccess )
184 : {
185 27 : if (pbSuccess)
186 18 : *pbSuccess = TRUE;
187 :
188 27 : return 0;
189 : }
190 :
191 : /************************************************************************/
192 : /* GetColorInterpretation() */
193 : /************************************************************************/
194 :
195 27 : GDALColorInterp ADRGRasterBand::GetColorInterpretation()
196 :
197 : {
198 27 : if( nBand == 1 )
199 9 : return GCI_RedBand;
200 :
201 18 : else if( nBand == 2 )
202 9 : return GCI_GreenBand;
203 :
204 : else
205 9 : return GCI_BlueBand;
206 : }
207 :
208 : /************************************************************************/
209 : /* IReadBlock() */
210 : /************************************************************************/
211 :
212 : CPLErr ADRGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
213 14 : void * pImage )
214 :
215 : {
216 14 : ADRGDataset* poDS = (ADRGDataset*)this->poDS;
217 : int offset;
218 14 : int nBlock = nBlockYOff * poDS->NFC + nBlockXOff;
219 14 : if (nBlockXOff >= poDS->NFC || nBlockYOff >= poDS->NFL)
220 : {
221 : CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
222 0 : nBlockXOff, poDS->NFC, nBlockYOff, poDS->NFL);
223 0 : return CE_Failure;
224 : }
225 14 : CPLDebug("ADRG", "(%d,%d) -> nBlock = %d", nBlockXOff, nBlockYOff, nBlock);
226 :
227 14 : if (poDS->TILEINDEX)
228 : {
229 14 : if (poDS->TILEINDEX[nBlock] == 0)
230 : {
231 0 : memset(pImage, 0, 128 * 128);
232 0 : return CE_None;
233 : }
234 14 : offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
235 : }
236 : else
237 0 : offset = poDS->offsetInIMG + nBlock * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
238 :
239 14 : if (VSIFSeekL(poDS->fdIMG, offset, SEEK_SET) != 0)
240 : {
241 0 : CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
242 0 : return CE_Failure;
243 : }
244 14 : if (VSIFReadL(pImage, 1, 128 * 128, poDS->fdIMG) != 128 * 128)
245 : {
246 0 : CPLError(CE_Failure, CPLE_FileIO, "Cannot read data at offset %d", offset);
247 0 : return CE_Failure;
248 : }
249 :
250 14 : return CE_None;
251 : }
252 :
253 : /************************************************************************/
254 : /* IWriteBlock() */
255 : /************************************************************************/
256 :
257 : CPLErr ADRGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
258 9 : void * pImage )
259 :
260 : {
261 9 : ADRGDataset* poDS = (ADRGDataset*)this->poDS;
262 : int offset;
263 9 : int nBlock = nBlockYOff * poDS->NFC + nBlockXOff;
264 9 : if (poDS->eAccess != GA_Update)
265 : {
266 0 : return CE_Failure;
267 : }
268 9 : if (nBlockXOff >= poDS->NFC || nBlockYOff >= poDS->NFL)
269 : {
270 : CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
271 0 : nBlockXOff, poDS->NFC, nBlockYOff, poDS->NFL);
272 0 : return CE_Failure;
273 : }
274 9 : CPLDebug("ADRG", "(%d,%d) -> nBlock = %d", nBlockXOff, nBlockYOff, nBlock);
275 :
276 9 : if (poDS->TILEINDEX[nBlock] == 0)
277 : {
278 : unsigned int i;
279 3 : int* pi = (int*)pImage;
280 3 : for(i=0;i<128*128 / sizeof(int);i++)
281 : {
282 3 : if (pi[i])
283 3 : break;
284 : }
285 3 : if (i == 128*128 / sizeof(int))
286 : {
287 0 : return CE_None;
288 : }
289 :
290 3 : poDS->TILEINDEX[nBlock] = poDS->nNextAvailableBlock ++;
291 : }
292 :
293 9 : offset = poDS->offsetInIMG + (poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
294 :
295 9 : if (VSIFSeekL(poDS->fdIMG, offset, SEEK_SET) != 0)
296 : {
297 0 : CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
298 0 : return CE_Failure;
299 : }
300 9 : if (VSIFWriteL(pImage, 1, 128 * 128, poDS->fdIMG) != 128 * 128)
301 : {
302 0 : CPLError(CE_Failure, CPLE_FileIO, "Cannot read data at offset %d", offset);
303 0 : return CE_Failure;
304 : }
305 :
306 9 : return CE_None;
307 : }
308 :
309 267 : static unsigned int WriteSubFieldStr(FILE* fd, const char* pszStr, unsigned int size)
310 : {
311 267 : char* str = (char*)CPLMalloc(size+1);
312 267 : memset(str, ' ', size);
313 267 : if (strlen(pszStr) > size)
314 : {
315 0 : CPLError(CE_Failure, CPLE_AppDefined, "strlen(pszStr) > size");
316 0 : CPLFree(str);
317 0 : return size;
318 : }
319 267 : strcpy(str, pszStr);
320 267 : str[strlen(pszStr)] = ' ';
321 267 : VSIFWriteL(str, 1, size, fd);
322 267 : CPLFree(str);
323 267 : return size;
324 : }
325 :
326 820 : static unsigned int WriteSubFieldInt(FILE* fd, int val, unsigned int size)
327 : {
328 820 : char* str = (char*)CPLMalloc(size+1);
329 : char formatStr[32];
330 820 : sprintf( formatStr, "%%0%dd", size);
331 820 : sprintf( str, formatStr, val);
332 820 : VSIFWriteL(str, 1, size, fd);
333 820 : CPLFree(str);
334 820 : return size;
335 : }
336 :
337 280 : static unsigned int WriteFieldTerminator(FILE* fd)
338 : {
339 280 : char fieldTerminator = 30;
340 280 : VSIFWriteL(&fieldTerminator, 1, 1, fd);
341 280 : return 1;
342 : }
343 :
344 168 : static unsigned int WriteUnitTerminator(FILE* fd)
345 : {
346 168 : char fieldTerminator = 31;
347 168 : VSIFWriteL(&fieldTerminator, 1, 1, fd);
348 168 : return 1;
349 : }
350 :
351 37 : static unsigned int WriteLongitude(FILE* fd, double val)
352 : {
353 : char str[11+1];
354 37 : char sign = (val >= 0) ? '+' : '-';
355 37 : if (val < 0) val = -val;
356 37 : int ddd = (int)val;
357 37 : int mm = (int)((val - ddd) * 60);
358 37 : double ssdotss = ((val - ddd) * 60 - mm) * 60;
359 37 : sprintf(str, "%c%03d%02d%02.2f", sign, ddd, mm, ssdotss);
360 37 : VSIFWriteL(str, 1, 11, fd);
361 37 : return 11;
362 : }
363 :
364 37 : static unsigned int WriteLatitude(FILE* fd, double val)
365 : {
366 : char str[10+1];
367 37 : char sign = (val >= 0) ? '+' : '-';
368 37 : if (val < 0) val = -val;
369 37 : int dd = (int)val;
370 37 : int mm = (int)((val - dd) * 60);
371 37 : double ssdotss = ((val - dd) * 60 - mm) * 60;
372 37 : sprintf(str, "%c%02d%02d%02.2f", sign, dd, mm, ssdotss);
373 37 : VSIFWriteL(str, 1, 10, fd);
374 37 : return 10;
375 : }
376 :
377 : static int BeginLeader(FILE* fd, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
378 33 : int nFields)
379 : {
380 33 : int pos = (int)VSIFTellL(fd);
381 33 : VSIFSeekL(fd, 24 + (sizeFieldLength + sizeFieldPos + sizeFieldTag) * (vsi_l_offset)nFields + 1, SEEK_CUR);
382 33 : return pos;
383 : }
384 :
385 : static void FinishWriteLeader(FILE* fd, int beginPos, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
386 33 : int nFields, int* sizeOfFields, const char** nameOfFields)
387 : {
388 33 : int endPos = (int)VSIFTellL(fd);
389 33 : VSIFSeekL(fd, beginPos, SEEK_SET);
390 :
391 33 : int nLeaderSize = 24;
392 : char szLeader[24+1];
393 33 : memset(szLeader, ' ', nLeaderSize);
394 :
395 : int i;
396 33 : int nDataSize = 0;
397 33 : int nFieldOffset = 0;
398 172 : for(i=0;i<nFields;i++)
399 139 : nDataSize += sizeOfFields[i];
400 33 : nFieldOffset = (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
401 33 : nDataSize += nFieldOffset;
402 :
403 33 : sprintf( szLeader+0, "%05d", (int) (nDataSize + nLeaderSize) );
404 33 : szLeader[5] = ' ';
405 33 : szLeader[6] = 'D';
406 :
407 33 : sprintf( szLeader + 12, "%05d", (int) (nFieldOffset + nLeaderSize) );
408 33 : szLeader[17] = ' ';
409 :
410 33 : szLeader[20] = (char) ('0' + sizeFieldLength);
411 33 : szLeader[21] = (char) ('0' + sizeFieldPos);
412 33 : szLeader[22] = '0';
413 33 : szLeader[23] = (char) ('0' + sizeFieldTag);
414 :
415 33 : VSIFWriteL(szLeader, 1, nLeaderSize, fd);
416 :
417 33 : int acc = 0;
418 172 : for(i=0;i<nFields;i++)
419 : {
420 139 : VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd);
421 139 : WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength);
422 139 : WriteSubFieldInt(fd, acc, sizeFieldPos);
423 139 : acc += sizeOfFields[i];
424 : }
425 33 : WriteFieldTerminator(fd);
426 :
427 33 : VSIFSeekL(fd, endPos, SEEK_SET);
428 33 : }
429 :
430 :
431 : static int BeginHeader(FILE* fd, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
432 12 : int nFields)
433 : {
434 12 : int pos = (int)VSIFTellL(fd);
435 12 : VSIFSeekL(fd, 24 + (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1, SEEK_CUR);
436 12 : return pos;
437 : }
438 :
439 : static void FinishWriteHeader(FILE* fd, int beginPos, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
440 12 : int nFields, int* sizeOfFields, const char** nameOfFields)
441 : {
442 12 : int endPos = (int)VSIFTellL(fd);
443 12 : VSIFSeekL(fd, beginPos, SEEK_SET);
444 :
445 12 : int nLeaderSize = 24;
446 : char szLeader[24+1];
447 12 : memset(szLeader, ' ', nLeaderSize);
448 :
449 : int i;
450 12 : int nDataSize = 0;
451 12 : int nFieldOffset = 0;
452 108 : for(i=0;i<nFields;i++)
453 96 : nDataSize += sizeOfFields[i];
454 12 : nFieldOffset = (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
455 12 : nDataSize += nFieldOffset;
456 :
457 12 : sprintf( szLeader+0, "%05d", (int) (nDataSize + nLeaderSize) );
458 12 : szLeader[5] = '2';
459 12 : szLeader[6] = 'L';
460 :
461 12 : szLeader[10] = '0';
462 12 : szLeader[11] = '6';
463 12 : sprintf( szLeader + 12, "%05d", (int) (nFieldOffset + nLeaderSize) );
464 12 : szLeader[17] = ' ';
465 :
466 12 : szLeader[20] = (char) ('0' + sizeFieldLength);
467 12 : szLeader[21] = (char) ('0' + sizeFieldPos);
468 12 : szLeader[22] = '0';
469 12 : szLeader[23] = (char) ('0' + sizeFieldTag);
470 :
471 12 : VSIFWriteL(szLeader, 1, nLeaderSize, fd);
472 :
473 12 : int acc = 0;
474 108 : for(i=0;i<nFields;i++)
475 : {
476 96 : VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd);
477 96 : WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength);
478 96 : WriteSubFieldInt(fd, acc, sizeFieldPos);
479 96 : acc += sizeOfFields[i];
480 : }
481 12 : WriteFieldTerminator(fd);
482 :
483 12 : VSIFSeekL(fd, endPos, SEEK_SET);
484 12 : }
485 :
486 : static int WriteFieldDecl(FILE* fd, char _data_struct_code , char _data_type_code, const char* _fieldName,
487 96 : const char* _arrayDescr, const char* _formatControls)
488 : {
489 96 : VSIFWriteL(&_data_struct_code, 1, 1, fd);
490 96 : VSIFWriteL(&_data_type_code, 1, 1, fd);
491 96 : if (_data_struct_code == ' ')
492 : {
493 12 : VSIFWriteL(" ", 1 , 4, fd);
494 : }
495 : else
496 : {
497 84 : VSIFWriteL("00;&", 1 , 4, fd);
498 : }
499 96 : int len = 6;
500 96 : VSIFWriteL(_fieldName, 1, strlen(_fieldName), fd);
501 96 : len += strlen(_fieldName);
502 96 : if (_arrayDescr[0])
503 : {
504 84 : len += WriteUnitTerminator(fd);
505 84 : VSIFWriteL(_arrayDescr, 1, strlen(_arrayDescr), fd);
506 84 : len += strlen(_arrayDescr);
507 :
508 84 : len += WriteUnitTerminator(fd);
509 84 : VSIFWriteL(_formatControls, 1, strlen(_formatControls), fd);
510 84 : len += strlen(_formatControls);
511 : }
512 96 : len += WriteFieldTerminator(fd);
513 96 : return len;
514 : }
515 :
516 :
517 : /************************************************************************/
518 : /* ADRGDataset() */
519 : /************************************************************************/
520 :
521 16 : ADRGDataset::ADRGDataset()
522 : {
523 16 : bCreation = FALSE;
524 16 : poOverviewDS = NULL;
525 16 : fdIMG = NULL;
526 16 : fdGEN = NULL;
527 16 : fdTHF = NULL;
528 16 : TILEINDEX = NULL;
529 16 : papszSubDatasets = NULL;
530 16 : }
531 :
532 : /************************************************************************/
533 : /* ~ADRGDataset() */
534 : /************************************************************************/
535 :
536 16 : ADRGDataset::~ADRGDataset()
537 : {
538 16 : if (poOverviewDS)
539 : {
540 0 : delete poOverviewDS;
541 : }
542 :
543 16 : CSLDestroy(papszSubDatasets);
544 :
545 16 : if (bCreation)
546 : {
547 4 : GDALPamDataset::FlushCache();
548 :
549 : /* Write header and padding of image */
550 4 : VSIFSeekL(fdIMG, 0, SEEK_SET);
551 : {
552 4 : FILE* fd = fdIMG;
553 4 : int nFields = 0;
554 4 : int sizeOfFields[] = { 0, 0, 0, 0 };
555 4 : const char* nameOfFields[] = { "000", "001", "PAD", "SCN" };
556 4 : int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
557 :
558 4 : sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "GEO_DATA_FILE", "", ""); /* 000 */
559 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
560 : "RTY!RID",
561 4 : "(A(3),A(2))");
562 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "PADDING_FIELD", /* PAD */
563 : "PAD",
564 4 : "(A)");
565 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '0', "PIXEL_FIELD", /* SCN */
566 : "*PIX",
567 4 : "(A(1))");
568 :
569 4 : FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
570 :
571 : /* Write IMAGE_RECORD */
572 : {
573 4 : int nFields = 0;
574 4 : int sizeOfFields[] = {0, 0, 0};
575 4 : const char* nameOfFields[] = { "001", "PAD", "SCN" };
576 4 : int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
577 :
578 : /* Field 001 */
579 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "IMG", 3); /* RTY */
580 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
581 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
582 4 : nFields++;
583 :
584 : /* Field PAD */
585 4 : int endPos = (int)VSIFTellL(fd);
586 4 : char* pad = (char*)CPLMalloc(2047 - endPos);
587 4 : memset(pad, ' ', 2047 - endPos);
588 4 : VSIFWriteL(pad, 1, 2047 - endPos, fd);
589 4 : CPLFree(pad);
590 4 : WriteFieldTerminator(fd);
591 4 : sizeOfFields[nFields] += 2047 - endPos + 1;
592 4 : nFields++;
593 :
594 : /* Field SCN */
595 4 : sizeOfFields[nFields] = (nNextAvailableBlock - 1) * 128 * 128 * 3;
596 4 : nFields++;
597 :
598 4 : FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
599 : }
600 : }
601 :
602 : /* Write terminal field terminator */
603 4 : int offset = offsetInIMG + (nNextAvailableBlock - 1) * 128 * 128 * 3;
604 4 : VSIFSeekL(fdIMG, offset, SEEK_SET);
605 4 : WriteFieldTerminator(fdIMG);
606 :
607 4 : WriteGENFile();
608 4 : WriteTHFFile();
609 : }
610 :
611 16 : if (fdIMG)
612 : {
613 15 : VSIFCloseL(fdIMG);
614 : }
615 :
616 16 : if (fdGEN)
617 : {
618 4 : VSIFCloseL(fdGEN);
619 : }
620 16 : if (fdTHF)
621 : {
622 4 : VSIFCloseL(fdTHF);
623 : }
624 :
625 16 : if (TILEINDEX)
626 : {
627 15 : delete [] TILEINDEX;
628 : }
629 16 : }
630 :
631 : /************************************************************************/
632 : /* GetFileList() */
633 : /************************************************************************/
634 :
635 2 : char ** ADRGDataset::GetFileList()
636 : {
637 2 : char** papszFileList = GDALPamDataset::GetFileList();
638 :
639 2 : if (osGENFileName.size() > 0 && osIMGFileName.size() > 0)
640 : {
641 2 : CPLString osMainFilename = GetDescription();
642 : int bMainFileReal;
643 : VSIStatBufL sStat;
644 :
645 2 : bMainFileReal = VSIStatL( osMainFilename, &sStat ) == 0;
646 2 : if (bMainFileReal)
647 : {
648 2 : CPLString osShortMainFilename = CPLGetFilename(osMainFilename);
649 2 : CPLString osShortGENFileName = CPLGetFilename(osGENFileName);
650 2 : if ( !EQUAL(osShortMainFilename.c_str(), osShortGENFileName.c_str()) )
651 0 : papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
652 : }
653 : else
654 0 : papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
655 :
656 2 : papszFileList = CSLAddString(papszFileList, osIMGFileName.c_str());
657 : }
658 :
659 2 : return papszFileList;
660 : }
661 :
662 : /************************************************************************/
663 : /* AddSubDataset() */
664 : /************************************************************************/
665 :
666 2 : void ADRGDataset::AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName )
667 : {
668 : char szName[80];
669 2 : int nCount = CSLCount(papszSubDatasets ) / 2;
670 :
671 2 : CPLString osSubDatasetName;
672 2 : osSubDatasetName = "ADRG:";
673 2 : osSubDatasetName += pszGENFileName;
674 2 : osSubDatasetName += ",";
675 2 : osSubDatasetName += pszIMGFileName;
676 :
677 2 : sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
678 : papszSubDatasets =
679 2 : CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
680 :
681 2 : sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
682 : papszSubDatasets =
683 2 : CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
684 2 : }
685 :
686 : /************************************************************************/
687 : /* GetMetadata() */
688 : /************************************************************************/
689 :
690 10 : char **ADRGDataset::GetMetadata( const char *pszDomain )
691 :
692 : {
693 10 : if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
694 0 : return papszSubDatasets;
695 :
696 10 : return GDALPamDataset::GetMetadata( pszDomain );
697 : }
698 :
699 : /************************************************************************/
700 : /* GetProjectionRef() */
701 : /************************************************************************/
702 :
703 9 : const char* ADRGDataset::GetProjectionRef()
704 : {
705 9 : return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
706 : }
707 :
708 : /************************************************************************/
709 : /* GetGeoTransform() */
710 : /************************************************************************/
711 :
712 3 : CPLErr ADRGDataset::GetGeoTransform( double * padfGeoTransform)
713 : {
714 3 : if (papszSubDatasets != NULL)
715 0 : return CE_Failure;
716 :
717 3 : padfGeoTransform[0] = LSO;
718 3 : padfGeoTransform[1] = 360. / ARV;
719 3 : padfGeoTransform[2] = 0.0;
720 3 : padfGeoTransform[3] = PSO;
721 3 : padfGeoTransform[4] = 0.0;
722 3 : padfGeoTransform[5] = - 360. / BRV;
723 :
724 3 : return CE_None;
725 : }
726 :
727 : /************************************************************************/
728 : /* SetGeoTransform() */
729 : /************************************************************************/
730 :
731 4 : CPLErr ADRGDataset::SetGeoTransform( double * padfGeoTransform )
732 :
733 : {
734 4 : memcpy( adfGeoTransform, padfGeoTransform, sizeof(double)*6 );
735 4 : bGeoTransformValid = TRUE;
736 4 : return CE_None;
737 : }
738 :
739 : /************************************************************************/
740 : /* GetLongitudeFromString() */
741 : /************************************************************************/
742 :
743 11 : double ADRGDataset::GetLongitudeFromString(const char* str)
744 : {
745 11 : char ddd[3+1] = { 0 };
746 11 : char mm[2+1] = { 0 };
747 11 : char ssdotss[5+1] = { 0 };
748 11 : int sign = (str[0] == '+') ? 1 : - 1;
749 11 : str++;
750 11 : strncpy(ddd, str, 3);
751 11 : str+=3;
752 11 : strncpy(mm, str, 2);
753 11 : str+=2;
754 11 : strncpy(ssdotss, str, 5);
755 11 : return sign * (atof(ddd) + atof(mm) / 60 + atof(ssdotss) / 3600);
756 : }
757 :
758 : /************************************************************************/
759 : /* GetLatitudeFromString() */
760 : /************************************************************************/
761 :
762 11 : double ADRGDataset::GetLatitudeFromString(const char* str)
763 : {
764 11 : char ddd[2+1] = { 0 };
765 11 : char mm[2+1] = { 0 };
766 11 : char ssdotss[5+1] = { 0 };
767 11 : int sign = (str[0] == '+') ? 1 : - 1;
768 11 : str++;
769 11 : strncpy(ddd, str, 2);
770 11 : str+=2;
771 11 : strncpy(mm, str, 2);
772 11 : str+=2;
773 11 : strncpy(ssdotss, str, 5);
774 11 : return sign * (atof(ddd) + atof(mm) / 60 + atof(ssdotss) / 3600);
775 : }
776 :
777 : /************************************************************************/
778 : /* FindRecordInGENForIMG() */
779 : /************************************************************************/
780 :
781 : DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
782 : const char* pszGENFileName,
783 2 : const char* pszIMGFileName)
784 : {
785 : /* Finds the GEN file corresponding to the IMG file */
786 2 : if (!module.Open(pszGENFileName, TRUE))
787 0 : return NULL;
788 :
789 :
790 2 : CPLString osShortIMGFilename = CPLGetFilename(pszIMGFileName);
791 :
792 : DDFField* field;
793 : DDFFieldDefn *fieldDefn;
794 : DDFSubfieldDefn* subfieldDefn;
795 :
796 : /* Now finds the record */
797 5 : while (TRUE)
798 : {
799 7 : CPLPushErrorHandler( CPLQuietErrorHandler );
800 7 : DDFRecord* record = module.ReadRecord();
801 7 : CPLPopErrorHandler();
802 7 : CPLErrorReset();
803 7 : if (record == NULL)
804 2 : return NULL;
805 :
806 7 : if (record->GetFieldCount() >= 5)
807 : {
808 5 : field = record->GetField(0);
809 5 : fieldDefn = field->GetFieldDefn();
810 5 : if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
811 : fieldDefn->GetSubfieldCount() == 2))
812 : {
813 0 : continue;
814 : }
815 :
816 5 : subfieldDefn = fieldDefn->GetSubfield(0);
817 5 : if (!(strcmp(subfieldDefn->GetName(), "RTY") == 0 &&
818 : (subfieldDefn->GetFormat())[0] == 'A'))
819 : {
820 0 : continue;
821 : }
822 :
823 5 : const char* RTY = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 3, NULL);
824 :
825 : /* Ignore overviews */
826 5 : if ( strcmp(RTY, "OVV") == 0 )
827 2 : continue;
828 :
829 3 : if ( strcmp(RTY, "GIN") != 0 )
830 0 : continue;
831 :
832 3 : field = record->GetField(3);
833 3 : fieldDefn = field->GetFieldDefn();
834 :
835 3 : if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
836 : fieldDefn->GetSubfieldCount() == 15))
837 : {
838 0 : continue;
839 : }
840 :
841 3 : subfieldDefn = fieldDefn->GetSubfield(13);
842 3 : if (!(strcmp(subfieldDefn->GetName(), "BAD") == 0 &&
843 : (subfieldDefn->GetFormat())[0] == 'A'))
844 : {
845 0 : continue;
846 : }
847 :
848 3 : CPLString osBAD = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 12, NULL);
849 : {
850 3 : char* c = (char*) strchr(osBAD.c_str(), ' ');
851 3 : if (c)
852 0 : *c = 0;
853 : }
854 :
855 3 : if (EQUAL(osShortIMGFilename.c_str(), osBAD.c_str()))
856 : {
857 2 : return record;
858 0 : }
859 : }
860 0 : }
861 : }
862 :
863 : /************************************************************************/
864 : /* OpenDataset() */
865 : /************************************************************************/
866 :
867 : ADRGDataset* ADRGDataset::OpenDataset(
868 11 : const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record)
869 : {
870 11 : DDFModule module;
871 :
872 11 : int SCA = 0;
873 11 : int ZNA = 0;
874 : double PSP;
875 : int ARV;
876 : int BRV;
877 : double LSO;
878 : double PSO;
879 : int NFL;
880 : int NFC;
881 11 : CPLString osBAD;
882 : int TIF;
883 11 : int* TILEINDEX = NULL;
884 : int i;
885 :
886 : DDFField* field;
887 : DDFFieldDefn *fieldDefn;
888 : DDFSubfieldDefn* subfieldDefn;
889 :
890 11 : if (record == NULL)
891 : {
892 2 : record = FindRecordInGENForIMG(module, pszGENFileName, pszIMGFileName);
893 2 : if (record == NULL)
894 0 : return NULL;
895 : }
896 :
897 11 : field = record->GetField(1);
898 11 : fieldDefn = field->GetFieldDefn();
899 :
900 11 : if (!(strcmp(fieldDefn->GetName(), "DSI") == 0 &&
901 : fieldDefn->GetSubfieldCount() == 2))
902 : {
903 0 : return NULL;
904 : }
905 :
906 11 : subfieldDefn = fieldDefn->GetSubfield(0);
907 11 : if (!(strcmp(subfieldDefn->GetName(), "PRT") == 0 &&
908 : (subfieldDefn->GetFormat())[0] == 'A' &&
909 : strcmp(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 4, NULL), "ADRG") == 0))
910 : {
911 0 : return NULL;
912 : }
913 :
914 11 : subfieldDefn = fieldDefn->GetSubfield(1);
915 11 : if (!(strcmp(subfieldDefn->GetName(), "NAM") == 0 &&
916 : (subfieldDefn->GetFormat())[0] == 'A'))
917 : {
918 0 : return NULL;
919 : }
920 :
921 11 : CPLString osNAM = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 8, NULL);
922 :
923 11 : field = record->GetField(2);
924 11 : fieldDefn = field->GetFieldDefn();
925 :
926 11 : int isGIN = TRUE;
927 :
928 11 : if (isGIN)
929 : {
930 11 : if (!(strcmp(fieldDefn->GetName(), "GEN") == 0 &&
931 : fieldDefn->GetSubfieldCount() == 21))
932 : {
933 0 : return NULL;
934 : }
935 :
936 11 : subfieldDefn = fieldDefn->GetSubfield(0);
937 11 : if (!(strcmp(subfieldDefn->GetName(), "STR") == 0 &&
938 : (subfieldDefn->GetFormat())[0] == 'I' &&
939 : subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 1, NULL) == 3))
940 : {
941 0 : return NULL;
942 : }
943 :
944 11 : subfieldDefn = fieldDefn->GetSubfield(12);
945 11 : if (!(strcmp(subfieldDefn->GetName(), "SCA") == 0 &&
946 : (subfieldDefn->GetFormat())[0] == 'I'))
947 : {
948 0 : return NULL;
949 : }
950 :
951 11 : SCA = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 9, NULL);
952 11 : CPLDebug("ADRG", "SCA=%d", SCA);
953 :
954 11 : subfieldDefn = fieldDefn->GetSubfield(13);
955 11 : if (!(strcmp(subfieldDefn->GetName(), "ZNA") == 0 &&
956 : (subfieldDefn->GetFormat())[0] == 'I'))
957 : {
958 0 : return NULL;
959 : }
960 :
961 11 : ZNA = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 2, NULL);
962 11 : CPLDebug("ADRG", "ZNA=%d", ZNA);
963 :
964 11 : subfieldDefn = fieldDefn->GetSubfield(14);
965 11 : if (!(strcmp(subfieldDefn->GetName(), "PSP") == 0 &&
966 : (subfieldDefn->GetFormat())[0] == 'R'))
967 : {
968 0 : return NULL;
969 : }
970 :
971 11 : PSP = subfieldDefn->ExtractFloatData(field->GetSubfieldData(subfieldDefn), 5, NULL);
972 11 : CPLDebug("ADRG", "PSP=%f", PSP);
973 :
974 11 : subfieldDefn = fieldDefn->GetSubfield(16);
975 11 : if (!(strcmp(subfieldDefn->GetName(), "ARV") == 0 &&
976 : (subfieldDefn->GetFormat())[0] == 'I'))
977 : {
978 0 : return NULL;
979 : }
980 :
981 11 : ARV = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 8, NULL);
982 11 : CPLDebug("ADRG", "ARV=%d", ARV);
983 :
984 11 : subfieldDefn = fieldDefn->GetSubfield(17);
985 11 : if (!(strcmp(subfieldDefn->GetName(), "BRV") == 0 &&
986 : (subfieldDefn->GetFormat())[0] == 'I'))
987 : {
988 0 : return NULL;
989 : }
990 :
991 11 : BRV = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 8, NULL);
992 11 : CPLDebug("ADRG", "BRV=%d", BRV);
993 :
994 :
995 11 : subfieldDefn = fieldDefn->GetSubfield(18);
996 11 : if (!(strcmp(subfieldDefn->GetName(), "LSO") == 0 &&
997 : (subfieldDefn->GetFormat())[0] == 'A'))
998 : {
999 0 : return NULL;
1000 : }
1001 :
1002 11 : LSO = GetLongitudeFromString(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 11, NULL));
1003 11 : CPLDebug("ADRG", "LSO=%f", LSO);
1004 :
1005 11 : subfieldDefn = fieldDefn->GetSubfield(19);
1006 11 : if (!(strcmp(subfieldDefn->GetName(), "PSO") == 0 &&
1007 : (subfieldDefn->GetFormat())[0] == 'A'))
1008 : {
1009 0 : return NULL;
1010 : }
1011 :
1012 11 : PSO = GetLatitudeFromString(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 10, NULL));
1013 11 : CPLDebug("ADRG", "PSO=%f", PSO);
1014 : }
1015 : else
1016 : {
1017 0 : if (!(strcmp(fieldDefn->GetName(), "OVI") == 0 &&
1018 : fieldDefn->GetSubfieldCount() == 5))
1019 : {
1020 0 : return NULL;
1021 : }
1022 :
1023 0 : subfieldDefn = fieldDefn->GetSubfield(0);
1024 0 : if (!(strcmp(subfieldDefn->GetName(), "STR") == 0 &&
1025 : (subfieldDefn->GetFormat())[0] == 'I' &&
1026 : subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 1, NULL) == 3))
1027 : {
1028 0 : return NULL;
1029 : }
1030 :
1031 0 : subfieldDefn = fieldDefn->GetSubfield(1);
1032 0 : if (!(strcmp(subfieldDefn->GetName(), "ARV") == 0 &&
1033 : (subfieldDefn->GetFormat())[0] == 'I'))
1034 : {
1035 0 : return NULL;
1036 : }
1037 :
1038 0 : ARV = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 8, NULL);
1039 0 : CPLDebug("ADRG", "ARV=%d", ARV);
1040 :
1041 0 : subfieldDefn = fieldDefn->GetSubfield(2);
1042 0 : if (!(strcmp(subfieldDefn->GetName(), "BRV") == 0 &&
1043 : (subfieldDefn->GetFormat())[0] == 'I'))
1044 : {
1045 0 : return NULL;
1046 : }
1047 :
1048 0 : BRV = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 8, NULL);
1049 0 : CPLDebug("ADRG", "BRV=%d", BRV);
1050 :
1051 :
1052 0 : subfieldDefn = fieldDefn->GetSubfield(3);
1053 0 : if (!(strcmp(subfieldDefn->GetName(), "LSO") == 0 &&
1054 : (subfieldDefn->GetFormat())[0] == 'A'))
1055 : {
1056 0 : return NULL;
1057 : }
1058 :
1059 0 : LSO = GetLongitudeFromString(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 11, NULL));
1060 0 : CPLDebug("ADRG", "LSO=%f", LSO);
1061 :
1062 0 : subfieldDefn = fieldDefn->GetSubfield(4);
1063 0 : if (!(strcmp(subfieldDefn->GetName(), "PSO") == 0 &&
1064 : (subfieldDefn->GetFormat())[0] == 'A'))
1065 : {
1066 0 : return NULL;
1067 : }
1068 :
1069 0 : PSO = GetLatitudeFromString(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 10, NULL));
1070 0 : CPLDebug("ADRG", "PSO=%f", PSO);
1071 : }
1072 :
1073 11 : field = record->GetField(3);
1074 11 : fieldDefn = field->GetFieldDefn();
1075 :
1076 11 : if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
1077 : fieldDefn->GetSubfieldCount() == 15))
1078 : {
1079 0 : return NULL;
1080 : }
1081 :
1082 11 : subfieldDefn = fieldDefn->GetSubfield(4);
1083 11 : if (!(strcmp(subfieldDefn->GetName(), "NFL") == 0 &&
1084 : (subfieldDefn->GetFormat())[0] == 'I'))
1085 : {
1086 0 : return NULL;
1087 : }
1088 :
1089 11 : NFL = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 3, NULL);
1090 11 : CPLDebug("ADRG", "NFL=%d", NFL);
1091 :
1092 11 : subfieldDefn = fieldDefn->GetSubfield(5);
1093 11 : if (!(strcmp(subfieldDefn->GetName(), "NFC") == 0 &&
1094 : (subfieldDefn->GetFormat())[0] == 'I'))
1095 : {
1096 0 : return NULL;
1097 : }
1098 :
1099 11 : NFC = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 3, NULL);
1100 11 : CPLDebug("ADRG", "NFC=%d", NFC);
1101 :
1102 11 : subfieldDefn = fieldDefn->GetSubfield(6);
1103 11 : if (!(strcmp(subfieldDefn->GetName(), "PNC") == 0 &&
1104 : (subfieldDefn->GetFormat())[0] == 'I'))
1105 : {
1106 0 : return NULL;
1107 : }
1108 :
1109 11 : int PNC = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 6, NULL);
1110 11 : CPLDebug("ADRG", "PNC=%d", PNC);
1111 11 : if (PNC != 128)
1112 : {
1113 0 : return NULL;
1114 : }
1115 :
1116 11 : subfieldDefn = fieldDefn->GetSubfield(7);
1117 11 : if (!(strcmp(subfieldDefn->GetName(), "PNL") == 0 &&
1118 : (subfieldDefn->GetFormat())[0] == 'I'))
1119 : {
1120 0 : return NULL;
1121 : }
1122 :
1123 11 : int PNL = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 6, NULL);
1124 11 : CPLDebug("ADRG", "PNL=%d", PNL);
1125 11 : if (PNL != 128)
1126 : {
1127 0 : return NULL;
1128 : }
1129 :
1130 11 : subfieldDefn = fieldDefn->GetSubfield(13);
1131 11 : if (!(strcmp(subfieldDefn->GetName(), "BAD") == 0 &&
1132 : (subfieldDefn->GetFormat())[0] == 'A'))
1133 : {
1134 0 : return NULL;
1135 : }
1136 :
1137 11 : osBAD = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 12, NULL);
1138 : {
1139 11 : char* c = (char*) strchr(osBAD.c_str(), ' ');
1140 11 : if (c)
1141 0 : *c = 0;
1142 : }
1143 11 : CPLDebug("ADRG", "BAD=%s", osBAD.c_str());
1144 :
1145 11 : subfieldDefn = fieldDefn->GetSubfield(14);
1146 11 : if (!(strcmp(subfieldDefn->GetName(), "TIF") == 0 &&
1147 : (subfieldDefn->GetFormat())[0] == 'A'))
1148 : {
1149 0 : return NULL;
1150 : }
1151 :
1152 11 : TIF = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 1, NULL)[0] == 'Y';
1153 11 : CPLDebug("ADRG", "TIF=%d", TIF);
1154 :
1155 11 : if (TIF)
1156 : {
1157 11 : if (record->GetFieldCount() != 6)
1158 : {
1159 0 : return NULL;
1160 : }
1161 :
1162 11 : field = record->GetField(5);
1163 11 : fieldDefn = field->GetFieldDefn();
1164 :
1165 11 : if (!(strcmp(fieldDefn->GetName(), "TIM") == 0))
1166 : {
1167 0 : return NULL;
1168 : }
1169 :
1170 11 : if (field->GetDataSize() != 5 * NFL * NFC + 1)
1171 : {
1172 0 : return NULL;
1173 : }
1174 :
1175 11 : TILEINDEX = new int [NFL * NFC];
1176 11 : const char* ptr = field->GetData();
1177 11 : char offset[5+1]={0};
1178 22 : for(i=0;i<NFL*NFC;i++)
1179 : {
1180 11 : strncpy(offset, ptr, 5);
1181 11 : ptr += 5;
1182 11 : TILEINDEX[i] = atoi(offset);
1183 : //CPLDebug("ADRG", "TSI[%d]=%d", i, TILEINDEX[i]);
1184 : }
1185 : }
1186 :
1187 11 : FILE* fdIMG = VSIFOpenL(pszIMGFileName, "rb");
1188 11 : if (fdIMG == NULL)
1189 : {
1190 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s\n", pszIMGFileName);
1191 0 : return NULL;
1192 : }
1193 :
1194 11 : if (ZNA == 9 || ZNA == 18)
1195 : {
1196 0 : CPLError(CE_Failure, CPLE_AppDefined, "Polar cases are not handled by ADRG driver");
1197 0 : VSIFCloseL(fdIMG);
1198 0 : return NULL;
1199 : }
1200 :
1201 : /* Skip ISO8211 header of IMG file */
1202 11 : int offsetInIMG = 0;
1203 : char c;
1204 : char recordName[3];
1205 11 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
1206 : {
1207 0 : VSIFCloseL(fdIMG);
1208 0 : return NULL;
1209 : }
1210 2849 : while (!VSIFEofL(fdIMG))
1211 : {
1212 2838 : if (c == 30)
1213 : {
1214 66 : if (VSIFReadL(recordName, 1, 3, fdIMG) != 3)
1215 : {
1216 0 : VSIFCloseL(fdIMG);
1217 0 : return NULL;
1218 : }
1219 66 : offsetInIMG += 3;
1220 66 : if (strncmp(recordName,"IMG",3) == 0)
1221 : {
1222 11 : offsetInIMG += 4;
1223 11 : if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0)
1224 : {
1225 0 : VSIFCloseL(fdIMG);
1226 0 : return NULL;
1227 : }
1228 11 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
1229 : {
1230 0 : VSIFCloseL(fdIMG);
1231 0 : return NULL;
1232 : }
1233 19470 : while(c ==' ')
1234 : {
1235 19448 : offsetInIMG ++;
1236 19448 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
1237 : {
1238 0 : VSIFCloseL(fdIMG);
1239 0 : return NULL;
1240 : }
1241 : }
1242 11 : offsetInIMG ++;
1243 11 : break;
1244 : }
1245 : }
1246 :
1247 2827 : offsetInIMG ++;
1248 2827 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
1249 : {
1250 0 : VSIFCloseL(fdIMG);
1251 0 : return NULL;
1252 : }
1253 : }
1254 :
1255 11 : if (VSIFEofL(fdIMG))
1256 : {
1257 0 : VSIFCloseL(fdIMG);
1258 0 : return NULL;
1259 : }
1260 :
1261 11 : CPLDebug("ADRG", "Img offset data = %d", offsetInIMG);
1262 :
1263 11 : ADRGDataset* poDS = new ADRGDataset();
1264 :
1265 22 : poDS->osGENFileName = pszGENFileName;
1266 11 : poDS->osIMGFileName = pszIMGFileName;
1267 11 : poDS->NFC = NFC;
1268 11 : poDS->NFL = NFL;
1269 11 : poDS->nRasterXSize = NFC * 128;
1270 11 : poDS->nRasterYSize = NFL * 128;
1271 11 : poDS->LSO = LSO;
1272 11 : poDS->PSO = PSO;
1273 11 : poDS->ARV = ARV;
1274 11 : poDS->BRV = BRV;
1275 11 : poDS->TILEINDEX = TILEINDEX;
1276 11 : poDS->fdIMG = fdIMG;
1277 11 : poDS->offsetInIMG = offsetInIMG;
1278 11 : poDS->poOverviewDS = NULL;
1279 :
1280 11 : if (isGIN)
1281 : {
1282 : char pszValue[32];
1283 11 : sprintf(pszValue, "%d", SCA);
1284 11 : poDS->SetMetadataItem( "ADRG_SCA", pszValue );
1285 : }
1286 :
1287 11 : poDS->SetMetadataItem( "ADRG_NAM", osNAM.c_str() );
1288 :
1289 11 : poDS->nBands = 3;
1290 44 : for( i = 0; i < poDS->nBands; i++ )
1291 33 : poDS->SetBand( i+1, new ADRGRasterBand( poDS, i+1 ) );
1292 :
1293 11 : return poDS;
1294 : }
1295 :
1296 : /************************************************************************/
1297 : /* GetGENListFromTHF() */
1298 : /************************************************************************/
1299 :
1300 2 : char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
1301 : {
1302 2 : DDFModule module;
1303 : DDFRecord * record;
1304 : DDFField* field;
1305 : DDFFieldDefn *fieldDefn;
1306 : DDFSubfieldDefn* subfieldDefn;
1307 : int i;
1308 2 : int nFilenames = 0;
1309 2 : char** papszFileNames = NULL;
1310 :
1311 2 : if (!module.Open(pszFileName, TRUE))
1312 0 : return papszFileNames;
1313 :
1314 8 : while (TRUE)
1315 : {
1316 10 : CPLPushErrorHandler( CPLQuietErrorHandler );
1317 10 : record = module.ReadRecord();
1318 10 : CPLPopErrorHandler();
1319 10 : CPLErrorReset();
1320 10 : if (record == NULL)
1321 2 : break;
1322 :
1323 8 : if (record->GetFieldCount() >= 2)
1324 : {
1325 8 : field = record->GetField(0);
1326 8 : fieldDefn = field->GetFieldDefn();
1327 8 : if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
1328 : fieldDefn->GetSubfieldCount() == 2))
1329 : {
1330 0 : continue;
1331 : }
1332 :
1333 8 : subfieldDefn = fieldDefn->GetSubfield(0);
1334 8 : if (!(strcmp(subfieldDefn->GetName(), "RTY") == 0 &&
1335 : (subfieldDefn->GetFormat())[0] == 'A'))
1336 : {
1337 0 : continue;
1338 : }
1339 :
1340 8 : const char* RTY = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 3, NULL);
1341 8 : if (! ( strcmp(RTY, "TFN") == 0 ))
1342 : {
1343 6 : continue;
1344 : }
1345 :
1346 11 : for (i = 1; i < record->GetFieldCount() ; i++)
1347 : {
1348 9 : field = record->GetField(i);
1349 9 : fieldDefn = field->GetFieldDefn();
1350 :
1351 9 : if (!(strcmp(fieldDefn->GetName(), "VFF") == 0 &&
1352 : fieldDefn->GetSubfieldCount() == 1))
1353 : {
1354 0 : continue;
1355 : }
1356 :
1357 9 : subfieldDefn = fieldDefn->GetSubfield(0);
1358 9 : if (!(strcmp(subfieldDefn->GetName(), "VFF") == 0 &&
1359 : (subfieldDefn->GetFormat())[0] == 'A'))
1360 : {
1361 0 : continue;
1362 : }
1363 :
1364 9 : CPLString osSubFileName(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 300, NULL));
1365 9 : char* c = (char*) strchr(osSubFileName.c_str(), ' ');
1366 9 : if (c)
1367 9 : *c = 0;
1368 9 : if (EQUAL(CPLGetExtension(osSubFileName.c_str()), "GEN"))
1369 : {
1370 2 : CPLDebug("ADRG", "Found GEN file in THF : %s", osSubFileName.c_str());
1371 2 : CPLString osGENFileName(CPLGetDirname(pszFileName));
1372 2 : char** tokens = CSLTokenizeString2( osSubFileName.c_str(), "/\"", 0);
1373 2 : char** ptr = tokens;
1374 2 : if (ptr == NULL)
1375 0 : continue;
1376 6 : while(*ptr)
1377 : {
1378 2 : char** papszDirContent = VSIReadDir(osGENFileName.c_str());
1379 2 : char** ptrDir = papszDirContent;
1380 2 : if (ptrDir)
1381 : {
1382 15 : while(*ptrDir)
1383 : {
1384 13 : if (EQUAL(*ptrDir, *ptr))
1385 : {
1386 2 : osGENFileName = CPLFormFilename(osGENFileName.c_str(), *ptrDir, NULL);
1387 2 : CPLDebug("ADRG", "Building GEN full file name : %s", osGENFileName.c_str());
1388 2 : break;
1389 : }
1390 11 : ptrDir ++;
1391 : }
1392 : }
1393 2 : if (ptrDir == NULL)
1394 0 : break;
1395 2 : CSLDestroy(papszDirContent);
1396 2 : ptr++;
1397 : }
1398 2 : int isNameValid = *ptr == NULL;
1399 2 : CSLDestroy(tokens);
1400 2 : if (isNameValid)
1401 : {
1402 2 : papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
1403 2 : papszFileNames[nFilenames] = CPLStrdup(osGENFileName.c_str());
1404 2 : papszFileNames[nFilenames + 1] = NULL;
1405 2 : nFilenames ++;
1406 0 : }
1407 : }
1408 : }
1409 : }
1410 : }
1411 2 : return papszFileNames;
1412 : }
1413 :
1414 : /************************************************************************/
1415 : /* GetIMGListFromGEN() */
1416 : /************************************************************************/
1417 :
1418 : char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
1419 10 : int *pnRecordIndex)
1420 : {
1421 : DDFRecord * record;
1422 : DDFField* field;
1423 : DDFFieldDefn *fieldDefn;
1424 : DDFSubfieldDefn* subfieldDefn;
1425 10 : int nFilenames = 0;
1426 10 : char** papszFileNames = NULL;
1427 10 : int nRecordIndex = -1;
1428 :
1429 10 : if (pnRecordIndex)
1430 10 : *pnRecordIndex = -1;
1431 :
1432 10 : DDFModule module;
1433 10 : if (!module.Open(pszFileName, TRUE))
1434 0 : return NULL;
1435 :
1436 31 : while (TRUE)
1437 : {
1438 41 : nRecordIndex ++;
1439 :
1440 41 : CPLPushErrorHandler( CPLQuietErrorHandler );
1441 41 : record = module.ReadRecord();
1442 41 : CPLPopErrorHandler();
1443 41 : CPLErrorReset();
1444 41 : if (record == NULL)
1445 10 : break;
1446 :
1447 31 : if (record->GetFieldCount() >= 5)
1448 : {
1449 21 : field = record->GetField(0);
1450 21 : fieldDefn = field->GetFieldDefn();
1451 21 : if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
1452 : fieldDefn->GetSubfieldCount() == 2))
1453 : {
1454 0 : continue;
1455 : }
1456 :
1457 21 : subfieldDefn = fieldDefn->GetSubfield(0);
1458 21 : if (!(strcmp(subfieldDefn->GetName(), "RTY") == 0 &&
1459 : (subfieldDefn->GetFormat())[0] == 'A'))
1460 : {
1461 0 : continue;
1462 : }
1463 :
1464 21 : const char* RTY = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 3, NULL);
1465 :
1466 : /* Ignore overviews */
1467 21 : if ( strcmp(RTY, "OVV") == 0 )
1468 10 : continue;
1469 :
1470 11 : if ( strcmp(RTY, "GIN") != 0 )
1471 0 : continue;
1472 :
1473 11 : field = record->GetField(3);
1474 11 : fieldDefn = field->GetFieldDefn();
1475 :
1476 11 : if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
1477 : fieldDefn->GetSubfieldCount() == 15))
1478 : {
1479 0 : continue;
1480 : }
1481 :
1482 11 : subfieldDefn = fieldDefn->GetSubfield(13);
1483 11 : if (!(strcmp(subfieldDefn->GetName(), "BAD") == 0 &&
1484 : (subfieldDefn->GetFormat())[0] == 'A'))
1485 : {
1486 0 : continue;
1487 : }
1488 :
1489 11 : CPLString osBAD = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 12, NULL);
1490 : {
1491 11 : char* c = (char*) strchr(osBAD.c_str(), ' ');
1492 11 : if (c)
1493 0 : *c = 0;
1494 : }
1495 11 : CPLDebug("ADRG", "BAD=%s", osBAD.c_str());
1496 :
1497 : /* Build full IMG file name from BAD value */
1498 11 : CPLString osGENDir(CPLGetDirname(pszFileName));
1499 :
1500 11 : CPLString osFileName = CPLFormFilename(osGENDir.c_str(), osBAD.c_str(), NULL);
1501 : VSIStatBufL sStatBuf;
1502 11 : if( VSIStatL( osFileName, &sStatBuf ) == 0 )
1503 : {
1504 11 : osBAD = osFileName;
1505 11 : CPLDebug("ADRG", "Building IMG full file name : %s", osBAD.c_str());
1506 : }
1507 : else
1508 : {
1509 : char** papszDirContent;
1510 0 : if (strcmp(osGENDir.c_str(), "/vsimem") == 0)
1511 : {
1512 0 : CPLString osTmp = osGENDir + "/";
1513 0 : papszDirContent = VSIReadDir(osTmp);
1514 : }
1515 : else
1516 0 : papszDirContent = VSIReadDir(osGENDir);
1517 0 : char** ptrDir = papszDirContent;
1518 0 : while(ptrDir && *ptrDir)
1519 : {
1520 0 : if (EQUAL(*ptrDir, osBAD.c_str()))
1521 : {
1522 0 : osBAD = CPLFormFilename(osGENDir.c_str(), *ptrDir, NULL);
1523 0 : CPLDebug("ADRG", "Building IMG full file name : %s", osBAD.c_str());
1524 0 : break;
1525 : }
1526 0 : ptrDir ++;
1527 : }
1528 0 : CSLDestroy(papszDirContent);
1529 : }
1530 :
1531 11 : if (nFilenames == 0 && pnRecordIndex)
1532 10 : *pnRecordIndex = nRecordIndex;
1533 :
1534 11 : papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
1535 11 : papszFileNames[nFilenames] = CPLStrdup(osBAD.c_str());
1536 11 : papszFileNames[nFilenames + 1] = NULL;
1537 11 : nFilenames ++;
1538 : }
1539 : }
1540 :
1541 10 : return papszFileNames;
1542 : }
1543 :
1544 : /************************************************************************/
1545 : /* Open() */
1546 : /************************************************************************/
1547 :
1548 9568 : GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
1549 : {
1550 9568 : int nRecordIndex = -1;
1551 9568 : CPLString osGENFileName;
1552 9568 : CPLString osIMGFileName;
1553 9568 : int bFromSubdataset = FALSE;
1554 :
1555 9568 : if( EQUALN(poOpenInfo->pszFilename, "ADRG:", 5) )
1556 : {
1557 2 : char** papszTokens = CSLTokenizeString2(poOpenInfo->pszFilename + 5, ",", 0);
1558 2 : if (CSLCount(papszTokens) == 2)
1559 : {
1560 2 : osGENFileName = papszTokens[0];
1561 2 : osIMGFileName = papszTokens[1];
1562 2 : bFromSubdataset = TRUE;
1563 : }
1564 2 : CSLDestroy(papszTokens);
1565 : }
1566 : else
1567 : {
1568 9566 : if( poOpenInfo->nHeaderBytes < 500 )
1569 9349 : return NULL;
1570 :
1571 217 : CPLString osFileName(poOpenInfo->pszFilename);
1572 217 : if (EQUAL(CPLGetExtension(osFileName.c_str()), "THF"))
1573 : {
1574 2 : char** papszFileNames = GetGENListFromTHF(osFileName.c_str());
1575 2 : if (papszFileNames == NULL)
1576 0 : return NULL;
1577 2 : if (papszFileNames[1] == NULL)
1578 : {
1579 2 : osFileName = papszFileNames[0];
1580 2 : CSLDestroy(papszFileNames);
1581 : }
1582 : else
1583 : {
1584 0 : char** ptr = papszFileNames;
1585 0 : ADRGDataset* poDS = new ADRGDataset();
1586 0 : while(*ptr)
1587 : {
1588 0 : char** papszIMGFileNames = GetIMGListFromGEN(*ptr);
1589 0 : char** papszIMGIter = papszIMGFileNames;
1590 0 : while(papszIMGIter && *papszIMGIter)
1591 : {
1592 0 : poDS->AddSubDataset(*ptr, *papszIMGIter);
1593 0 : papszIMGIter ++;
1594 : }
1595 0 : CSLDestroy(papszIMGFileNames);
1596 :
1597 0 : ptr ++;
1598 : }
1599 0 : CSLDestroy(papszFileNames);
1600 0 : return poDS;
1601 : }
1602 : }
1603 :
1604 217 : if (EQUAL(CPLGetExtension(osFileName.c_str()), "GEN"))
1605 : {
1606 10 : osGENFileName = osFileName;
1607 :
1608 10 : char** papszFileNames = GetIMGListFromGEN(osFileName.c_str(), &nRecordIndex);
1609 10 : if (papszFileNames == NULL)
1610 0 : return NULL;
1611 10 : if (papszFileNames[1] == NULL)
1612 : {
1613 9 : osIMGFileName = papszFileNames[0];
1614 9 : CSLDestroy(papszFileNames);
1615 : }
1616 : else
1617 : {
1618 1 : char** ptr = papszFileNames;
1619 1 : ADRGDataset* poDS = new ADRGDataset();
1620 4 : while(*ptr)
1621 : {
1622 2 : poDS->AddSubDataset(osFileName.c_str(), *ptr);
1623 2 : ptr ++;
1624 : }
1625 1 : CSLDestroy(papszFileNames);
1626 1 : return poDS;
1627 : }
1628 0 : }
1629 : }
1630 :
1631 218 : if (osGENFileName.size() > 0 &&
1632 : osIMGFileName.size() > 0)
1633 : {
1634 11 : if( poOpenInfo->eAccess == GA_Update )
1635 : {
1636 : CPLError( CE_Failure, CPLE_NotSupported,
1637 : "The ADRG driver does not support update access to existing"
1638 0 : " datasets.\n" );
1639 0 : return NULL;
1640 : }
1641 :
1642 11 : DDFModule module;
1643 11 : DDFRecord* record = NULL;
1644 11 : if (nRecordIndex >= 0 &&
1645 : module.Open(osGENFileName.c_str(), TRUE))
1646 : {
1647 : int i;
1648 36 : for(i=0;i<=nRecordIndex;i++)
1649 : {
1650 27 : CPLPushErrorHandler( CPLQuietErrorHandler );
1651 27 : record = module.ReadRecord();
1652 27 : CPLPopErrorHandler();
1653 27 : CPLErrorReset();
1654 27 : if (record == NULL)
1655 0 : break;
1656 : }
1657 : }
1658 :
1659 11 : ADRGDataset* poDS = OpenDataset(osGENFileName.c_str(), osIMGFileName.c_str(), record);
1660 :
1661 11 : if (poDS)
1662 : {
1663 : /* -------------------------------------------------------------------- */
1664 : /* Initialize any PAM information. */
1665 : /* -------------------------------------------------------------------- */
1666 11 : poDS->SetDescription( poOpenInfo->pszFilename );
1667 11 : poDS->TryLoadXML();
1668 :
1669 : /* -------------------------------------------------------------------- */
1670 : /* Check for external overviews. */
1671 : /* -------------------------------------------------------------------- */
1672 11 : if( bFromSubdataset )
1673 2 : poDS->oOvManager.Initialize( poDS, osIMGFileName.c_str() );
1674 : else
1675 9 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
1676 :
1677 11 : return poDS;
1678 0 : }
1679 : }
1680 :
1681 207 : return NULL;
1682 : }
1683 :
1684 : /************************************************************************/
1685 : /* Create() */
1686 : /************************************************************************/
1687 :
1688 : GDALDataset *ADRGDataset::Create(const char* pszFilename, int nXSize, int nYSize,
1689 44 : int nBands, GDALDataType eType, char **papszOptions)
1690 : {
1691 : int i;
1692 :
1693 44 : if( eType != GDT_Byte)
1694 : {
1695 : CPLError( CE_Failure, CPLE_AppDefined,
1696 : "Attempt to create ADRG dataset with an illegal\n"
1697 : "data type (%s), only Byte supported by the format.\n",
1698 30 : GDALGetDataTypeName(eType) );
1699 :
1700 30 : return NULL;
1701 : }
1702 :
1703 14 : if( nBands != 3 )
1704 : {
1705 : CPLError( CE_Failure, CPLE_NotSupported,
1706 : "ADRG driver doesn't support %d bands. Must be 3 (rgb) bands.\n",
1707 9 : nBands );
1708 9 : return NULL;
1709 : }
1710 :
1711 5 : if(nXSize < 1 || nYSize < 1)
1712 : {
1713 : CPLError( CE_Failure, CPLE_NotSupported,
1714 : "Specified pixel dimensions (% d x %d) are bad.\n",
1715 0 : nXSize, nYSize );
1716 : }
1717 :
1718 5 : if (!EQUAL(CPLGetExtension(pszFilename), "gen"))
1719 : {
1720 : CPLError( CE_Failure, CPLE_NotSupported,
1721 1 : "Invalid filename. Must be ABCDEF01.GEN\n");
1722 1 : return NULL;
1723 : }
1724 :
1725 4 : CPLString osBaseFileName(CPLGetBasename(pszFilename));
1726 4 : if (strlen(osBaseFileName) != 8 || osBaseFileName[6] != '0' || osBaseFileName[7] != '1')
1727 : {
1728 : CPLError( CE_Failure, CPLE_NotSupported,
1729 0 : "Invalid filename. Must be xxxxxx01.GEN where x is between A and Z\n");
1730 4 : return NULL;
1731 : }
1732 :
1733 28 : for(i=0;i<6;i++)
1734 : {
1735 24 : if (!(osBaseFileName[i] >= 'A' && osBaseFileName[i] <= 'Z'))
1736 : {
1737 : CPLError( CE_Failure, CPLE_NotSupported,
1738 0 : "Invalid filename. Must be xxxxxx01.GEN where x is between A and Z\n");
1739 0 : return NULL;
1740 : }
1741 : }
1742 :
1743 4 : FILE* fdGEN = VSIFOpenL(pszFilename, "wb");
1744 4 : if (fdGEN == NULL)
1745 : {
1746 : CPLError( CE_Failure, CPLE_FileIO,
1747 0 : "Cannot create GEN file : %s.\n", pszFilename);
1748 0 : return NULL;
1749 : }
1750 :
1751 4 : CPLString osDirname(CPLGetDirname(pszFilename));
1752 4 : CPLString osTransh01THF(CPLFormFilename(osDirname.c_str(), "TRANSH01.THF", NULL));
1753 4 : FILE* fdTHF = VSIFOpenL(osTransh01THF.c_str(), "wb");
1754 4 : if (fdTHF == NULL)
1755 : {
1756 0 : VSIFCloseL(fdGEN);
1757 : CPLError( CE_Failure, CPLE_FileIO,
1758 0 : "Cannot create THF file : %s.\n", osTransh01THF.c_str());
1759 0 : return NULL;
1760 : }
1761 :
1762 4 : CPLString osImgFilename = CPLResetExtension(pszFilename, "IMG");
1763 4 : FILE* fdIMG = VSIFOpenL(osImgFilename.c_str(), "w+b");
1764 4 : if (fdIMG == NULL)
1765 : {
1766 0 : VSIFCloseL(fdGEN);
1767 0 : VSIFCloseL(fdTHF);
1768 : CPLError( CE_Failure, CPLE_FileIO,
1769 0 : "Cannot create image file : %s.\n", osImgFilename.c_str());
1770 0 : return NULL;
1771 : }
1772 :
1773 4 : ADRGDataset* poDS = new ADRGDataset();
1774 :
1775 4 : poDS->eAccess = GA_Update;
1776 :
1777 4 : poDS->fdGEN = fdGEN;
1778 4 : poDS->fdIMG = fdIMG;
1779 4 : poDS->fdTHF = fdTHF;
1780 :
1781 4 : poDS->osBaseFileName = osBaseFileName;
1782 4 : poDS->bCreation = TRUE;
1783 4 : poDS->nNextAvailableBlock = 1;
1784 4 : poDS->NFC = (nXSize + 127) / 128;
1785 4 : poDS->NFL = (nYSize + 127) / 128;
1786 4 : poDS->nRasterXSize = nXSize;
1787 4 : poDS->nRasterYSize = nYSize;
1788 4 : poDS->bGeoTransformValid = FALSE;
1789 4 : poDS->TILEINDEX = new int [poDS->NFC*poDS->NFL];
1790 4 : memset(poDS->TILEINDEX, 0, sizeof(int)*poDS->NFC*poDS->NFL);
1791 4 : poDS->offsetInIMG = 2048;
1792 4 : poDS->poOverviewDS = NULL;
1793 :
1794 4 : poDS->nBands = 3;
1795 16 : for( i = 0; i < poDS->nBands; i++ )
1796 12 : poDS->SetBand( i+1, new ADRGRasterBand( poDS, i+1 ) );
1797 :
1798 4 : return poDS;
1799 : }
1800 :
1801 : /************************************************************************/
1802 : /* WriteGENFile_Header() */
1803 : /************************************************************************/
1804 :
1805 4 : static void WriteGENFile_Header(FILE* fd)
1806 : {
1807 4 : int nFields = 0;
1808 4 : int sizeOfFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, };
1809 4 : const char* nameOfFields[] = { "000", "001", "DRF", "DSI", "OVI", "GEN", "SPR", "BDF", "TIM" };
1810 4 : int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
1811 :
1812 4 : sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "GENERAL_INFORMATION_FILE", "", ""); /* 000 */
1813 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
1814 : "RTY!RID",
1815 4 : "(A(3),A(2))");
1816 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '1', "DATA_SET_DESCRIPTION_FIELD", /* DRF */
1817 : "NSH!NSV!NOZ!NOS",
1818 4 : "(4I(2))");
1819 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "DATA_SET-ID_FIELD", /* DSI */
1820 : "PRT!NAM",
1821 4 : "(A(4),A(8))");
1822 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "OVERVIEW_INFORMATION_FIELD", /* OVI */
1823 : "STR!ARV!BRV!LSO!PSO",
1824 4 : "(I(1),I(8),I(8),A(11),A(10))");
1825 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "GENERAL_INFORMATION_FIELD", /* GEN */
1826 : "STR!LOD!LAD!UNIloa!SWO!SWA!NWO!NWA!NEO!NEA!SEO!SEA!SCA!ZNA!PSP!IMR!ARV!BRV!LSO!PSO!TXT",
1827 4 : "(I(1),2R(6),I(3),A(11),A(10),A(11),A(10),A(11),A(10),A(11),A(10),I(9),I(2),R(5),A(1),2I(8),A(11),A(10),A(64))");
1828 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "DATA_SET_PARAMETERS_FIELD", /* SPR */
1829 : "NUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF",
1830 4 : "(4I(6),2I(3),2I(6),5I(1),A(12),A(1))");
1831 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '6', "BAND_ID_FIELD", /* BDF */
1832 : "*BID!WS1!WS2",
1833 4 : "(A(5),I(5),I(5))");
1834 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '1', "TILE_INDEX_MAP_FIELD", /* TIM */
1835 : "*TSI",
1836 4 : "(I(5))");
1837 :
1838 4 : FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
1839 4 : }
1840 :
1841 : /************************************************************************/
1842 : /* WriteGENFile_DataSetDescriptionRecord() */
1843 : /************************************************************************/
1844 :
1845 : /* Write DATA_SET_DESCRIPTION_RECORD */
1846 4 : static void WriteGENFile_DataSetDescriptionRecord(FILE* fd)
1847 : {
1848 4 : int nFields = 0;
1849 4 : int sizeOfFields[] = {0, 0};
1850 4 : const char* nameOfFields[] = { "001", "DRF" };
1851 4 : int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
1852 :
1853 : /* Field 001 */
1854 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "DSS", 3); /* RTY */
1855 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
1856 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1857 4 : nFields++;
1858 :
1859 : /* Field DRF */
1860 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NSH */
1861 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NSV */
1862 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOZ */
1863 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOS */
1864 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1865 4 : nFields++;
1866 :
1867 4 : FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
1868 4 : }
1869 :
1870 : /************************************************************************/
1871 : /* WriteGENFile_OverviewRecord() */
1872 : /************************************************************************/
1873 :
1874 : /* Write OVERVIEW_RECORD */
1875 : static void WriteGENFile_OverviewRecord(FILE* fd, CPLString& osBaseFileName, int ARV, int BRV, double LSO, double PSO,
1876 4 : int nOvSizeX, int nOvSizeY, int NFL, int NFC, int* TILEINDEX)
1877 : {
1878 4 : int nFields = 0;
1879 4 : int sizeOfFields[] = {0, 0, 0, 0, 0, 0};
1880 4 : const char* nameOfFields[] = { "001", "DSI", "OVI", "SPR", "BDF", "TIM" };
1881 4 : int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
1882 :
1883 : /* Field 001 */
1884 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "OVV", 3); /* RTY */
1885 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
1886 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1887 4 : nFields++;
1888 :
1889 : /* Field DSI */
1890 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
1891 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
1892 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1893 4 : nFields++;
1894 :
1895 : /* Field OVI */
1896 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
1897 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); /* ARV */ /* FIXME */
1898 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8); /* BRV */ /* FIXME */
1899 4 : sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* LSO */ /* FIXME */
1900 4 : sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */ /* FIXME */
1901 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1902 4 : nFields++;
1903 :
1904 : /* Field SPR */
1905 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
1906 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeX-1, 6); /* NUS */
1907 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeY-1, 6); /* NLL */
1908 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
1909 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nOvSizeY + 127) / 128, 3); /* NFL */
1910 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nOvSizeX + 127) / 128, 3); /* NFC */
1911 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
1912 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
1913 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
1914 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
1915 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
1916 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
1917 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
1918 : char tmp[12+1];
1919 4 : sprintf(tmp, "%s.IMG", osBaseFileName.c_str()); /* FIXME */
1920 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 12); /* BAD */
1921 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */
1922 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1923 4 : nFields++;
1924 :
1925 : /* Field BDF */
1926 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
1927 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
1928 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
1929 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
1930 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
1931 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
1932 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
1933 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
1934 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
1935 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1936 4 : nFields++;
1937 :
1938 : /* Field TIM */
1939 : int i;
1940 8 : for(i=0;i<NFL*NFC;i++)
1941 : {
1942 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
1943 : }
1944 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1945 4 : nFields++;
1946 :
1947 4 : FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
1948 4 : }
1949 :
1950 : /************************************************************************/
1951 : /* WriteGENFile_GeneralInformationRecord() */
1952 : /************************************************************************/
1953 :
1954 : /* Write GENERAL_INFORMATION_RECORD */
1955 : static void WriteGENFile_GeneralInformationRecord(FILE* fd, CPLString& osNAM, CPLString& osBAD,
1956 : int ARV, int BRV, double LSO, double PSO,
1957 : double* adfGeoTransform, int SCA,
1958 : int nRasterXSize, int nRasterYSize,
1959 5 : int NFL, int NFC, int* TILEINDEX)
1960 :
1961 : {
1962 5 : int nFields = 0;
1963 5 : int sizeOfFields[] = {0, 0, 0, 0, 0, 0};
1964 5 : const char* nameOfFields[] = { "001", "DSI", "GEN", "SPR", "BDF", "TIM" };
1965 5 : int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
1966 :
1967 : /* Field 001 */
1968 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "GIN", 3); /* RTY */
1969 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
1970 5 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1971 5 : nFields++;
1972 :
1973 : /* Field DSI */
1974 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
1975 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, osNAM.c_str(), 8); /* NAM */
1976 5 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1977 5 : nFields++;
1978 :
1979 : /* Field `GEN */
1980 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
1981 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); /* LOD */ /* FIXME */
1982 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); /* LAD */ /* FIXME */
1983 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 16, 3); /* UNIloa */ /* FIXME */
1984 5 : sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */
1985 5 : sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */
1986 5 : sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* NWO */
1987 5 : sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NWA */
1988 5 : sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */
1989 5 : sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */
1990 5 : sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* SEO */
1991 5 : sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SEA */
1992 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, SCA, 9); /* SCA */
1993 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* ZNA */ /* FIXME */
1994 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "100.0", 5); /* PSP */
1995 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* IMR */
1996 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); /* ARV */
1997 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8); /* BRV */
1998 5 : sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* LSO */
1999 5 : sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */
2000 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 64); /* TXT */
2001 5 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2002 5 : nFields++;
2003 :
2004 : /* Field SPR */
2005 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
2006 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nRasterXSize-1, 6); /* NUS */
2007 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nRasterYSize-1, 6); /* NLL */
2008 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
2009 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nRasterYSize + 127) / 128, 3); /* NFL */
2010 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nRasterXSize + 127) / 128, 3); /* NFC */
2011 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
2012 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
2013 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
2014 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
2015 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
2016 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
2017 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
2018 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, osBAD.c_str(), 12); /* BAD */
2019 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */
2020 5 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2021 5 : nFields++;
2022 :
2023 : /* Field BDF */
2024 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
2025 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2026 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2027 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
2028 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2029 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2030 5 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
2031 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2032 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2033 5 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2034 5 : nFields++;
2035 :
2036 : /* Field TIM */
2037 : int i;
2038 10 : for(i=0;i<NFL*NFC;i++)
2039 : {
2040 5 : sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
2041 : }
2042 5 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2043 5 : nFields++;
2044 :
2045 5 : FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
2046 5 : }
2047 :
2048 : /************************************************************************/
2049 : /* WriteGENFile() */
2050 : /************************************************************************/
2051 :
2052 4 : void ADRGDataset::WriteGENFile()
2053 : {
2054 4 : if (!bGeoTransformValid)
2055 : {
2056 0 : CPLError(CE_Failure, CPLE_AppDefined, "No geo transform available !");
2057 0 : adfGeoTransform[0] = 0;
2058 0 : adfGeoTransform[3] = 0;
2059 0 : adfGeoTransform[1] = 1;
2060 0 : adfGeoTransform[5] = 1;
2061 : }
2062 :
2063 4 : LSO = adfGeoTransform[0];
2064 4 : PSO = adfGeoTransform[3];
2065 4 : ARV = (int)floor(360. / adfGeoTransform[1] + .5);
2066 4 : BRV = (int)floor(-360. / adfGeoTransform[5] + .5);
2067 :
2068 : /*ARV = ((ARV + 255) / 512) * 512;
2069 : BRV = ((BRV + 255) / 512) * 512;*/
2070 :
2071 4 : int SCA = (int)floor(1000000. * 400384 / BRV + 0.5);
2072 :
2073 4 : int nOvSizeX = nRasterXSize; // FIXME
2074 4 : int nOvSizeY = nRasterYSize; // FIXME
2075 :
2076 : /* Write header */
2077 4 : WriteGENFile_Header(fdGEN);
2078 :
2079 : /* Write DATA_SET_DESCRIPTION_RECORD */
2080 4 : WriteGENFile_DataSetDescriptionRecord(fdGEN);
2081 :
2082 : /* Write OVERVIEW_RECORD */
2083 : WriteGENFile_OverviewRecord(fdGEN, osBaseFileName, ARV, BRV, LSO, PSO,
2084 4 : nOvSizeX, nOvSizeY, NFL, NFC, TILEINDEX);
2085 :
2086 : /* Write GENERAL_INFORMATION_RECORD */
2087 4 : CPLString osNAM = osBaseFileName;
2088 : char tmp[12+1];
2089 4 : sprintf(tmp, "%s.IMG", osNAM.c_str());
2090 4 : CPLString osBAD = tmp;
2091 : WriteGENFile_GeneralInformationRecord(fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
2092 4 : adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
2093 :
2094 4 : if (CSLTestBoolean(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF")))
2095 : {
2096 1 : strncpy(tmp, osBaseFileName.c_str(), 6);
2097 1 : tmp[6] = '\0';
2098 1 : strcat(tmp, "02");
2099 1 : osNAM = tmp;
2100 1 : sprintf(tmp, "%s.IMG", osNAM.c_str());
2101 1 : osBAD = tmp;
2102 : WriteGENFile_GeneralInformationRecord(fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
2103 1 : adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
2104 4 : }
2105 4 : }
2106 :
2107 : /************************************************************************/
2108 : /* WriteTHFFile() */
2109 : /************************************************************************/
2110 :
2111 4 : void ADRGDataset::WriteTHFFile()
2112 : {
2113 4 : FILE* fd = fdTHF;
2114 :
2115 : /* Write header */
2116 : {
2117 4 : int nFields = 0;
2118 4 : int sizeOfFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2119 4 : const char* nameOfFields[] = { "000", "001", "VDR", "FDR", "QSR", "QUV", "CPS", "CPT", "SPR", "BDF", "VFF"};
2120 4 : int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
2121 :
2122 4 : sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "TRANSMITTAL_HEADER_FILE", "", ""); /* 000 */
2123 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
2124 : "RTY!RID",
2125 4 : "(A(3),A(2))");
2126 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "TRANSMITTAL_HEADER_FIELD", /* VDR */
2127 : "MSD!VOO!ADR!NOV!SQN!NOF!URF!EDN!DAT",
2128 4 : "(A(1),A(200),A(1),I(1),I(1),I(3),A(16),I(3),A(12))");
2129 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "DATA_SET_DESCRIPTION_FIELD", /* FDR */
2130 : "NAM!STR!PRT!SWO!SWA!NEO!NEA",
2131 4 : "(A(8),I(1),A(4),A(11),A(10),A(11),A(10))");
2132 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "SECURITY_AND_RELEASE_FIELD", /* QSR */
2133 : "QSS!QOD!DAT!QLE",
2134 4 : "(A(1),A(1),A(12),A(200))");
2135 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "VOLUME_UP_TO_DATENESS_FIELD", /* QUV */
2136 : "SRC!DAT!SPA",
2137 4 : "(A(100),A(12),A(20))");
2138 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "TEST_PATCH_IDENTIFIER_FIELD", /* CPS */
2139 : "PNM!DWV!REF!PUR!PIR!PIG!PIB",
2140 4 : "(A(7),I(6),R(5),R(5),I(3),I(3),I(3))");
2141 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "TEST_PATCH_INFORMATION_FIELD", /* CPT */
2142 : "STR!SCR",
2143 4 : "(I(1),A(100))");
2144 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "DATA_SET_PARAMETERS_FIELD", /* SPR */
2145 : "NUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF",
2146 4 : "(I(6),I(6),I(6),I(6),I(3),I(3),I(6),I(6),I(1),I(1),I(1),I(1),I(1),A(12),A(1))");
2147 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '6', "BAND_ID_FIELD", /* BDF */
2148 : "*BID!WS1!WS2",
2149 4 : "(A(5),I(5),I(5))");
2150 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "TRANSMITTAL_FILENAMES_FIELD", /* VFF */
2151 : "VFF",
2152 4 : "(A(51))");
2153 :
2154 4 : FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
2155 : }
2156 :
2157 : /* Write TRANSMITTAL_DESCRIPTION_RECORD */
2158 : {
2159 4 : int nFields = 0;
2160 4 : int sizeOfFields[] = {0, 0, 0};
2161 4 : const char* nameOfFields[] = { "001", "VDR", "FDR" };
2162 4 : int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
2163 :
2164 : /* Field 001 */
2165 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "VTH", 3); /* RTY */
2166 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
2167 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2168 4 : nFields++;
2169 :
2170 : /* Field VDR */
2171 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* MSD */
2172 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200); /* VOO */ /* Title and address of originator */
2173 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* ADR */
2174 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* NOV */
2175 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* SQN */
2176 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* NOF */
2177 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 16); /* URF */ /* DMA stock number for this CDROM */
2178 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* EDN */
2179 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "017,19940101", 12); /* DAT */ /* Publication date */
2180 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2181 4 : nFields++;
2182 :
2183 : /* Field FDR */
2184 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
2185 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
2186 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
2187 4 : sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */
2188 4 : sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */
2189 4 : sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */
2190 4 : sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */
2191 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2192 4 : nFields++;
2193 :
2194 4 : FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
2195 : }
2196 :
2197 : /* Write SECURITY_AND_UPDATE_RECORD */
2198 : {
2199 4 : int nFields = 0;
2200 4 : int sizeOfFields[] = {0, 0, 0};
2201 4 : const char* nameOfFields[] = { "001", "QSR", "QUV" };
2202 4 : int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
2203 :
2204 : /* Field 001 */
2205 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "LCF", 3); /* RTY */
2206 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
2207 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2208 4 : nFields++;
2209 :
2210 : /* Field VDR */
2211 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "U", 1); /* QSS */
2212 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* QOD */
2213 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 12); /* DAT */
2214 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200); /* QLE */
2215 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2216 4 : nFields++;
2217 :
2218 : /* Field FDR */
2219 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "MILITARY SPECIFICATION ARC DIGITIZED RASTER GRAPHICS (ADRG)", 100); /* SRC */
2220 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "022,19900222", 12); /* DAT */
2221 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "MIL-A-89007", 20); /* SPA */
2222 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2223 4 : nFields++;
2224 :
2225 4 : FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
2226 : }
2227 :
2228 : /* Write TEST_PATCH_DATA_RECORD */
2229 : {
2230 4 : int nFields = 0;
2231 4 : int sizeOfFields[] = {0, 0, 0, 0, 0};
2232 4 : const char* nameOfFields[] = { "001", "CPS", "CPT", "SPR", "BDF" };
2233 4 : int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
2234 :
2235 : /* Field 001 */
2236 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "TPA", 3); /* RTY */
2237 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
2238 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2239 4 : nFields++;
2240 :
2241 : /* Field CPS */
2242 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Black", 7); /* PNM */
2243 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 6); /* DMV */
2244 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 5); /* REF */
2245 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 5); /* PUR */
2246 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIR */
2247 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIG */
2248 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIB */
2249 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2250 4 : nFields++;
2251 :
2252 : /* Field CPT */
2253 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
2254 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 100); /* SCR */
2255 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2256 4 : nFields++;
2257 :
2258 4 : int nPatchXSize = 512;
2259 4 : int nPatchYSize = 512;
2260 :
2261 : /* Field SPR */
2262 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
2263 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nPatchXSize-1, 6); /* NUS */
2264 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nPatchYSize-1, 6); /* NLL */
2265 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
2266 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nPatchYSize + 127) / 128, 3); /* NFL */
2267 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nPatchXSize + 127) / 128, 3); /* NFC */
2268 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
2269 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
2270 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
2271 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
2272 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
2273 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
2274 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
2275 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 12); /* BAD */
2276 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* TIF */
2277 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2278 4 : nFields++;
2279 :
2280 : /* Field BDF */
2281 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
2282 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2283 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2284 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
2285 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2286 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2287 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
2288 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2289 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2290 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2291 4 : nFields++;
2292 :
2293 4 : FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
2294 : }
2295 :
2296 : /* Write TRANSMITTAL_FILENAMES_RECORD */
2297 : {
2298 : char tmp[12+1];
2299 :
2300 4 : int nFields = 0;
2301 4 : int sizeOfFields[] = {0, 0, 0, 0, 0, 0, 0};
2302 :
2303 : /* Debug option to simulate ADRG datasets made of several images */
2304 4 : int nTotalFields = (CSLTestBoolean(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF"))) ? 6 : 5;
2305 :
2306 4 : const char* nameOfFields[] = { "001", "VFF", "VFF", "VFF", "VFF", "VFF", "VFF" };
2307 4 : int pos = BeginLeader(fd, 9, 9, 3, nTotalFields);
2308 :
2309 : /* Field 001 */
2310 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "TFN", 3); /* RTY */
2311 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
2312 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2313 4 : nFields++;
2314 :
2315 : /* Field VFF */
2316 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "TRANSH01.THF", 51); /* VFF */
2317 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2318 4 : nFields++;
2319 :
2320 : /* Field VFF */
2321 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 51); /* VFF */
2322 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2323 4 : nFields++;
2324 :
2325 : /* Field VFF */
2326 4 : sprintf(tmp, "%s.GEN", osBaseFileName.c_str());
2327 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
2328 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2329 4 : nFields++;
2330 :
2331 : /* Field VFF */
2332 4 : sprintf(tmp, "%s.IMG", osBaseFileName.c_str());
2333 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
2334 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2335 4 : nFields++;
2336 :
2337 4 : if (nTotalFields == 6)
2338 : {
2339 : /* Field VFF */
2340 1 : strncpy(tmp, osBaseFileName.c_str(), 6);
2341 1 : tmp[6] = '\0';
2342 1 : strcat(tmp, "02.IMG");
2343 1 : sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
2344 1 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2345 1 : nFields++;
2346 : }
2347 :
2348 4 : FinishWriteLeader(fd, pos, 9, 9, 3, nTotalFields, sizeOfFields, nameOfFields);
2349 : }
2350 4 : }
2351 :
2352 : /************************************************************************/
2353 : /* GDALRegister_ADRG() */
2354 : /************************************************************************/
2355 :
2356 409 : void GDALRegister_ADRG()
2357 :
2358 : {
2359 : GDALDriver *poDriver;
2360 :
2361 409 : if( GDALGetDriverByName( "ADRG" ) == NULL )
2362 : {
2363 392 : poDriver = new GDALDriver();
2364 :
2365 392 : poDriver->SetDescription( "ADRG" );
2366 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
2367 392 : "ARC Digitized Raster Graphics" );
2368 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
2369 392 : "frmt_various.html#ADRG" );
2370 392 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gen" );
2371 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
2372 392 : "Byte" );
2373 :
2374 392 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
2375 :
2376 392 : poDriver->pfnOpen = ADRGDataset::Open;
2377 392 : poDriver->pfnCreate = ADRGDataset::Create;
2378 :
2379 392 : GetGDALDriverManager()->RegisterDriver( poDriver );
2380 : }
2381 409 : }
2382 :
|