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