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 78 : {
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 39 : ADRGRasterBand::ADRGRasterBand( ADRGDataset *poDS, int nBand )
128 :
129 : {
130 39 : this->poDS = poDS;
131 39 : this->nBand = nBand;
132 :
133 39 : eDataType = GDT_Byte;
134 :
135 39 : nBlockXSize = 128;
136 39 : nBlockYSize = 128;
137 39 : }
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 14 : CPLErr ADRGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
213 : 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 9 : CPLErr ADRGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
258 : 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 204 : static unsigned int WriteSubFieldStr(FILE* fd, const char* pszStr, unsigned int size)
310 : {
311 204 : char* str = (char*)CPLMalloc(size+1);
312 204 : memset(str, ' ', size);
313 204 : 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 204 : strcpy(str, pszStr);
320 204 : str[strlen(pszStr)] = ' ';
321 204 : VSIFWriteL(str, 1, size, fd);
322 204 : CPLFree(str);
323 204 : return size;
324 : }
325 :
326 625 : static unsigned int WriteSubFieldInt(FILE* fd, int val, unsigned int size)
327 : {
328 625 : char* str = (char*)CPLMalloc(size+1);
329 : char formatStr[32];
330 625 : sprintf( formatStr, "%%0%dd", size);
331 625 : sprintf( str, formatStr, val);
332 625 : VSIFWriteL(str, 1, size, fd);
333 625 : CPLFree(str);
334 625 : return size;
335 : }
336 :
337 212 : static unsigned int WriteFieldTerminator(FILE* fd)
338 : {
339 212 : char fieldTerminator = 30;
340 212 : VSIFWriteL(&fieldTerminator, 1, 1, fd);
341 212 : return 1;
342 : }
343 :
344 126 : static unsigned int WriteUnitTerminator(FILE* fd)
345 : {
346 126 : char fieldTerminator = 31;
347 126 : VSIFWriteL(&fieldTerminator, 1, 1, fd);
348 126 : return 1;
349 : }
350 :
351 29 : static unsigned int WriteLongitude(FILE* fd, double val)
352 : {
353 : char str[11+1];
354 29 : char sign = (val >= 0) ? '+' : '-';
355 29 : if (val < 0) val = -val;
356 29 : int ddd = (int)val;
357 29 : int mm = (int)((val - ddd) * 60);
358 29 : double ssdotss = ((val - ddd) * 60 - mm) * 60;
359 29 : sprintf(str, "%c%03d%02d%02.2f", sign, ddd, mm, ssdotss);
360 29 : VSIFWriteL(str, 1, 11, fd);
361 29 : return 11;
362 : }
363 :
364 29 : static unsigned int WriteLatitude(FILE* fd, double val)
365 : {
366 : char str[10+1];
367 29 : char sign = (val >= 0) ? '+' : '-';
368 29 : if (val < 0) val = -val;
369 29 : int dd = (int)val;
370 29 : int mm = (int)((val - dd) * 60);
371 29 : double ssdotss = ((val - dd) * 60 - mm) * 60;
372 29 : sprintf(str, "%c%02d%02d%02.2f", sign, dd, mm, ssdotss);
373 29 : VSIFWriteL(str, 1, 10, fd);
374 29 : return 10;
375 : }
376 :
377 25 : static int BeginLeader(FILE* fd, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
378 : int nFields)
379 : {
380 25 : int pos = (int)VSIFTellL(fd);
381 25 : VSIFSeekL(fd, 24 + (sizeFieldLength + sizeFieldPos + sizeFieldTag) * (vsi_l_offset)nFields + 1, SEEK_CUR);
382 25 : return pos;
383 : }
384 :
385 25 : static void FinishWriteLeader(FILE* fd, int beginPos, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
386 : int nFields, int* sizeOfFields, const char** nameOfFields)
387 : {
388 25 : int endPos = (int)VSIFTellL(fd);
389 25 : VSIFSeekL(fd, beginPos, SEEK_SET);
390 :
391 25 : int nLeaderSize = 24;
392 : char szLeader[24+1];
393 25 : memset(szLeader, ' ', nLeaderSize);
394 :
395 : int i;
396 25 : int nDataSize = 0;
397 25 : int nFieldOffset = 0;
398 131 : for(i=0;i<nFields;i++)
399 106 : nDataSize += sizeOfFields[i];
400 25 : nFieldOffset = (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
401 25 : nDataSize += nFieldOffset;
402 :
403 25 : sprintf( szLeader+0, "%05d", (int) (nDataSize + nLeaderSize) );
404 25 : szLeader[5] = ' ';
405 25 : szLeader[6] = 'D';
406 :
407 25 : sprintf( szLeader + 12, "%05d", (int) (nFieldOffset + nLeaderSize) );
408 25 : szLeader[17] = ' ';
409 :
410 25 : szLeader[20] = (char) ('0' + sizeFieldLength);
411 25 : szLeader[21] = (char) ('0' + sizeFieldPos);
412 25 : szLeader[22] = '0';
413 25 : szLeader[23] = (char) ('0' + sizeFieldTag);
414 :
415 25 : VSIFWriteL(szLeader, 1, nLeaderSize, fd);
416 :
417 25 : int acc = 0;
418 131 : for(i=0;i<nFields;i++)
419 : {
420 106 : VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd);
421 106 : WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength);
422 106 : WriteSubFieldInt(fd, acc, sizeFieldPos);
423 106 : acc += sizeOfFields[i];
424 : }
425 25 : WriteFieldTerminator(fd);
426 :
427 25 : VSIFSeekL(fd, endPos, SEEK_SET);
428 25 : }
429 :
430 :
431 9 : static int BeginHeader(FILE* fd, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
432 : int nFields)
433 : {
434 9 : int pos = (int)VSIFTellL(fd);
435 9 : VSIFSeekL(fd, 24 + (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1, SEEK_CUR);
436 9 : return pos;
437 : }
438 :
439 9 : static void FinishWriteHeader(FILE* fd, int beginPos, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
440 : int nFields, int* sizeOfFields, const char** nameOfFields)
441 : {
442 9 : int endPos = (int)VSIFTellL(fd);
443 9 : VSIFSeekL(fd, beginPos, SEEK_SET);
444 :
445 9 : int nLeaderSize = 24;
446 : char szLeader[24+1];
447 9 : memset(szLeader, ' ', nLeaderSize);
448 :
449 : int i;
450 9 : int nDataSize = 0;
451 9 : int nFieldOffset = 0;
452 81 : for(i=0;i<nFields;i++)
453 72 : nDataSize += sizeOfFields[i];
454 9 : nFieldOffset = (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
455 9 : nDataSize += nFieldOffset;
456 :
457 9 : sprintf( szLeader+0, "%05d", (int) (nDataSize + nLeaderSize) );
458 9 : szLeader[5] = '2';
459 9 : szLeader[6] = 'L';
460 :
461 9 : szLeader[10] = '0';
462 9 : szLeader[11] = '6';
463 9 : sprintf( szLeader + 12, "%05d", (int) (nFieldOffset + nLeaderSize) );
464 9 : szLeader[17] = ' ';
465 :
466 9 : szLeader[20] = (char) ('0' + sizeFieldLength);
467 9 : szLeader[21] = (char) ('0' + sizeFieldPos);
468 9 : szLeader[22] = '0';
469 9 : szLeader[23] = (char) ('0' + sizeFieldTag);
470 :
471 9 : VSIFWriteL(szLeader, 1, nLeaderSize, fd);
472 :
473 9 : int acc = 0;
474 81 : for(i=0;i<nFields;i++)
475 : {
476 72 : VSIFWriteL(nameOfFields[i], 1, sizeFieldTag, fd);
477 72 : WriteSubFieldInt(fd, sizeOfFields[i], sizeFieldLength);
478 72 : WriteSubFieldInt(fd, acc, sizeFieldPos);
479 72 : acc += sizeOfFields[i];
480 : }
481 9 : WriteFieldTerminator(fd);
482 :
483 9 : VSIFSeekL(fd, endPos, SEEK_SET);
484 9 : }
485 :
486 72 : static int WriteFieldDecl(FILE* fd, char _data_struct_code , char _data_type_code, const char* _fieldName,
487 : const char* _arrayDescr, const char* _formatControls)
488 : {
489 72 : VSIFWriteL(&_data_struct_code, 1, 1, fd);
490 72 : VSIFWriteL(&_data_type_code, 1, 1, fd);
491 72 : if (_data_struct_code == ' ')
492 : {
493 9 : VSIFWriteL(" ", 1 , 4, fd);
494 : }
495 : else
496 : {
497 63 : VSIFWriteL("00;&", 1 , 4, fd);
498 : }
499 72 : int len = 6;
500 72 : VSIFWriteL(_fieldName, 1, strlen(_fieldName), fd);
501 72 : len += strlen(_fieldName);
502 72 : if (_arrayDescr[0])
503 : {
504 63 : len += WriteUnitTerminator(fd);
505 63 : VSIFWriteL(_arrayDescr, 1, strlen(_arrayDescr), fd);
506 63 : len += strlen(_arrayDescr);
507 :
508 63 : len += WriteUnitTerminator(fd);
509 63 : VSIFWriteL(_formatControls, 1, strlen(_formatControls), fd);
510 63 : len += strlen(_formatControls);
511 : }
512 72 : len += WriteFieldTerminator(fd);
513 72 : return len;
514 : }
515 :
516 :
517 : /************************************************************************/
518 : /* ADRGDataset() */
519 : /************************************************************************/
520 :
521 14 : ADRGDataset::ADRGDataset()
522 : {
523 14 : bCreation = FALSE;
524 14 : poOverviewDS = NULL;
525 14 : fdIMG = NULL;
526 14 : fdGEN = NULL;
527 14 : fdTHF = NULL;
528 14 : TILEINDEX = NULL;
529 14 : papszSubDatasets = NULL;
530 14 : }
531 :
532 : /************************************************************************/
533 : /* ~ADRGDataset() */
534 : /************************************************************************/
535 :
536 28 : ADRGDataset::~ADRGDataset()
537 : {
538 14 : if (poOverviewDS)
539 : {
540 0 : delete poOverviewDS;
541 : }
542 :
543 14 : CSLDestroy(papszSubDatasets);
544 :
545 14 : if (bCreation)
546 : {
547 3 : GDALPamDataset::FlushCache();
548 :
549 : /* Write header and padding of image */
550 3 : VSIFSeekL(fdIMG, 0, SEEK_SET);
551 : {
552 3 : FILE* fd = fdIMG;
553 3 : int nFields = 0;
554 3 : int sizeOfFields[] = { 0, 0, 0, 0 };
555 3 : const char* nameOfFields[] = { "000", "001", "PAD", "SCN" };
556 3 : int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
557 :
558 3 : sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "GEO_DATA_FILE", "", ""); /* 000 */
559 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
560 : "RTY!RID",
561 3 : "(A(3),A(2))");
562 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "PADDING_FIELD", /* PAD */
563 : "PAD",
564 3 : "(A)");
565 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '0', "PIXEL_FIELD", /* SCN */
566 : "*PIX",
567 3 : "(A(1))");
568 :
569 3 : FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
570 :
571 : /* Write IMAGE_RECORD */
572 : {
573 3 : int nFields = 0;
574 3 : int sizeOfFields[] = {0, 0, 0};
575 3 : const char* nameOfFields[] = { "001", "PAD", "SCN" };
576 3 : int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
577 :
578 : /* Field 001 */
579 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "IMG", 3); /* RTY */
580 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
581 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
582 3 : nFields++;
583 :
584 : /* Field PAD */
585 3 : int endPos = (int)VSIFTellL(fd);
586 3 : char* pad = (char*)CPLMalloc(2047 - endPos);
587 3 : memset(pad, ' ', 2047 - endPos);
588 3 : VSIFWriteL(pad, 1, 2047 - endPos, fd);
589 3 : CPLFree(pad);
590 3 : WriteFieldTerminator(fd);
591 3 : sizeOfFields[nFields] += 2047 - endPos + 1;
592 3 : nFields++;
593 :
594 : /* Field SCN */
595 3 : sizeOfFields[nFields] = (nNextAvailableBlock - 1) * 128 * 128 * 3;
596 3 : nFields++;
597 :
598 3 : FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
599 : }
600 : }
601 :
602 : /* Write terminal field terminator */
603 3 : int offset = offsetInIMG + (nNextAvailableBlock - 1) * 128 * 128 * 3;
604 3 : VSIFSeekL(fdIMG, offset, SEEK_SET);
605 3 : WriteFieldTerminator(fdIMG);
606 :
607 3 : WriteGENFile();
608 3 : WriteTHFFile();
609 : }
610 :
611 14 : if (fdIMG)
612 : {
613 13 : VSIFCloseL(fdIMG);
614 : }
615 :
616 14 : if (fdGEN)
617 : {
618 3 : VSIFCloseL(fdGEN);
619 : }
620 14 : if (fdTHF)
621 : {
622 3 : VSIFCloseL(fdTHF);
623 : }
624 :
625 14 : if (TILEINDEX)
626 : {
627 13 : delete [] TILEINDEX;
628 : }
629 28 : }
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 3 : CPLErr ADRGDataset::SetGeoTransform( double * padfGeoTransform )
732 :
733 : {
734 3 : memcpy( adfGeoTransform, padfGeoTransform, sizeof(double)*6 );
735 3 : bGeoTransformValid = TRUE;
736 3 : return CE_None;
737 : }
738 :
739 : /************************************************************************/
740 : /* GetLongitudeFromString() */
741 : /************************************************************************/
742 :
743 10 : double ADRGDataset::GetLongitudeFromString(const char* str)
744 : {
745 10 : char ddd[3+1] = { 0 };
746 10 : char mm[2+1] = { 0 };
747 10 : char ssdotss[5+1] = { 0 };
748 10 : int sign = (str[0] == '+') ? 1 : - 1;
749 10 : str++;
750 10 : strncpy(ddd, str, 3);
751 10 : str+=3;
752 10 : strncpy(mm, str, 2);
753 10 : str+=2;
754 10 : strncpy(ssdotss, str, 5);
755 10 : return sign * (atof(ddd) + atof(mm) / 60 + atof(ssdotss) / 3600);
756 : }
757 :
758 : /************************************************************************/
759 : /* GetLatitudeFromString() */
760 : /************************************************************************/
761 :
762 10 : double ADRGDataset::GetLatitudeFromString(const char* str)
763 : {
764 10 : char ddd[2+1] = { 0 };
765 10 : char mm[2+1] = { 0 };
766 10 : char ssdotss[5+1] = { 0 };
767 10 : int sign = (str[0] == '+') ? 1 : - 1;
768 10 : str++;
769 10 : strncpy(ddd, str, 2);
770 10 : str+=2;
771 10 : strncpy(mm, str, 2);
772 10 : str+=2;
773 10 : strncpy(ssdotss, str, 5);
774 10 : return sign * (atof(ddd) + atof(mm) / 60 + atof(ssdotss) / 3600);
775 : }
776 :
777 : /************************************************************************/
778 : /* FindRecordInGENForIMG() */
779 : /************************************************************************/
780 :
781 2 : DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
782 : const char* pszGENFileName,
783 : 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 0 : 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 10 : if (!(strcmp(subfieldDefn->GetName(), "RTY") == 0 &&
818 5 : (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 6 : if (!(strcmp(subfieldDefn->GetName(), "BAD") == 0 &&
843 3 : (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 10 : ADRGDataset* ADRGDataset::OpenDataset(
868 : const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record)
869 : {
870 10 : DDFModule module;
871 :
872 10 : int SCA = 0;
873 10 : 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 10 : CPLString osBAD;
882 : int TIF;
883 10 : int* TILEINDEX = NULL;
884 : int i;
885 :
886 : DDFField* field;
887 : DDFFieldDefn *fieldDefn;
888 : DDFSubfieldDefn* subfieldDefn;
889 :
890 10 : if (record == NULL)
891 : {
892 2 : record = FindRecordInGENForIMG(module, pszGENFileName, pszIMGFileName);
893 2 : if (record == NULL)
894 0 : return NULL;
895 : }
896 :
897 10 : field = record->GetField(1);
898 10 : fieldDefn = field->GetFieldDefn();
899 :
900 10 : if (!(strcmp(fieldDefn->GetName(), "DSI") == 0 &&
901 : fieldDefn->GetSubfieldCount() == 2))
902 : {
903 0 : return NULL;
904 : }
905 :
906 10 : subfieldDefn = fieldDefn->GetSubfield(0);
907 20 : if (!(strcmp(subfieldDefn->GetName(), "PRT") == 0 &&
908 10 : (subfieldDefn->GetFormat())[0] == 'A' &&
909 : strcmp(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 4, NULL), "ADRG") == 0))
910 : {
911 0 : return NULL;
912 : }
913 :
914 10 : subfieldDefn = fieldDefn->GetSubfield(1);
915 20 : if (!(strcmp(subfieldDefn->GetName(), "NAM") == 0 &&
916 10 : (subfieldDefn->GetFormat())[0] == 'A'))
917 : {
918 0 : return NULL;
919 : }
920 :
921 10 : CPLString osNAM = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 8, NULL);
922 :
923 10 : field = record->GetField(2);
924 10 : fieldDefn = field->GetFieldDefn();
925 :
926 10 : int isGIN = TRUE;
927 :
928 10 : if (isGIN)
929 : {
930 10 : if (!(strcmp(fieldDefn->GetName(), "GEN") == 0 &&
931 : fieldDefn->GetSubfieldCount() == 21))
932 : {
933 0 : return NULL;
934 : }
935 :
936 10 : subfieldDefn = fieldDefn->GetSubfield(0);
937 20 : if (!(strcmp(subfieldDefn->GetName(), "STR") == 0 &&
938 10 : (subfieldDefn->GetFormat())[0] == 'I' &&
939 : subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 1, NULL) == 3))
940 : {
941 0 : return NULL;
942 : }
943 :
944 10 : subfieldDefn = fieldDefn->GetSubfield(12);
945 20 : if (!(strcmp(subfieldDefn->GetName(), "SCA") == 0 &&
946 10 : (subfieldDefn->GetFormat())[0] == 'I'))
947 : {
948 0 : return NULL;
949 : }
950 :
951 10 : SCA = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 9, NULL);
952 10 : CPLDebug("ADRG", "SCA=%d", SCA);
953 :
954 10 : subfieldDefn = fieldDefn->GetSubfield(13);
955 20 : if (!(strcmp(subfieldDefn->GetName(), "ZNA") == 0 &&
956 10 : (subfieldDefn->GetFormat())[0] == 'I'))
957 : {
958 0 : return NULL;
959 : }
960 :
961 10 : ZNA = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 2, NULL);
962 10 : CPLDebug("ADRG", "ZNA=%d", ZNA);
963 :
964 10 : subfieldDefn = fieldDefn->GetSubfield(14);
965 20 : if (!(strcmp(subfieldDefn->GetName(), "PSP") == 0 &&
966 10 : (subfieldDefn->GetFormat())[0] == 'R'))
967 : {
968 0 : return NULL;
969 : }
970 :
971 10 : PSP = subfieldDefn->ExtractFloatData(field->GetSubfieldData(subfieldDefn), 5, NULL);
972 10 : CPLDebug("ADRG", "PSP=%f", PSP);
973 :
974 10 : subfieldDefn = fieldDefn->GetSubfield(16);
975 20 : if (!(strcmp(subfieldDefn->GetName(), "ARV") == 0 &&
976 10 : (subfieldDefn->GetFormat())[0] == 'I'))
977 : {
978 0 : return NULL;
979 : }
980 :
981 10 : ARV = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 8, NULL);
982 10 : CPLDebug("ADRG", "ARV=%d", ARV);
983 :
984 10 : subfieldDefn = fieldDefn->GetSubfield(17);
985 20 : if (!(strcmp(subfieldDefn->GetName(), "BRV") == 0 &&
986 10 : (subfieldDefn->GetFormat())[0] == 'I'))
987 : {
988 0 : return NULL;
989 : }
990 :
991 10 : BRV = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 8, NULL);
992 10 : CPLDebug("ADRG", "BRV=%d", BRV);
993 :
994 :
995 10 : subfieldDefn = fieldDefn->GetSubfield(18);
996 20 : if (!(strcmp(subfieldDefn->GetName(), "LSO") == 0 &&
997 10 : (subfieldDefn->GetFormat())[0] == 'A'))
998 : {
999 0 : return NULL;
1000 : }
1001 :
1002 10 : LSO = GetLongitudeFromString(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 11, NULL));
1003 10 : CPLDebug("ADRG", "LSO=%f", LSO);
1004 :
1005 10 : subfieldDefn = fieldDefn->GetSubfield(19);
1006 20 : if (!(strcmp(subfieldDefn->GetName(), "PSO") == 0 &&
1007 10 : (subfieldDefn->GetFormat())[0] == 'A'))
1008 : {
1009 0 : return NULL;
1010 : }
1011 :
1012 10 : PSO = GetLatitudeFromString(subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 10, NULL));
1013 10 : 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 0 : (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 0 : (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 0 : (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 0 : (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 0 : (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 10 : field = record->GetField(3);
1074 10 : fieldDefn = field->GetFieldDefn();
1075 :
1076 10 : if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
1077 : fieldDefn->GetSubfieldCount() == 15))
1078 : {
1079 0 : return NULL;
1080 : }
1081 :
1082 10 : subfieldDefn = fieldDefn->GetSubfield(4);
1083 20 : if (!(strcmp(subfieldDefn->GetName(), "NFL") == 0 &&
1084 10 : (subfieldDefn->GetFormat())[0] == 'I'))
1085 : {
1086 0 : return NULL;
1087 : }
1088 :
1089 10 : NFL = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 3, NULL);
1090 10 : CPLDebug("ADRG", "NFL=%d", NFL);
1091 :
1092 10 : subfieldDefn = fieldDefn->GetSubfield(5);
1093 20 : if (!(strcmp(subfieldDefn->GetName(), "NFC") == 0 &&
1094 10 : (subfieldDefn->GetFormat())[0] == 'I'))
1095 : {
1096 0 : return NULL;
1097 : }
1098 :
1099 10 : NFC = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 3, NULL);
1100 10 : CPLDebug("ADRG", "NFC=%d", NFC);
1101 :
1102 10 : subfieldDefn = fieldDefn->GetSubfield(6);
1103 20 : if (!(strcmp(subfieldDefn->GetName(), "PNC") == 0 &&
1104 10 : (subfieldDefn->GetFormat())[0] == 'I'))
1105 : {
1106 0 : return NULL;
1107 : }
1108 :
1109 10 : int PNC = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 6, NULL);
1110 10 : CPLDebug("ADRG", "PNC=%d", PNC);
1111 10 : if (PNC != 128)
1112 : {
1113 0 : return NULL;
1114 : }
1115 :
1116 10 : subfieldDefn = fieldDefn->GetSubfield(7);
1117 20 : if (!(strcmp(subfieldDefn->GetName(), "PNL") == 0 &&
1118 10 : (subfieldDefn->GetFormat())[0] == 'I'))
1119 : {
1120 0 : return NULL;
1121 : }
1122 :
1123 10 : int PNL = subfieldDefn->ExtractIntData(field->GetSubfieldData(subfieldDefn), 6, NULL);
1124 10 : CPLDebug("ADRG", "PNL=%d", PNL);
1125 10 : if (PNL != 128)
1126 : {
1127 0 : return NULL;
1128 : }
1129 :
1130 10 : subfieldDefn = fieldDefn->GetSubfield(13);
1131 20 : if (!(strcmp(subfieldDefn->GetName(), "BAD") == 0 &&
1132 10 : (subfieldDefn->GetFormat())[0] == 'A'))
1133 : {
1134 0 : return NULL;
1135 : }
1136 :
1137 10 : osBAD = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 12, NULL);
1138 : {
1139 10 : char* c = (char*) strchr(osBAD.c_str(), ' ');
1140 10 : if (c)
1141 0 : *c = 0;
1142 : }
1143 10 : CPLDebug("ADRG", "BAD=%s", osBAD.c_str());
1144 :
1145 10 : subfieldDefn = fieldDefn->GetSubfield(14);
1146 20 : if (!(strcmp(subfieldDefn->GetName(), "TIF") == 0 &&
1147 10 : (subfieldDefn->GetFormat())[0] == 'A'))
1148 : {
1149 0 : return NULL;
1150 : }
1151 :
1152 10 : TIF = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 1, NULL)[0] == 'Y';
1153 10 : CPLDebug("ADRG", "TIF=%d", TIF);
1154 :
1155 10 : if (TIF)
1156 : {
1157 10 : if (record->GetFieldCount() != 6)
1158 : {
1159 0 : return NULL;
1160 : }
1161 :
1162 10 : field = record->GetField(5);
1163 10 : fieldDefn = field->GetFieldDefn();
1164 :
1165 10 : if (!(strcmp(fieldDefn->GetName(), "TIM") == 0))
1166 : {
1167 0 : return NULL;
1168 : }
1169 :
1170 10 : if (field->GetDataSize() != 5 * NFL * NFC + 1)
1171 : {
1172 0 : return NULL;
1173 : }
1174 :
1175 10 : TILEINDEX = new int [NFL * NFC];
1176 10 : const char* ptr = field->GetData();
1177 10 : char offset[5+1]={0};
1178 20 : for(i=0;i<NFL*NFC;i++)
1179 : {
1180 10 : strncpy(offset, ptr, 5);
1181 10 : ptr += 5;
1182 10 : TILEINDEX[i] = atoi(offset);
1183 : //CPLDebug("ADRG", "TSI[%d]=%d", i, TILEINDEX[i]);
1184 : }
1185 : }
1186 :
1187 10 : FILE* fdIMG = VSIFOpenL(pszIMGFileName, "rb");
1188 10 : if (fdIMG == NULL)
1189 : {
1190 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s\n", pszIMGFileName);
1191 0 : return NULL;
1192 : }
1193 :
1194 10 : 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 10 : int offsetInIMG = 0;
1203 : char c;
1204 : char recordName[3];
1205 10 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
1206 : {
1207 0 : VSIFCloseL(fdIMG);
1208 0 : return NULL;
1209 : }
1210 2590 : while (!VSIFEofL(fdIMG))
1211 : {
1212 2580 : if (c == 30)
1213 : {
1214 60 : if (VSIFReadL(recordName, 1, 3, fdIMG) != 3)
1215 : {
1216 0 : VSIFCloseL(fdIMG);
1217 0 : return NULL;
1218 : }
1219 60 : offsetInIMG += 3;
1220 60 : if (strncmp(recordName,"IMG",3) == 0)
1221 : {
1222 10 : offsetInIMG += 4;
1223 10 : if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0)
1224 : {
1225 0 : VSIFCloseL(fdIMG);
1226 0 : return NULL;
1227 : }
1228 10 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
1229 : {
1230 0 : VSIFCloseL(fdIMG);
1231 0 : return NULL;
1232 : }
1233 17700 : while(c ==' ')
1234 : {
1235 17680 : offsetInIMG ++;
1236 17680 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
1237 : {
1238 0 : VSIFCloseL(fdIMG);
1239 0 : return NULL;
1240 : }
1241 : }
1242 10 : offsetInIMG ++;
1243 10 : break;
1244 : }
1245 : }
1246 :
1247 2570 : offsetInIMG ++;
1248 2570 : if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
1249 : {
1250 0 : VSIFCloseL(fdIMG);
1251 0 : return NULL;
1252 : }
1253 : }
1254 :
1255 10 : if (VSIFEofL(fdIMG))
1256 : {
1257 0 : VSIFCloseL(fdIMG);
1258 0 : return NULL;
1259 : }
1260 :
1261 10 : CPLDebug("ADRG", "Img offset data = %d", offsetInIMG);
1262 :
1263 10 : ADRGDataset* poDS = new ADRGDataset();
1264 :
1265 20 : poDS->osGENFileName = pszGENFileName;
1266 10 : poDS->osIMGFileName = pszIMGFileName;
1267 10 : poDS->NFC = NFC;
1268 10 : poDS->NFL = NFL;
1269 10 : poDS->nRasterXSize = NFC * 128;
1270 10 : poDS->nRasterYSize = NFL * 128;
1271 10 : poDS->LSO = LSO;
1272 10 : poDS->PSO = PSO;
1273 10 : poDS->ARV = ARV;
1274 10 : poDS->BRV = BRV;
1275 10 : poDS->TILEINDEX = TILEINDEX;
1276 10 : poDS->fdIMG = fdIMG;
1277 10 : poDS->offsetInIMG = offsetInIMG;
1278 10 : poDS->poOverviewDS = NULL;
1279 :
1280 10 : if (isGIN)
1281 : {
1282 : char pszValue[32];
1283 10 : sprintf(pszValue, "%d", SCA);
1284 10 : poDS->SetMetadataItem( "ADRG_SCA", pszValue );
1285 : }
1286 :
1287 10 : poDS->SetMetadataItem( "ADRG_NAM", osNAM.c_str() );
1288 :
1289 10 : poDS->nBands = 3;
1290 40 : for( i = 0; i < poDS->nBands; i++ )
1291 30 : poDS->SetBand( i+1, new ADRGRasterBand( poDS, i+1 ) );
1292 :
1293 10 : 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 : 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 16 : if (!(strcmp(subfieldDefn->GetName(), "RTY") == 0 &&
1335 8 : (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 2 : 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 18 : if (!(strcmp(subfieldDefn->GetName(), "VFF") == 0 &&
1359 9 : (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 17 : while(*ptrDir)
1383 : {
1384 15 : 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 13 : 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 9 : char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
1419 : int *pnRecordIndex)
1420 : {
1421 : DDFRecord * record;
1422 : DDFField* field;
1423 : DDFFieldDefn *fieldDefn;
1424 : DDFSubfieldDefn* subfieldDefn;
1425 9 : int nFilenames = 0;
1426 9 : char** papszFileNames = NULL;
1427 9 : int nRecordIndex = -1;
1428 :
1429 9 : if (pnRecordIndex)
1430 9 : *pnRecordIndex = -1;
1431 :
1432 9 : DDFModule module;
1433 9 : if (!module.Open(pszFileName, TRUE))
1434 0 : return NULL;
1435 :
1436 28 : while (TRUE)
1437 : {
1438 37 : nRecordIndex ++;
1439 :
1440 37 : CPLPushErrorHandler( CPLQuietErrorHandler );
1441 37 : record = module.ReadRecord();
1442 37 : CPLPopErrorHandler();
1443 37 : CPLErrorReset();
1444 37 : if (record == NULL)
1445 : break;
1446 :
1447 28 : if (record->GetFieldCount() >= 5)
1448 : {
1449 19 : field = record->GetField(0);
1450 19 : fieldDefn = field->GetFieldDefn();
1451 19 : if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
1452 : fieldDefn->GetSubfieldCount() == 2))
1453 : {
1454 0 : continue;
1455 : }
1456 :
1457 19 : subfieldDefn = fieldDefn->GetSubfield(0);
1458 38 : if (!(strcmp(subfieldDefn->GetName(), "RTY") == 0 &&
1459 19 : (subfieldDefn->GetFormat())[0] == 'A'))
1460 : {
1461 0 : continue;
1462 : }
1463 :
1464 19 : const char* RTY = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 3, NULL);
1465 :
1466 : /* Ignore overviews */
1467 19 : if ( strcmp(RTY, "OVV") == 0 )
1468 9 : continue;
1469 :
1470 10 : if ( strcmp(RTY, "GIN") != 0 )
1471 0 : continue;
1472 :
1473 10 : field = record->GetField(3);
1474 10 : fieldDefn = field->GetFieldDefn();
1475 :
1476 10 : if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
1477 : fieldDefn->GetSubfieldCount() == 15))
1478 : {
1479 0 : continue;
1480 : }
1481 :
1482 10 : subfieldDefn = fieldDefn->GetSubfield(13);
1483 20 : if (!(strcmp(subfieldDefn->GetName(), "BAD") == 0 &&
1484 10 : (subfieldDefn->GetFormat())[0] == 'A'))
1485 : {
1486 0 : continue;
1487 : }
1488 :
1489 10 : CPLString osBAD = subfieldDefn->ExtractStringData(field->GetSubfieldData(subfieldDefn), 12, NULL);
1490 : {
1491 10 : char* c = (char*) strchr(osBAD.c_str(), ' ');
1492 10 : if (c)
1493 0 : *c = 0;
1494 : }
1495 10 : CPLDebug("ADRG", "BAD=%s", osBAD.c_str());
1496 :
1497 : /* Build full IMG file name from BAD value */
1498 10 : CPLString osGENDir(CPLGetDirname(pszFileName));
1499 :
1500 10 : CPLString osFileName = CPLFormFilename(osGENDir.c_str(), osBAD.c_str(), NULL);
1501 : VSIStatBufL sStatBuf;
1502 10 : if( VSIStatL( osFileName, &sStatBuf ) == 0 )
1503 : {
1504 10 : osBAD = osFileName;
1505 10 : 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 10 : if (nFilenames == 0 && pnRecordIndex)
1532 9 : *pnRecordIndex = nRecordIndex;
1533 :
1534 10 : papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
1535 10 : papszFileNames[nFilenames] = CPLStrdup(osBAD.c_str());
1536 10 : papszFileNames[nFilenames + 1] = NULL;
1537 10 : nFilenames ++;
1538 : }
1539 : }
1540 :
1541 9 : return papszFileNames;
1542 : }
1543 :
1544 : /************************************************************************/
1545 : /* Open() */
1546 : /************************************************************************/
1547 :
1548 8443 : GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
1549 : {
1550 8443 : int nRecordIndex = -1;
1551 8443 : CPLString osGENFileName;
1552 8443 : CPLString osIMGFileName;
1553 8443 : int bFromSubdataset = FALSE;
1554 :
1555 8443 : 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 8441 : if( poOpenInfo->nHeaderBytes < 500 )
1569 8319 : return NULL;
1570 :
1571 122 : CPLString osFileName(poOpenInfo->pszFilename);
1572 122 : 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 122 : if (EQUAL(CPLGetExtension(osFileName.c_str()), "GEN"))
1605 : {
1606 9 : osGENFileName = osFileName;
1607 :
1608 9 : char** papszFileNames = GetIMGListFromGEN(osFileName.c_str(), &nRecordIndex);
1609 9 : if (papszFileNames == NULL)
1610 0 : return NULL;
1611 9 : if (papszFileNames[1] == NULL)
1612 : {
1613 8 : osIMGFileName = papszFileNames[0];
1614 8 : 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 123 : if (osGENFileName.size() > 0 &&
1632 : osIMGFileName.size() > 0)
1633 : {
1634 10 : 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 10 : DDFModule module;
1643 10 : DDFRecord* record = NULL;
1644 10 : if (nRecordIndex >= 0 &&
1645 : module.Open(osGENFileName.c_str(), TRUE))
1646 : {
1647 : int i;
1648 32 : for(i=0;i<=nRecordIndex;i++)
1649 : {
1650 24 : CPLPushErrorHandler( CPLQuietErrorHandler );
1651 24 : record = module.ReadRecord();
1652 24 : CPLPopErrorHandler();
1653 24 : CPLErrorReset();
1654 24 : if (record == NULL)
1655 0 : break;
1656 : }
1657 : }
1658 :
1659 10 : ADRGDataset* poDS = OpenDataset(osGENFileName.c_str(), osIMGFileName.c_str(), record);
1660 :
1661 10 : if (poDS)
1662 : {
1663 : /* -------------------------------------------------------------------- */
1664 : /* Initialize any PAM information. */
1665 : /* -------------------------------------------------------------------- */
1666 10 : poDS->SetDescription( poOpenInfo->pszFilename );
1667 10 : poDS->TryLoadXML();
1668 :
1669 : /* -------------------------------------------------------------------- */
1670 : /* Check for external overviews. */
1671 : /* -------------------------------------------------------------------- */
1672 10 : if( bFromSubdataset )
1673 2 : poDS->oOvManager.Initialize( poDS, osIMGFileName.c_str() );
1674 : else
1675 8 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
1676 :
1677 10 : return poDS;
1678 0 : }
1679 : }
1680 :
1681 113 : return NULL;
1682 : }
1683 :
1684 : /************************************************************************/
1685 : /* Create() */
1686 : /************************************************************************/
1687 :
1688 34 : GDALDataset *ADRGDataset::Create(const char* pszFilename, int nXSize, int nYSize,
1689 : int nBands, GDALDataType eType, char **papszOptions)
1690 : {
1691 : int i;
1692 :
1693 34 : 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 20 : GDALGetDataTypeName(eType) );
1699 :
1700 20 : 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 2 : "Invalid filename. Must be ABCDEF01.GEN\n");
1722 2 : return NULL;
1723 : }
1724 :
1725 3 : CPLString osBaseFileName(CPLGetBasename(pszFilename));
1726 3 : 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 0 : return NULL;
1731 : }
1732 :
1733 21 : for(i=0;i<6;i++)
1734 : {
1735 18 : 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 3 : FILE* fdGEN = VSIFOpenL(pszFilename, "wb");
1744 3 : 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 3 : CPLString osDirname(CPLGetDirname(pszFilename));
1752 3 : CPLString osTransh01THF(CPLFormFilename(osDirname.c_str(), "TRANSH01.THF", NULL));
1753 3 : FILE* fdTHF = VSIFOpenL(osTransh01THF.c_str(), "wb");
1754 3 : 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 3 : CPLString osImgFilename = CPLResetExtension(pszFilename, "IMG");
1763 3 : FILE* fdIMG = VSIFOpenL(osImgFilename.c_str(), "w+b");
1764 3 : 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 3 : ADRGDataset* poDS = new ADRGDataset();
1774 :
1775 3 : poDS->eAccess = GA_Update;
1776 :
1777 3 : poDS->fdGEN = fdGEN;
1778 3 : poDS->fdIMG = fdIMG;
1779 3 : poDS->fdTHF = fdTHF;
1780 :
1781 3 : poDS->osBaseFileName = osBaseFileName;
1782 3 : poDS->bCreation = TRUE;
1783 3 : poDS->nNextAvailableBlock = 1;
1784 3 : poDS->NFC = (nXSize + 127) / 128;
1785 3 : poDS->NFL = (nYSize + 127) / 128;
1786 3 : poDS->nRasterXSize = nXSize;
1787 3 : poDS->nRasterYSize = nYSize;
1788 3 : poDS->bGeoTransformValid = FALSE;
1789 3 : poDS->TILEINDEX = new int [poDS->NFC*poDS->NFL];
1790 3 : memset(poDS->TILEINDEX, 0, sizeof(int)*poDS->NFC*poDS->NFL);
1791 3 : poDS->offsetInIMG = 2048;
1792 3 : poDS->poOverviewDS = NULL;
1793 :
1794 3 : poDS->nBands = 3;
1795 12 : for( i = 0; i < poDS->nBands; i++ )
1796 9 : poDS->SetBand( i+1, new ADRGRasterBand( poDS, i+1 ) );
1797 :
1798 3 : return poDS;
1799 : }
1800 :
1801 : /************************************************************************/
1802 : /* WriteGENFile_Header() */
1803 : /************************************************************************/
1804 :
1805 3 : static void WriteGENFile_Header(FILE* fd)
1806 : {
1807 3 : int nFields = 0;
1808 3 : int sizeOfFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, };
1809 3 : const char* nameOfFields[] = { "000", "001", "DRF", "DSI", "OVI", "GEN", "SPR", "BDF", "TIM" };
1810 3 : int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
1811 :
1812 3 : sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "GENERAL_INFORMATION_FILE", "", ""); /* 000 */
1813 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
1814 : "RTY!RID",
1815 3 : "(A(3),A(2))");
1816 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '1', "DATA_SET_DESCRIPTION_FIELD", /* DRF */
1817 : "NSH!NSV!NOZ!NOS",
1818 3 : "(4I(2))");
1819 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "DATA_SET-ID_FIELD", /* DSI */
1820 : "PRT!NAM",
1821 3 : "(A(4),A(8))");
1822 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "OVERVIEW_INFORMATION_FIELD", /* OVI */
1823 : "STR!ARV!BRV!LSO!PSO",
1824 3 : "(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 3 : "(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 3 : "(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 3 : "(A(5),I(5),I(5))");
1834 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '1', "TILE_INDEX_MAP_FIELD", /* TIM */
1835 : "*TSI",
1836 3 : "(I(5))");
1837 :
1838 3 : FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
1839 3 : }
1840 :
1841 : /************************************************************************/
1842 : /* WriteGENFile_DataSetDescriptionRecord() */
1843 : /************************************************************************/
1844 :
1845 : /* Write DATA_SET_DESCRIPTION_RECORD */
1846 3 : static void WriteGENFile_DataSetDescriptionRecord(FILE* fd)
1847 : {
1848 3 : int nFields = 0;
1849 3 : int sizeOfFields[] = {0, 0};
1850 3 : const char* nameOfFields[] = { "001", "DRF" };
1851 3 : int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
1852 :
1853 : /* Field 001 */
1854 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "DSS", 3); /* RTY */
1855 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
1856 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1857 3 : nFields++;
1858 :
1859 : /* Field DRF */
1860 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NSH */
1861 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NSV */
1862 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOZ */
1863 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOS */
1864 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1865 3 : nFields++;
1866 :
1867 3 : FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
1868 3 : }
1869 :
1870 : /************************************************************************/
1871 : /* WriteGENFile_OverviewRecord() */
1872 : /************************************************************************/
1873 :
1874 : /* Write OVERVIEW_RECORD */
1875 3 : static void WriteGENFile_OverviewRecord(FILE* fd, CPLString& osBaseFileName, int ARV, int BRV, double LSO, double PSO,
1876 : int nOvSizeX, int nOvSizeY, int NFL, int NFC, int* TILEINDEX)
1877 : {
1878 3 : int nFields = 0;
1879 3 : int sizeOfFields[] = {0, 0, 0, 0, 0, 0};
1880 3 : const char* nameOfFields[] = { "001", "DSI", "OVI", "SPR", "BDF", "TIM" };
1881 3 : int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
1882 :
1883 : /* Field 001 */
1884 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "OVV", 3); /* RTY */
1885 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
1886 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1887 3 : nFields++;
1888 :
1889 : /* Field DSI */
1890 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
1891 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
1892 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1893 3 : nFields++;
1894 :
1895 : /* Field OVI */
1896 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
1897 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); /* ARV */ /* FIXME */
1898 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8); /* BRV */ /* FIXME */
1899 3 : sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* LSO */ /* FIXME */
1900 3 : sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */ /* FIXME */
1901 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1902 3 : nFields++;
1903 :
1904 : /* Field SPR */
1905 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
1906 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeX-1, 6); /* NUS */
1907 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeY-1, 6); /* NLL */
1908 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
1909 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nOvSizeY + 127) / 128, 3); /* NFL */
1910 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nOvSizeX + 127) / 128, 3); /* NFC */
1911 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
1912 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
1913 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
1914 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
1915 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
1916 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
1917 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
1918 : char tmp[12+1];
1919 3 : sprintf(tmp, "%s.IMG", osBaseFileName.c_str()); /* FIXME */
1920 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 12); /* BAD */
1921 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */
1922 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1923 3 : nFields++;
1924 :
1925 : /* Field BDF */
1926 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
1927 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
1928 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
1929 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
1930 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
1931 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
1932 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
1933 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
1934 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
1935 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1936 3 : nFields++;
1937 :
1938 : /* Field TIM */
1939 : int i;
1940 6 : for(i=0;i<NFL*NFC;i++)
1941 : {
1942 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
1943 : }
1944 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1945 3 : nFields++;
1946 :
1947 3 : FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
1948 3 : }
1949 :
1950 : /************************************************************************/
1951 : /* WriteGENFile_GeneralInformationRecord() */
1952 : /************************************************************************/
1953 :
1954 : /* Write GENERAL_INFORMATION_RECORD */
1955 4 : 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 : int NFL, int NFC, int* TILEINDEX)
1960 :
1961 : {
1962 4 : int nFields = 0;
1963 4 : int sizeOfFields[] = {0, 0, 0, 0, 0, 0};
1964 4 : const char* nameOfFields[] = { "001", "DSI", "GEN", "SPR", "BDF", "TIM" };
1965 4 : int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
1966 :
1967 : /* Field 001 */
1968 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "GIN", 3); /* RTY */
1969 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
1970 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1971 4 : nFields++;
1972 :
1973 : /* Field DSI */
1974 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
1975 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, osNAM.c_str(), 8); /* NAM */
1976 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
1977 4 : nFields++;
1978 :
1979 : /* Field `GEN */
1980 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
1981 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); /* LOD */ /* FIXME */
1982 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); /* LAD */ /* FIXME */
1983 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 16, 3); /* UNIloa */ /* FIXME */
1984 4 : sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */
1985 4 : sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */
1986 4 : sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* NWO */
1987 4 : sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NWA */
1988 4 : sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */
1989 4 : sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */
1990 4 : sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* SEO */
1991 4 : sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SEA */
1992 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, SCA, 9); /* SCA */
1993 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* ZNA */ /* FIXME */
1994 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "100.0", 5); /* PSP */
1995 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* IMR */
1996 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); /* ARV */
1997 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8); /* BRV */
1998 4 : sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* LSO */
1999 4 : sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */
2000 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 64); /* TXT */
2001 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2002 4 : nFields++;
2003 :
2004 : /* Field SPR */
2005 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
2006 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nRasterXSize-1, 6); /* NUS */
2007 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nRasterYSize-1, 6); /* NLL */
2008 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
2009 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nRasterYSize + 127) / 128, 3); /* NFL */
2010 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nRasterXSize + 127) / 128, 3); /* NFC */
2011 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
2012 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
2013 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
2014 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
2015 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
2016 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
2017 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
2018 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, osBAD.c_str(), 12); /* BAD */
2019 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Y", 1); /* TIF */
2020 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2021 4 : nFields++;
2022 :
2023 : /* Field BDF */
2024 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
2025 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2026 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2027 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
2028 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2029 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2030 4 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
2031 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2032 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2033 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2034 4 : nFields++;
2035 :
2036 : /* Field TIM */
2037 : int i;
2038 8 : for(i=0;i<NFL*NFC;i++)
2039 : {
2040 4 : sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
2041 : }
2042 4 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2043 4 : nFields++;
2044 :
2045 4 : FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
2046 4 : }
2047 :
2048 : /************************************************************************/
2049 : /* WriteGENFile() */
2050 : /************************************************************************/
2051 :
2052 3 : void ADRGDataset::WriteGENFile()
2053 : {
2054 3 : 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 3 : LSO = adfGeoTransform[0];
2064 3 : PSO = adfGeoTransform[3];
2065 3 : ARV = (int)floor(360. / adfGeoTransform[1] + .5);
2066 3 : BRV = (int)floor(-360. / adfGeoTransform[5] + .5);
2067 :
2068 : /*ARV = ((ARV + 255) / 512) * 512;
2069 : BRV = ((BRV + 255) / 512) * 512;*/
2070 :
2071 3 : int SCA = (int)floor(1000000. * 400384 / BRV + 0.5);
2072 :
2073 3 : int nOvSizeX = nRasterXSize; // FIXME
2074 3 : int nOvSizeY = nRasterYSize; // FIXME
2075 :
2076 : /* Write header */
2077 3 : WriteGENFile_Header(fdGEN);
2078 :
2079 : /* Write DATA_SET_DESCRIPTION_RECORD */
2080 3 : WriteGENFile_DataSetDescriptionRecord(fdGEN);
2081 :
2082 : /* Write OVERVIEW_RECORD */
2083 : WriteGENFile_OverviewRecord(fdGEN, osBaseFileName, ARV, BRV, LSO, PSO,
2084 3 : nOvSizeX, nOvSizeY, NFL, NFC, TILEINDEX);
2085 :
2086 : /* Write GENERAL_INFORMATION_RECORD */
2087 3 : CPLString osNAM = osBaseFileName;
2088 : char tmp[12+1];
2089 3 : sprintf(tmp, "%s.IMG", osNAM.c_str());
2090 3 : CPLString osBAD = tmp;
2091 : WriteGENFile_GeneralInformationRecord(fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
2092 3 : adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
2093 :
2094 3 : 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 3 : }
2105 3 : }
2106 :
2107 : /************************************************************************/
2108 : /* WriteTHFFile() */
2109 : /************************************************************************/
2110 :
2111 3 : void ADRGDataset::WriteTHFFile()
2112 : {
2113 3 : FILE* fd = fdTHF;
2114 :
2115 : /* Write header */
2116 : {
2117 3 : int nFields = 0;
2118 3 : int sizeOfFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2119 3 : const char* nameOfFields[] = { "000", "001", "VDR", "FDR", "QSR", "QUV", "CPS", "CPT", "SPR", "BDF", "VFF"};
2120 3 : int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
2121 :
2122 3 : sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "TRANSMITTAL_HEADER_FILE", "", ""); /* 000 */
2123 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
2124 : "RTY!RID",
2125 3 : "(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 3 : "(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 3 : "(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 3 : "(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 3 : "(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 3 : "(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 3 : "(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 3 : "(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 3 : "(A(5),I(5),I(5))");
2150 : sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "TRANSMITTAL_FILENAMES_FIELD", /* VFF */
2151 : "VFF",
2152 3 : "(A(51))");
2153 :
2154 3 : FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
2155 : }
2156 :
2157 : /* Write TRANSMITTAL_DESCRIPTION_RECORD */
2158 : {
2159 3 : int nFields = 0;
2160 3 : int sizeOfFields[] = {0, 0, 0};
2161 3 : const char* nameOfFields[] = { "001", "VDR", "FDR" };
2162 3 : int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
2163 :
2164 : /* Field 001 */
2165 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "VTH", 3); /* RTY */
2166 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
2167 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2168 3 : nFields++;
2169 :
2170 : /* Field VDR */
2171 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* MSD */
2172 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200); /* VOO */ /* Title and address of originator */
2173 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* ADR */
2174 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* NOV */
2175 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* SQN */
2176 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* NOF */
2177 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 16); /* URF */ /* DMA stock number for this CDROM */
2178 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* EDN */
2179 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "017,19940101", 12); /* DAT */ /* Publication date */
2180 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2181 3 : nFields++;
2182 :
2183 : /* Field FDR */
2184 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
2185 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
2186 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
2187 3 : sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */
2188 3 : sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */
2189 3 : sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */
2190 3 : sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */
2191 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2192 3 : nFields++;
2193 :
2194 3 : FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
2195 : }
2196 :
2197 : /* Write SECURITY_AND_UPDATE_RECORD */
2198 : {
2199 3 : int nFields = 0;
2200 3 : int sizeOfFields[] = {0, 0, 0};
2201 3 : const char* nameOfFields[] = { "001", "QSR", "QUV" };
2202 3 : int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
2203 :
2204 : /* Field 001 */
2205 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "LCF", 3); /* RTY */
2206 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
2207 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2208 3 : nFields++;
2209 :
2210 : /* Field VDR */
2211 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "U", 1); /* QSS */
2212 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* QOD */
2213 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 12); /* DAT */
2214 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200); /* QLE */
2215 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2216 3 : nFields++;
2217 :
2218 : /* Field FDR */
2219 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "MILITARY SPECIFICATION ARC DIGITIZED RASTER GRAPHICS (ADRG)", 100); /* SRC */
2220 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "022,19900222", 12); /* DAT */
2221 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "MIL-A-89007", 20); /* SPA */
2222 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2223 3 : nFields++;
2224 :
2225 3 : FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
2226 : }
2227 :
2228 : /* Write TEST_PATCH_DATA_RECORD */
2229 : {
2230 3 : int nFields = 0;
2231 3 : int sizeOfFields[] = {0, 0, 0, 0, 0};
2232 3 : const char* nameOfFields[] = { "001", "CPS", "CPT", "SPR", "BDF" };
2233 3 : int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
2234 :
2235 : /* Field 001 */
2236 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "TPA", 3); /* RTY */
2237 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
2238 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2239 3 : nFields++;
2240 :
2241 : /* Field CPS */
2242 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Black", 7); /* PNM */
2243 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 6); /* DMV */
2244 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 5); /* REF */
2245 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 5); /* PUR */
2246 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIR */
2247 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIG */
2248 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 3); /* PIB */
2249 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2250 3 : nFields++;
2251 :
2252 : /* Field CPT */
2253 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
2254 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 100); /* SCR */
2255 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2256 3 : nFields++;
2257 :
2258 3 : int nPatchXSize = 512;
2259 3 : int nPatchYSize = 512;
2260 :
2261 : /* Field SPR */
2262 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
2263 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nPatchXSize-1, 6); /* NUS */
2264 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, nPatchYSize-1, 6); /* NLL */
2265 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
2266 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nPatchYSize + 127) / 128, 3); /* NFL */
2267 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, (nPatchXSize + 127) / 128, 3); /* NFC */
2268 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
2269 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
2270 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
2271 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* ROD */
2272 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
2273 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
2274 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
2275 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 12); /* BAD */
2276 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* TIF */
2277 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2278 3 : nFields++;
2279 :
2280 : /* Field BDF */
2281 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Red", 5); /* BID */
2282 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2283 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2284 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Green", 5); /* BID */
2285 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2286 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2287 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "Blue", 5); /* BID */
2288 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
2289 3 : sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
2290 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2291 3 : nFields++;
2292 :
2293 3 : 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 3 : int nFields = 0;
2301 3 : int sizeOfFields[] = {0, 0, 0, 0, 0, 0, 0};
2302 :
2303 : /* Debug option to simulate ADRG datasets made of several images */
2304 3 : int nTotalFields = (CSLTestBoolean(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF"))) ? 6 : 5;
2305 :
2306 3 : const char* nameOfFields[] = { "001", "VFF", "VFF", "VFF", "VFF", "VFF", "VFF" };
2307 3 : int pos = BeginLeader(fd, 9, 9, 3, nTotalFields);
2308 :
2309 : /* Field 001 */
2310 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "TFN", 3); /* RTY */
2311 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "01", 2); /* RID */
2312 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2313 3 : nFields++;
2314 :
2315 : /* Field VFF */
2316 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "TRANSH01.THF", 51); /* VFF */
2317 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2318 3 : nFields++;
2319 :
2320 : /* Field VFF */
2321 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 51); /* VFF */
2322 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2323 3 : nFields++;
2324 :
2325 : /* Field VFF */
2326 3 : sprintf(tmp, "%s.GEN", osBaseFileName.c_str());
2327 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
2328 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2329 3 : nFields++;
2330 :
2331 : /* Field VFF */
2332 3 : sprintf(tmp, "%s.IMG", osBaseFileName.c_str());
2333 3 : sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
2334 3 : sizeOfFields[nFields] += WriteFieldTerminator(fd);
2335 3 : nFields++;
2336 :
2337 3 : 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 3 : FinishWriteLeader(fd, pos, 9, 9, 3, nTotalFields, sizeOfFields, nameOfFields);
2349 : }
2350 3 : }
2351 :
2352 : /************************************************************************/
2353 : /* GDALRegister_ADRG() */
2354 : /************************************************************************/
2355 :
2356 338 : void GDALRegister_ADRG()
2357 :
2358 : {
2359 : GDALDriver *poDriver;
2360 :
2361 338 : if( GDALGetDriverByName( "ADRG" ) == NULL )
2362 : {
2363 336 : poDriver = new GDALDriver();
2364 :
2365 336 : poDriver->SetDescription( "ADRG" );
2366 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
2367 336 : "ARC Digitized Raster Graphics" );
2368 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
2369 336 : "frmt_various.html#ADRG" );
2370 336 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gen" );
2371 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
2372 336 : "Byte" );
2373 :
2374 336 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
2375 :
2376 336 : poDriver->pfnOpen = ADRGDataset::Open;
2377 336 : poDriver->pfnCreate = ADRGDataset::Create;
2378 :
2379 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
2380 : }
2381 338 : }
2382 :
|